Strategy Rules:- Setup:
- First swing low: A downward reversal of the low price three percent or greater
- Rally: An upward reversal off the first swing low – a move of the high price greater than or equal to 3 percent
- Second swing low: Finally, second trough of the low price of 3 percent and greater, that should be lower than the first swing low.
- The pivot lows must occur within 30 days of each other;
- The second pivot point (second swing low) should break down through a support level of the lowest low of the last 30 days
- Enter long with a stop order at the high price of bar when the second swing low is detected.
- Exit long position after 30 days.
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using WealthLab;
using WealthLab.Indicators;
namespace WealthLab.Strategies
{
public class Spring_Distance : WealthScript
{
private StrategyParameter paramSwing;
private StrategyParameter paramDays;
private StrategyParameter paramDistance;
private StrategyParameter paramSupport;
public Spring_Distance()
{
paramSwing = CreateParameter("Swing %", 3, 2, 10, 0.5 );
paramDays = CreateParameter("Time-based", 30, 15, 50, 5 );
paramDistance = CreateParameter("Distance", 30, 10, 50, 10 );
paramSupport = CreateParameter("Support, days", 30, 10, 100, 10 );
}
protected override void Execute()
{
// Find the recent Spring setup
PeakTroughMode mode = PeakTroughMode.Percent;
LineStyle ls = LineStyle.Solid; LineStyle ld = LineStyle.Dashed;
double swing = paramSwing.Value;
int days = paramDays.ValueInt;
int distance = paramDistance.ValueInt;
int support = paramSupport.ValueInt;
bool foundSpring = false;
int detectedBar = 0;
double t1 = 0; double p1 = 0; double t2 = 0;
int tb1 = 0; int pb1 = 0; int tb2 = 0;
DataSeries pkHigh = Peak.Series( High, swing, mode );
DataSeries pkBarHigh = PeakBar.Series( High, swing, mode );
DataSeries tgLow = Trough.Series( Low, swing, mode );
DataSeries tgBarLow = TroughBar.Series( Low, swing, mode );
SetBarColors( Color.Silver, Color.Silver );
for(int bar = 30; bar < Bars.Count; bar++)
{
if (IsLastPositionActive)
{ Position p = LastPosition;
if ( bar+1 - p.EntryBar >= days )
SellAtMarket( bar+1, p, "Timed" );
}else
{
if( foundSpring )
{ foundSpring = false;
if( BuyAtStop( bar+1, High[bar] ) != null )
LastActivePosition.Priority = Close[bar];
} else
{
//determine locations and values of most recent peaks and troughs
t1 = tgLow[bar];
tb1 = (int)tgBarLow[bar];
if (tb1 == -1) continue;
p1 = pkHigh[bar];
pb1 = (int)pkBarHigh[bar];
if (pb1 == -1) continue;
t2 = tgLow[pb1];
tb2 = (int)tgBarLow[pb1];
if (tb2 == -1) continue;
//is the first swing low higher than the second?
if( ( t1 < t2 ) & ( Math.Abs(tb2-tb1) <= distance ) &
( Low[tb1] <= Lowest.Value( bar, Low, support ) ) )
{
//don't detect the same setup twice
if ( tb2 != detectedBar )
{
foundSpring = true;
detectedBar = tb2;
AnnotateBar( "T1", tb2, false, Color.Red );
AnnotateBar( "P1", pb1, false, Color.Blue );
AnnotateBar( "T2", tb1, false, Color.Orange );
DrawLine(PricePane,tb2,High[tb2],tb2,Low[tb2],Color.Red,ld,2);
DrawLine(PricePane,tb1,Low[tb1],pb1,High[pb1],Color.Orange,ld,2);
DrawLine(PricePane,pb1,High[pb1],tb2,Low[tb2],Color.Blue,ld,2);
DrawLine(PricePane,bar,High[bar],tb1,Low[tb1],Color.Green,ld,2);
}
}
}
}
}
}
}
}