Active Trader Magazine
  



Trading strategy and system code

(Click here for Trading System Lab code)

Click on a month to see code for that issue of Active Trader:

Sep 2000 Oct 2000 Dec 2000 JanFeb 01 Apr 2001 May 2001
Jun 2001 Sep 2001 Jan 2002 Mar 2002 Apr 2002 May 2002
Jun 2002 Jul 2002 Aug 2002 Sep 2002 Oct 2002 Dec 2002
Feb 2003 May 2003 Jun 2003 Jul 2003 Aug 2003 Sep 2003
Aug 2004 Sep 2004 Feb 2005 Apr 2005 Aug 2005 Dec 2005
Feb 2006 Mar 2006 Apr 2006 May 2006 Nov 2006 Dec 2006
Jan 2007 Feb 2007 Apr 2007 Jun 2007 Jul 2007 Oct 2007
Nov 2007 Dec 2007 Jan 2008 Feb 2008 Mar 2008 May 2008
Feb 2009 May 2009 June 2009 July 2009 Sep 2009 Dec 2009
Jan 2010 Mar 2010 Apr 2010 Jul 2010 Aug 2010 Oct 2010
Nov 2010 Feb 2011 Sep 2011 Oct 2012 Dec 2012 Mar 2013
Dec 2013 May 2014

 

 

 

 

 

 




September 2000

For "Pivotal Trading" by John Ehlers, starting on p. 54:

Vars: Pivot(0), S1(0), S2(0), R1(0), R2(0);
Pivot = (H[1] + L[1] + C[1]) / 3;
R1 = 2*Pivot - L[1];
S1 = 2*Pivot - H[1];
R2 = Pivot + (R1 - S1);
S2 = Pivot - (R1 - S1);
Plot1(R1, "R1");
Plot2(S1, "S1");

Back to top

October 2000

TradeStation (EasyLanguage) code for "Moving beyond the closing price" by Thomas Stridsman, starting on p. 60

Inputs: LookBack(20);

Variable: PercChange(0),
NewLevel(0),
AvgPercChange(0);

PercChange = (Close -
Close[1])/Close[1];

AvgPercChange =
Average(PercChange,20);

NewLevel = Close *
(1 + AvgPercChange);
Plot1[1](NewLevel,);

**

Inputs: StDevs(1);

Variable:StdDevChange(0),
UpLevel(0), DownLevel(0);

StdDevChange =
StdDev(PercChange, 20);

UpLevel = Close *
(1 + AvgPercChange +
StDevs * StdDevChange);

DownLevel = Close *
(1 + AvgPercChange -
StDevs * StdDevChange);
Plot2[-1](UpLevel,);
Plot3[-1](DownLevel,);

**

HighPercChange = (High - Close[1])/Close[1];

**

Input: VSStd(1);

Vars: SumVS(0), AvgVS(0), DiffVS(0), StdVS(0), SetArr(0),
SumArr(0), DiffArr(0), VSLow(0), VSMid(0), VSHigh(0);

{First we define the array}

Array: VS[20](0);

{Then we‰re using a loop function to fill it with the different price changes}

For SetArr = 0 To 4 Begin

VS[SetArr * 4 + 0] = (O[SetArr] - C[SetArr + 1]) / C[SetArr + 1];

VS[SetArr * 4 + 1] = (H[SetArr] - C[SetArr + 1]) / C[SetArr + 1];

VS[SetArr * 4 + 2] = (L[SetArr] - C[SetArr + 1]) / C[SetArr + 1];

VS[SetArr * 4 + 3] = (C[SetArr] - C[SetArr + 1]) / C[SetArr + 1];

End;

For SumArr = 0 To 19 Begin

If SumArr = 0 Then

SumVS = 0;

SumVS = SumVS + VS[SumArr];

If SumArr = 19 Then

{Here we calculate the average price change over the period}

AvgVS = SumVS / 20;

For DiffArr = 0 To 19 Begin

If DiffArr = 0 Then

DiffVS = 0;

{Then we calculate the standard deviation}

DiffVS = DiffVS + Square(VS[DiffArr] - AvgVS);

If DiffArr = 19 Then

StdVS = SquareRoot(DiffVS / 20);

End;

End;

{Finally, we add the moving average (and the standard deviations) to the latest close for an indication of tomorrow‰s trading range}

VSLow = C * (1 + (AvgVS - StdVS * VSStd));

VSMid = C * (1 + AvgVS);

VSHigh = C * (1 + (AvgVS + StdVS * VSStd));

Plot1[-1](VSLow, ‹VS Low);

Plot2[-1](VSMid, ‹VS Mid);

Plot3[-1](VSHigh, ‹VS High);

Back to top

December 2000

For "Trading the momentum of market breadth" by Brown, starting on p. 40:

{Data1 = Either the SPY S&P 500 index tracking stock or the S&P 500 commodity futures contract.

Data2 = Advancing issues of the Nyse.}

Inputs: RL(7), BZ(3), SZ(1);

If ROC(Close Data2, RL) > BZ Then Buy;

If ROC(Close Data2, RL) < SZ Then Sell;

For "Doubly adaptive profit targets" by Chuck LeBeau, starting on p. 78:

Vars: TrendIndicator(0), RiskReward(0);

If ADX(14) > ADX(14)[1] Then
TrendIndicator = 4;
If ADX(14) <= ADX(14)[1] Then
TrendIndicator = 2;

Condition1 = MarketPosition = 0 and Close > Average(Close, 50) and Open
Tomorrow > High and TrendIndicator = 4;

If Condition1 Then Begin
Buy Tomorrow at High Limit;
RiskReward = AvgTrueRange(20);
End;

If MarketPosition = 1 Then Begin
ExitLong ("Profit") Tomorrow at (EntryPrice + RiskReward * TrendIndicator)
Limit;
ExitLong ("Loss") Tomorrow at (EntryPrice - RiskReward * TrendIndicator)
Stop;
If Close < Average(Close, 50) Then ExitLong ("Trend") at Market;
End;

Back to top

Jan./Feb. 2001

For "Better System Performance measures" by Thomas Stridsman, p. 62:

Vars: TotTr(0), Prof(0), TradeStr2(""), CumProf(1), ETop(0), TradeStr2(""),CumProf(1), EBot(0), EDraw(0), TradeStr2("");

TotTr = TotalTrades;

If TotTr > TotTr[1] Then Begin

Prof = 1 + PositionProfit(1) / (EntryPrice(1) * BigPointValue);

CumProf = CumProf * Prof;

ETop = MaxList(ETop, CumProf);

EBot = MinList(EBot, CumProf);

EDraw = CumProf / ETop;

TradeStr2 = NumToStr((Prof - 1) * 100, 2) + "," + NumToStr((CumProf - 1) * 100, 2) + "," + NumToStr((ETop - 1) * 100, 2) + "," + NumToStr((EBot - 1) * 100, 2) + "," + NumToStr((EDraw - 1) * 100, 2) + NewLine;

{Make sure that you have a temp directory on your hard drive, or re-write the path inside the FileAppend command to an exsisting directory of your choice.}

FileAppend("C:TempChap1-2.csv", TradeStr2);

End;

Back to top

April 2001

TradeStation (EasyLanguage) for "Trading the VIX" by Price Headley, starting on p. 52:

Data1 is the OEX and Data2 is the VIX index.

{Code by Price Headley, BigTrends.com}

If Close of Data1 > Average(Close of Data1, 10) and Close of Data2[5] < BollingerBand(Close of Data2, 21, 2)[5] and Close of Data2[6] > BollingerBand(Close of Data2, 21, 2)[6] Then
Buy on Close of Data1;

If BarsSinceEntry = 5 and Close of Data1 < Close of Data1[5] Then
ExitLong on Close of Data1;

If Close of Data1 < Average(Close of Data1, 10) and Close of Data2[10] > BollingerBand(Close of Data2, 21, -2)[10] and Close of Data2[11] < BollingerBand(Close of Data2, 21, -2)[11] Then
Sell on Close of Data1;

If BarsSinceEntry = 5 and Close of Data1 > Close of Data1[5] Then
ExitShort on Close of Data1;

Back to top

May 2001

For "Avoiding system testing traps" by Thomas Stridsman, starting on p. 96:

Inputs: Len(63);

Vars: PointRange(0), SumPosRange(0), SumNegRange(0), AvgPosRange(0), AvgNegRange(0);

PointRange = High - Low;
If Close > Close[1] Then
SumPosRange = SumPosRange * (Len - 1) / Len + PointRange;
If Close < Close[1] Then
SumNegRange = SumNegRange * (Len - 1) / Len + PointRange;

AvgPosRange = SumPosRange / Len;
AvgNegRange = SumNegRange / Len;

{Plot statements to use in indicator only}
Plot1(AvgPosRange, "");
Plot2(AvgNegRange, "");

{Buy/sell statements to use in system only}
{This identifies the up trend}
If PosRange > NegRange and MarketPosition = 0 Then
Buy on O;
If PosRange < NegRange Then
ExitLong ("Down Trend") on Open;

{This identifies the down trend}
If NegRange > PosRange * 1.06 and NegRange >= NegRange[1] and PosRange < PosRange[1] and MarketPosition = 0 Then
Sell on O;
If NegRange < PosRange * 1.06 Then
ExitShort ("Up Trend") on O;

{This is the short-term trading rules within the up trend}
If BarsSinceEntry >=1 Then Begin
ExitLong ("Loss Long") tomorrow at EntryPrice - NegRange stop;
ExitLong ("Trail Long") tomorrow at Open tomorrow - NegRange stop;
ExitLong ("Profit Long 2") tomorrow at Open tomorrow + 3*PosRange limit;
ExitLong ("Profit Long 1") tomorrow at EntryPrice + 6*PosRange limit;
End;

{This is the short-term trading rules within the down trend}
If BarsSinceEntry >=1 Then Begin
ExitShort ("Loss Short") tomorrow at EntryPrice + PosRange stop;
ExitShort ("Trail Short") tomorrow at Open tomorrow + PosRange stop;
ExitShort ("Profit Short 2") tomorrow at Open tomorrow - 2*NegRange limit;
ExitShort ("Profit Short 1") tomorrow at EntryPrice - 4*NegRange limit;
End;

Back to top

June 2001

For "Measuring Trend Momentum" by Tushar Chande, starting on p. 62:

{Tushar Chande 2001: VIDYA/CDMA}

Input: Len(10);
Vars: Diff(0), MyConst(0), MyAdx(0), Varma(0), EmaIndex(0);

{… Index of EMA …}
If Len > 0 then EmaIndex = (2 / (1 + Len)) else EmaIndex = 0.20;

{… Stochastic oscillator using ADX …}
MyAdx = ADX(20);
Diff = Highest(MyAdx, 20) - Lowest(MyAdx, 20);
If Diff > 0 then MyConst = (MyAdx - Lowest(MyAdx, 20))/Diff else MyConst = EmaIndex;

{… Clamp length to that implied by input value of Len …}
If MyConst > EmaIndex then MyConst = EmaIndex;

{… Create the variable MA …}
If CurrentBar < 50 then Varma = Close else Varma = (1 - MyConst) * Varma[1] + MyConst * Close;

Plot1(Varma, "VarMA") ;
Plot2(XAverage(Close, Len), "XAvg"

Back to top

September 2001

Programming code for 3L-R and GAP-2H patternsfrom "Keeping it simple" by Michael Harris, starting on p. 82:

{*****************************************************
Description : 3L-R Pattern Entry Signal
Developed By : Michael Harris, Tradingpatterns.com
*****************************************************}

if l[1] < l[2] and l[2] < l[3] and h[0] > h[3] then
buy ("3L-R") next bar on the open;

{*****************************************************
Description : 3L-R Pattern Long Exit Signal
Developed By : Michael Harris, Tradingpatterns.com
Comments: ptarget and stopl are in percentage terms
*****************************************************}
variables: profitprice(0), stopprice(0);
input: ptarget(8), stopl(8);

profitprice = entryprice*(1+ptarget/100);
stopprice = entryprice*(1-stopl/100);

if marketposition =1 then begin
exitlong ("3L-R Exit") at profitprice limit;
exitlong ("3L-R Stop") at stopprice stop;
end;

**

{***********************************************
Description : GAP-2H Pattern Entry Signal
Developed By : Michael Harris, Tradingpatterns.com
***********************************************}
if h[0] > h[1] and h[2] > l[2] and l[0] > l[1] and l[1] > h[2] and
h[1] > l[0] then
buy ("GPA-2H") next bar on the open;

{***********************************************
Description : GAP-2H Pattern Long Exit Signal
Developed By : Michael Harris, Tradingpatterns.com
Comments: ptarget and stopl are in percentage terms
***********************************************}
variables: profitprice(0), stopprice(0);
input: ptarget(7), stopl(7);

profitprice = entryprice*(1+ptarget/100);
stopprice = entryprice*(1-stopl/100);

if marketposition =1 then begin
exitlong ("GAP-2H Exit") at profitprice limit;
exitlong ("GAP-2H Stop") at stopprice stop;
end;

Back to top

January 2002

For "True Strength Index (TSI)" by Thom Hartle, starting on p. 58:

TSI(close,r,s) = 100*EMA(EMA(mtm,r),s)/EMA(EMA(|mtm|,r),s)

where mtm = closetoday - closeyesterday

EMA(mtm,r) = exponential moving average of mtm with alpha = r

EMA(EMA(mtm,r),s) = exponential moving average of EMA(mtm,r) with alpha = s

|mtm| = absolute value of mtm

r = 25, s = 13

**
For MetaStock, use the Indicator Builder:

100*(Mov(Mov((CLOSE - Ref(CLOSE,-1)),25,E),13,E))/(Mov(Mov(Abs(CLOSE - Ref(CLOSE,-1)),25,E),13,E))

For CQGNet, you first create the momentum (MTM) value, then create the TSI indicator in the custom studies module:

Under the User Values tab create a new User Value "MTM" (Figure 2):

Close(@) - Close (@)[-1]

Next, under the Custom Studies tab create the new Custom Study TSI (Figure 3):

100*( MA(MA( V.mtm(@),Exp,25.000),Exp,13.000) )/( MA(MA( Abs( V.mtm(@)),Exp,25.000),Exp,13.000) )

Back to top

March 2002

For "Putting stops to the test" by Thomas Stridsman, p. 82:

{This code is for a ShowMe}
If High[1] < High[3] and Close[1] < Open[1] and Open < High[1] and High > High[1] Then
Plot1(High * 1.01, "");
If Low[1] > Low[3] and Close[1] > Open[1] and Open > Low[1] and Low < Low[1] Then
Plot2(Low * 0.99, "");
{End ShowMe}

{This code is for a signal}
Inputs: TestRuns(9), ExitLevels(0);
Variables: EntryTrigger(0), LongStopLoss(0), ShortStopLoss(0), ExitTrigger(0);
EntryTrigger = IntPortion(Random(2));
ExitTrigger = (ExitLevels / 5 + 0.2) / 100;
If EntryTrigger = 1 and MarketPosition = 0 Then Begin
If High < High[2] and Close < Open and Open Next Bar < High Then Begin
Buy Next Bar at High Stop;
LongStopLoss = 1 - ExitTrigger;
End;
If Low > Low[2] and Close > Open and Open Next Bar > Low Then Begin
Sell Next Bar at Low Stop;
ShortStopLoss = 1 + ExitTrigger;
End;
End;
If MarketPosition = 1 Then
ExitLong Next Bar at EntryPrice * LongStopLoss Stop;
If MarketPosition = -1 Then
ExitShort Next Bar at EntryPrice * ShortStopLoss Stop;
If BarsSinceEntry = 4 Then Begin
ExitLong Next Bar at Market;
ExitShort Next Bar at Market;
End;

Variables: NoTrades(0), MarPos(0), TrProfit(0), SumTrProfit(0), AvgTrade(0), TestString(""), FileString("");
NoTrades = TotalTrades;
MarPos = MarketPosition;
If NoTrades > NoTrades[1] Then Begin
If MarPos[1] = 1 Then
TrProfit = (ExitPrice(1) - EntryPrice(1)) * 100 / EntryPrice(1);
If MarPos[1] = -1 Then
TrProfit = (EntryPrice(1) - ExitPrice(1)) * 100 / EntryPrice(1);
SumTrProfit = SumTrProfit + TrProfit;
End;

If LastCalcDate = Date + 1 Then Begin
AvgTrade = SumTrProfit / NoTrades;
TestString = LeftStr (GetSymbolName, 5) + "," + NumToStr(TestRuns, 0) + "," + NumToStr(ExitTrigger*100, 2) + "," + NumToStr(AvgTrade, 2) + NewLine;
FileString = "D:TempStopTest-" + RightStr(NumToStr(CurrentDate, 0), 4) + ".csv";
FileAppend(FileString, TestString);
End;
{End Signal}

Back to top

 

April 2002

For "Balancing stop size and trade length" by Thomas Stridsman, p. 66:

Inputs: TestRuns(9), ExitLevels(0), BarsInTrade(0);
Variables: EntryTrigger(0), LongStopLoss(0), ShortStopLoss(0), ExitTrigger(0);
EntryTrigger = IntPortion(Random(2));
ExitTrigger = (ExitLevels / 5 + 0.2) / 100;
If EntryTrigger = 1 and MarketPosition = 0 Then Begin
If High < High[2] and Close < Open and Open Next Bar < High Then Begin
Buy Next Bar at High Stop;
LongStopLoss = 1 - ExitTrigger;
End;
If Low > Low[2] and Close > Open and Open Next Bar > Low Then Begin
Sell Next Bar at Low Stop;
ShortStopLoss = 1 + ExitTrigger;
End;
End;
If MarketPosition = 1 Then
ExitLong Next Bar at EntryPrice * LongStopLoss Stop;
If MarketPosition = -1 Then
ExitShort Next Bar at EntryPrice * ShortStopLoss Stop;
If BarsSinceEntry = BarsInTrade+1 Then Begin
ExitLong Next Bar at Market;
ExitShort Next Bar at Market;
End;

Variables: NoTrades(0), MarPos(0), TrProfit(0), SumTrProfit(0), AvgTrade(0), TestString(""), FileString("");

NoTrades = TotalTrades;
MarPos = MarketPosition;
If NoTrades > NoTrades[1] Then Begin
If MarPos[1] = 1 Then
TrProfit = (ExitPrice(1) - EntryPrice(1)) * 100 / EntryPrice(1);
If MarPos[1] = -1 Then
TrProfit = (EntryPrice(1) - ExitPrice(1)) * 100 / EntryPrice(1);
SumTrProfit = SumTrProfit + TrProfit;
End;

If LastCalcDate = Date + 1 Then Begin
AvgTrade = SumTrProfit / NoTrades;
TestString = LeftStr(GetSymbolName, 5) + "," + NumToStr(TestRuns, 0) + "," + NumToStr(ExitTrigger*100, 2) + "," +
NumToStr(BarsInTrade+1, 2) + "," + NumToStr(AvgTrade, 2) + NewLine;
FileString = "D:TempStopTest-" + RightStr(NumToStr(CurrentDate, 0), 4) + ".csv";
FileAppend(FileString, TestString);
End;

Back to top

May 2002

For "Looking for a target" by Thomas Stridsman, p. 84:

Inputs: BarsInTrade(0), ProfitExit(0), LossExit(0);
Variables: EntryTrigger(0), LongStop(0), ShortStop(0), LongTarget(0), ShortTarget(0), LimitExit(0), StopExit(0);
EntryTrigger = IntPortion(Random(2));
LimitExit = (ProfitExit / 2 + 0.5) / 100;
StopExit = (LossExit / 5 + 0.2) / 100;
If EntryTrigger = 1 and MarketPosition = 0 Then Begin
If High < High[2] and Close < Open and Open Next Bar < High Then Begin
Buy Next Bar at High Stop;
LongStop = 1 - StopExit;
LongTarget = 1 + LimitExit;
End;
If Low > Low[2] and Close > Open and Open Next Bar > Low Then Begin
Sell Next Bar at Low Stop;
ShortStop = 1 + StopExit;
ShortTarget = 1 - LimitExit;
End;
End;
If MarketPosition = 1 Then Begin
ExitLong Next Bar at EntryPrice * LongStop Stop;
ExitLong Next Bar at EntryPrice * LongTarget Limit;
End;
If MarketPosition = -1 Then Begin
ExitShort Next Bar at EntryPrice * ShortStop Stop;
ExitShort Next Bar at EntryPrice * ShortTarget Limit;
End;
If BarsSinceEntry = BarsInTrade+1 Then Begin
ExitLong Next Bar at Market;
ExitShort Next Bar at Market;
End;

Variables: NoTrades(0), MarPos(0), TrProfit(0), SumTrProfit(0), AvgTrade(0), TestString(""), FileString("");

NoTrades = TotalTrades;
MarPos = MarketPosition;
If NoTrades > NoTrades[1] Then Begin
If MarPos[1] = 1 Then
TrProfit = (ExitPrice(1) - EntryPrice(1)) * 100 / EntryPrice(1);
If MarPos[1] = -1 Then
TrProfit = (EntryPrice(1) - ExitPrice(1)) * 100 / EntryPrice(1);
SumTrProfit = SumTrProfit + TrProfit;
End;

If LastCalcDate = Date + 2 Then Begin
AvgTrade = SumTrProfit / NoTrades;
TestString = LeftStr(GetSymbolName, 5) + "," + NumToStr(BarsInTrade+1, 2) + "," + NumToStr(LimitExit*100, 2) + "," +
NumToStr(StopExit*100, 2) + "," + NumToStr(AvgTrade, 2) + NewLine;
FileString = "D:TempStopTest-" + RightStr(NumToStr(CurrentDate, 0), 4) + ".csv";
FileAppend(FileString, TestString);
End;

MetaStock formula for the StochRSI, p. 52:

(Sum(RSI(5)-LLV(RSI(5),3),3)/Sum(HHV(RSI(5),3)-LLV(RSI(5),3),3))*100

Back to top

June 2002

For "Simple but Effective" by Michael Harris, p. 64:

T-Bond C-6 PATTERN

MetaStock Code

{Long positions only, profit target = 1 point, stop-loss = 1 point, entry at the open of next day}

(Ref(c,-5)>Ref(c,-4)) and (Ref(c,-4)>Ref(c,-3)) and (Ref(c,-3)>Ref(c,-2)) and (Ref(c,-2)>Ref(c,0)) and Ref(c,0)>Ref(c,-1))

EasyLanguage Code (2000i)

input:targetpoints(0), stoppoints(0), multiplier(1);
variables: profitprice(0), stopprice(0);
If c[5]>c[4] and c[4]>c[3] and c[3]>c[2] and c[2]>c[0] and c[0]>c[1] then begin
Buy next bar on the open;
If marketposition = 0 then begin
exitlong next bar at open of tomorrow+ (targetpoints * multiplier) points limit;
exitlong next bar at open of tomorrow- (stoppoints * multiplier) points stop;
end;
end:
if marketposition = 1 then begin
profitprice = entryprice + (targetpoints * multiplier) points;
stopprice = entryprice - (stoppoints * multiplier) points;
exitlong at profitprice limit;
exitlong at stopprice stop:
end;

S&P 500 C-6 PATTERN

MetaStock Code

{Long positions only, profit target = 3%, stop-loss = 3% (of entry price), entry at the open of next day}

(Ref(c,0)>Ref(c,-2)) and (Ref(c,-2)>Ref(c,-1)) and (Ref(c,-1)>Ref(c,-3)) and (Ref(c,-3)>Ref(c,-4)) and Ref(c,-4)>Ref(c,-5))

EasyLanguage Code (2000i)

input:ptarget(0), stop1(0);
variables: profitprice(0), stopprice(0);
If c[0]>c[2] and c[2]>c[1] and c[1]>c[3] and c[3]>c[4] and c[4]>c[5] then begin
Buy next bar on the open;
If marketposition = 0 then begin
exitlong next bar at open of tomorrow * (1 + ptarget/100) limit;
exitlong next bar at open of tomorrow * (1 - stop1/100) stop;
end;
end:
if marketposition = 1 then begin
profitprice = entryprice * (1 + ptarget/100) points;
stopprice = entryprice * (1 - stop1/100) points;
exitlong at profitprice limit;
exitlong at stopprice stop:
end;

MSFT C-6 PATTERN

MetaStock Code

{Long positions only, profit target = 10%, stop-loss = 10% (of entry price), entry at the open of next day}

(Ref(c,-1)>Ref(c,0)) and (Ref(c,0)>Ref(c,-2)) and (Ref(c,-2)>Ref(c,-3)) and (Ref(c,-3)>Ref(c,-4)) and Ref(c,-4)>Ref(c,-5))

EasyLanguage Code (2000i)

input:ptarget(0), stop1(0);
variables: profitprice(0), stopprice(0);
If c[1]>c[0] and c[0]>c[2] and c[2]>c[3] and c[3]>c[4] and c[4]>c[5] then begin
Buy next bar on the open;
If marketposition = 0 then begin
exitlong next bar at open of tomorrow * (1 + ptarget/100) limit;
exitlong next bar at open of tomorrow * (1 - stop1/100) stop;
end;
end:
if marketposition = 1 then begin
profitprice = entryprice * (1 + ptarget/100) points;
stopprice = entryprice * (1 - stop1/100) points;
exitlong at profitprice limit;
exitlong at stopprice stop:
end;

For "Happy Trails" by Thomas Stridsman, p. 76

The EntryTrigger at the top of the code ensures that each signal will be traded at random so that every trading sequence will be unique. The bottom part of the code exports the necessary data for further analysis in Excel. Note: If you use the system in live trading, you need to get rid of the EntryTrigger variable.

Inputs: BarsInTrade(0), ProfitExit(0), LossExit(0);
Variables: EntryTrigger(0), LongStop(0), ShortStop(0), LongTarget(0), ShortTarget(0), LimitExit(0), StopExit(0), Top(0), Bottom(0);
EntryTrigger = IntPortion(Random(2));
LimitExit = (ProfitExit / 2 + 0.5) / 100;
StopExit = (LossExit / 5 + 0.2) / 100;
If EntryTrigger = 1 and MarketPosition = 0 Then Begin
If High < High[2] and Close < Open and Open Next Bar < High Then Begin
Buy Next Bar at High Stop;
Top = High;
LongStop = 1 - StopExit;
LongTarget = 1 + LimitExit;
End;
If Low > Low[2] and Close > Open and Open Next Bar > Low Then Begin
Sell Next Bar at Low Stop;
Bottom = Low;
ShortStop = 1 + StopExit;
ShortTarget = 1 - LimitExit;
End;
End;
If MarketPosition = 1 Then Begin
Top = MaxList(Top, High);
ExitLong Next Bar at Top * LongStop Stop;
ExitLong Next Bar at EntryPrice * LongTarget Limit;
End;
If MarketPosition = -1 Then Begin
Bottom = MinList(Bottom, Low);
ExitShort Next Bar at Bottom * ShortStop Stop;
ExitShort Next Bar at EntryPrice * ShortTarget Limit;
End;
If BarsSinceEntry = BarsInTrade+1 Then Begin
ExitLong Next Bar at Market;
ExitShort Next Bar at Market;
End;

Variables: NoTrades(0), MarPos(0), TrProfit(0), SumTrProfit(0), AvgTrade(0), TestString(""), FileString("");

NoTrades = TotalTrades;
MarPos = MarketPosition;
If NoTrades > NoTrades[1] Then Begin
If MarPos[1] = 1 Then
TrProfit = (ExitPrice(1) - EntryPrice(1)) * 100 / EntryPrice(1);
If MarPos[1] = -1 Then
TrProfit = (EntryPrice(1) - ExitPrice(1)) * 100 / EntryPrice(1);
SumTrProfit = SumTrProfit + TrProfit;
End;

If LastCalcDate = Date + 2 Then Begin
AvgTrade = SumTrProfit / NoTrades;
TestString = LeftStr(GetSymbolName, 5) + "," + NumToStr(BarsInTrade+1, 2) + "," + NumToStr(LimitExit*100, 2) + "," +
NumToStr(StopExit*100, 2) + "," + NumToStr(AvgTrade, 2) + NewLine;
FileString = "D:TempStopTest-" + RightStr(NumToStr(CurrentDate, 0), 4) + ".csv";
FileAppend(FileString, TestString);
End;

Back to top

July 2002

eSignal formula for the Chaikin Money Flow featured in "Fundamentally Technical Trading" by Thom Hartle, p. 48:

function preMain() {
setStudyTitle("Chaikin Money Flow");
setCursorLabelName("CMF");

// Default plot type is Line
setPlotType(PLOTTYPE_HISTOGRAM);
}

function main(nInputLength) {
// If the user did not provide an input length, set a default
if(nInputLength == null) {
nInputLength = 21;
}

// Get the last 21 bars of L, H, C, V data
var arClose = close(0, -21);
var arLow = low(0, -21);
var arHigh = high(0, -21);
var arVolume = volume(0, -21);

// Not enough data to process (yet).
if(arClose == null || arLow == null || arHigh == null || arVolume == null)
return;

var i;
var vSumVolume = 0;
var vSum = 0;

// Sum up the values
for(i = 0; i < 21; i++) {
vSum += (((arClose[i]-arLow[i])-(arHigh[i]-arClose[i]))/(arHigh[i]-arLow[i]))*arVolume[i];
vSumVolume += arVolume[i];
}

return vSum / vSumVolume;

}

Back to top

August 2002

For "The good, the bad and the volatility" by Thomas Stridsman, p. 56:

Variables: VQI(0), SumVQI(0);
If TrueRange <> 0 and (High - Low) <> 0 Then
VQI = ((Close - Close[1]) / TrueRange + (Close - Open) / (High - Low)) * 0.5
Else
VQI=VQI[1];
VQI = AbsValue(VQI) * ((Close - Close[1] + (Close - Open)) * 0.5);
SumVQI = SumVQI + VQI;
Plot1(SumVQI,"");
Plot2(Average(SumVQI,9),"");
Plot3(Average(SumVQI,200),"");

Back to top

September 2002

For "QQQ system" by Michael Harris, p. 70:

Metastock code:

{LONG, %, TARGET: 7.0, STOP: 7.0, ENTRY AT: OPEN}

(Ref(h,-3)> Ref(h,-2)) and (Ref(h,-2) > Ref(l,-3)) and (Ref(l,-3) > Ref(h,-1)) and (Ref(h,-1) > Ref(l,-2)) and (Ref(l,-2) > Ref(h,0)) and (Ref(h,0) > Ref(l,-1)) and (Ref(l,-1) > Ref(l,0))

TradeStation code:

input: ptarget(0), stop(0);
variables: profitprice(0); stopprice(0);

If h[3] > h[2] and h[2] > l[3] and l[3] > h[1] and h[1] > l[2] and l[2] > h[0] and h[0] > l[1] and l[1] > l[0] then begin
Buy Next Bar on the open;
If Marketposition = 0 then begin
exitlong next bar at 0 of tomorrow*1(1+ptarget/100) limit;
exitlong next bar at 0 of tomorrow*1(1-stop/100)stop;
end;
end;

if marketposition= 1 then begin
profitprice= entryprice * (1 + ptarget/100);
stopprice= entryprice * (1 - stop/100);
exitlong at profitprice limit;
exitlong at stopprice stop;
end;

For the Meander System in "Keeping track of the odds: The trader's equation" by Shirley, p. 84:

{Run with Stop loss at 250, shares = 500 and fees and slippage of .0225/share}

input: Mlt(2);
input: MaLength(45);
{{Compute the Standard Deviations of the movements relative to the open}}
Value1 = Stddev((High-open),5);
Value2 = Stddev((open - low),5);

{{Fade movements beyond Mlt standard deviations that are against the prevailing trend as defined by ma of length MaLength}}

If Marketposition = 0 then Begin
If (AverageFC(Close,MaLength) - AverageFC(Close[1],MaLength)) > 0 then begin
Buy ("LongScalp") next bar at open of next bar - (Value2*Mlt) limit;
Sell next bar at open of next bar + (Value1*Mlt) limit;
end;
If (AverageFC(Close,MaLength) - AverageFC(Close[1],MaLength)) < 0 then begin
Sell short ("ShortScalp") next bar at open of next bar + (Value1*Mlt) limit;
buy to cover ("Cover#1") next bar at open of next bar - (Value2*Mlt) limit;
end;
end;

If Marketposition = 1 then
Sell next bar at open of next bar + (Value1*Mlt) limit;
If Marketposition = -1 then
buy to cover next bar at open of next bar - (Value2 * Mlt) limit;

Back to top

October 2002

Amibroker code for the True Strength Index (TSI) mentioned in "In phase with the market" by Dudella, p. 52:

u=3;
r=5;
s=8;

x=100*EMA(EMA(ROC(C,u),r),s)/EMA(EMA(abs(ROC(C,u)),r),s);

Plot(x,"TSI",IIf(x>Ref(x,-1),colorGreen,colorRed),styleHistogram);
Plot(MA(x,5),"MA of TSI",colorYellow,1);

Back to top

 

December 2002

MetaStock code for "Give your system a KISS" by Mark Seleznov, p. 38.

Enter long C>(Ref(HHV(H,1),-1)*(1.005))
Close long C<(Ref(LLV(L,1),-1)*(1.005))
Enter short C<(Ref(LLV(L,1),-1)*(1.005))
Close short C>(Ref(HHV(H,1),-1)*(1.005))

Initial equity: N/A
Positions: Long and short
Entry trade price: Close
Entry trade delay: 0
Exit trade price: Close
Exit trade delay: 0
Entry commission: 0 points
Exit commission: 0 points
Interest rate: N/A
Margin req: N/A

Code for the StochRSI

Value1 = RSI( Close, 5 );
Value2 = Lowest( Value1, 3 ) ;
Value3 = Highest( Value1, 3 ) ;
Plot1( ( Summation( Value1 - Value 2, 3 ) / Summation( Value3 - Value2, 3 ) ) * 100 );

Back to top

February 2003

TradeStation code for "One Step at a Time" by Bodri, p. 66:

Basic channel breakout:

Buy at Highest (H, ChLen) stop;
Sell at Lowest (L, ChLen) stop:

Filter:

If CIf C>C[1] then Sell at Lowest(L, ChLen) stop;

Advanced filter:

If CIf C>C[1] and C[1]>C[2] then Sell at Lowest(L, ChLen) stop;

Back to top

May 2003

For "Outside bars: Testing, 1-2-3" by Andrews, p. 42

The following is generic "code" that can be modified for a particular
software program:

 

Bullish outside reversal bar

high > high[1] and

low < low[1] and

(high - close)/(high - low) < .50 and

close > open and

close > close[2] and

10-day EMA < 10-day EMA[1] and

low < 10-day EMA

The definition is reversed (i.e., low replacing high, high replacing low,
"greater than" replacing "less than" and "less than" replacing "greater
than") for bearish outside reversal bars.

Back to top

June 2003

Tradestation (EasyLanguage) code for dymamic position-sizing version of intraday breakout system found in "Dynamic position sizing" by Dan Shirley, p. 78:

{Intraday breakout after McNutt}
Input: Size(100), DoLong(True), DoShort(True), Start1(1000), Stop1(1200), Start2(1345), Stop2(1600);
Input:BailLimit(350),FloorAmt(350);
Var:
ThreeUp(False),ThreeDown(False),TrueSize(100),TrueRisk(0),NotThreeDown(True),
NotFourUp(True),
AvPositionProfit(0),GapDown(False),Netvol(0);
{construct logicals}
ThreeDown = (CloseD(1) < CloseD(2)) and (CloseD(2) < CloseD(3)) and
(CloseD(3) < CloseD(4));
NotThreeDown = (CloseD(1) > CloseD(2)) or (CloseD(2) > CloseD(3)) or
CloseD(3) > CloseD(4));
NotFourUp = (CloseD(1) < CloseD(2)) or CloseD(2) < CloseD(3)) or
(CloseD(3) < CloseD(4)) or CloseD(4) < CloseD(5);
GapDown = OpenD(0) < LowD(1);
Condition3 = (Time > Start1 and Time < Stop1) or (Time > Start2 and Time < Stop2);
Condition4 = DailyWinners(Date) = 0 and DailyLosers(Date) = 0;
{NYSE up volume in data2 and NYSE down volume in data3}
netvol = close of data2 - close of data3;
TrueSize = Size;
{adjust risk}
If ((Threedown or GapDown or netvol > 100000) and MarketPosition = 1) or
(netvol < -100000 and marketposition = -1) then
TrueRisk = BailLimit*2
Else Begin
TrueRisk = BailLimit;
End;
{set entry stops}
If Condition3 and Condition4 and DoShort and NotThreeDown Then Begin
If NetVol < -100000 then Truesize = size*2;
Sell Short TrueSize shares Next Bar LowD(0) - .02 stop;
end;
If Condition3 and Condition4 and DoLong and NotFourUp Then begin
If Threedown or Gapdown or netvol > 100000 Then TrueSize = Size*2;
Buy TrueSize Shares Next Bar HighD(0) + .02 Stop;
End;
{Exit conditions => bail at break-even after floor is reached}
Condition5 = MaxPositionProfit > FloorAmt;
If Condition5 and MarketPosition = 1 and PositionProfit <=0 then Begin
If Threedown or Gapdown or netvol > 100000 then TrueSize = size*2;
Sell TrueSize shares next bar (High + Low)/2 Limit;
End
If Condition5 and Marketposition = -1 and PositionProfit <=0 Then Begin
If netvol < -100000 then truesize = size*2;
Buy to cover TrueSize shares next bar (High + Low)/2 limit;
End;
{Stop Loss}
setstopposition;
SetstopLoss(TrueRisk);

Back to top

July 2003

MetaStock code for BandWidth indicator used in "Setting up trades with Relative Bandwidth," p. 52:

BandWidth = (BBandTop(C,10,S,2)-BBandBot(C,10,S,2)/Mov(C,10,S)*100

MetaStock code for stochastic oscillator of the BandWidth indicator:

(Sum(Fml("BandWidth") - LLV(Fml
("BandWidth"),10),3)/Sum(HHV(Fml("BandWidth"),10)-
LLV(Fml("BandWidth"),10),3))*100; 20; 80

Spreadsheet for "Relative volume analysis" by Thom Hartle, p. 22:

Click here to download

Back to top

August 2003

TradeStation code for Gartley 222 pattern found in "Trading the Gartley 222" by Aaron Behle and Mark Conway, p. 38:

Inputs:
Length(100),
Strength(8),
Tolerance(0.10),
BullColor(Blue),
BearColor(Red);

Variables:
F1(0.618),
F2(0.786),
F3(1.27),
F4(1.618),
P1Bar(-1),
P2Bar(-1),
T1Bar(-1),
T2Bar(-1),
P1(0.0),
P2(0.0),
T1(0.0),
T2(0.0),
PTValid(False),
HLValid(False),
InZone(False),
GD(0.0),
XA(0.0),
AB(0.0),
BC(0.0),
CD(0.0),
AD(0.0),
C1(False),
C2(False),
C3(False),
C4(False),
ABdXA(0.0),
BCdAB(0.0),
CDdBC(0.0),
ADdXA(0.0),
TL1(-1),
TL2(-1),
TL3(-1),
TL4(-1),
TL5(-1),
TL6(-1);

P1Bar = SwingHighBar(1, High, Strength, Length);
P2Bar = SwingHighBar(2, High, Strength, Length);
T1Bar = SwingLowBar(1, Low, Strength, Length);
T2Bar = SwingLowBar(2, Low, Strength, Length);
If P1Bar <> -1 and
P2Bar <> -1 and
T1Bar <> -1 and
T2Bar <> -1 Then Begin
{Test for a bullish 222}
{Trough X is T2}
T2 = Low[T2Bar];
{Peak A is P2}
P2 = High[P2Bar];
{Trough B is T1}
T1 = Low[T1Bar];
{Peak C is P1}
P1 = High[P1Bar];
{D is the buy point}
GD = Low;
PTValid = P1Bar < T1Bar and T1Bar < P2Bar and P2Bar < T2Bar;
HLValid = P1 < P2 and T1 > T2 and P1 > T1;
InZone = GD < T1 and GD > T2 and P2 >= Highest(High, T2Bar);
If PTValid and HLValid and InZone Then Begin
XA = P2 - T2;
AB = P2 - T1;
BC = P1 - T1;
CD = P1 - GD;
AD = P2 - GD;
ABdXA = AB / XA; {AB should be 61.8% of XA}
C1 = ABdXA > F1 - Tolerance and ABdXA < F1 + Tolerance;
BCdAB = BC / AB; {BC should be 61.8-78.6% of AB}
C2 = BCdAB > F1 - Tolerance and BCdAB < F2 + Tolerance;
CDdBC = CD / BC; {CD should be 127-161.8% of BC}
C3 = CDdBC > F3 - Tolerance and CDdBC < F4 + Tolerance;
ADdXA = AD / XA; {AD should be 78.6% of XA}
C4 = ADdXA > F2 - Tolerance and ADdXA < F2 + Tolerance;
If C1 and C2 and C3 and C4 Then Begin
TL1 = TL_New(Date[T2Bar], Time[T2Bar], T2, Date[P2Bar], Time[P2Bar], P2);
If TL1 >= 0 Then Begin
TL_SetColor(TL1, BullColor);
TL_SetStyle(TL1, Tool_Solid);
TL_SetSize(TL1, 2);
End;
TL2 = TL_New(Date[P2Bar], Time[P2Bar], P2, Date[T1Bar], Time[T1Bar], T1);
If TL2 >= 0 Then Begin
TL_SetColor(TL2, BullColor);
TL_SetStyle(TL2, Tool_Solid);
TL_SetSize(TL2, 2);
End;
TL3 = TL_New(Date[T1Bar], Time[T1Bar], T1, Date[P1Bar], Time[P1Bar], P1);
If TL3 >= 0 Then Begin
TL_SetColor(TL3, BullColor);
TL_SetStyle(TL3, Tool_Solid);
TL_SetSize(TL3, 2);
End;
TL4 = TL_New(Date[P1Bar], Time[P1Bar], P1, Date, Time, GD);
If TL4 >= 0 Then Begin
TL_SetColor(TL4, BullColor);
TL_SetStyle(TL4, Tool_Solid);
TL_SetSize(TL4, 2);
End;
TL5 = TL_New(Date[T1Bar], Time[T1Bar], T1, Date, Time, GD);
If TL5 >= 0 Then Begin
TL_SetColor(TL5, BullColor);
TL_SetStyle(TL5, Tool_Dotted);
End;
TL6 = TL_New(Date[T2Bar], Time[T2Bar], T2, Date, Time, GD);
If TL6 >= 0 Then Begin
TL_SetColor(TL6, BullColor);
TL_SetStyle(TL6, Tool_Dotted);
End;
End;
End;
{Test for a bearish 222}
{Peak X is P2}
{Trough A is T2}
{Peak B is P1}

{Trough C is T1}
{GD is the short point}
GD = High;
PTValid = T1Bar < P1Bar and P1Bar < T2Bar and T2Bar < P2Bar;
HLValid = T1 > T2 and P1 < P2 and T1 < P1;
InZone = GD > P1 and GD < P2 and T2 <= Lowest(Low, P2Bar);
If PTValid and HLValid and InZone Then Begin
XA = P2 - T2;
AB = P1 - T2;
BC = P1 - T1;
CD = GD - T1;
AD = GD - T2;
ABdXA = AB / XA; {AB should be 61.8% of XA}
C1 = ABdXA > F1 - Tolerance and ABdXA < F1 + Tolerance;
BCdAB = BC / AB; {BC should be 61.8-78.6% of AB}
C2 = BCdAB > F1 - Tolerance and BCdAB < F2 + Tolerance;
CDdBC = CD / BC; {CD should be 127-161.8% of BC}
C3 = CDdBC > F3 - Tolerance and CDdBC < F4 + Tolerance;
ADdXA = AD / XA; {AD should be 78.6% of XA}
C4 = ADdXA > F2 - Tolerance and ADdXA < F2 + Tolerance;
If C1 and C2 and C3 and C4 Then Begin
TL1 = TL_New(Date[P2Bar], Time[P2Bar], P2, Date[T2Bar], Time[T2Bar], T2);
If TL1 >= 0 Then Begin
TL_SetColor(TL1, BearColor);
TL_SetStyle(TL1, Tool_Solid);
TL_SetSize(TL1, 2);
End;
TL2 = TL_New(Date[T2Bar], Time[T2Bar], T2, Date[P1Bar], Time[P1Bar], P1);
If TL2 >= 0 Then Begin
TL_SetColor(TL2, BearColor);
TL_SetStyle(TL2, Tool_Solid);
TL_SetSize(TL2, 2);
End;
TL3 = TL_New(Date[P1Bar], Time[P1Bar], P1, Date[T1Bar], Time[T1Bar], T1);
If TL3 >= 0 Then Begin
TL_SetColor(TL3, BearColor);
TL_SetStyle(TL3, Tool_Solid);
TL_SetSize(TL3, 2);
End;
TL4 = TL_New(Date[T1Bar], Time[T1Bar], T1, Date, Time, GD);
If TL4 >= 0 Then Begin
TL_SetColor(TL4, BearColor);
TL_SetStyle(TL4, Tool_Solid);
TL_SetSize(TL4, 2);
End;
TL5 = TL_New(Date[P1Bar], Time[P1Bar], P1, Date, Time, GD);
If TL5 >= 0 Then Begin
TL_SetColor(TL5, BearColor);
TL_SetStyle(TL5, Tool_Dotted);
End;
TL6 = TL_New(Date[P2Bar], Time[P2Bar], P2, Date, Time, GD);
If TL6 >= 0 Then Begin
TL_SetColor(TL6, BearColor);
TL_SetStyle(TL6, Tool_Dotted);
End;
End;
End;
End;

Wealth-Lab code:

procedure Gartley222
(
VPFactor: float;
Tolerance: float;
Lookback: integer;
HoldBars: integer;
VolMin: integer
);
begin
var ATRValue, VP, Reversal: float;
var F1, F2, F3, F4, P1, P2, T1, T2: float;
var Bar, P1Bar, P2Bar, T1Bar, T2Bar, p: integer;
var XA, AB, BC, CD, AD, D, XD, DT, ABdXA, BCdAB, CDdBC, ADdXA: float;
var PTValid, HLValid, InZone, C1, C2, C3, C4: boolean;
var BT, BS, ST, SS: float;

{Fibonacci Constants}
F1 := 0.618;
F2 := 0.786;
F3 := 1.27;
F4 := 1.618;

InstallTimeBasedExit(HoldBars);
for Bar := Lookback to BarCount() - 1 do
begin
ApplyAutoStops(Bar);
ATRValue := ATR(Bar, Lookback);
SetShareSize( 1000 * Int( 10 / ATRValue ) );
VP := 100 * ATRValue / PriceClose(Bar);
{Find peaks and troughs}
Reversal := Int(VPFactor * VP);
P1 := Peak(Bar, #High, F1 * Reversal);
P1Bar := PeakBar(Bar, #High, F1 * Reversal);
P2 := Peak(P1Bar, #High, Reversal);
P2Bar := PeakBar(P1Bar, #High, Reversal);
T1 := Trough(Bar, #Low, F1 * Reversal);
T1Bar := TroughBar(Bar, #Low, F1 * Reversal);
T2 := Trough(T1Bar, #Low, Reversal);
T2Bar := TroughBar(T1Bar, #Low, Reversal);
{Test for a bullish 222}
{Trough X is T2}
{Peak A is P2}
{Trough B is T1}
{Peak C is P1}
{D is the buy zone}
D := PriceLow(Bar);
PTValid := (P1Bar > T1Bar) and (T1Bar > P2Bar) and (P2Bar > T2Bar);
HLValid := (P1 < P2) and (T1 > T2) and (P1 > T1);
InZone := (D < T1) and (D > T2);
if (MarketPosition = 0) and
(SMA(Bar, #Volume, Lookback) >= VolMin) and
(PTValid) and (HLValid) and (InZone) then
begin
XA := P2 - T2;
AB := P2 - T1;
BC := P1 - T1;
XD := P2 - (F2 * XA);
CD := P1 - XD;
AD := P2 - XD;
ABdXA := AB / XA; {AB should be 61.8% of XA}
C1 := (ABdXA > F1 - Tolerance) and (ABdXA < F1 + Tolerance);
BCdAB := BC / AB; {BC should be 61.8-78.6% of AB}
C2 := (BCdAB > F1 - Tolerance) and (BCdAB < F2 + Tolerance);
CDdBC := CD / BC; {CD should be 127-161.8% of BC}
C3 := (CDdBC > F3 - Tolerance) and (CDdBC < F4 + Tolerance);
ADdXA := AD / XA; {AD should be 78.6% of XA}
C4 := (ADdXA > F2 - Tolerance) and (ADdXA < F2 + Tolerance);
if C1 and C2 and C3 and C4 then
begin
DrawLine(P2Bar, P2, T2Bar, T2, 0, #Blue, #Solid);
DrawLine(T1Bar, T1, P2Bar, P2, 0, #Blue, #Solid);
DrawLine(P1Bar, P1, T1Bar, T1, 0, #Blue, #Solid);
DrawLine(Bar, D, P1Bar, P1, 0, #Blue, #Solid);
DrawLine(Bar, D, T1Bar, T1, 0, #Blue, #Dotted);
DrawLine(Bar, D, T2Bar, T2, 0, #Blue, #Dotted);
AnnotateBar('B', Bar, True, #Blue, 10);
BuyAtLimit(Bar, XD, 'G222 LE');
DT := F1 * CD;
BT := XD + DT;
BS := T2;
end;
end;
{Test for a bearish 222}
{Peak X is P2}
{Trough A is T2}
{Peak B is P1}
{Trough C is T1}
{D is the short zone}
D := PriceHigh(Bar);
PTValid := (T1Bar > P1Bar) and (P1Bar > T2Bar) and (T2Bar > P2Bar);
HLValid := (T1 > T2) and (P1 < P2) and (T1 < P1);
InZone := (D > P1) and (D < P2);
if (MarketPosition = 0) and
(PriceClose( Bar ) >= 5) and
(SMA(Bar, #Volume, Lookback) >= VolMin) and
(PTValid) and (HLValid) and (InZone) then
begin
XA := P2 - T2;
AB := P1 - T2;
BC := P1 - T1;
XD := T2 + (F2 * XA);
CD := XD - T1;
AD := XD - T2;
ABdXA := AB / XA; {AB should be 61.8% of XA}
C1 := (ABdXA > F1 - Tolerance) and (ABdXA < F1 + Tolerance);
BCdAB := BC / AB; {BC should be 61.8-78.6% of AB}
C2 := (BCdAB > F1 - Tolerance) and (BCdAB < F2 + Tolerance);
CDdBC := CD / BC; {CD should be 127-161.8% of BC}
C3 := (CDdBC > F3 - Tolerance) and (CDdBC < F4 + Tolerance);
ADdXA := AD / XA; {AD should be 78.6% of XA}
C4 := (ADdXA > F2 - Tolerance) and (ADdXA < F2 + Tolerance);
if C1 and C2 and C3 and C4 then
begin
DrawLine(T2Bar, T2, P2Bar, P2, 0, #Red, #Solid);
DrawLine(P1Bar, P1, T2Bar, T2, 0, #Red, #Solid);
DrawLine(T1Bar, T1, P1Bar, P1, 0, #Red, #Solid);
DrawLine(Bar, D, T1Bar, T1, 0, #Red, #Solid);
DrawLine(Bar, D, P1Bar, P1, 0, #Red, #Dotted);
DrawLine(Bar, D, P2Bar, P2, 0, #Red, #Dotted);
AnnotateBar('S', Bar, False, #Red, 10);
ShortAtLimit(Bar, XD, 'G222 SE');
DT := F1 * CD;
ST := XD - DT;
SS := P2;
end;
end;
if LastPositionActive then
begin
if MarketPosition = 1 then begin
SellAtLimit(Bar+1, BT, #All, 'G222 LX+');
SellAtStop(Bar+1, BS, #All, 'G222 LX-');
end;
if MarketPosition = -1 then begin
CoverAtLimit(Bar+1, ST, #All, 'G222 LX+');
CoverAtStop(Bar+1, SS, #All, 'G222 LX-');
end;
end;
end;
end;

Gartley222(2.0, 0.1, 20, 7, 2000000);

TradeStation code for S&P breakout system used in "George Pruitt: The trend is still a friend" by Mark Etzkorn, p. 64:

Download the Word file

Back to top

September 2003

For "Rounding out a trading strategy" by Andrews and Mark Etzkorn, p. 58:

Modified outside bar rule:

 

high > high[1] and low < low[1] and

(high - close)/(high - low) < .50 and

close > open and

close > close[2] and

close > 20-day moving average and

(high[1] > 20-day moving average[1] or

high[2] > 20-day moving average[2])

 

Invert the rules for bearish outside bars and short trades.


MetaStock Code:

These formulas can be used in an Indicator builder, expert advisor or
system tester.

Modified outside bar rule

Bullish (BUY) :

BCD:=H>Ref(H,-1) AND L<.5="">O AND
C>Ref(C,-2)
AND C>Mov(C,20,S) AND (Ref(H,-1)>Ref(Mov(C,20,S),-1) OR Ref(H,-2)
>Ref(Mov(C,20,S),-2));
SCD:=HRef(L,-1) AND (H-C)/(H-L)>.5 AND CCAND CBCD AND BarsSince(Ref(BCD,-1))>BarsSince(Ref(SCD,-1))

Bearish (SELL) :

BCD:=H>Ref(H,-1) AND L<.5="">O AND
C>Ref(C,-2)
AND C>Mov(C,20,S) AND (Ref(H,-1)>Ref(Mov(C,20,S),-1) OR Ref(H,-2)
>Ref(Mov(C,20,S),-2));
SCD:=HRef(L,-1) AND (H-C)/(H-L)>.5 AND CCAND CRef(H,-2)SCD AND BarsSince(Ref(BCD,-1))< p=""><>

Back to top


August 2004

MetaStock code for "Put/Call VXO indicator (PCVXO)" by Jay Kaeppel, p. 28:

Depending on your data vendor, the ticker symbols for the put/call ratio
and the VXO will be different. This formula assumes the ticker symbols
are $PCR and $VXO, respectively. The below formulas also assume the
data is stored locally in the folder c:metastock dataindex. If either the ticker symbols or the data path is different, your will need to
change the appropriate values in the first two lines.

s1:=security("c:metastock dataindex$PCR",C);
s2:=security("c:metastock dataindex$VXO",C);
r1:= mov(s1,10,s)/mov(s1,65,s);
r2:= mov(s2,10,s)/mov(s2,65,s);
100*((r1+r2)/2)

AmiBroker code:

Replace ^VXO and ^PCR below with your data vendor symbols for VXO and CBOE put/call ratio

Vxo = Foreign("^VXO", "C" );
Pcr = Foreign("^PCR", "C" );

VxoRatio = MA( Vxo, 10 ) / MA( Vxo, 65 );
PcrRatio = MA( Pcr, 10 ) / MA( Pcr, 65 );

PCVXO = 100*(VxoRadio + PcrRatio)/2;

Plot( PCVXO, "Put/Call VXO indicator", colorRed );

Back to top

September 2004

TradeStation code for the "CCI-stochastic indicator (CCI-STO)" by Star, p. 52:

*Code courtesy of Mark Mills

{Average(3,(Today's 14-day CCI reading - Lowest 14-day CCI reading (over the past 5 periods)/Highest 14-day
CCI reading (over the past 5 periods) - Lowest 14-day CCI reading (over the past 5 periods))*100)

CCI-Stochastic}

inputs:
CCILength( 14 ),
HighLowPeriod( 5 ),
Smooth( 3 ) ;
variables:
TodayCCI( 0 ),
TodayLowCCI( 0 ),
TodayHighCCI( 0 ),
CCISto( 0 ) ;
TodayCCI = CCI( CCILength ) ;
TodayLowCCI = Lowest( TodayCCI, HighLowPeriod ) ;
TodayHighCCI = Highest( TodayCCI, HighLowPeriod ) ;
if CurrentBar > Smooth + HighLowPeriod then
begin
CCISto = Average((TodayCCI - TodayLowCCI)/(TodayHighCCI - TodayLowCCI), Smooth );
Plot1( CCISto, "CCISto");
end ;

AmiBroker code:

function CCISTO( perCCI, perSTO, perMA )
{
vCCI = CCI( perCCI );

Cs = 100 * ( vCCI - LLV( vCCI, perSTO ) )/
( HHV( VCCI, perSTO ) - LLV( VCCI, perSTO ) );

return MA( Cs, perMA );
}

Plot( CCISTO( 14, 5, 3 ), "CCISTO", colorRed );

Metastock code:

(Sum(CCI(14)-LLV(CCI(14),5),3)/
Sum(HHV(CCI(14),5)-LLV(CCI(14),5),3))*100

eSignal code:

function preMain() {
setStudyTitle("Stochastic of CCI");
setCursorLabelName("SoCCI %K", 0);
setCursorLabelName("SoCCI %D", 1);

setDefaultBarFgColor(Color.blue, 0);
setDefaultBarFgColor(Color.red, 1);

setStudyMax(110);
setStudyMin(-5);

// Study Parameters
var sp1 = new FunctionParameter("nCCILength", FunctionParameter.NUMBER);
sp1.setLowerLimit(1);
sp1.setDefault(14); //Edit this value to set a new default

var sp2 = new FunctionParameter("nCCISource", FunctionParameter.STRING);
sp2.setName("CCISource");
sp2.addOption("Close");
sp2.addOption("High");
sp2.addOption("Low");
sp2.addOption("Open");
sp2.addOption("HL/2");
sp2.addOption("HLC/3");
sp2.addOption("OHLC/4");
sp2.setDefault("Close"); //Edit this value to set a new default

var sp4 = new FunctionParameter("nKlength2", FunctionParameter.NUMBER);
sp4.setName("Stoch2 %K Length");
sp4.setLowerLimit(1);
sp4.setDefault(14);

var sp5 = new FunctionParameter("nKsmooth2", FunctionParameter.NUMBER);
sp5.setName("Stoch2 %K Smoothing");
sp5.setLowerLimit(1);
sp5.setDefault(1);

var sp6 = new FunctionParameter("nDlength2", FunctionParameter.NUMBER);
sp6.setName("Stoch2 %D Length");
sp6.setLowerLimit(1);
sp6.setDefault(3);

// Formula Parameters
var fp1 = new FunctionParameter("nBand1", FunctionParameter.NUMBER);
fp1.setName("Upper Band");
fp1.setDefault(80);

var fp2 = new FunctionParameter("nBand2", FunctionParameter.NUMBER);
fp2.setName("Lower Band");
fp2.setDefault(20);

var fp3 = new FunctionParameter("cBands", FunctionParameter.COLOR);
fp3.setName("Band's Color");
fp3.setDefault(Color.black);

var fp4 = new FunctionParameter("bBands", FunctionParameter.STRING);
fp4.setName("Display Bands");
fp4.addOption("True");
fp4.addOption("False");
fp4.setDefault("True");

}

var bEdit = true;
var study = null;
var vCCI = null;
var vK2 = null;
var vD2 = null;
var aCCI = null;
var aStochK2 = null;

function main(nCCILength, nCCISource, nKlength2, nKsmooth2, nDlength2, nBand1, nBand2, cBands, bBands) {
var nState = getBarState();

if (bEdit == true) {
addBand(nBand1, PS_SOLID, 1, cBands, "SoS Upper");
addBand(nBand2, PS_SOLID, 1, cBands, "SoS Lower");
if (bBands == "False") {
removeBand("SoS Upper");
removeBand("SoS Lower");
}
if (aCCI == null) aCCI = new Array((Math.round(nKlength2) + Math.round(nKsmooth2) -1));
if (aStochK2 == null) aStochK2 = new Array(Math.round(nDlength2));
bEdit = false;
}

if (nState == BARSTATE_NEWBAR) {
if (vCCI != null) {
aCCI.pop();
aCCI.unshift(vCCI);
}
if (vK2 != null) {
aStochK2.pop();
aStochK2.unshift(vK2);
}
}

if (study == null) study = new CCIStudy(Math.round(nCCILength), nCCISource);
if (study == null) return;

vCCI = study.getValue(CCIStudy.CCI);
if (vCCI == null) return;
aCCI[0] = vCCI;

if (aCCI[Math.round(nKlength2) - 1] == null) return;

vK2 = StochK2(Math.round(nKlength2), Math.round(nKsmooth2));
if (vK2 == null) return;
aStochK2[0] = vK2;

if (aStochK2[Math.round(nDlength2) - 1] == null) return;

vD2 = StochD2(Math.round(nDlength2));
if (vD2 == null) return;

return new Array(vK2, vD2);
}


/*********************/
/***** Functions *****/
/*********************/

function StochHH(nInputOffset, nInputLength) {
var nOffset = nInputOffset;
var nLength = nInputLength;
var hh = 0;
var i = 0;

for(i = 0; i < nLength; i++) {
if(i == 0) {
hh = aCCI[i+nOffset];
} else {
hh = Math.max(hh, aCCI[i+nOffset]);
}
}
return hh;
}


function StochLL(nInputOffset, nInputLength) {
var nOffset = nInputOffset;
var nLength = nInputLength;
var ll = 0;
var i = 0;

for(i = 0; i < nLength; i++) {
if(i == 0) {
ll = aCCI[i+nOffset];
} else {
ll = Math.min(ll, aCCI[i+nOffset]);
}
}
return ll;
}


function StochK2(inputLength, inputSmoothing) {
var percentK;
var StochK;
var ll, hh;
var sum = 0;
var i = 0;
var nOffset = 0;
var nDO;
var nLength = inputLength;
var nSmoothing = inputSmoothing;

for(i = 0; i < nSmoothing; i++) {
nDO = i + nOffset;
StochK = aCCI[nDO];

ll = StochLL(nDO, nLength);
if(ll == null) return null;

hh = StochHH(nDO, nLength);
if(hh == null) return null;

percentK = ((StochK - ll) / (hh - ll)) * 100;

sum += percentK;
}

sum /= nSmoothing;
return sum;
}


function StochD2(nInputLength) {
var sum = 0;
var i = 0;
for (i = 0; i < nInputLength; ++i) {
sum += aStochK2[i];
}
sum /= nInputLength;
return sum;
}

Back to top

February 2005

TradeStation code for the "Fibonacci Swing Filter" by G. Vetrivel, p. 32:

if l>=h[1] then Sell Short Next Bar at l-.05 stop;

 

if l=h[1]-(h[1]-l[1])*.236 then Sell Short Next Bar at
h[1]-(h[1]-l[1])*.236 -.05 stop;
if l=h[1]-(h[1]-l[1])*.382 then Sell Short Next
Bar at h[1]-(h[1]-l[1])*.382-.05 stop;
if l=h[1]-(h[1]-l[1])*.5 then Sell Short Next
Bar at h[1]-(h[1]-l[1])*.5-.05 stop;
if l=h[1]-(h[1]-l[1])*.618 then Sell Short Next
Bar at h[1]-(h[1]-l[1])*.618-.05 stop;
if l=h[1]-(h[1]-l[1])*.786 then Sell Short Next
Bar at h[1]-(h[1]-l[1])*.786-.05 stop;
if l=h[1]-(h[1]-l[1])*.875 then Sell Short Next
Bar at h[1]-(h[1]-l[1])*.875-.05 stop;
if ll[1] then Sell Short Next Bar at l[1]-.05
stop;
if l<=l[1] then Sell Short Next Bar at l-.05 stop;

 

if h<=l[1] then Buy Next Bar at h+.05 stop;

 

if h>l[1] and h<=l[1]+(h[1]-l[1])*.236 then Buy Next Bar at
l[1]+(h[1]-l[1])*.236+.05 stop;
if h>l[1]+(h[1]-l[1])*.236 and h<=l[1]+(h[1]-l[1])*.382 then Buy Next Bar
at l[1]+(h[1]-l[1])*.382+.05 stop;
if h>l[1]+(h[1]-l[1])*.382 and h<=l[1]+(h[1]-l[1])*.5 then Buy Next Bar at
l[1]+(h[1]-l[1])*.5+.05 stop;
if h>l[1]+(h[1]-l[1])*.5 and h<=l[1]+(h[1]-l[1])*.618 then Buy Next Bar at
l[1]+(h[1]-l[1])*.618+.05 stop;
if h>l[1]+(h[1]-l[1])*.618 and h<=l[1]+(h[1]-l[1])*.786 then Buy Next Bar
at l[1]+(h[1]-l[1])*.786+.05 stop;
if h>l[1]+(h[1]-l[1])*.786 and h<=l[1]+(h[1]-l[1])*.875 then Buy Next Bar
at l[1]+(h[1]-l[1])*.875+.05 stop;
if h>l[1]+(h[1]-l[1])*.875 and h<="" h[1]+.05="" bar="" next="" buy="">

TradeStation code for "Volume Price Confirmation indicator (VPCI)" by G. Vetrivel, p. 38:

{*******************************************************************
Description : This Indicator plots VPCI, Volume Price Confirmation indicator
Developed by: Buff Dormeier, CMT
Marketguru@gmail.com or (800) 552-0774
********************************************************************}

Inputs:len2(10),VolToday(true), BBLength(3), StandardDev(2),
UpColor(DarkGreen), DnColor(Red);
;

variables:
VPCI(0),len(0),volumevolitility(0),vadjuster(0),vspread(0),smoothVPCI(0);
len=len2*4;
VPCI= (bd.vwma(l,len,voltoday) -
average(l,len))*(((bd.vwma(l,len,voltoday))/average(l,len))) *
((bd.vwma(l,len2,voltoday))/average(l,len2))
* ((AVERAGE(V,len2)/ AVERAGE(V,len)));
smoothVPCI= bd.vwma(VPCI,len,voltoday);
volumevolitility= (average (volume,5)/average(volume,15))*standardDev;
vspread= average(l,len)-(bd.vwma(l,len,voltoday));
vadjuster= vspread + average(l,len);
Plot1 (VPCI, "T");
Plot2 (smoothVPCI,"ST");

Some TradeStation users will need additional code for the VWMA (Volume Weighted Moving Average):

Function returns a Volume Weighted SMA
// futures volume is always reported 1-day late
// therefore, this function has the ability to calculate a MA with an offset of 1
// Date last changed: January 30, 2000

Inputs: price(numericSeries), { data to be averaged; e.g. close }
length(numericSimple), { length of moving average }
volToday(trueFalse); { true = volume is available for today (e.g. stocks)
false = volume is NOT available for today (e.g. futures) }

Vars: beg(0), { days back to begin working with for average }
sumOfVol(0), { sum of volume }
vwPx(0), { volume weighted price }
vwMa(0), { volume weighted moving average }
counter(0); { counter }

{ initialize/reset first 4 variables }
if currentBar = 1 then begin
if volToday = true then
beg = 0
else if volToday = false then
beg = 1;
end;
sumOfVol = 0;
vwPx = 0;
vwMa = 0;

{ update sumOfVol variable on each bar }
for counter = beg to (length-1+beg) begin
sumOfVol = sumOfVol + volume[counter];
end;

{ update vwPx and vwMa variables on each bar }
for counter = beg to (length-1+beg) begin
if sumOfVol > 0 then
vwPx = price[counter] * volume[counter] / sumOfVol;
vwMa = vwMa + vwPx;
end;

Back to top

April 2005

TradeStation (EasyLanguage) code for "Extreme Open-Close Days" by Xavier Maria Raj, p. 34:

Initial system test:

VAR:X(0),Y(0),R(0); R=RANGE

IF C>H-((R/10)) AND OIF CH-((R/10)) THEN Y=1 ELSE Y=0
IF X=1 THEN Buy Next Bar AT H+.05 STOP;
IF Y=1 THEN Sell Short Next Bar AT L-.05 STOP;
Sell This Bar AT C;
Buy to Cover This Bar AT C;

Revised system test:

VAR:X(0),Y(0),R(0); R=RANGE

IF C>H-((R/10)) AND OIF CH-((R/10)) THEN Y=1 ELSE Y=0
IF X=1 THEN Buy Next Bar AT H+.05 STOP;
IF Y=1 THEN Sell Short Next Bar AT L-.05 STOP;
Sell This Bar AT C;
Buy to Cover This Bar AT C;
Sell Next Bar AT MEDIANPRICE-.05 STOP;
Buy to Cover Newxt Bar AT MEDIANPRICE +.05 STOP;
Sell AT ("P1") Next Bar H+10 LIMIT;
Buy to Cover AT ("P2") Next Bar L-10 LIMIT;

Back to top


August 2005

TradeStation code for "Aggressive Gap Trading" by Tsutae Kamada, p. 37:

Entry rule:

inputs: Length( 20 );
if close > close[1] and
close[1] > close[2] and
close[2] > close[3] and
low[2] > close[3] and
open[2] > close[3] and
open[2] > average(close,Length)
then buy ("buy") next bar on open;

Exit rule:
if currentbar>1 and low < low [1]
then sell ("sell") this bar at close;

Back to top


December 2005

TradeStation code for "E-Mini Morning Reversal and Afternoon Breakout Patterns " by Tsutae Kamada, p. 26:

[LegacyColorValue = true];

var:x(0);

if entriestoday(d)<1 then begin
if t>830 and t<930 then begin
if highd(0)>highd(1) then Sell Short Next Bar at
minlist(highd(1), l) stop;
if lowd(0)h) stop;
end;

if t>=1300 and t<1430 then begin
Buy Next Bar and maxlist(h,highd(0)) stop;
Sell Short Next Bar at minlist(l,lowd(0)) stop;
end;
end;

Sell Next Bar at lowd(0) stop;
Buy to Cover Next Bar at highd(0) stop:

if t=1500 then begin
Sell This Bar at c;
Buy to Cover This Bar at c;
end;

Back to top


February 2006

Traders' Studio code for "System Testing Redundancy" by Thomas Stridsman, p. 32:

Sub ChicagoLong (Contracts As Integer)

Dim TradeCont As Integer

Dim MinMove As Double

Dim ATR As BarArray(50)

MinMove = GetActiveMinMove()

'Calculate recent historical volatility using True Range:

ATR = Average(TrueRange, LookBack, 0)

If Contracts = 0 Then

'Calculate contracts to trade as a function of a constant risk to $100,000 over the dollar value of the volatility:

TradeCont = 100000 / ATR * GetActivePointValue() / MinMove)

Else

TradeCont = Contracts

End If

Back to top


March 2006

Traders' Studio code for "Medians on the Move" by Thomas Stridsman, p. 28:

Sub AtmMarch (LookBack, DaysInTrade As Integer, LossMult As Double)
'Copyright (C), 2005: Thomas Stridsman
'Created with Traders' Studio, Version 1.3.4

Dim MyArray As Array
Dim Counter, ArraySize, ArrayMidPoint As Integer
Dim MinMove, EP, HC As Double
Dim ATR, MyTypical As BarArray(50)

MinMove = GetActiveMinMove()
ATR = Average(TrueRange, LookBack, 0)

ArraySize = LookBack * 2
ReDim(MyArray, ArraySize)
For Counter = 0 To (LookBack - 1) Step 1
MyArray[Counter * 2 + 0] = Close[Counter]
MyArray[Counter * 2 + 1] = Close[Counter]
Next
NumSort(MyArray)

ArrayMidPoint = ArraySize / 2

MyTypical = (MyArray[ArrayMidPoint-1] + MyArray[ArrayMidPoint]) /2
'SUBSTITUTE WITH THIS TO RUN MA SYSTEM: MyTypical = Average(Close, LookBack)

If Close < MyTypical Then
Buy("Buy", 1, MyTypical + MinMove, Stop, Day)
End If

If MarketPosition = +1 Then
EP = GetEntryPrice(0)
HC = Highest(Close, BarsSinceEntry, 0)
ExitLong("XL-L", "Buy", 1, Max(EP, HC) - LossMult * ATR - MinMove, Stop, Day)
If BarsSinceEntry >= DaysInTrade Then
ExitLong("XL-T", "Buy", 1, 0, Market, Day)
End If
End If

End Sub

Back to top


April 2006

Spreadsheet for Small-trader money management, by Thomas Stridsman, p. 32

Download here

Back to top


May 2006

TradeStation code for "Using the TICK to identify the intraday trend," by David Bean, p. 32:

{Data1 is @ES.D or any of the following: @ER2.D, @YM.D, @NQ.D, @EMD.D
Data2 is $TICK. Both Data1 and Data2 are 15 minute charts - a custom session should be built for @YM.D to trade between 8:30 am CST and 3:15 pm CST instead of starting at 7:20 am CST.
*there are 27, 15 minute bars in the trading day}

Inputs: R(5), L1(27);
If Time=945 and H of data2 > 750 and L of data2 > -350 Then Buy Next Bar at market;
If Time=945 and C of data2 > 500 and L of data2 > -350 Then Buy Next Bar at market;

If Time=945 and Open > LowD(1) - 2*Average(Range,27) and L of data2 < -350 and H of data2 < 750 Then Sell Short Next Bar at OpenD(0) Limit;
If Time=945 and Open > LowD(1) - 2*Average(Range,27) and C of data2 < -100 and H of data2 < 750 Then Sell Short Next Bar at OpenD(0) Limit;
If Time=945 and C > C[1] and L of data2 < -350 and H of data2 < 750 Then Sell Short Next Bar at CloseD(1) Stop;
If Time=945 and C > C[1] and C of data2 < -100 and H of data2 < 750 Then Sell Short Next Bar at CloseD(1) Stop;

If Time=945 and C>(O + Average(Range,27)) and L of data2 > -350 Then Buy Next Bar at market;
If Time=945 and C<(O - Average(Range,27)) and H of data2 < 750 Then Sell Short Next Bar at market;

SetStopLoss(R*BigPointValue*Average(Range,L1));
SetExitonClose;

eSignal code for "Using the TICK to identify the intraday trend," by David Bean, p. 32:

/***************************************
Provided By : eSignal (c) Copyright 2006
Description: Using The TICK To Identify The Intraday Trend
by David Bean

Version 1.0 05/02/2006

Notes:
* May 2006 Issue of Active Trader Magazine
* Study requires version 7.9.1 or higher.
* Study must be used on a 15 minute or lower interval only.
* Study is configured for futures contracts only.
* If used in any time zone other than US Eastern Standard time, the
Start Time and End Time parameters need to be modified to local time.
* Study parameters are set for Emini S&P futures contract (ES #F=2) and
Eastern Standard time.
* Study is compatible for real time use and Back Testing with the
Strategy Analyzer.
* Study requires a time template that includes the bars based
on the specified Start Time and End Time parameters.

Formula Parameters: Defaults:
Local Start Time of Entry Bar 945
R Multiplier 5
Contract's Point Value 50
Local End Time of Trading Session 1615
***************************************/


function preMain() {
setPriceStudy(true);
setStudyTitle("Bean TICK Strategy ");
setCursorLabelName("Position", 0);
setCursorLabelName("Stop", 1);
setDefaultBarThickness(1, 0);
setDefaultBarThickness(2, 1);
setDefaultBarFgColor(Color.grey, 0);
setDefaultBarFgColor(Color.red, 1);
setPlotType(PLOTTYPE_DOT, 0);
setPlotType(PLOTTYPE_FLATLINES, 1);
setColorPriceBars(true);
setDefaultPriceBarColor(Color.grey);
setShowTitleParameters(false);

var fp1 = new FunctionParameter("nStart", FunctionParameter.NUMBER);
fp1.setName("Local Start Time of Entry Bar");
fp1.setDefault(945);
var fp2 = new FunctionParameter("nR", FunctionParameter.NUMBER);
fp2.setName("R Multiplier");
fp2.setLowerLimit(1);
fp2.setDefault(5);
var fp3 = new FunctionParameter("nPoints", FunctionParameter.NUMBER);
fp3.setName("Contract's Point Value");
fp3.setLowerLimit(0);
fp3.setDefault(50);
var fp5 = new FunctionParameter("nEnd", FunctionParameter.NUMBER);
fp5.setName("Local End Time of Trading Session");
fp5.setDefault(1615);
}

var bVersion = null;
var bInit = false;

var xAvgRange = null;
var sPosition = "Flat";
var nStop = null;
var bBT = true; // allow back testing
var bNewDay = false;
var bEntryBar = false;

function main(nStart, nR, nPoints, nEnd) {
if (bVersion == null) bVersion = verify();
if (bVersion == false) return;

if (getInterval() > 15) {
drawTextAbsolute(5, 35, "This study requires a chart interval of 15 minutes or lower.",
Color.white, Color.blue, Text.RELATIVETOBOTTOM|Text.RELATIVETOLEFT|Text.BOLD|Text.LEFT,
null, 13, "error");
return;
}

var nState = getBarState();

if (bInit == false) {
xAvgRange = efsInternal("calcAR", inv(15));
bInit = true;
}

if (day(0) != day(-1)) {
bNewDay = true;
}
if (bNewDay == true) {
var nTime = (hour(0)*100) + minute(0);
if (nTime >= nStart) {
bEntryBar = true;
bNewDay = false;
}
}

if (isLastBarOnChart() == true) bBT = false;


// Exit
if (sPosition != "Flat") {
var nBarTime = (hour(0)*100) + minute(0);
var nO = open(0);
var nH = high(0);
var nL = low(0);
var nStopLimit = nStop;
if (sPosition == "Long" && nL <= nStop) { // Exit 1
if (nO < nStop) nStopLimit = nO;
if (bBT == true) Strategy.doSell("Long Stop", Strategy.STOP, Strategy.THISBAR, Strategy.ALL, nStopLimit);
doPriceBarColors();
sPosition = "Flat";
Alert.playSound("train.wav");
drawShape(Shape.DIAMOND, BelowBar1, Color.khaki, "exit"+rawtime(0));
} else if (sPosition == "Short" && nH >= nStop) { // Exit 1
if (nO > nStop) nStopLimit = nO;
if (bBT == true) Strategy.doCover("Short Stop", Strategy.STOP, Strategy.THISBAR, Strategy.ALL, nStopLimit);
doPriceBarColors();
sPosition = "Flat";
Alert.playSound("train.wav");
drawShape(Shape.DIAMOND, AboveBar1, Color.khaki, "exit"+rawtime(0));
} else if (nBarTime >= (nEnd-getInterval()) ) { // Exit 2
if (bBT == true) {
if (sPosition == "Long") Strategy.doSell("End of Day", Strategy.CLOSE, Strategy.THISBAR);
if (sPosition == "Short") Strategy.doCover("End of Day", Strategy.CLOSE, Strategy.THISBAR);
}
doPriceBarColors();
sPosition = "Flat";
Alert.playSound("train.wav");
drawShape(Shape.DIAMOND, AboveBar1, Color.khaki);
} else if (day(0) != day(-1) ) { // Exit 2 (lack of bars due to low volume)
if (bBT == true) {
if (sPosition == "Long") Strategy.doSell("End of Day", Strategy.MARKET, Strategy.THISBAR);
if (sPosition == "Short") Strategy.doCover("End of Day", Strategy.MARKET, Strategy.THISBAR);
}
doPriceBarColors();
sPosition = "Flat";
Alert.playSound("train.wav");
drawShape(Shape.DIAMOND, AboveBar1, Color.khaki);
}
} else {
if (nState == BARSTATE_NEWBAR) nStop = null;
}

// Entry
if (bEntryBar == true && sPosition == "Flat") {
var nTickHigh_1 = high( -1, sym("$TICK,15"));
var nTickLow_1 = low( -1, sym("$TICK,15"));
var nTickClose_1 = close( -1, sym("$TICK,15"));
var nOpen_1 = open( -1, inv(15));
var nHigh_1 = high( -1, inv(15));
var nLow_1 = low( -1, inv(15));
var nClose_1 = close( -1, inv(15));
var nAvgRange_1 = xAvgRange.getValue(-1);
var nDailyOpen = open( 0, inv("D"));
var nDailyLow_1 = low( -1, inv("D"));
var nDailyClose_1 = close( -1, inv("D"));
var sRule = 0;
if (nTickHigh_1 == null || nTickLow_1 == null || nAvgRange_1 == null) return;

// Long Entry
if (nTickLow_1 > -350) {
if (nTickHigh_1 > 750) { // Rule 1
sPosition = "Long";
sRule = 1;
} else if (nTickClose_1 > 500) { // Rule 2
sPosition = "Long";
sRule = 2;
} else if (nClose_1 > (nOpen_1 + nAvgRange_1) ) { // Rule 3
sPosition = "Long";
sRule = 3;
}
if (sPosition == "Long") {
if (bBT == true) Strategy.doLong("Rule " + sRule, Strategy.MARKET, Strategy.THISBAR);
drawShape(Shape.UPARROW, BelowBar2, Color.green, rawtime(0));
drawText(sRule, BelowBar4, Color.green, Text.CENTER|Text.BOLD, rawtime(0));
Alert.playSound("pop.wav");
}
}

// Short Entry
if (sPosition == "Flat" && nTickHigh_1 < 750) {
if (nDailyOpen > (nDailyLow_1 - (2*nAvgRange_1)) && nTickLow_1 < -350 &&
low(0) <= nDailyOpen && high(0) >= nDailyOpen) { // Rule 1
sPosition = "Short";
sRule = 1;
} else if (nDailyOpen > (nDailyLow_1 - (2*nAvgRange_1)) && nTickClose_1 < -100 &&
low(0) <= nDailyOpen && high(0) >= nDailyOpen) { // Rule 2
sPosition = "Short";
sRule = 2;
} else if (nClose_1 > nDailyClose_1 && nTickLow_1 < -350 &&
low(0) <= nDailyClose_1 && high(0) >= nDailyClose_1) { // Rule 3
sPosition = "Short";
sRule = 3;
} else if (nClose_1 > nDailyClose_1 && nTickClose_1 < -100 &&
low(0) <= nDailyClose_1 && high(0) >= nDailyClose_1) { // Rule 4
sPosition = "Short";
sRule = 4;
} else if (nClose_1 < (nOpen_1 - nAvgRange_1) ) { // Rule 5
sPosition = "Short";
sRule = 5;
}
if (sPosition == "Short") {
if (bBT == true) {
if (sRule == 1 || sRule == 2) {
Strategy.doShort("Rule " + sRule, Strategy.LIMIT, Strategy.THISBAR, Strategy.DEFAULT, nDailyOpen);
} else if (sRule == 3 || sRule == 4) {
Strategy.doShort("Rule " + sRule, Strategy.STOP, Strategy.THISBAR, Strategy.DEFAULT, nDailyClose_1);
} else if (sRule == 5) {
Strategy.doShort("Rule " + sRule, Strategy.MARKET, Strategy.THISBAR);
}
}
drawShape(Shape.DOWNARROW, AboveBar2, Color.red, rawtime(0));
drawText(sRule, AboveBar4, Color.red, Text.CENTER|Text.BOLD, rawtime(0));
Alert.playSound("ding.wav");
}
}

bEntryBar = false;

// Set Stop
if (sPosition != "Flat") {
nStop = (nR * nPoints * xAvgRange.getValue(0)) / nPoints;
if (sPosition == "Long") {
nStop = open(0) - nStop;
} else if (sPosition == "Short") {
if (sRule == 1 || sRule == 2) nStop = nDailyOpen + nStop;
else if (sRule == 3 || sRule == 4) nStop = nDailyClose_1 + nStop;
else if (sRule == 5) nStop = open(0) + nStop;
}
}
}

// Color Price Bars
doPriceBarColors();

return new Array(sPosition, nStop);
}


function doPriceBarColors() {
if (Strategy.isLong() || sPosition == "Long") setPriceBarColor(Color.green);
else if (Strategy.isShort() || sPosition == "Short") setPriceBarColor(Color.red);
return;
}

var xRange = null;

function calcAR(nInv) {
if (xRange == null) xRange = efsInternal("calcRange");
return sma(27, xRange);
}

function calcRange() {
return high(-1) - low(-1);
}

function verify() {
var b = false;
if (getBuildNumber() < 730) {
drawTextAbsolute(5, 35, "This study requires version 7.9.1 or later.",
Color.white, Color.blue, Text.RELATIVETOBOTTOM|Text.RELATIVETOLEFT|Text.BOLD|Text.LEFT,
null, 13, "error");
drawTextAbsolute(5, 20, "Click HERE to upgrade.@URL=http://www.esignal.com/download/default.asp",
Color.white, Color.blue, Text.RELATIVETOBOTTOM|Text.RELATIVETOLEFT|Text.BOLD|Text.LEFT,
null, 13, "upgrade");
return b;
} else {
b = true;
}

return b;
}

Back to top




November 2006


From the article "The six signal composite indicator," by Art Collins.

Component formulas

Component 1: Close vs. 40-day average
inputs: x(40);
if c>average(c,x) then buy next bar at market;
if c
setexitonclose;


Component 2: Two-day/Five-day average fade
if average(c,2)
if average(c,2)>average(c,5) then sell short next bar at market;
setexitonclose;


Component 3: 50-day extreme highest/lowest close
Input: m(50);
if highestbar(c,m)>lowestbar(c,m) then buy next bar at market;
if highestbar(c,m)
setexitonclose;


Component 4: Go-with close direction following tight ranges, fade following wide ones
inputs:n(10);
if (rangec[1])or (range>average(range,n) and c
at market;
if (rangeaverage(range,n) and c>c[1])then sell short
next bar at market;
setexitonclose;


Component 5: Close vs. 15-day high-low averages
if c>(average(h,15)+average(l,15))/2 then buy next bar at market;
if c<(average(h,15)+average(l,15))/2 then sell short next bar at market;
setexitonclose;


Component 6: Fading two of the last three open-to-close moves
variables: e(0);
if c>o then e=1;
if cif average(e,3)<0 then buy next bar at market;
if average(e,3)>0 then sell short next bar at market;
setexitonclose;


Six indicators combined
variables: e(0),aa(0),bb(0),cc(0),dd(0),ee(0),ff(0),gg(0);
if c>o then e=1;
if cIF average(c,2)if average(c,2)>average(c,5)then aa=-1;
if c>average(c,40) then bb=1;
if cif highestbar(c,50)>lowestbar(c,50) then cc=1;
if highestbar(c,50)if (rangec[1] or (range>average(range,10)) and cif (rangeaverage(range,10)) and c>c[1] then dd=-1;
if c>(average(h,15)+average(l,15))/2 then ee=1;
if c<(average(h,15)+average(l,15))/2 then ee=-1;
if average(e,3)<0 then ff=1;
if average(e,3)>0 then ff=-1;
if aa+bb+cc+dd+ee+ff>0 then buy next bar at market;
if aa+bb+cc+dd+ee+ff<0 then sell short next bar at market;
setexitonclose;

Back to top


December 2006

eSignal code for Trading System Lab, "Trading the equity curve," p. 44

/***************************************
Provided By : eSignal (c) Copyright 2006
Description: Trading the equity curve
by Volker Knapp

Version 1.0 11/17/2006

Notes:
* Dec 2006 Issue of Active Trader Magazine
* Study requires version 8.0 or later.


Formula Parameters: Default:
KAMA Periods 10
KAMA Fast Length 2
KAMA Slow Length 30
Commission per Trade 8
Slippage per Trade 0.002 (0.2%)
Bollinger Band Periods 38
Bollinger Band Standard Deviations 3
*****************************************************************/

function preMain() {
setPriceStudy(true);
setStudyTitle("Equity Curve MA");
setShowTitleParameters(false);
setCursorLabelName("Upper BB", 0);
setCursorLabelName("Lower BB", 1);
setCursorLabelName("Equity Fast MA", 2);
setCursorLabelName("Equity Slow MA", 3);
setDefaultBarFgColor(Color.grey, 0);
setDefaultBarFgColor(Color.grey, 1);
setDefaultBarFgColor(Color.red, 2);
setDefaultBarFgColor(Color.green, 3);
setDefaultBarThickness(2, 0);
setDefaultBarThickness(2, 1);


// KAMA parameters
var fp1 = new FunctionParameter( "Period", FunctionParameter.NUMBER);
fp1.setName( "KAMA Periods" );
fp1.setLowerLimit( 5 );
fp1.setUpperLimit( 125 );
fp1.setDefault( 10 );
var fp2 = new FunctionParameter( "Fast", FunctionParameter.NUMBER);
fp2.setName( "KAMA Fast Length" );
fp2.setLowerLimit( 1 );
fp2.setUpperLimit( 125 );
fp2.setDefault( 2 );
var fp3 = new FunctionParameter( "Slow", FunctionParameter.NUMBER);
fp3.setName( "KAMA Slow Length" );
fp3.setLowerLimit( 1 );
fp3.setUpperLimit( 125 );
fp3.setDefault( 30 );
var fp4 = new FunctionParameter( "Commission", FunctionParameter.NUMBER);
fp4.setName( "Commission per Trade" );
fp4.setLowerLimit( 0 );
fp4.setDefault( 8 );
var fp5 = new FunctionParameter( "Slippage", FunctionParameter.NUMBER);
fp5.setName( "Slippage per Trade" );
fp5.setLowerLimit( 0 );
fp5.setDefault( 0.002 );
var fp5b = new FunctionParameter( "Lot", FunctionParameter.NUMBER);
fp5b.setName( "Lot Size" );
fp5b.setLowerLimit( 1 );
fp5b.setDefault( 100 );
var fp6 = new FunctionParameter( "BBPeriods", FunctionParameter.NUMBER);
fp6.setName( "Bollinger Band Periods" );
fp6.setLowerLimit( 1 );
fp6.setDefault( 38 );
var fp7 = new FunctionParameter( "BBStdv", FunctionParameter.NUMBER);
fp7.setName( "Bollinger Band Standard Deviations" );
fp7.setLowerLimit( 0 );
fp7.setDefault( 3 );
var fp8 = new FunctionParameter( "SMA_fast", FunctionParameter.NUMBER);
fp8.setName( "Fast SMA Length " );
fp8.setLowerLimit( 0 );
fp8.setDefault( 3 );
var fp9 = new FunctionParameter( "SMA_slow", FunctionParameter.NUMBER);
fp9.setName( "Slow SMA Length " );
fp9.setLowerLimit( 0 );
fp9.setDefault( 10 );
}

// Global Variables
var bVersion = null; // Version flag
var bInit = false; // Initialization flag

var bBT = true; // Back Testing flag

// Basis Strategy Variables
var xUpper = null;
var xLower = null;
var xEquity = null; // Equity Series
var nEquity = 100000;
var nLot = 100;
var nEntry = null;
var nExit = null;
var nCom = 8*2; // Commission per trade
var nSlip = 0.002; // 0.2% Slippage per trade
var vPosition = 0; // 1=long, 0=flat, -1=short

// Strategy of Basis (B)
var xSMA_fast = null;
var xSMA_slow = null;
var vPositionB = 0; // 1=long, 0=flat, -1=short

// KAMA globals
var xKamaH = null;
var xKamaL = null;
var nKama = 0; // Kama value
var nKama_1 = 0; // previous bar's Kama value
var nFast = 0;
var nSlow = 0;


function main(Period, Fast, Slow, Commission, Slippage, BBPeriods, BBStdv,
SMA_fast, SMA_slow) {
if (bVersion == null) bVersion = verify();
if (bVersion == false) return;

var nState = getBarState();

if(bInit == false) {
xKamaH = efsInternal("kama", Period, Fast, Slow, high());
xKamaL = efsInternal("kama", Period, Fast, Slow, low());
xUpper = upperBB(BBPeriods, BBStdv, xKamaH);
xLower = lowerBB(BBPeriods, BBStdv, xKamaL);

// Basis Strategy for Paper trading equity curve needs to go
// into the getBasisEquity series function. Any existing strategy
// may be used in place of the current strategy.
xEquity = efsInternal("getBasisEquity", xUpper, xLower);
xSMA_fast = sma(SMA_fast, xEquity);
xSMA_slow = sma(SMA_slow, xEquity);

nCom = Commission * 2;
nSlip = Slippage;

bInit = true;
}

if (nState == BARSTATE_NEWBAR) {
if (getCurrentBarIndex() == 0) bBT = false;
}

var nU = xUpper.getValue(-1);
var nL = xLower.getValue(-1);
var nSMA_fast_1 = xSMA_fast.getValue(-1);
var nSMA_slow_1 = xSMA_slow.getValue(-1);
if(nU == null || nL == null ||
nSMA_fast_1 == null || nSMA_slow_1 == null) return;


/***** Strategy of Basis (B) *****/
if (nState == BARSTATE_NEWBAR) {
if (nSMA_fast_1 > nSMA_slow_1) {
// Long Trade Signal
if (vPositionB != 1 && close(-1) > nU) {
drawShape(Shape.UPARROW, AboveBar1, Color.green, rawtime(0));
vPositionB = 1;
if (bBT == true) {
Strategy.doLong("Long", Strategy.MARKET, Strategy.THISBAR);
}
// Short Trade Signal
} else if (vPositionB != -1 && close(-1) < nL) {
drawShape(Shape.DOWNARROW, BelowBar1, Color.red, rawtime(0));
vPositionB = -1;
if (bBT == true) {
Strategy.doShort("Short", Strategy.MARKET, Strategy.THISBAR);
}
}
}
}

if(vPositionB == 1) {
setBarFgColor(Color.darkgreen, 0);
setBarFgColor(Color.darkgreen, 1);
} else if(vPositionB == -1) {
setBarFgColor(Color.red, 0);
setBarFgColor(Color.red, 1);
}

return new Array((xUpper.getValue(0)).toFixed(2)*1,
(xLower.getValue(0)).toFixed(2)*1,
(xSMA_fast.getValue(0)).toFixed(2),
(xSMA_slow.getValue(0)).toFixed(2));
}


function getBasisEquity(xU, xL) {
var nState = getBarState();
var nU = xU.getValue(-1);
var nL = xL.getValue(-1);

if (nState == BARSTATE_NEWBAR) {
// Long Trade Signal
if (vPosition != 1 && close(-1) > nU) {
nExit = open(0) + (nSlip * open(0));
if (vPosition == -1) {
nEquity += ((nEntry - nExit) * nLot) - nCom;
}
vPosition = 1;
nEntry = open(0) + (nSlip * open(0));
// Short Trade Signal
} else if (vPosition != -1 && close(-1) < nL) {
nExit = open(0) - (nSlip * open(0));
if (vPosition == 1) {
nEquity += ((nExit - nEntry) * nLot) - nCom;
}
vPosition = -1;
nEntry = open(0) - (nSlip * open(0));
}
}

return nEquity;
}

function kama(Period, Fast, Slow, xSource) {
/***************************************************
kama series modified from KAMA.efs by
Divergence Software, Inc.
http://share.esignal.com/groupgo.jsp?groupid=114
****************************************************/

var x = 0;
var nNoise;
var nSignal;
var nSmooth;

if (bInit == false) {
nFast = 2 / ( Fast + 1 );
nSlow = 2 / ( Slow + 1 );
bInit = true;
}

if (getBarState() == BARSTATE_NEWBAR) {
nKama_1 = nKama;
}

if (xSource.getValue(-(Period+1)) == null) return close(0);

nSignal = Math.abs( xSource.getValue(0) - xSource.getValue(-Period) );

nNoise = 0;
while( xnNoise += Math.abs( xSource.getValue(-x)-xSource.getValue(-(x+1)) );
x++;
}

if ( nNoise==0 ) nNoise = 1.0;
nSmooth = Math.pow( ( nSignal/nNoise ) * ( nFast - nSlow ) + nSlow , 2 );
nKama = nKama_1 + nSmooth * ( xSource.getValue(0) - nKama_1 );

return nKama;
}


function verify() {
var b = false;
if (getBuildNumber() < 779) {
drawTextAbsolute(5, 35, "This study requires version 8.0 or later.",
Color.white, Color.blue, Text.RELATIVETOBOTTOM|Text.RELATIVETOLEFT|Text.BOLD|Text.LEFT,
null, 13, "error");
drawTextAbsolute(5, 20, "Click HERE to upgrade.@URL=http://www.esignal.com/download/default.asp",
Color.white, Color.blue, Text.RELATIVETOBOTTOM|Text.RELATIVETOLEFT|Text.BOLD|Text.LEFT,
null, 13, "upgrade");
return b;
} else {
b = true;
}

return b;
}

Back to top


January 2007

eSignal code for "Gauging gap opportunities," p. 14

/***************************************
Provided By : eSignal (c) Copyright 2006
Description: Gauging Gap Opportunities
by David Bukey

Version 1.0 11/10/2006

Notes:
* Jan 2007 Issue of Active Trader Magazine
* Study requires version 8.0 or later.


Formula Parameters: Default:
Filled Gap Price Bar Color lime
Fill Target Color blue
Fill Target Thickness 2
*****************************************************************/

function preMain() {
setPriceStudy(true);
setStudyTitle("Filled Gaps ");
setCursorLabelName("Fill Target", 0);
setShowTitleParameters(false);
setPlotType(PLOTTYPE_FLATLINES, 0);
setColorPriceBars(true);
setDefaultPriceBarColor(Color.grey);

var fp1 = new FunctionParameter("nFillColor", FunctionParameter.COLOR);
fp1.setName("Filled Gap Price Bar Color");
fp1.setDefault(Color.lime);
var fp2 = new FunctionParameter("nColor", FunctionParameter.COLOR);
fp2.setName("Fill Target Color");
fp2.setDefault(Color.blue);
var fp3 = new FunctionParameter("nThick", FunctionParameter.NUMBER);
fp3.setName("Fill Target Thickness");
fp3.setLowerLimit(1);
fp3.setDefault(2);
var fp4 = new FunctionParameter("nLimit", FunctionParameter.NUMBER);
fp4.setName("Limit for # of bars to fill gap.");
fp4.setLowerLimit(1);
fp4.setDefault(5);
}

// Global Variables
var bVersion = null; // Version flag
var bInit = false; // Initialization flag

var nFill = null;
var nCount = 0;
var nGap = 0;

function main(nFillColor, nColor, nThick, nLimit) {
if (bVersion == null) bVersion = verify();
if (bVersion == false) return;

var nState = getBarState();

//Initialization
if (bInit == false) {
setDefaultBarFgColor(nColor, 0);
setDefaultBarThickness(nThick, 0);
bInit = true;
}

var nH_2 = high(-2);
var nH_1 = high(-1);
var nH_0 = high(0);
var nL_2 = low(-2);
var nL_1 = low(-1);
var nL_0 = low(0);
if (nH_2 == null || nL_2 == null) return;


if (nState == BARSTATE_NEWBAR && nCount > 0) {
if (nGap != 0) {
nCount++;
if (nCount > nLimit) {
nCount = 0;
nGap = 0;
nFill = null;
}
} else {
nFill = null;
}
} else if (nCount <= 1) { // first gap bar
if (nL_0 > nH_1 ) {
nCount = 1
nFill = nH_1;
nGap = 1;
drawShapeRelative(0, (nFill+nL_0)/2, Shape.UPARROW,
null, Color.red, null, "gap"+rawtime(0));
}
if (nH_0 < nL_1 ) {
nCount = 1;
nFill = nL_1;
nGap = -1;
drawShapeRelative(0, (nFill+nH_0)/2, Shape.DOWNARROW,
null, Color.red, null, "gap"+rawtime(0));
}
if (nL_0 <= nH_1 && nH_0 >= nL_1) {
nCount = 0;
nFill = null;
nGap = 0;
removeShape("gap"+rawtime(0));
}
}

if (nCount > 1) { // Filled Gap check
if ( (nGap == 1 && nL_0 <= nFill) || (nGap == -1 && nH_0 >= nFill) ) {
setPriceBarColor(nFillColor);
nGap = 0;
nCount = 0;
}
}


return nFill;
}


function verify() {
var b = false;
if (getBuildNumber() < 779) {
drawTextAbsolute(5, 35, "This study requires version 8.0 or later.",
Color.white, Color.blue, Text.RELATIVETOBOTTOM|Text.RELATIVETOLEFT|Text.BOLD|Text.LEFT,
null, 13, "error");
drawTextAbsolute(5, 20, "Click HERE to upgrade.@URL=http://www.esignal.com/download/default.asp",
Color.white, Color.blue, Text.RELATIVETOBOTTOM|Text.RELATIVETOLEFT|Text.BOLD|Text.LEFT,
null, 13, "upgrade");
return b;
} else {
b = true;
}

return b;
}

eSignal code for Trading System Lab, "Exiting after profitable closes," p. 38

/***************************************
Provided By : eSignal (c) Copyright 2006
Description: Exiting after profitable closes
by Volker Knapp

Version 1.0 11/13/2006

Notes:
* Jan 2007 Issue of Active Trader Magazine
* Study requires version 8.0 or later.
* Long only system, compatible for Back Testing
and real time.
* Parameters optimized for Daily interval.


Formula Parameters: Default:
Number of days for Trend Entry 20
Number of days for Counter Trend Entry 10
Number of days for Trend Exit 20
Number of days for Counter Trend Exit 8
Fixed Stop Percent 0.10
*****************************************************************/

function preMain() {
setPriceStudy(true);
setStudyTitle("Highest High Trend System ");
setShowTitleParameters(false);
setCursorLabelName("HH", 0);
setCursorLabelName("LL", 1);
setCursorLabelName("Stop", 2);
setDefaultBarThickness(2, 0);
setDefaultBarThickness(2, 1);
setDefaultBarThickness(2, 2);
setDefaultBarFgColor(Color.blue, 0);
setDefaultBarFgColor(Color.blue, 1);
setDefaultBarFgColor(Color.red, 2);
setPlotType(PLOTTYPE_FLATLINES, 2);

var fp1 = new FunctionParameter("nTdays", FunctionParameter.NUMBER);
fp1.setName("Number of days for Trend Entry");
fp1.setLowerLimit(1);
fp1.setDefault(20);
var fp2 = new FunctionParameter("nCTdays", FunctionParameter.NUMBER);
fp2.setName("Number of days for Counter Trend Entry");
fp2.setLowerLimit(1);
fp2.setDefault(10);
var fp3 = new FunctionParameter("nTexit", FunctionParameter.NUMBER);
fp3.setName("Number of days for Trend Exit");
fp3.setLowerLimit(1);
fp3.setDefault(20);
var fp4 = new FunctionParameter("nCTexit", FunctionParameter.NUMBER);
fp4.setName("Number of days for Counter Trend Exit");
fp4.setLowerLimit(1);
fp4.setDefault(8);
var fp5 = new FunctionParameter("nStopPrct", FunctionParameter.NUMBER);
fp5.setName("Fixed Stop Percent");
fp5.setLowerLimit(0);
fp5.setUpperLimit(1);
fp5.setDefault(0.10);
}

// Global Variables
var bVersion = null; // Version flag
var bInit = false; // Initialization flag

var nCount = 0;
var xHH_Trend = null;
var xLL_CTrend = null;
var vPosition = 0; // 0 = flat, 1 = Trend long, 2 = Counter Trend Long
var nEntry = null; // entry price
var nStop = null; // stop price
var bExitTrade = false;
var bBT = true; // back test flag

function main(nTdays, nCTdays, nTexit, nCTexit, nStopPrct) {
if (bVersion == null) bVersion = verify();
if (bVersion == false) return;

var nState = getBarState();

//Initialization
if (bInit == false) {
xHH_Trend = upperDonchian(nTdays, high());
xLL_CTrend = lowerDonchian(nCTdays, low());
bInit = true;
}

var nH_0 = high(0);
var nL_0 = low(0);
var nC_1 = close(-1);
var nOpen = open(0);
var nHH = xHH_Trend.getValue(0);
var nLL = xLL_CTrend.getValue(0);
var nHH_1 = xHH_Trend.getValue(-1);
var nLL_1 = xLL_CTrend.getValue(-1);
if (nHH_1 == null || nLL_1 == null) return;

// Record Keeping
if (nState == BARSTATE_NEWBAR) {
bExitTrade = false;
if (vPosition == 0) {
nCount = 0;
nEntry = null;
nStop = null;
}
if (getCurrentBarIndex() == 0) bBT = false;
}

// Exit Conditions
if (vPosition != 0 && nState == BARSTATE_NEWBAR) {
var sText = "";
/*var sText = "Unprofitable Close";
if (nCount >= 1 && nC_1 < nEntry) {
// not a profitable close
// exit position
vPosition = 0;
bExitTrade = true;
}*/
nCount++;
// Trend Exit
if (vPosition == 1 && nCount >= nTexit) {
sText = "Counter Trend Exit";
bExitTrade = true;
}
// Counter Trend Exit
if (vPosition == 2 && nCount >= nCTexit) {
sText = "Counter Trend Exit";
bExitTrade = true;
}

if (bExitTrade == true) {
vPosition = 0;
drawShape(Shape.DIAMOND, AboveBar1, Color.red, "xtop"+rawtime(0));
drawShape(Shape.DIAMOND, BelowBar1, Color.red, "xbot"+rawtime(0));
Alert.playSound("train.wav");
if (bBT) {
Strategy.doSell(sText, Strategy.MARKET, Strategy.THISBAR);
}
}
}
// Fixed %Stop Exit
if (bExitTrade == false && vPosition != 0) {
if (nL_0 <= nStop) {
vPosition = 0;
bExitTrade = true;
drawShape(Shape.DIAMOND, AboveBar1, Color.red, "xtop"+rawtime(0));
drawShape(Shape.DIAMOND, BelowBar1, Color.red, "xbot"+rawtime(0));
Alert.playSound("train.wav");
if (bBT) {
Strategy.doSell("Stop Exit", Strategy.STOP, Strategy.THISBAR,
Strategy.DEFAULT, Math.min(nOpen, nStop));
}
}
}



// Entry Conditions
if (vPosition == 0 && bExitTrade == false) {
// Trend Entry
if (nH_0 > nHH_1) {
vPosition = 1;
nEntry = Math.max(nOpen, nHH_1);
nStop = nEntry * (1 - nStopPrct); // fixed stop
drawShape(Shape.UPARROW, AboveBar1, Color.green, rawtime(0));
Alert.playSound("ding.wav");
if (bBT) {
Strategy.doLong("Trend Signal", Strategy.STOP,
Strategy.THISBAR, Strategy.DEFAULT, nEntry);
}
} else if (nL_0 < nLL_1) { // Counter Trend Entry
vPosition = 2;
nEntry = Math.min(nOpen, nLL_1);
nStop = nEntry * (1 - nStopPrct); // fixed stop
drawShape(Shape.UPARROW, AboveBar1, Color.green, rawtime(0));
Alert.playSound("ding.wav");
if (bBT) {
Strategy.doLong("Counter Trend Signal", Strategy.LIMIT,
Strategy.THISBAR, Strategy.DEFAULT, nEntry);
}
}
}

return new Array(nHH, nLL, nStop);
}


function verify() {
var b = false;
if (getBuildNumber() < 779) {
drawTextAbsolute(5, 35, "This study requires version 8.0 or later.",
Color.white, Color.blue, Text.RELATIVETOBOTTOM|Text.RELATIVETOLEFT|Text.BOLD|Text.LEFT,
null, 13, "error");
drawTextAbsolute(5, 20, "Click HERE to upgrade.@URL=http://www.esignal.com/download/default.asp",
Color.white, Color.blue, Text.RELATIVETOBOTTOM|Text.RELATIVETOLEFT|Text.BOLD|Text.LEFT,
null, 13, "upgrade");
return b;
} else {
b = true;
}

return b;

Code for updated version of "The ultimate stop-loss equation," p. 20

Sub UnBiasedRange(LookBack As Integer)?'Copyright (C), 2006:Thomas Stridsman

Dim Typical, LatestMove, Target As BarArray(250)?Dim
TypicalMove, CloseVariation, TypicalBar, BarVariation As
Double

Typical = (O+H+L+C)/4?LatestMove = Typical - Typical[1]

TypicalMove = Average(LatestMove, LookBack,
0)?CloseVariation = StdDev(LatestMove, LookBack,
0)?TypicalBar = Average(TrueRange, LookBack,
0)?BarVariation = StdDev(TrueRange, LookBack, 0)

If TypicalMove > 0 Then? Target = Typical + TypicalMove
- CloseVariation - TypicalBar - BarVariation?Else If
TypicalMove < 0 Then? Target = Typical + TypicalMove +
CloseVariation + TypicalBar+ BarVariation?Else If
TypicalMove = 0 Then? Target = Typical?End If?End
If?End If

Plot1(Target)

End Sub

Back to top

February 2007

TradeStation code for the article “Turning systems upside down” by Art Collins (Active Trader), February 2007.

Nine-day reversal — first day follow-through
inputs: n(9);
if l[1]c[1] then buy this bar on close;
if barssinceentry=1 then setexitonclose;
if h[1]>highest(h,n)[2]and h>h[1] and cif barssinceentry=1 then setexitonclose;

Fading the reversal day signal
variables:hh(0),ll(0);
if marketposition=1 and barssinceentry=0 then hh=h;
if marketposition=-1 and barssinceentry=0 then ll=l;
if marketposition<1 and h>h[1] and cif(h<=h[1] or c>=c[1]) then sell next bar at hh limit;
if barssinceentry>0 then sell next bar at ll-minmove/pricescale stop;
if marketposition>-1 and lc[1] then sell short next bar at market;
if (l>=l[1] or c<=c[1]) then buy to cover next bar at ll limit;
if barssinceentry>0 then buy to cover next bar at hh+minmove/pricescale stop;

Fading the RSI indicator
inputs: Length(9),n(15),b(9.15),x(14.45),z(15.1);
variables: e(0);
e = RSI( Close, Length ) ;
if time>=(b*100) and time<=(x*100) and e>(100-n) then buy next bar at market;
if time=(z*100) then sell next bar at market;
if  time>=(b*100) and time<=(x*100) and eif time=(z*100) then buy to cover next bar at market;

Back to top


April 2007


eSignal code for "Closing Price Divergences, " p. 37

*************************************** Provided By : eSignal (c) Copyright 2007 Description: Closing-Price Divergences by Clive Corcoran Version 1.0 1/18/2007 Notes: * Study requires version 8.0 or later.
* This study is designed for back testing, not real time analysis.
* This study is intended for Equities only.
* The Starting Equity amount entered for the study will also need to be entered into the Strategy Analyzer settings.

Formula Parameters: Default:
Starting Equity 100000
Position Size (%of Equity) 2 *************************************************/

function preMain() {
setPriceStudy(true);
setStudyTitle("Price-Close Location Divergence");
setCursorLabelName("65th Percentile", 0);
setCursorLabelName("35th Percentile", 1);
setCursorLabelName("Closing Bias", 2);
setCursorLabelName("Close Stop 3%", 3);
setCursorLabelName("IntraBar Stop 5%", 4);
setCursorLabelName("Target1 5%", 5);
setCursorLabelName("Target2 7%", 6);
setCursorLabelName("long count", 7);
setCursorLabelName("short count", 8);
setDefaultBarFgColor(Color.blue, 0);
setDefaultBarFgColor(Color.blue, 1);
setDefaultBarFgColor(Color.magenta, 2);
setDefaultBarFgColor(Color.red, 3);
setDefaultBarFgColor(Color.red, 4);
setDefaultBarFgColor(Color.green, 5);
setDefaultBarFgColor(Color.green, 6);
//setDefaultBarThickness(2, 3);
setPlotType(PLOTTYPE_FLATLINES, 3);
setPlotType(PLOTTYPE_FLATLINES, 4);
setPlotType(PLOTTYPE_FLATLINES, 5);
setPlotType(PLOTTYPE_FLATLINES, 6);

setDefaultFont("Arial", 12, null, Text.BOLD|Text.FRAME|Text.CENTER);

var fp1 = new FunctionParameter("Equity", FunctionParameter.NUMBER);
fp1.setName("Starting Equity");
fp1.setLowerLimit(1);
fp1.setDefault(100000);
var fp2 = new FunctionParameter("PosSize", FunctionParameter.NUMBER);
fp2.setName("Position Size (%of Equity)");
fp2.setLowerLimit(0.1);
fp2.setDefault(2);
}

// Global Variables
var xRankC = null;
var xBiasC = null;
var aLongCount = new Array(21);
var aShortCount = new Array(21);

for (var i = 0; i < 21; i++) {
aLongCount[i] = 0;
aShortCount[i] = 0;
}

var nEquity = null; // Starting Equity
var nPS = null; // Position size as % of Equity
var vPosition = 0; // 0=flat, 1=long, -1=short
var nEntryPrice = null;
var nStop1 = null;
var nStop2 = null; var nTarget1 = null;
var nTarget2 = null;
var bTargetBreach = false;
var nLotSize = null;
var nLongCount = 0;
var nShortCount = 0;
var nLongCount_1 = 0;
var nShortCount_1 = 0;

var bInit = false; // initialization flag
var bBT = true;

function main(Equity, PosSize) {
var nState = getBarState();
if (getCurrentBarIndex() >= -1) bBT = false; // disable back testing functions
if (getCurrentBarIndex() == 0) return;

if(bInit == false) {
nEquity = Equity;
nPS = PosSize;
xRankC = efsInternal("calcPercentiles");
xBiasC = efsInternal("calcBias");
bInit = true; // Prevents this code block from executing again.
}

//if (getCurrentBarCount() < 21) return;

// Retrieve previous bar's values of Donchian Series for back testing conditions.
//var n = x.getValue(-1);
var x35th = getSeries(xRankC, 0);
var x65th = getSeries(xRankC, 1);
var nBias = xBiasC.getValue(0);
var nBias_1 = xBiasC.getValue(-1);
var n35th_1 = x35th.getValue(-1);
var n65th_1 = x65th.getValue(-1);
var bLong = false;
var bShort = false;
var bExitTrade = false;
var nExitPrice = null;

// Validate the study variables to ensure they contain valid data.
if(n35th_1 == null || n65th_1 == null || nBias_1 == null) {
return; // Exit the formula if variables contain invalid data.
}

// Record keeping
if (nState == BARSTATE_NEWBAR) {
nLongCount_1 = nLongCount;
nShortCount_1 = nShortCount;
aLongCount.pop();
aLongCount.unshift(0);
aShortCount.pop();
aShortCount.unshift(0);
// Long count
if (close(-1) <= n35th_1 && nBias_1 > 0.10) {
aLongCount[0] = 1;
}

// Short count
if (close(-1) >= n65th_1 && nBias_1 < -0.10) {
aShortCount[0] = 1;
}

nLongCount = 0;
nShortCount = 0;
for (var i = 0; i < 21; i++) {
nLongCount += aLongCount[i];
nShortCount += aShortCount[i];
if (i < 5) {
if (aLongCount[i] == 1) bLong = true;
if (aShortCount[i] == 1) bShort = true;
}
}

if (vPosition == 0) { nStop1 = null;
nStop2 = null;
nTarget1 = null;
nTarget2 = null;
bTargetBreach = false;
}
}

// Back Testing logic
if (getCurrentBarCount() > 21) { // study primed, begin evaluation
if (nState == BARSTATE_NEWBAR) {
// Exit Strategy
if (vPosition != 0) {
// Long Exit
if (vPosition == 1) {
if (bTargetBreach == false && high(0) > nTarget1) { // Profit Target1
bTargetBreach = true;
bExitTrade = true;
nExitPrice = Math.max(open(0), nTarget1);
drawShapeRelative(0, nExitPrice, Shape.DIAMOND, null, Color.green,
null, rawtime(0));
drawText("1", AboveBar2, Color.green, null, rawtime(0));
if (bBT == true) {
nEquity += (nExitPrice-nEntryPrice)*Math.round(nLotSize*.65);
Strategy.doSell("Target 1", Strategy.LIMIT, Strategy.THISBAR,
Math.round(nLotSize*.65), nExitPrice);
} } else if (bTargetBreach == true && high(0) > nTarget2) { // Profit Target2
vPosition = 0;
bExitTrade = true;
nExitPrice = Math.max(open(0), nTarget2);
drawShapeRelative(0, nExitPrice, Shape.DIAMOND, null, Color.green,
null, rawtime(0));
drawText("2", AboveBar2, Color.green, null, rawtime(0));
if (bBT == true) {
nEquity += (nExitPrice-nEntryPrice)*Strategy.getPositionSize();
Strategy.doSell("Target 2", Strategy.LIMIT, Strategy.THISBAR,
Strategy.getPositionSize(), nExitPrice);
}
}
} if (vPosition == 1 && bExitTrade == false) { // protective stops
if (close(-1) <= nStop1) {
vPosition = 0;
bExitTrade = true;
nExitPrice = open(0);
drawShapeRelative(0, nExitPrice, Shape.DIAMOND, null, Color.red,
null, rawtime(0));
drawText("1", BelowBar2, Color.red, null, rawtime(0));
if (bBT == true) {
nEquity += (nExitPrice-nEntryPrice)*Strategy.getPositionSize();
Strategy.doSell("Close Stop", Strategy.STOP, Strategy.THISBAR,
Strategy.getPositionSize(), nExitPrice);
}
} else if (low(0) <= nStop2) {
vPosition = 0;
bExitTrade = true;
nExitPrice = Math.min(open(0), nStop2);
drawShapeRelative(0, nExitPrice, Shape.DIAMOND, null, Color.red,
null, rawtime(0));
drawText("2", BelowBar2, Color.red, null, rawtime(0));
if (bBT == true) {
nEquity += (nExitPrice-nEntryPrice)*Strategy.getPositionSize();
Strategy.doSell("IntraBar Stop", Strategy.STOP, Strategy.THISBAR,
Strategy.getPositionSize(), nExitPrice);
}
}
}

// Short Exit
if (vPosition == -1) {
if (bTargetBreach == false && low(0) < nTarget1) { // Profit Target1
bTargetBreach = true;
bExitTrade = true;
nExitPrice = Math.min(open(0), nTarget1);
drawShapeRelative(0, nExitPrice, Shape.DIAMOND, null, Color.green,
null, rawtime(0));
drawText("1", BelowBar2, Color.green, null, rawtime(0));
if (bBT == true) {
nEquity += (nEntryPrice-nExitPrice)*Math.round(nLotSize*.65);
Strategy.doCover("Target 1", Strategy.LIMIT, Strategy.THISBAR,
Math.round(nLotSize*.65), nExitPrice);
}
} else if (bTargetBreach == true && low(0) < nTarget2) { // Profit Target2
vPosition = 0;
bExitTrade = true;
nExitPrice = Math.min(open(0), nTarget2);
drawShapeRelative(0, nExitPrice, Shape.DIAMOND, null, Color.green,
null, rawtime(0));
drawText("2", BelowBar2, Color.green, null, rawtime(0));
if (bBT == true) {
nEquity += (nEntryPrice-nExitPrice)*Math.abs(Strategy.getPositionSize());
Strategy.doCover("Target 2", Strategy.LIMIT, Strategy.THISBAR,
Math.abs(Strategy.getPositionSize()), nExitPrice);
}
}
}
if (vPosition == -1 && bExitTrade == false) { // protective stops
if (close(-1) >= nStop1) {
vPosition = 0;
bExitTrade = true;
nExitPrice = open(0);
drawShapeRelative(0, nExitPrice, Shape.DIAMOND, null, Color.red,
null, rawtime(0));
drawText("1", AboveBar2, Color.red, null, rawtime(0));
if (bBT == true) {
nEquity += (nEntryPrice-nExitPrice)*Math.abs(Strategy.getPositionSize());
Strategy.doCover("Close Stop", Strategy.STOP, Strategy.THISBAR,
Math.abs(Strategy.getPositionSize()), nExitPrice);
}
} else if (high(0) >= nStop2) {
vPosition = 0;
bExitTrade = true;
nExitPrice = Math.max(open(0), nStop2);
drawShapeRelative(0, nExitPrice, Shape.DIAMOND, null, Color.red,
null, rawtime(0));
drawText("2", AboveBar2, Color.red, null, rawtime(0));
if (bBT == true) {
nEquity += (nEntryPrice-nExitPrice)*Math.abs(Strategy.getPositionSize());
Strategy.doCover("IntraBar Stop", Strategy.STOP, Strategy.THISBAR,
Math.abs(Strategy.getPositionSize()), nExitPrice);
}
}
}
}

// Entry Strategy
if (vPosition == 0 && bExitTrade == false) {
// Long Signal
//if (bLong == true && aLongCount[0] > aLongCount[1]) {
if (bLong == true && nLongCount == 5 && nLongCount_1 == 4) {
vPosition = 1;
drawShape(Shape.UPARROW, BelowBar1, Color.green, rawtime(0));
if (bBT == true) {
nLotSize = getLotSize(open(0));
Strategy.doLong("Long Trigger", Strategy.MARKET, Strategy.THISBAR,
nLotSize);
}
nEntryPrice = open(0);
nStop1 = nEntryPrice - (0.03*nEntryPrice);
nStop2 = nEntryPrice - (0.05*nEntryPrice);
nTarget1 = nEntryPrice + (0.05*nEntryPrice);
nTarget2 = nEntryPrice + (0.07*nEntryPrice);
}

// Short Signal
//if (vPosition == 0 && bShort == true && aShortCount[0] > aShortCount[1]) {
if (vPosition == 0 && bShort == true && nShortCount == 5 && nShortCount_1 == 4) {
vPosition = -1;
drawShape(Shape.DOWNARROW, AboveBar1, Color.red, rawtime(0));
if (bBT == true) {
nLotSize = getLotSize(open(0));
Strategy.doShort("Short Trigger", Strategy.MARKET, Strategy.THISBAR,
nLotSize);
}
nEntryPrice = open(0);
nStop1 = nEntryPrice + (0.03*nEntryPrice);
nStop2 = nEntryPrice + (0.05*nEntryPrice);
nTarget1 = nEntryPrice - (0.05*nEntryPrice);
nTarget2 = nEntryPrice - (0.07*nEntryPrice);
}
}
}
}

return new Array(x65th, x35th, nBias.toFixed(2), nStop1, nStop2, nTarget1, nTarget2,
nLongCount+"", nShortCount+"");
}

var aClose = new Array(21);

function calcPercentiles() {
var nState = getBarState();
var n35 = null;
var n65 = null;
var aSort = new Array(21);

if (nState == BARSTATE_NEWBAR) {
aClose.pop();
aClose.unshift(close(0));
}
aClose[0] = close(0);

if (aClose[20] == null) return;

for (var i = 0; i < 21; i++) {
aSort[i] = aClose[i];
}

aSort.sort(compareNumbers);

n35 = aSort[7];
n65 = aSort[13];

return new Array(n35, n65);
}

function compareNumbers(a, b) {
return a - b;
}

function calcBias() {
var c_0 = close(0);
var c_1 = close(-1);
var nATR = atr(1, 0);

if (close(-1) == null || nATR == null) return;

return (c_0 - c_1) / nATR;
}

function getLotSize(Price) {
return ((nPS/100) * nEquity) / Price;
}

Back to top

 

June 2007

TradeStation code for "Short-term, channel trading ," p. 29

The base strategy
inputs:length(10);
vars:lrgh(0),lrgl(0);
lrgh=linearregvalue(h,length,0);
lrgl=linearregvalue(l,length,0);
buy next bar at lrgh stop;
sell short next bar at lrgl stop;

The first filter
if (lrgh > lrgh[1] ) then buy next bar at lrgh stop;
if (lrgl < lrgl[1] ) then sell short next bar at lrgl stop;

The second filter
if (lrgh < lrgh[1] and cif (lrgl > lrgl[1] and c>lrgl ) then sell short next bar at lrgl stop;

Behle-Conway modified exit strategy

Inputs: stopbars(3), exitfactor(0.25),
length(14), profitbars (3), profitfactor (0.9);
Vars: sellstop(0),Coverstop(0),ATR(0), selltarget1(0),covertarget1(0),selltarget2(0),covertarget2(0);

ATR=Avgtruerange(length);
Sellstop=lowest(low,stopbars)-(exitfactor*ATR);
Coverstop=highest(high,stopbars)=(exitfactor*ATR);
Selltarget1 =h+(profitfactor*atr);
Covertarget1=low - (profitfactor*atr):
Selltarget2=highest(h,profitbars)+(2*profitfactor*atr);
Covertarget2=lowest(l,profitbars)-(2*profitfactor*atr);

If marketposition<>0 then begin
Sell next bar at sellstop on stop;
Buy to cover next bar at coverstopon stop;
End;

If Marketposition<>0 then begin

Sell currentcontracts/2 contracts next bar at selltarget1 on stop;
Buy to cover currentcontracts/2 contracts next bar at covertarget1 on stop;
Sell next bar at selltarget2 on stop;
Buy to cover next bar at covertarget2 on stop;

End;

Back to top


July 2007


TradeStation code for "Intraday hybrid strategy ," p. 22

// ================================
// Trend_Channel DT (Version 1.0)
// By: Lee Leibfarth
// 3-15-07
//
// TARGET : 610-Tick ER2
// ================================
inputs:
TradeSize(2),
Period(11),
Mult(3.5),
ProfitTargetAmount(250),
StopLossAmount(200),
IntradayStartTime(0940),
IntradayEndTime(1530);
variables:
RangeCalc(0),
StopLevel(0),
TradeDirection(0),
LStop(0),
SStop(0);
{========== Calculation Module ===========}
RangeCalc = xaverage((H - L), period);
LStop=maxlist(c[1] - RangeCalc * Mult, iff(l[1] < StopLevel[1], 0, StopLevel[1]) );
SStop=minlist(c[1] + RangeCalc * Mult, iff(h[1] > StopLevel[1], c*2, StopLevel[1]) );
if SStop > SStop[1] or h crosses over SStop then TradeDirection = 1;
if LStop < LStop[1] or l crosses under LStop then TradeDirection = -1;
if TradeDirection < 1 then StopLevel = SStop else StopLevel = LStop; {========== Entry Rules ===========}
if time > IntradayStartTime and time < IntradayEndTime and mp = 0 then begin
if TradeDirection[1] < 1 then buy ("ENTRY L") TradeSize contracts next bar at StopLevel stop;
if TradeDirection[1] > -1 then sellshort ("ENTRY S") TradeSize contracts next bar at StopLevel stop;
end;
{========== Exit Rules ===========}
if MP = 1 then begin
sell ("CHANNEL LS") TradeSize / 2 contracts next bar at entryprice - StopLossAmount / bigpointvalue stop;
if currentcontracts = TradeSize then begin
sell ("CHANNEL LX") TradeSize / 2 contracts next bar at entryprice + ProfitTargetAmount / bigpointvalue limit;
end;
sellshort ("TREND SE") TradeSize contracts next bar at Lstop stop;
end;
if MP = -1 then begin
buytocover ("CHANNEL SS") TradeSize / 2 contracts next bar at entryprice + StopLossAmount / bigpointvalue stop;
if currentcontracts = TradeSize then begin
buytocover ("CHANNEL SX") TradeSize / 2 contracts next bar at entryprice - ProfitTargetAmount / bigpointvalue limit;
end;
buy ("TREND LE") TradeSize contracts next bar at Sstop stop; end;
if marketposition <> 0 and time >=1600 then begin
- sell ("EOD SX")next bar at market;
buytocover ("EOD LX") next bar at market;
end;
setexitonclose;

Back to top

October 2007

TradeStation code for "Sharpening a countertrend strategy," p. 40

// ================================
// PP Stochastic (Version 1.0)
// By: Lee Leibfarth
// 6-23-07
//
// TARGET : Daily ER2
// ================================
inputs:
StochLength(8),
OverSoldLine(20),
OverBoughtLine(90),
StopLoss(800),
ProfitTarget(2200),
UsePositionSizing(true),
InitialAccount(40000),
InitMargin(4000),
RiskPercentage(.30);
variables:
TradeSize(1),
Balance(0),
oFastK(0),
oFastD(0),
oSlowK(0),
oSlowD(0);
value1 = Stochastic( h, l, c, StochLength, 3, 3, 1, oFastK, oFastD, oSlowK, oSlowD);
if UsePositionSizing then TradeSize = floor((InitialAccount + netprofit) * RiskPercentage / InitMargin);
if oFastK crosses over OverBoughtLine then sellshort ("ST_Sell") TradeSize contracts next bar at market ;
if oFastK crosses under OverSoldLine then buy ("ST_Buy") TradeSize contracts next bar at market ;
setstopcontract;
setstoploss(StopLoss);
setprofittarget(ProfitTarget);

Back to top


November 2007

AmiBroker code for "Testing the mean-reversion z-score system," p. 14.

Z-score system code:

// ZScore.afl
//
// z-score is a measure of the distance a single element
// of a data series is from the mean, measured in
// standard deviations.

function zscore(price,Length)
{
av = MA(price,Length);
st = StDev(price,Length);
zs = (price - av) / st;
return zs;
}

// The parameters that will be optimized
ZLength = Optimize("ZLen",4,2,50,2);
BuyLevel = Optimize("BuyLevel",-1.60,-3.00,0.00,0.02);
HoldDays = Optimize("HoldDays",5,1,10,1);

// Compute the z-score indicator
zz= zscore(C,ZLength);

// Enter the long position when the z-score rises
// through a specific level
Buy = Cross(zz,BuyLevel);
Sell = BarsSince(Buy)>=HoldDays;
Sell = ExRem(Sell,Buy);

// Plot the z-score and some reference levels
Plot(zz,"z-score",colorRed,styleLine|styleOwnScale,-2,2);
Plot(0,"0",colorRed,styleDots|styleOwnScale,-2,2);
Plot(1,"1",colorPink,styleDots|styleOwnScale,-2,2);
Plot(-1,"-1",colorPink,styleDots|styleOwnScale,-2,2);

Random entry code:

// RandomEntry.afl
//
// Example of a random entry trading system
//
// Be either Long or Flat.
// Generate signals after the close of daily bars.
//
// Take positions at the Close of the signal bar.
SetTradeDelays(0,0,0,0);
BuyPrice = Close;
SellPrice = Close;

dummy = Optimize("Dummy",1,1,100,1);

// Generate a random number, between 0.00 and 0.99
rn = Random();

// To be long 10% of the time, Buy if rn is <= 0.10
Buy = rn <= 0.10;
Sell = Ref(Buy,-1)==1;

// Compute the account equity.
e = Equity();

// Plot series of interest.
Plot(Close,"Close",colorBlack,styleCandle);
PlotShapes(shapeUpArrow*Buy+shapeDownArrow*Sell,
IIf(Buy,colorGreen,colorRed));
Plot(rn,"Random",colorBlue,styleLine|styleOwnScale);
Plot(e,"Equity",colorGreen,styleLine|styleOwnScale);

 

Back to top


December 2007

Mechanica code for "Filtering Bollinger Band breakouts," p. 34.

'Resources
SYSTEM = 1
SLIPPAGE = 0
COL1 = CLOSE
COL2 = SMA[COL1,40]
COL3 = STD[COL1,40,0]
COL4 = 4 * COL3 / COL2
COL5 = SMA[LOW,20]
COL6 = SMA[HIGH,20]
COL7 = ATR[1]
COL8 = EMA[COL7,15]
SIZING[1] = POINTVALUE * COL8

'Trade Entry
STARTDATE = 19840101
IF HIGH[1] > COL2[1] + COL4[1] AND COL4[1] > 1.25 * COL4[5] THEN BUYOPEN
IF LOW[1] < COL2[1] - COL4[1] AND COL4[1] > 1.25 * COL4[5] THEN SELLOPEN

'Trade In Progress & Exit
SELLSTOP = COL5[1]
BUYSTOP = COL6[1]------NetAddressPart-00--=a8O4118S08475fd687
Content-Type: text/plain; name=OVOLEXP.siz..txt"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline; filename=OVOLEXP.siz..txt"

Money management code
STARTUPCASH = 1000000
NEWCONTRACTS = (.0075 * TOTALEQUITY) / SIZING[1]

Back to top


January 2008

AmiBroker code for "Designing and testing a pattern-based trading system," p. 22.

// ThreeDay.afl
//
// Buy when the low is lower than the
// lowest low of the previous three days.
// Short when the high is higher than the
// highest high of the previous three days.
//
// Long positions are entered using a
// limit order at the previous lowest low.
// Short positions are entered using a
// limit order at the previous highest high.
//
// Exit all positions at the Close after
// three days.

SetTradeDelays(0,0,0,0);

PriorLow = Ref(LLV(L,3),-1);
PriorHigh = Ref(HHV(H,3),-1);

BuyPrice = Min(PriorLow, Open);
SellPrice = Close;
ShortPrice = Max(PriorHigh, Open);
CoverPrice = Close;

FourDayLow = LFourDayHigh = H>PriorHigh;

Buy = FourDayLow AND DayOfWeek()==3; // Wednesday
Sell = BarsSince(Buy)>=3;

Short = FourDayHigh AND DayOfWeek()==1; // Monday
Cover = BarsSince(Short)>=3;

**
// BuyMultiDayLow.afl
//
// AmiBroker code for a trading system
// that buys when the low of the day
// is lower than a multi-day low.
//
// BPSwitch chooses the BuyPrice to be either
// Close or PriorLow
// 0 == Prior Low; 1 == Close
BPSwitch = Optimize("BPSwitch",0,0,1,1);

// LLBBars determines how many days in the
// long multi-day look-back
LLBBars = Optimize("LLBBars",3,1,10,1);

// HoldDays determines how many days to
// hold the long position
LHoldDays = Optimize("LHoldDays",1,0,10,1);

// BuyDOW chooses which day of the week to buy.
// DayOfWeek() == 1 on Monday, 2 on Tuesday, ...
BuyDOW = Optimize("BuyDOW",2,1,5,1);


SetTradeDelays(0,0,0,0);
SellPrice = C;

PriorLow = Ref(LLV(L,LLBBars),-1);

BuyPrice = IIf(BPSwitch==1,C,PriorLow);

MultiDayLow = L< p=""><>

Buy = MultiDayLow AND DayOfWeek()==BuyDOW;
Sell = BarsSince(Buy)>=LHoldDays;
**

// SellMultiDayHigh.afl
//
// AmiBroker code for a trading system
// that sells when the high of the day
// is higher than a multi-day high.
//
// SPSwitch chooses the ShortPrice to be either
// Close or PriorHigh
// 0 == PriorHigh; 1 == Close
SPSwitch = Optimize("SPSwitch",1,0,1,1);

// SLBBars determines how many days in the
// short multi-day look-back
SLBBars = Optimize("SLBBars",10,1,10,1);

// SHoldDays determines how many days to
// hold the short position
SHoldDays = Optimize("SHoldDays",3,0,10,1);

// SellDOW chooses which day of the week to sell.
// DayOfWeek() == 1 on Monday, 2 on Tuesday, ...
SellDOW = Optimize("SellDOW",2,1,5,1);

SetTradeDelays(0,0,0,0);
CoverPrice = C;

PriorHigh = Ref(HHV(H,SLBBars),-1);

ShortPrice = IIf(SPSwitch==1,C,PriorHigh);

MultiDayHigh = H>PriorHigh;

Short = MultiDayHigh AND DayOfWeek()==SellDOW;
Cover = BarsSince(Short)>=SHoldDays;

Formulas for Symmetrical reversal bars, p. 30.

Symmetrical reversal up pattern (lower opens, higher closes):

1. ABS(H1 - H0) < 0.0625
2. ABS(L1 - L0) < 0.0625
3. (O1-L1)/(H1-L1) > 0.50
4. (C1-L1)/(H1-L1) < 0.50
5. (O0-L0)/(H0-L0) < 0.50
6. (C0-L0)/(H0-L0) > 0.50

where

O = open of the day
L = low of the day
H = high of the day
C = close of the day
ABS = absolute value
Subscripts0,1.., denote today, one day ago, etc.

Note: T-note prices trade in 32nds and halves of 32nds; prices have been converted to decimal equivalents for all the calculations.

Symmetrical reversal down pattern (higher opens, lower closes):

1. ABS(H1 - H0) < 0.0625
2. ABS(L1 - L0) < 0.0625
3. (O1-L1)/(H1-L1) < 0.50
4. (C1-L1)/(H1-L1) > 0.50
5. (O0-L0)/(H0-L0) > 0.50
6. (C0-L0)/(H0-L0) < 0.50

Back to top


February 2008

Treasury patterns

Bullish 1 (lower opens, higher closes):

1. ABS(H1 - H0) < 0.0625
2. ABS(L1 - L0) < 0.0625
3. (O1-L1)/(H1-L1) > 0.50
4. (C1-L1)/(H1-L1) < 0.50
5. (O0-L0)/(H0-L0) < 0.50
6. (C0-L0)/(H0-L0) > 0.50

where

O = open of the day
L = low of the day
H = high of the day
C = close of the day
ABS = absolute value
Subscripts0,1.., denote today, one day ago, etc.

Note: T-note prices trade in 32nds and halves of 32nds; prices have been converted to decimal equivalents for all the calculations.

Pattern definition 1 ("Bullish 2"):

1. ABS(H1 - H0) < 0.0625
2. ABS(L1 - L0) < 0.0625
3. (O1-L1)/(H1-L1) > 0.66
4. (C1-L1)/(H1-L1) < 0.33
5. (O0-L0)/(H0-L0) < 0.33
6. (C0-L0)/(H0-L0) > 0.66

Pattern definition 2 ("Bullish 3"):

1. ABS(H1 - H0) < 0.03125
2. ABS(L1 - L0) < 0.03125
3. (O1-L1)/(H1-L1) > 0.66
4. (C1-L1)/(H1-L1) < 0.33
5. (O0-L0)/(H0-L0) < 0.33
6. (C0-L0)/(H0-L0) > 0.66

Bearish patterns

Bearish 1 (higher opens, lower closes):

1. ABS(H1 - H0) < 0.0625
2. ABS(L1 - L0) < 0.0625
3. (O1-L1)/(H1-L1) < 0.50
4. (C1-L1)/(H1-L1) > 0.50
5. (O0-L0)/(H0-L0) > 0.50
6. (C0-L0)/(H0-L0) < 0.50

Pattern definition 1 ("Bearish 2"):

1. ABS(H1 - H0) < 0.0625
2. ABS(L1 - L0) < 0.0625
3. (O1-L1)/(H1-L1) < 0.66
4. (C1-L1)/(H1-L1) > 0.33
5. (O0-L0)/(H0-L0) > 0.33
6. (C0-L0)/(H0-L0) < 0.66

Pattern definition 2 ("Bearish 3"):

1. ABS(H1 - H0) < 0.03125
2. ABS(L1 - L0) < 0.03125
3. (O1-L1)/(H1-L1) < 0.66
4. (C1-L1)/(H1-L1) > 0.33
5. (O0-L0)/(H0-L0) > 0.33
6. (C0-L0)/(H0-L0) < 0.66

Euro/U.S. dollar currency pair (USD/EUR) patterns:

Bullish 1 (lower opens, higher closes):

1. ABS(H1 - H0) < 0.0002
2. ABS(L1 - L0) < 0.0002
3. (O1-L1)/(H1-L1) > 0.50
4. (C1-L1)/(H1-L1) < 0.50
5. (O0-L0)/(H0-L0) < 0.50
6. (C0-L0)/(H0-L0) > 0.50

Pattern definition 1 ("Bullish 2"):

1. ABS(H1 - H0) < 0.0002
2. ABS(L1 - L0) < 0.0002
3. (O1-L1)/(H1-L1) > 0.66
4. (C1-L1)/(H1-L1) < 0.33
5. (O0-L0)/(H0-L0) < 0.33
6. (C0-L0)/(H0-L0) > 0.66

Pattern definition 2 ("Bullish 3"):

1. ABS(H1 - H0) < 0.0001
2. ABS(L1 - L0) < 0.0001
3. (O1-L1)/(H1-L1) > 0.66
4. (C1-L1)/(H1-L1) < 0.33
5. (O0-L0)/(H0-L0) < 0.33
6. (C0-L0)/(H0-L0) > 0.66

Bearish patterns

Bearish 1 (higher opens, lower closes):

1. ABS(H1 - H0) < 0.0002
2. ABS(L1 - L0) < 0.0002
3. (O1-L1)/(H1-L1) < 0.50
4. (C1-L1)/(H1-L1) > 0.50
5. (O0-L0)/(H0-L0) > 0.50
6. (C0-L0)/(H0-L0) < 0.50

Pattern definition 1 ("Bearish 2"):

1. ABS(H1 - H0) < 0.0002
2. ABS(L1 - L0) < 0.0002
3. (O1-L1)/(H1-L1) < 0.66
4. (C1-L1)/(H1-L1) > 0.33
5. (O0-L0)/(H0-L0) > 0.33
6. (C0-L0)/(H0-L0) < 0.66

Pattern definition 2 ("Bearish 3"):

1. ABS(H1 - H0) < 0.0001
2. ABS(L1 - L0) < 0.0001
3. (O1-L1)/(H1-L1) < 0.66
4. (C1-L1)/(H1-L1) > 0.33
5. (O0-L0)/(H0-L0) > 0.33
6. (C0-L0)/(H0-L0) < 0.66

Back to top

March 2008


Mechanica code

Stop-and-reverse system (run using Simultest)

SYSTEM = 1
COL1 = MAX[H,80,1]
COL2 = MIN[L,80,1]
COL3 = ATR[20]
COL4 = CLOSE
SIZING[1] = COL3[1] * POINTVALUE[1]

STARTDATE = 19840101
'IF CLOSE[1] > COL1[1] THEN BUYOPEN
BUYSTOP = COL1[1]

'IF LONG > 0 AND CLOSE[1] < COL2[1] THEN SELLOPEN
IF LONG > 0 THEN SELLSTOP = COL2[1]

SYSTEM = 2
COL1 = MAX[H,80,1]
COL2 = MIN[L,80,1]
COL3 = ATR[20]
SIZING[1] = COL3[1] * POINTVALUE[1]

STARTDATE = 19840101
'IF CLOSE[1] < COL2[1] THEN SELLOPEN
SELLSTOP = COL2[1]

'IF SHORT > 0 AND CLOSE[1] > COL1[1] THEN BUYOPEN
IF SHORT > 0 THEN BUYSTOP = COL1[1]

Revised system

SYSTEM = 1
COL1 = MAX[H,80,1]
COL2 = MIN[L,80,1]
COL3 = MAX[H,20,1]
COL4 = MIN[L,20,1]
COL5 = ATR[20]
SIZING[1] = COL5[1] * POINTVALUE[1]

STARTDATE = 19840101
BUYSTOP = COL1[1]
SELLSTOP = COL2[1]

IF LONG > 0 THEN SELLSTOP = COL4[1]
IF SHORT > 0 THEN BUYSTOP = COL3[1]

Money management code (both systems)

STARTDATE = 19840101
STARTUPCASH = 1000000
NEWCONTRACTS = (TOTALEQUITY * .02) / NEWRISK

Back to top

May 2008 "System death: When good systems go bad"

Mechanica code

55-21 breakout system

SYSTEM = 1
COL1 = HIGH[55]
COL2 = LOW[21]
COL3 = LOW[55]
COL4 = HIGH[21]
COL5 = CLOSE
COL6 = ATR[1]
COL7 = EMA[COL6,15]
SIZING[1] = POINTVALUE * COL7

'Entry Code
IF CLOSE[1] > COL1[1] THEN BUYOPEN
IF CLOSE[1] < COL3[1] THEN SELLOPEN

'Exit Code
IF LONG > 0 THEN SELLSTOP = COL2[1]
IF SHORT > 0 THEN BUYSTOP = COL4[1]

80-20 MA crossover system
SYSTEM = 2

COL1 = CLOSE
COL2 = EMA[COL1,20]
COL3 = EMA[COL1,80]
COL6 = ATR[1]
COL7 = EMA[COL6,15]
SIZING[1] = POINTVALUE * COL7

'Entry Code
IF COL2[1] > COL3[1] THEN BUYOPEN

'Exit Code
IF LONG > 0 AND DAYSINTRADE = 1 THEN MEMORY[1] = COL2[1] - 4 * COL7[1]
IF LONG > 0 AND DAYSINTRADE > 1 THEN SELLSTOP = MEMORY[1]
IF LONG > 0 AND COL2[1] < COL3[1] THEN SELLOPEN

SYSTEM = 1
COL1 = CLOSE
COL2 = EMA[COL1,20]
COL3 = EMA[COL1,80]
COL6 = ATR[1]
COL7 = EMA[COL6,15]
SIZING[1] = POINTVALUE * COL7

'Entry Code
IF COL2[1] < COL3[1] THEN SELLOPEN

'Exit Code
IF SHORT > 0 AND DAYSINTRADE = 1 THEN MEMORY[1] = COL2[1] + 4 * COL7[1]
IF SHORT > 0 AND DAYSINTRADE > 1 THEN BUYSTOP = MEMORY[1]
IF SHORT > 0 AND COL2[1] > COL3[1] THEN BUYOPEN

Money management code (both systems)

STARTDATE = 19860101
STARTUPCASH = 1500000
NEWCONTRACTS = (.005 * TOTALEQUITY) / SIZING[1]

Back to top



February 2009

TradeStation code for Joe Krutsinger's "Trading late-day breakouts" in the February 2009 issue of Active Trader.

Inputs: StopLossAmt(500),Tim(1330);

If time >=Tim and Time<=Tim+59
    and TradesToday(date)<1 then begin

 If MarketPosition<>1 then Buy next bar at HighD(0) stop;
 
If MarketPosition<>-1 then Sell short next bar at LowD(0) stop;
 
end;
 
If StopLossAmt > 0 then
    SetStopLoss( StopLossAmt );

SetStopShare;
SetExitOnClose ;


SEPARATE TRADESTODAY FUNCTION:

[LegacyColorValue = true];
 
{
User Function: TradesToday
 
Inputs : Target date.
Returns: Number of entries on specified date.
Properties
  [ ] Auto Detect
  [*] Simple
  [ ] Series
 
Sample Usage :
  if (TradesToday(Date[0]) >= 2)
    then EntryOK = FALSE ;
or
  if (Condition1 and Condition2 and TradesToday(Date[0]) < 2)
  then begin
    { ... do something here ... }
  end ;
 
Provided by Product Support Dept.
         of Omega Research, Inc.
}
 
Inputs: Date0(NumericSimple) ;
Vars  : Loop(0), Cnt(0) ;
 
Cnt = 0 ;
for Loop = 0 to 10 begin
  if (EntryDate(Loop) = Date0)
    then Cnt = Cnt + 1 ;
end ; { next Loop }
 
TradesToday = Cnt ;

May 2009

TradeStation code for Emilio Tomasini’s and Urban Jaekle’s “Controlling risk in a seasonal strategy” in the May 2009 issue of Active Trader.

[LegacyColorValue = true];

{Copyright Urban Jäkle,

Some facts about the system:

1) Only end of day data is needed,
2) It produces long entries for any stock index futures market,
e.g. S&P 500, Nasdaq 100 , Russell 2000, EuroStoxx, DAX, Nikkei 225, Hang Seng, KOSPI, SMI, etc.
3) All trades are exited after a hold period of 4 days or if not stopped out before by any applied exits.
4) This code includes a volatility based stop, but no other stop-losses or profit targets.

{__________________The two inputs_________________________}

{1. How long to stay in the market: DaysInMarket(4), }
{ 2. Distance for the ATR based stop: Percentage(0.65), }

Inputs: DaysInMarket(4), Percentage(0.65) ;
Variables: StopDistance(0), LiquidationPoint(0);

StopDistance= Percentage*Average(Range,8);
LiquidationPoint=Close-StopDistance;  {Setting the ATR based stop}

{__________Entry: Go long on the Close of the last day of each month_______________}

If
   
(DayOfMonth(Date)=29 AND DayOfWeek(Date)=5) OR
(DayOfMonth(Date)=30 AND
(Month(Date)=4 OR Month(Date)=6 OR Month(Date)=9 OR Month(Date)=11))
 OR
DayOfMonth(Date)=31 OR

(DayOfMonth(Date)=28 AND Month(Date)=2) OR

(DayOfMonth(Date)=28 AND (Month(Date)=4 OR Month(Date)=6 OR Month(Date)=9 OR Month(Date)=11) AND DayOfWeek(Date)=5)

OR (DayOfMonth(Date)=30 AND DayOfWeek(Date)=5)
OR (DayOfMonth(Date)=29 AND Month(Date)=2)
OR (DayOfMonth(Date)=27 AND Month(Date)=2 AND DayOfWeek(Date)=5)
OR (DayOfMonth(Date)=26 AND Month(Date)=2 AND DayOfWeek(Date)=5)

then Buy("BuyDay") this bar on close;

{__________And finally the exit ___________}

Sell("IniStop") next bar at LiquidationPoint stop; {The average range based stop}

If BarsSinceEntry=DaysInMarket then Sell this bar on close;

{Exit each trade latest after 4 days at close}

Back to top



Code for Markos Katsanos’ “Intermarket soybean strategy” in the May 2009 issue of Active Trader.

Regression Divergence indicator

D1:=Input("DAYS FOR DIV" ,1 ,1000 ,100 ); D3:=Input("DAYS FOR IM" ,1 ,1000 ,150);
SEC2:=Security("C:Metastock DataREUTERSFUTURES@:Cc1",C);
b:=Correl(C,SEC2,D1,0)*Stdev(C,D1)/(Stdev(SEC2,D1)+.001);
a:=Mov(C,D1,S)-b*Mov(SEC2,D1,S);
pred:=b*SEC2+a;DIVERG:=Mov((PRED-C),3,E);
(Mov( DIVERG - LLV(DIVERG,D3), 3,S) * 100)/(Mov( HHV(DIVERG,D3) - LLV(DIVERG,D3), 3,S)+.01 )

METASTOCK CODE FOR THE SOYBEAN INTERMARKET SYSTEM

Soybean Intermarket divergence system Copyright Markos Katsanos 2009
To recreate the tests click on enhanced system tester, click on new system and type the buy, sell, short and buy to cover code. To run the test, click on new simulation, add securities, and select the Soybean Pit Futures Continuous (Reuters Symbol:@:3Sc1).Then select periodicity daily, click on next and select Default size: 50 units. Then click on trade execution, uncheck realistic market prices, select buy price and sell price at close with 1 day delay and fill in the commissions of $100 per transaction. 
You will need also to change the first two lines of the code to point to the appropriate folder in your hard drive where the data for Soybean Oil and Corn continuous contacts are located.
If you wish to replicate the test please keep in mind that for the test to begin producing any signals, the indicators used should be first calculated and this requires at least 360 extra bars (514 calendar days) to be loaded. 

Buy
SEC1:=Security("C:Metastock DataREUTERSFUTURES@:BOc1",C);
SEC2:=Security("C:Metastock DataREUTERSFUTURES@:Cc1",C);
b:=Correl(C,SEC2,100,0)*Stdev(C,100)/(Stdev(SEC2,100)+.001); a:=mov(C,100,S)-b*MOV(SEC2,100,S); pred:=b*SEC2+a;DIVERG:=MOV((PRED-C),3,E);
IMC:=(Mov( DIVERG - LLV(DIVERG,200), 3,S) * 100)/(Mov( HHV(DIVERG,200) - LLV(DIVERG,200), 3,S)+.01 ); b1:=Correl(C,SEC1,150,0)*Stdev(C,150)/(Stdev(SEC1,150)+.001); a1:=mov(C,150,S)-b1*MOV(SEC1,150,S);
pred1:=b1*SEC1+a1;DIVERG1:=MOV((PRED1-C),3,E);
IMS:=(Mov( DIVERG1 - LLV(DIVERG1,200), 3,S) * 100)/(Mov( HHV(DIVERG1,200) - LLV(DIVERG1,200), 3,S)+.01 ); IMAX:=MAX(IMC,IMS);

HHV(IMAX,5)>85 AND CROSS(80, IMAX)  AND STOCH(15,3)>MOV(STOCH(15,3),4,S) AND ROC(C,2,%)>1

Sell
SEC1:=Security("C:Metastock DataREUTERSFUTURES@:BOc1",C);
SEC2:=Security("C:Metastock DataREUTERSFUTURES@:Cc1",C);
b:=Correl(C,SEC2,100,0)*Stdev(C,100)/(Stdev(SEC2,100)+.001); a:=mov(C,100,S)-b*MOV(SEC2,100,S); pred:=b*SEC2+a;DIVERG:=MOV((PRED-C),3,E);
IMC:=(Mov( DIVERG - LLV(DIVERG,200), 3,S) * 100)/(Mov( HHV(DIVERG,200) - LLV(DIVERG,200), 3,S)+.01 ); b1:=Correl(C,SEC1,150,0)*Stdev(C,150)/(Stdev(SEC1,150)+.001); a1:=mov(C,150,S)-b1*MOV(SEC1,150,S);
pred1:=b1*SEC1+a1;DIVERG1:=MOV((PRED1-C),3,E);
IMS:=(Mov( DIVERG1 - LLV(DIVERG1,200), 3,S) * 100)/(Mov( HHV(DIVERG1,200) - LLV(DIVERG1,200), 3,S)+.01 ); IMIN:=MIN(IMC,IMS);

LLV(IMIN,7)<20  AND IMIN>LLV(IMIN,7)+10

Sell Short
SEC1:=Security("C:Metastock DataREUTERSFUTURES@:BOc1",C);
SEC2:=Security("C:Metastock DataREUTERSFUTURES@:Cc1",C);
b:=Correl(C,SEC2,100,0)*Stdev(C,100)/(Stdev(SEC2,100)+.001); a:=mov(C,100,S)-b*MOV(SEC2,100,S); pred:=b*SEC2+a;DIVERG:=MOV((PRED-C),3,E);
IMC:=(Mov( DIVERG - LLV(DIVERG,200), 3,S) * 100)/(Mov( HHV(DIVERG,200) - LLV(DIVERG,200), 3,S)+.01 ); b1:=Correl(C,SEC1,150,0)*Stdev(C,150)/(Stdev(SEC1,150)+.001); a1:=mov(C,150,S)-b1*MOV(SEC1,150,S);
pred1:=b1*SEC1+a1;DIVERG1:=MOV((PRED1-C),3,E);
IMS:=(Mov( DIVERG1 - LLV(DIVERG1,200), 3,S) * 100)/(Mov( HHV(DIVERG1,200) - LLV(DIVERG1,200), 3,S)+.01 ); IMIN:=MIN(IMC,IMS);

 LLV(IMIN,5) <10 AND CROSS(IMIN,15) AND STOCH(15,3)
Buy to Cover
SEC1:=Security("C:Metastock DataREUTERSFUTURES@:BOc1",C);
SEC2:=Security("C:Metastock DataREUTERSFUTURES@:Cc1",C);
b:=Correl(C,SEC2,100,0)*Stdev(C,100)/(Stdev(SEC2,100)+.001); a:=mov(C,100,S)-b*MOV(SEC2,100,S); pred:=b*SEC2+a;DIVERG:=MOV((PRED-C),3,E);
IMC:=(Mov( DIVERG - LLV(DIVERG,200), 3,S) * 100)/(Mov( HHV(DIVERG,200) - LLV(DIVERG,200), 3,S)+.01 ); b1:=Correl(C,SEC1,150,0)*Stdev(C,150)/(Stdev(SEC1,150)+.001); a1:=mov(C,150,S)-b1*MOV(SEC1,150,S);
pred1:=b1*SEC1+a1;DIVERG1:=MOV((PRED1-C),3,E);
IMS:=(Mov( DIVERG1 - LLV(DIVERG1,200), 3,S) * 100)/(Mov( HHV(DIVERG1,200) - LLV(DIVERG1,200), 3,S)+.01 ); IMAX:=MAX(IMC,IMS);

HHV(IMAX,7)>70 AND IMAX
METASTOCK CODE FOR THE SOYBEAN COMBO SYSTEM

Buy
SEC1:=Security("C:Metastock DataREUTERSFUTURES@:BOc1",C);
SEC2:=Security("C:Metastock DataREUTERSFUTURES@:Cc1",C);
SEC3:=Security("C:Metastock dataREUTERSFOREX.DXY",C);
SEC4:=Security("C:Metastock dataREUTERSINDEX.CRB",C);
b:=Correl(C,SEC2,100,0)*Stdev(C,100)/(Stdev(SEC2,100)+.001); a:=mov(C,100,S)-b*MOV(SEC2,100,S); pred:=b*SEC2+a;DIVERG:=MOV((PRED-C),3,E); IMC:=(Mov( DIVERG - LLV(DIVERG,200), 3,S) * 100)/(Mov( HHV(DIVERG,200) - LLV(DIVERG,200), 3,S)+.01 ); b1:=Correl(C,SEC1,150,0)*Stdev(C,150)/(Stdev(SEC1,150)+.001); a1:=mov(C,150,S)-b1*MOV(SEC1,150,S); pred1:=b1*SEC1+a1;DIVERG1:=MOV((PRED1-C),3,E); IMS:=(Mov( DIVERG1 - LLV(DIVERG1,200), 3,S) * 100)/(Mov( HHV(DIVERG1,200) - LLV(DIVERG1,200), 3,S)+.01 ); IMAX:=MAX(IMC,IMS);

(HHV(IMAX,5)>85 AND CROSS(80, IMAX)  AND STOCH(15,3)>MOV(STOCH(15,3),4,S) AND ROC(C,2,%)>1 ) OR (CROSS(MOV(C,10,E),MOV(C,80,E)) AND MOV(C,10,E)>REF(MOV(C,80,E),-1) AND MOV(SEC3,50,E)REF(MOV(SEC4,50,E),-1))

Sell
SEC1:=Security("C:Metastock DataREUTERSFUTURES@:BOc1",C);
SEC2:=Security("C:Metastock DataREUTERSFUTURES@:Cc1",C);
b:=Correl(C,SEC2,100,0)*Stdev(C,100)/(Stdev(SEC2,100)+.001); a:=mov(C,100,S)-b*MOV(SEC2,100,S); pred:=b*SEC2+a;DIVERG:=MOV((PRED-C),3,E);
IMC:=(Mov( DIVERG - LLV(DIVERG,200), 3,S) * 100)/(Mov( HHV(DIVERG,200) - LLV(DIVERG,200), 3,S)+.01 ); b1:=Correl(C,SEC1,150,0)*Stdev(C,150)/(Stdev(SEC1,150)+.001); a1:=mov(C,150,S)-b1*MOV(SEC1,150,S);
pred1:=b1*SEC1+a1;DIVERG1:=MOV((PRED1-C),3,E);
IMS:=(Mov( DIVERG1 - LLV(DIVERG1,200), 3,S) * 100)/(Mov( HHV(DIVERG1,200) - LLV(DIVERG1,200), 3,S)+.01 ); IMIN:=MIN(IMC,IMS);

LLV(IMIN,7)<20  AND IMIN>LLV(IMIN,7)+10 OR C
Sell Short
SEC1:=Security("C:Metastock DataREUTERSFUTURES@:BOc1",C);
SEC2:=Security("C:Metastock DataREUTERSFUTURES@:Cc1",C);
SEC3:=Security("C:Metastock DataREUTERSFOREX.DXY",C);
SEC4:=Security("C:Metastock DataREUTERSINDEX.CRB",C);
 b:=Correl(C,SEC2,100,0)*Stdev(C,100)/(Stdev(SEC2,100)+.001); a:=mov(C,100,S)-b*MOV(SEC2,100,S); pred:=b*SEC2+a;DIVERG:=MOV((PRED-C),3,E);
IMC:=(Mov( DIVERG - LLV(DIVERG,200), 3,S) * 100)/(Mov( HHV(DIVERG,200) - LLV(DIVERG,200), 3,S)+.01 ); b1:=Correl(C,SEC1,150,0)*Stdev(C,150)/(Stdev(SEC1,150)+.001); a1:=mov(C,150,S)-b1*MOV(SEC1,150,S);
pred1:=b1*SEC1+a1;DIVERG1:=MOV((PRED1-C),3,E);IMS:=(Mov( DIVERG1 - LLV(DIVERG1,200), 3,S) * 100)/(Mov( HHV(DIVERG1,200) - LLV(DIVERG1,200), 3,S)+.01 ); IMIN:=MIN(IMC,IMS);
LLV(IMIN,5) <10 AND CROSS(IMIN,15) AND STOCH(15,3)OR (CROSS(MOV(C,80,E),MOV(C,10,E)) AND MOV(C,10,E)REF(MOV(SEC3,50,E),-1)  AND MOV(SEC4,50,E)
Buy to Cover
SEC1:=Security("C:Metastock DataREUTERSFUTURES@:BOc1",C);
SEC2:=Security("C:Metastock DataREUTERSFUTURES@:Cc1",C);
b:=Correl(C,SEC2,100,0)*Stdev(C,100)/(Stdev(SEC2,100)+.001); a:=mov(C,100,S)-b*MOV(SEC2,100,S); pred:=b*SEC2+a;DIVERG:=MOV((PRED-C),3,E);
IMC:=(Mov( DIVERG - LLV(DIVERG,200), 3,S) * 100)/(Mov( HHV(DIVERG,200) - LLV(DIVERG,200), 3,S)+.01 ); b1:=Correl(C,SEC1,150,0)*Stdev(C,150)/(Stdev(SEC1,150)+.001); a1:=mov(C,150,S)-b1*MOV(SEC1,150,S);
pred1:=b1*SEC1+a1;DIVERG1:=MOV((PRED1-C),3,E);
IMS:=(Mov( DIVERG1 - LLV(DIVERG1,200), 3,S) * 100)/(Mov( HHV(DIVERG1,200) - LLV(DIVERG1,200), 3,S)+.01 ); IMAX:=MAX(IMC,IMS);

HHV(IMAX,7)>70 AND IMAXREF(MOV(C,5,S),-1)+3*ATR(10)


EXPERT ADVISOR

To avoid the tedious task of running the tests every day to check if there are new signals, you can create an expert advisor and attach it to the Soybean futures chart.
To create the expert advisor click on the appropriate icon then click on new, and fill in an appropriate name (e.g. Soybean Intermarket & Seasonal Systems) in the name field and fill in the following in the Notes field: “see  the following article, “Intermarket soybean system” by Markos Katsanos published in the May 2009 issue of Active Trader.” Then click on symbols, select the appropriate action (e.g. BUY Intermarket) and fill in the same code that you used for the test above. Then click on Graphic and select an appropriate graphic (e.g. green arrow below price plot).
The same procedure should be repeated for the Sell, Short and Buy to cover codes for both systems.

TRANSLATING METASTOCK CODE IN OTHER LANGUAGES
The following points should be kept in mind when translating the code above in other languages (e.g. easy language or TradersSudio) and trying to replicate my results

1) Metastock closes existing positions if an opposite signal is triggered. The sell conditions are in addition to the short conditions and the buy to cover conditions are in addition to the buy conditions. So for example if a short condition is triggered while the system is still long the trade is reversed. When translating metastock code to other software the Buy conditions should be added to the Buy to Cover conditions and similarly the Sell Short conditions should be added to the Sell (long Exit conditions)

2) Test results may vary according to your data provider and the method used to create continuous contracts. For the tests above I used the following data from Reuters: Soybeans Pit continuous (@:3Sc1) and Soybean oil Composite continuous (@:BOc1), Corn Composite continuous (@:Cc1), and Dollar Index (.DXY) for the Intermarket securities

3) Metastock uses the population formula (it divides by N and not N-1) to calculate the standard deviation, which is the same with the STDEVP in Excel and not STDEV. In order to produce the same results with metastock you should multiply the sample standard deviation STDEV by SQRT(N-1/N)

4) Metastock has no futures testing capability so I tested Soybeans like a like a stock buying 50 units (the point value) when long the amount and selling 50 units when short.

Back to top



June 2009

 

TradeStation code for “System design, part 5: Searching for the exit,” in the June 2009 issue of Active Trader.

 

 

Entry rule

{Notes: The “L2Lmove” variable represents the difference between the most recent low and the low two bars earlier.}

inputs: dropsize(.021);

if low < low[1]

and low[1] < low[2]

and high < high[1]

and high[1] < high[2]

and close < close[1]

and close[1] < close[2]

and close[2] < close[3]

and (low[2] - low)/low[2] > dropsize

then

sell next bar at the open;

 

Momentum indicator exit rule

{Notes: The “Length” input represents the look-back period for the momentum calculation; the “SellThresh” input represents the level the momentum calculation must meet or exceed to the upside to indicate an “overbought” condition and a sell signal.}

inputs: Length(32), SellThresh(.62);

Value1 =  (close today-lowest(low,length))/(highest(high,length)-lowest(low,length));

If MarketPosition >=1 and

BarsSinceEntry >1 and

Value1 >= OBThresh then

sell next bar at the open;

 

 

AmiBroker code

 

SetTradeDelays( 0, 0, 1, 1 );

 

Length = 7; // this is the momentum lookback period.

 

SellThres = 0.75; //this is the overbought sell value for momentum

 

L2LMove = -0.021; // this is the drop amount

 

Length = Optimize( "length", 7, 5, 20, 5); // Optimizing Momentum lookback period daf =7, min=5, max=20, step=1

 

SellThres = Optimize( "sellthres", 0.75, 0.50, 1, 0.10); // Optimizing Mom Sell Threshold def =0.75, min=0.50, max=1,step 0.10

 

//L2Lmove = Optimize( "L2LMove", 0.021, 0.01, 0.04, 0.01); //Optimizing drop amount def=2.1%, min 1%, max=4%, step =1%%

 

MyMomentum = ( ( Close - LLV ( Low , Length ) ) / ( HHV ( High , Length )- LLV ( Low , Length ) ) ) ;

 

Buy = Low < Ref( Low , -1 )

 

AND Ref( Low , -1 ) < Ref( Low, -2 )

 

ANDHigh < Ref( High, -1 )

 

AND Ref( High , -1 ) < Ref( High, -2 )

 

ANDClose < Ref( Close, -1 )

 

AND Ref( Close , -1 ) < Ref( Close, -2 )

 

AND Ref( Close , -2 ) < Ref( Close, -3 )

 

AND ( ( (Low - Ref( Low , -2 ))/ Ref( Low , -2)) <= L2LMove );

 

 

SetOption( "MaxOpenPositions", 5 );

 

SetOption( "InitialEquity", 50000 );

 

PositionSize = -100;

 

// removed n-bar stop

 

Sell = MyMomentum >= SellThres;

 

Short = 0;

 

Cover = 0;

 

Back to top


July 2009

 

TradeStation code for “Trading system design, part 6: Adjusting to reality,” in the July issue of Active Trader

 

Entry rule

 

Trade entry initially occurred after a series of three consecutive 

lower closes, two consecutive lower highs and lower lows and a 

certain percentage-size

drop from the low two days ago to the most recent low:

 

If low < low[1]

and low[1] < low[2]

and high < high[1]

and high[1] < high[2]

and close < close[1]

and close[1] < close[2]

and close[2] < close[3]

and (low[2] - low)/low[2] >= percent

then buy tomorrow at the open;

 

These rules were modified based on the initial test results to:

 

if low < low[1]

and low[1] < low[2]

and high < high[1]

and high[1] < high[2]

and close < close[1]

and close[1] < close[2]

and close[2] < close[3]

and (low[2] - low)/low[2] >= median(TrueRange(10))

Then buy today at the close

 

Momentum indicator exit rule

{Notes: The “Length” input represents the look-back period for the momentum calculation; the “SellThresh” input represents the level the momentum calculation must meet or exceed to the upside to indicate an “overbought” condition and a sell signal.}

inputs: Length(32), SellThresh(.62);

Value1 =  (close today-lowest(low,length))/(highest(high,length)-lowest(low,length));

If MarketPosition >=1 and

BarsSinceEntry >1 and

Value1 >= OBThresh then

sell next bar at the open;


Back to top

September 2009

 

TradeStation code for “Three-day pullback volatility setup,” by Johnan Prathap in the September issue of Active Trader


Volatility function
Inputs: Length(NumericSimple);

If CurrentBar >= 1 AND Length <> 0 Then Begin
    If CurrentBar = 1 Then
        Volatility = TrueRange
    Else
        Volatility = ((Length - 1) * Volatility[1] + TrueRange) / Length;
End;

TrueRange function
TrueRange = Truehigh - TrueLow

Truehigh function
If Close[1] > high then Truehigh = Close[1] Else Truehigh = high;

Truelow
If Close[1] < low then Truelow = Close[1] Else Truelow = Low;

Long-only system
Inputs: Length(18), Tar(12), Stp(5);
var: vol(0), mp(0), hi(0),hi2(0);
vol = Volatility(Length) ;
mp = marketposition;

Condition1= Vol > vol[1] and vol[1] > vol[2] and vol[2] < vol[3] and low
if mp = 0 and condition1 then buy next bar at Open;

If mp = 1 then begin
Sell ("%TEX")next bar at entryprice+(entryprice*Tar/100) Limit;
Sell ("%StopEX")next bar at entryprice-(entryprice*Stp/100) Stop;
end;

Short-only system
Inputs: Length(42), Tar(12), Stp(5);
var: vol(0), mp(0), hi(0),hi2(0);
vol = Volatility(Length) ;
mp = marketposition;

Condition1= Vol < vol[1] and vol[1] < vol[2] and vol[2] > vol[3] and high > high[1] and high[1]> high[2] and high[2]>high[3] ;

if mp = 0 and condition1 then SellShort next bar at Open;

If mp = -1 then begin
buytocover ("%TEX")next bar at entryprice-(entryprice*Tar/100) Limit;
buytocover ("%StopEX")next bar at entryprice+(entryprice*Stp/100) Stop;
end;

Back to top

December 2009 issue, "From cliché to strategy" by  Kevin J. Davey, TradeStation code:

Strategy #1:
input: xATR(1);

//ENTRY RULES
if closesellshort next bar at market;
   
if close>close[1] and marketposition=0  then
buy next bar at market;

//EXIT RULE - LOSS
if openpositionprofit<0 then begin
    sell next bar at market;
    buytocover next bar at market;
end;

//EXIT RULE - PROFIT
if openpositionprofit>BigPointValue*xATR*AvgTrueRange(14) then begin
    sell next bar at market;
    buytocover next bar at market;
end;

Strategy #2:
//ENTRY RULES
if closesellshort next bar at market;
   
if close>close[1] and marketposition=0  then
buy next bar at market;

//EXIT RULE - LOSS
if openpositionprofit<0 then begin
    sell next bar at market;
    buytocover next bar at market;
end;

//EXIT RULE - PROFIT
if marketposition=1 and close>close[1] and close[1]>close[2] and close[2]>close[3] then
 sell next bar at market;

if marketposition=-1 and closebuytocover next bar at market;

Strategy #3:
input: yATR(1);

//ENTRY RULES
if closesellshort next bar at market;
   
if close>close[1] and marketposition=0  then
buy next bar at market;

//EXIT LOSS RULE 1
if openpositionprofit<0  then begin
    if close>close[1] and close[1]>close[2] then sell next bar at market;
    if closeend;

//EXIT LOSS RULE 2
if openpositionprofit<-BigPointValue*yATR*AvgTrueRange(14) then begin
    sell next bar at market;
    buytocover next bar at market;
end;

//EXIT RULE - PROFIT
if marketposition=1 and close>close[1] and close[1]>close[2] and close[2]>close[3] then
 sell next bar at market;

if marketposition=-1 and closebuytocover next bar at market;

January 2010 issue, "After testing, before trading" by  Kevin J. Davey:

The “cliché” system trades in the direction of the one-day trend. The entry rules are:

Go long at tomorrow’s open if today’s close is higher than yesterday’s close.   
Sell short at tomorrow’s open if today’s close is lower than yesterday’s close.

The system must be flat (no open positions) to take entry signals, to avoid confusing them with exit signals.

Three sets of exit rules were tested. The first set reflects the adage of cutting losses short and letting profits run:
Exit trade at tomorrow’s open if it is a loser at today’s close.
Exit trade at tomorrow’s open if its profit > x*ATR at today’s close.

Where:
ATR = 14-day average true range
x = ATR multiplier, ranging from 1-10

The second set of exit rules sells into strength:
1.   Exit trade at tomorrow’s open if it is a loser at today’s close.
2.   Exit winning long trade at tomorrow’s open if today’s close > close [1], close [1] > close [2], and close [2] > close [3].
3.   Cover winning short trade at tomorrow’s open if today’s close < close [1], close [1] < close [2], and close [2] < close [3].

Where:
close [1] = yesterday’s close
close [2] = close two days ago
close [3] = close three days ago

A third exit strategy offers losing trades a chance to bounce back: If a trade is underwater, the strategy waits until price closes in the direction of the trade twice in a row. But if the trade’s loss grows large enough, the strategy still needs to exit. To handle these situations, the third strategy adds a stop-loss exit based on the 14-day ATR:

1. Exit long trade at tomorrow’s open if it is a loser at today’s close, today’s close > close [1], and close [1] > close [2].
2. Cover short trade at tomorrow’s open if it is a loser at today’s close, today’s close < close [1], and close [1] < close [2].
3. Exit losing trade at tomorrow’s open if loss > y * ATR at today’s close.
4. Exit winning long trade at tomorrow’s open if today’s close > close [1], close [1] > close [2], and close [2] > close [3].
5. Cover winning short trade at tomorrow’s open if today’s close < close [1], close [1] < close [2], and close [2]< close [3].

Where: y = ATR multiplier ranging from 1-5.

Also,  this Excel spreadsheet can be used to perform a Monte Carlo simulation of trading results.

Back to top
 

March 2010

“Refining crude-oil breakouts” by Kevin J. Davey

Click here to download TradeStation code.

Back to top
 

April 2010

“Improving both ends of a system,” by Kevin Davey

TradeStation code:

//Table 1 code: moving avg cross, stop loss, exit last bar

{ Buys if Price crosses over Avg and then stays above Avg for one or more bars }

inputs: Price( Close ), Length( 30 ), ConfirmBars( 1 ) ;
variables: Counter( 0 ),Counter2( 0 ) ;

if Price > AverageFC( Price, Length ) then
    Counter = Counter + 1
else
    Counter = 0 ;

if CurrentBar > ConfirmBars and Counter = ConfirmBars then
    Buy ( "MACrossLE" ) next bar at market ;



{ Shorts if Price crosses under Avg and then stays below Avg for one or more bars }


if Price < AverageFC( Price, Length ) then
    Counter2 = Counter2 + 1
else
    Counter2 = 0 ;

if CurrentBar > ConfirmBars and Counter2 = ConfirmBars then
    Sell Short ( "MACrossSE" ) next bar at market ;


//stop loss
[IntrabarOrderGeneration = false]
inputs: PositionBasis( false ), Amount( 1 ) ;

if PositionBasis then
    SetStopPosition
else
    SetStopShare ;

SetStopLoss( Amount ) ;


//close position on last bar
   
if marketposition=1 and lastbaronchart then
    sell this bar on close;

if marketposition=-1 and lastbaronchart then
    buytocover this bar on close;

//*******************************************************************
//*******************************************************************
//*******************************************************************
//*******************************************************************
//*******************************************************************
//*******************************************************************
//*******************************************************************
//*******************************************************************
//Table 2 code: add in a profit target to version A

   
{ Buys if Price crosses over Avg and then stays above Avg for one or more bars }
input: profittarget(15000);
var: profExitAt(0);

inputs: Price( Close ), Length( 30 ), ConfirmBars( 1 ) ;
variables: Counter( 0 ),Counter2( 0 ) ;

if Price > AverageFC( Price, Length ) then
    Counter = Counter + 1
else
    Counter = 0 ;

if CurrentBar > ConfirmBars and Counter = ConfirmBars then begin
    Buy ( "MACrossLE" ) next bar at market ;
    ProfExitAt=close+profittarget/bigpointvalue;
end;


{ Shorts if Price crosses under Avg and then stays below Avg for one or more bars }


if Price < AverageFC( Price, Length ) then
    Counter2 = Counter2 + 1
else
    Counter2 = 0 ;

if CurrentBar > ConfirmBars and Counter2 = ConfirmBars then begin
    Sell Short ( "MACrossSE" ) next bar at market ;
    ProfExitAt=close-profittarget/bigpointvalue;
end;


[IntrabarOrderGeneration = false]
inputs: PositionBasis( false ), Amount( 1000 ) ;

if PositionBasis then
    SetStopPosition
else
    SetStopShare ;

SetStopLoss( Amount ) ;


//last bar exit

if marketposition=1 and lastbaronchart then
    sell this bar on close;



if marketposition=-1 and lastbaronchart then
    buytocover this bar on close;

//******************************
   
//profit exit

if close>ProfExitAt and marketposition=1 then     sell next bar at market;
if close
//*******************************************************************
//*******************************************************************
//*******************************************************************
//*******************************************************************
//*******************************************************************
//*******************************************************************
//*******************************************************************
//*******************************************************************
//Table 3A: add in an additional contract at x percent of profit, $1000 per trade loss

   
{ Buys if Price crosses over Avg and then stays above Avg for one or more bars }
input: profittarget(15000);
var: profExitAt(0);

inputs: Price( Close ), Length( 30 ), ConfirmBars( 1 ) ;
variables: Counter( 0 ),Counter2( 0 ) ;

if Price > AverageFC( Price, Length ) then
    Counter = Counter + 1
else
    Counter = 0 ;

if CurrentBar > ConfirmBars and Counter = ConfirmBars then begin
    Buy ( "MACrossLE" ) next bar at market ;
    ProfExitAt=close+profittarget/bigpointvalue;
end;


{ Shorts if Price crosses under Avg and then stays below Avg for one or more bars }


if Price < AverageFC( Price, Length ) then
    Counter2 = Counter2 + 1
else
    Counter2 = 0 ;

if CurrentBar > ConfirmBars and Counter2 = ConfirmBars then begin
    Sell Short ( "MACrossSE" ) next bar at market ;
    ProfExitAt=close-profittarget/bigpointvalue;
end;

   

[IntrabarOrderGeneration = false]
inputs: PositionBasis( false ), Amount( 1000 ) ;

if PositionBasis then
    SetStopPosition
else
    SetStopShare ;

SetStopLoss( Amount ) ;




if marketposition=1 and lastbaronchart then
    sell this bar on close;



if marketposition=-1 and lastbaronchart then
    buytocover this bar on close;

//******************************
   


if close>ProfExitAt and marketposition=1 then     sell next bar at market;
if close


//add contracts if profit is big enough
input:xp(.1);

If openpositionprofit>xp*profittarget and currentcontracts=1 then begin
        if marketposition=1 then buy ("Xtra Buy") next bar at market;
        if marketposition=-1 then sellshort ("Xtra Sell") next bar at market;

    end;

//*******************************************************************
//*******************************************************************
//*******************************************************************
//*******************************************************************
//*******************************************************************
//*******************************************************************
//*******************************************************************
//*******************************************************************


//Table 3B: add in an additional contract at x percent of loss, $1000 per trade loss

   
{ Buys if Price crosses over Avg and then stays above Avg for one or more bars }
input: profittarget(15000);
var: profExitAt(0);

inputs: Price( Close ), Length( 30 ), ConfirmBars( 1 ) ;
variables: Counter( 0 ),Counter2( 0 ) ;

if Price > AverageFC( Price, Length ) then
    Counter = Counter + 1
else
    Counter = 0 ;

if CurrentBar > ConfirmBars and Counter = ConfirmBars then begin
    Buy ( "MACrossLE" ) next bar at market ;
    ProfExitAt=close+profittarget/bigpointvalue;
end;


{ Shorts if Price crosses under Avg and then stays below Avg for one or more bars }


if Price < AverageFC( Price, Length ) then
    Counter2 = Counter2 + 1
else
    Counter2 = 0 ;

if CurrentBar > ConfirmBars and Counter2 = ConfirmBars then begin
    Sell Short ( "MACrossSE" ) next bar at market ;
    ProfExitAt=close-profittarget/bigpointvalue;
end;


[IntrabarOrderGeneration = false]
inputs: PositionBasis( false ), Amount( 1000 ) ;

if PositionBasis then
    SetStopPosition
else
    SetStopShare ;

SetStopLoss( Amount ) ;



if marketposition=1 and lastbaronchart then
    sell this bar on close;



if marketposition=-1 and lastbaronchart then
    buytocover this bar on close;

//******************************
   


if close>ProfExitAt and marketposition=1 then     sell next bar at market;
if close


//add contracts if profit is big enough
input:xp(.1);

If openpositionprofit<-xp*1000 and currentcontracts=1 then begin
        if marketposition=1 then buy ("Xtra Buy") next bar at market;
        if marketposition=-1 then sellshort ("Xtra Sell") next bar at market;

    end;

//*******************************************************************
//*******************************************************************
//*******************************************************************
//*******************************************************************
//*******************************************************************
//*******************************************************************
//*******************************************************************
//*******************************************************************
//Table 4 - Use Table 3a code with this addition

inputs: BarToExitOn( 20 ) ;

if BarsSinceEntry >= BarToExitOn  then
    Sell ( "TimeBarsLX" ) next bar at market ;

    if BarsSinceEntry >= BarToExitOn  then
    Buy To Cover ( "TimeBarsSX" ) next bar at market ;


//*******************************************************************
//*******************************************************************
//*******************************************************************
//*******************************************************************
//*******************************************************************
//*******************************************************************
//*******************************************************************
//*******************************************************************
//Table 5 - Similar to Table 3a and Table 4, but can only add contract
// one time to a winning trade - FINAL VERSION
   
{ Buys if Price crosses over Avg and then stays above Avg for one or more bars }
input: profittarget(15000);
var: profExitAt(0),neveradded(0);

inputs: Price( Close ), Length( 30 ), ConfirmBars( 1 ) ;
variables: Counter( 0 ),Counter2( 0 ) ;

if Price > AverageFC( Price, Length ) then
    Counter = Counter + 1
else
    Counter = 0 ;

if CurrentBar > ConfirmBars and Counter = ConfirmBars then begin

    Buy ( "MACrossLE" ) next bar at market ;
    ProfExitAt=close+profittarget/bigpointvalue;
    neveradded=0;
    end;


{ Shorts if Price crosses under Avg and then stays below Avg for one or more bars }


if Price < AverageFC( Price, Length ) then
    Counter2 = Counter2 + 1
else
    Counter2 = 0 ;

if CurrentBar > ConfirmBars and Counter2 = ConfirmBars then begin

    Sell Short ( "MACrossSE" ) next bar at market ;
    neveradded=0;
    ProfExitAt=close-profittarget/bigpointvalue;
end;

   

[IntrabarOrderGeneration = false]
inputs: PositionBasis( false ), Amount( 1000 ) ;

if PositionBasis then
    SetStopPosition
else
    SetStopShare ;

SetStopLoss( Amount ) ;




if marketposition=1 and lastbaronchart then
    sell this bar on close;



if marketposition=-1 and lastbaronchart then
    buytocover this bar on close;

//******************************
   
{if openpositionprofit>profittarget then begin
    sell next bar at market;
    buytocover next bar at market;
end;}

if close>ProfExitAt and marketposition=1 then     sell next bar at market;
if close


//add contracts if profit is big enough
input:xp(.1);

If openpositionprofit>xp*profittarget and currentcontracts=1 and neveradded=0 then begin
        neveradded=1;
        if marketposition=1 then buy ("Xtra Buy") next bar at market;
        if marketposition=-1 then sellshort ("Xtra Sell") next bar at market;

    end;


inputs: BarToExitOn( 20 ) ;

if BarsSinceEntry >= BarToExitOn  then
    Sell ( "TimeBarsLX" ) next bar at market ;

    if BarsSinceEntry >= BarToExitOn  then
    Buy To Cover ( "TimeBarsSX" ) next bar at market ;

Back to top

July 2010

For “Exiting on a high note,” by Kevin Davey

input:trials(500),exitmethod(1);

var: LongShort(0);
Var: BarstoNext(0);
Var:ATRexitL(-99999.),ATRexitS(99999.),ATRx(0);

//Entry logic
Longshort=random(1);  //chose a random number between 0 and 1
BarstoNext=intportion(random(10))+1; //entry should occur at BarsToNext bars after previous exit

if (totaltrades=0 or BarsSinceExit(1)>=BarsToNext) and marketposition=0 then begin
    ATRexitL=-99999.;  //for ATR exit
    ATRexitS=99999.;  //for ATR exit
    if LongShort<.5 then buy next bar at market;
    if LongShort>.5 then sellshort next bar at market;
    ATRx=AvgTrueRange(14);

end;


var:ExitBar(0);

if exitmethod=1 then begin  //random exit, ExitBars after entry
   
ExitBar=intportion(random(10))+1;

if BarssinceEntry>=ExitBar then begin
    sell next bar market;
    Buytocover next bar market;
end;

end; //exit method 1


input:profATR(2),lossATR(2);

if exitmethod=2 then begin  //ATR exit, with profit and stop targets
   
if openpositionprofit>profATR*AvgTrueRange(14)*BigPointValue or
     openpositionprofit<-lossATR*AvgTrueRange(14)*BigPointValue then begin
    sell ("ATR Sell") next bar market;
    Buytocover ("ATR Cover") next bar market;
end;

end; //exit method 2


input:movATR(2); 

if exitmethod=3 then begin //ATR exit, trails behind price

   
if marketposition=1 then ATRexitL=maxlist(ATRexitL[1],close[1]-movATR*AvgTrueRange(14),entryprice-movATR*AvgTrueRange(14));
if marketposition=-1 then ATRexitS=minlist(ATRexitS[1],close[1]+movATR*AvgTrueRange(14),entryprice+movATR*AvgTrueRange(14));
 
if (marketposition=1 and closeATRExitS) then begin
    sell ("movATR Sell") next bar market;
    Buytocover ("movATR Cover") next bar market;
end;

end; //exit method 3


input:channel(2);

if exitmethod=4 then begin  //breakout of channel exit

   
if (marketposition=1 and close<=lowest(close,channel)) or
   (marketposition=-1 and close>=highest(close,channel)) then begin
    sell ("Chnl Sell") next bar market;
    Buytocover ("Chnl Cover") next bar market;
end;

end; //exit method 4


input:mal(2);


if exitmethod=5 then begin  //break of moving average exit
   
 
if (marketposition=1 and close<=averagefc(close,mal)) or
   (marketposition=-1 and close>=averagefc(close,mal)) then begin
        sell ("MA Sell") next bar market;
    Buytocover ("MA Cover") next bar market;
end;

end; //exit method 5

input:RSIval(80);

if exitmethod=6 then begin  //break of RSI oversold/undersold exit
   
 
if (marketposition=1 and RSI(Close,14)   (marketposition=-1 and RSI(Close,14)>100-RSIval) then begin
        sell ("RSI Sell") next bar market;
    Buytocover ("RSI Cover") next bar market;
end;

end; //exit method 6

Back to top


Excel and TraderStudio code for “Baseline basics” by Thomas Stridsman (July 2010)

Excel code

(50-day lookback periods, closing prices in column E)
Center (in column G):
=(MAX(E2:E51)+MIN(E2:E51))/2
Mean (in column H):
=AVERAGE(E2:E51)
Median (in column I):
=MEDIAN(E2:E51)
Old Mode (in column J):
=MAX(MIN(3*I51-2*H51;MAX(E2:E51));MIN(E2:E51))
New Mode (in column K):
=IF(AND(J51>H51;H51H50);MAX(K50;J51);J51))

**

TradersStudio code

(The variable LookBack could be set to any lookback period for the indicators, for example 50 or 200 days.)
Common declarations:
Dim CenterLine, AverageLine, MedianLine, ModeLine As BarArray(50)
Dim MedianArray As Array
Dim LookBack, n As Integer
Dim EstMode As Double
Center:
CenterLine = (Highest(Close, LookBack, 0) + Lowest(Close, LookBack, 0)) * (1/2)
Mean:
AverageLine = Average(Close, LookBack, 0)
Median:
ReDim(MedianArray, LookBack)
For n = 0 To LookBack-1
    MedianArray[n] = Close[n]
Next
MedianLine = Median(MedianArray)
New Mode:
EstMode =  Max(Min(3 * MedianLine – 2 * AverageLine, Highest(Close, LookBack)), Lowest(Close, LookBack))
If EstMode > AverageLine And AverageLine < AverageLine[1] Then
    ModeLine = Min(ModeLine[1], EstMode)
Else
If EstMode < AverageLine And AverageLine > AverageLine[1] Then
    ModeLine = Max(ModeLine[1], EstMode)
Else
    ModeLine = EstMode
End If
End If

Back to top


August 2010

TradeStation code for “Entering on the right foot,” by Kevin J. Davey

input:trials(500),entrymethod(1);

var: LongShort(0);
Var: BarstoNext(0);
Var:ATRexitL(-99999.),ATRexitS(99999.),ATRx(0);


if entrymethod=1 then begin  //random entry

//Entry logic
Longshort=random(1);  //chose a random number between 0 and 1
BarstoNext=intportion(random(15))+1; //entry should occur at BarsToNext bars after previous exit

if (totaltrades=0 or BarsSinceExit(1)>=BarsToNext) and marketposition=0 then begin
    if LongShort<.5 then buy next bar at market;
    if LongShort>.5 then sellshort next bar at market;
end;

end; //exit method 1


if entrymethod=2 and marketposition=0 then begin  //Bollinger Band entry
inputs: Length( 20 ), NumDevsDn( 2 ) ;
variables: LowerBand( 0 ),UpperBand( 0 ) ;

LowerBand = BollingerBand( Close, Length, -NumDevsDn ) ;
UpperBand = BollingerBand( Close, Length, NumDevsDn ) ;

if CurrentBar > 1 and Low crosses over LowerBand then
{ CB > 1 check used to avoid spurious cross confirmation at CB = 1 }
    If close>=LowerBand then buy next bar at market;

if CurrentBar > 1 and High crosses under UpperBand then
{ CB > 1 check used to avoid spurious cross confirmation at CB = 1 }
    If Close<=Upperband then sellshort next bar at market;
    //SellShort ( "BBandSE" ) next bar at UpperBand stop ;

end;//entry method 2

if entrymethod=3 and marketposition=0 then begin
    inputs:  FastLength( 12 ) ;
variables:  MyMACD( 0 ), MACDAvg( 0 ), MACDDiff( 0 ),slowLength(0),MACDLength(0) ;
variables:  MyMACD2( 0 ), MACDAvg2( 0 ), MACDDiff2( 0 ) ;

SlowLength=2.*FastLength;
MACDLength=FastLength;

MyMACD = MACD( Close, FastLength, SlowLength ) ;
MACDAvg = XAverage( MyMACD, MACDLength ) ;
MACDDiff = MyMACD - MACDAvg ;

if CurrentBar > 2 and MACDDiff crosses over 0 then { CB > 2 check used to
 avoid spurious cross confirmation at CB = 2 (at CB = 1, MyMACD and MACDAvg will be
 the same) }
    Buy ( "MacdLE" ) next bar at market ;

MyMACD2 = MACD( Close, FastLength, SlowLength ) ;
MACDAvg2 = XAverage( MyMACD2, MACDLength ) ;
MACDDiff2 = MyMACD2 - MACDAvg2 ;

if CurrentBar > 2 and MACDDiff2 crosses under 0 then { CB > 2 check used to
 avoid spurious cross confirmation at CB = 2 (at CB = 1, MyMACD and MACDAvg will be
 the same) }
    Sell Short ( "MacdSE" ) next bar at market ;
end; //entry method 3 (MACD)

if entrymethod=4 and marketposition=0 then begin //(momentum)
    inputs:  Price( Close ), MomeLength( 12 ) ; ;
variables:  Mom( 0 ), Accel( 0 ) ;

Mom = Momentum( Price, MomeLength ) ;
Accel = Momentum( Mom, 1 ) ; { 1 bar acceleration }

if Mom > 0 and Accel > 0  then
    If high>high[1] then buy next bar at market;

if Mom < 0 and Accel < 0  then
    If low
end; //entry 4


if entrymethod=5  and marketposition=0 then begin //2 mov avg
    inputs: xPrice( Close ), MAFastLength( 9 );
variables: MAFastAvg( 0 ), MASlowAvg( 0 ),MAslowlength(0) ;

MASlowLength=2*MAFastLength;

MAFastAvg = AverageFC( xPrice, MAFastLength ) ;
MASlowAvg = AverageFC( xPrice, MASlowLength ) ;

if CurrentBar > 1 and MAFastAvg crosses over MASlowAvg then
{ CB > 1 check used to avoid spurious cross confirmation at CB = 1 }
    Buy ( "MA2CrossLE" ) next bar at market ;

if CurrentBar > 1 and MAFastAvg crosses under MASlowAvg then
{ CB > 1 check used to avoid spurious cross confirmation at CB = 1 }
    Sell Short ( "MA2CrossSE" ) next bar at market ;
end; //dual ma entry

if entrymethod=6 and marketposition=0 then begin
    inputs: RSILength( 14 ), OverSold( 30 ),overbought(70) ;
variables:  MyRSI( 0 ) ;

MyRSI = RSI( Close, Length ) ;

if Currentbar > 1 and MyRSI crosses over OverSold then
{ CB > 1 check used to avoid spurious cross confirmation at CB = 1 }
    Buy ( "RsiLE" ) next bar at market ;
if Currentbar > 1 and MyRSI crosses under OverBought then
{ CB > 1 check used to avoid spurious cross confirmation at CB = 1 }
    Sell Short ( "RsiSE" ) next bar at market ;

    end;//RSi entry


var:ExitBar(0);
//exit method
   
ExitBar=intportion(random(20))+1;

if BarssinceEntry>=ExitBar then begin
    sell next bar market;
    Buytocover next bar market;
end;

REVERSE ENTRIES –Bollinger Bands and RSI

if entrymethod=2 and marketposition=0 then begin  //reverse Bollinger Band entry
inputs: Length( 20 ), NumDevsDn( 2 ) ;
variables: LowerBand( 0 ),UpperBand( 0 ) ;

LowerBand = BollingerBand( Close, Length, -NumDevsDn ) ;
UpperBand = BollingerBand( Close, Length, NumDevsDn ) ;

if CurrentBar > 1 and Low crosses over LowerBand then
{ CB > 1 check used to avoid spurious cross confirmation at CB = 1 }
    If close>=LowerBand then sellshort next bar at market;

if CurrentBar > 1 and High crosses under UpperBand then
{ CB > 1 check used to avoid spurious cross confirmation at CB = 1 }
    If Close<=Upperband then buy next bar at market;

end;//entry method 2r


if entrymethod=6 and marketposition=0 then begin //reverse RSI entry
    inputs: RSILength( 14 ), OverSold( 30 ),overbought(70) ;
variables:  MyRSI( 0 ) ;

MyRSI = RSI( Close, Length ) ;

if Currentbar > 1 and MyRSI crosses over OverSold then
{ CB > 1 check used to avoid spurious cross confirmation at CB = 1 }
    SellShort( "RsiSE" ) next bar at market ;
if Currentbar > 1 and MyRSI crosses under OverBought then
{ CB > 1 check used to avoid spurious cross confirmation at CB = 1 }
    Buy ( "RsiLE" ) next bar at market ;

    end;//RSi entry 6r

Back to top


For “A baseline trend strategy” by Thomas Stridsman (August 2010)

Contracts = 1000000 / (Average(Range, LookBack, 0) * BigPointValue)

**

If Close < ExitLine Then
    Buy(““, Contracts, 0, Market, Day)
End If
If Close > ExitLine Then
    ExitLong(““, ““, GetCurrentSize(““), 0, Market, Day)
End If

**

If TestedLine > TestedLine[1] Then
    Buy(““, Contracts, 0, Market, Day)
End If
If TestedLine < TestedLine[1] Then
    ExitLong(““, ““, GetCurrentSize(““), 0, Market, Day)
End If

**

If EntryLine > EntryLine[1] And Close > ExitLine Then
    Buy(““, Contracts, 0, Market, Day)
End If
If EntryLine < EntryLine[1] Or Close < ExitLine Then
    ExitLong(““, ““, GetCurrentSize(““), 0, Market, Day)
End If

Back to top


October 2010

TraderStudio code for “Building a volatility-momentum system” by Thomas Stridsman

The code for the standard deviation is:

Dim CycleLen As Integer
Dim Vola, VolaMult As Double

Vola = StdDev(Close, CycleLen, 0) * VolaMult

The standard deviation could also be substituted with the absolute mean deviation, in which case the code would read:

Dim CycleLen, n As Integer
Dim Vola, Mean, MeanDiff, VolaMult As Double

Mean = Average(Close, CycleLen, 0)
MeanDiff = 0
For n = 0 To CycleLen-1
 MeanDiff = MeanDiff + Abs(Close[n] - Mean) / CycleLen
Next
Vola = MeanDiff * VolaMult

The code for the necessary momentum is:

Dim CycleShift As Integer
Dim Vola, LongEntry, ShortEntry As Double

CycleShift = CycleLen * 0.5
LongEntry = Low[CycleShift] + Vola
ShortEntry = High[CycleShift] - Vola

The entry and exit rules are:

Dim Size As Integer
Dim LongEntry, ShortEntry As Double

If High < LongEntry Then
    Buy(“Long”, Size, LongEntry, Stop, Day)
    ExitLong(“Close”, ““, GetCurrentSize(““), 0, Market, Day)
End If
If Low > ShortEntry Then
    Sell(“Short”, Size, ShortEntry, Stop, Day)
    ExitShort(“Close”, ““, GetCurrentSize(““), 0, Market, Day)
End If

The  “Panic” stop-loss:

Dim CycleShift As Integer

ExitLong(“Panic”, ““, GetCurrentSize(““), Lowest(Close, CycleShift, 0), Stop, Day)
ExitShort(“Panic”, ““, GetCurrentSize(““), Highest(Close, CycleShift, 0), Stop, Day)

Back to top

November 2010

TradeStation code for "An insider’s view of intraday markets" by David Bean

{Workspace setup is:
Data1 = @ES.D, 5 minute
Data2 = $ADD, 5 minute
Data3 = @ES.D, Daily
Data4 = $ADV, 5 minute
Data5 = $DECL, 5 minute}

Inputs: StpLs (350);
Vars: CADD(0);
CADD=Close of data4-Close of data5; {This is for $ADV and $DECL to back test prior to the start of the $ADD}

{Code is for EST, time adjustments need to be made
If Time>=935 and Time<1500 and C of data2>0 {and C of data2<600}{this is for adding the bullish bias condition}
    and C of data3>Average(C of data3,100)[1]
    Then Buy Next Bar at Lowest (L, 12)[1] Limit;

If Time>=935 and Time<1500 and C of data2<0
    and C of data3    Then Sell Short Next Bar at Highest (H, 12)[1] Limit;

{Use this code testing the strategy prior to 9/10/2007 – the start of the $ADD but don’t use both sets of code at the same time}
{
If Time>=935 and Time<1500 and CADD>0 {and CADD<600} {this is for adding the bullish bias condition}
    and C of data3>Average(C of data3,100)[1]
    Then Buy Next Bar at Lowest(L,12)[1] Limit;

If Time>=935 and Time<1500 and CADD<0
    and C of data3    Then Sell Short Next Bar at Highest(H,12)[1] Limit;
}

SetStopLoss(StpLs);
If Time=1605 Then Sell This Bar on Close;
If Time=1605 Then Buy to Cover This Bar on Close;
SetExitonClose;

Back to top


February 2011

“Reducing overnight risk in dip trading” By Ted Climo

**
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using WealthLab;
using WealthLab.Indicators;
using WealthLab.Rules;
using Community.Components;

//Whatever Daily bar watchlist you use, must have a duplicate 1min bar watchlist so that script can access & prioritize trades by which came 1st.
//You could use 5min sublist as well, it is faster & just as accurate on small watchlists like NDX100 components.
//64bit PCs & 64bit WLP can handle 3000 symbol watchlists no problem --- 32bit PCs may bog down on Mega-large watchlists.
//Earnings dates not available before 9/1/2004, so backtest limited to 6 yrs currently.
//NOTICE, forthcoming EPS dates displayed on individual symbol charts in upper left corner.
//Community.Components instructs strategy to ignore EPS dates for ETFs (since they have none).
//In forthcoming update, WLP adding Open vs Entry point feature in Quote Mgr so you can automate ONR filter #2 if so desired.
//Enjoy!  It has been a pleasure serving you.
namespace WealthLab.Strategies
{
    public class ActiveTraderMagDemo : WealthScript
    {       
        protected override void Execute()
        {
            // Non-split-adjusted Close and Volume, --- adds to historical accuracy
            DataSeries reverseAdjustment;
            DataSeriesOp.SplitReverseFactor( this, "split", out reverseAdjustment);
            DataSeries closeAdj = Close * reverseAdjustment;
            DataSeries volAdj = Volume / reverseAdjustment;
           
            PlotSeries(VolumePane, SMA.Series(Volume,10), Color.Black, LineStyle.Solid, 1 );
            PlotSeries(PricePane, SMA.Series(Close,200), Color.Black, LineStyle.Solid, 1 );

            DateTime nextReportDate = new DateTime(2010, 1, 1);
            FundamentalItem fi = GetFundamentalItem (Bars.Count - 1, Bars.Symbol, "earnings per share");
            if (fi != null)
                nextReportDate = EarningsDate.GetNextUseCache(Bars.Symbol, fi.Date);
            else
            {
                if (!EarningsDate._ignoreSymbols.Contains(Bars.Symbol))
                    nextReportDate = EarningsDate.GetNextUseCache(Bars.Symbol, nextReportDate);
            }
            DrawLabel(PricePane, "Next Earnings: " + nextReportDate.ToShortDateString() );
            PrintDebug(Bars.Symbol + "t" + nextReportDate.ToShortDateString());//shows upcoming EPS dates
           
            // first date is 6 years prior to last bar in chart
            TimeSpan sixYears = new TimeSpan(365 * 6, 0, 0, 0);
            DateTime firstDate = Date[Bars.Count - 1] - sixYears;
                       
            for(int bar = GetTradingLoopStartBar(1); bar < Bars.Count; bar++)
            {
                if (IsLastPositionActive)
                {
                    SellAtClose(bar + 1, LastPosition, "Exit 1 day later");
                }
                else
                {
                    if (EarningsDate.InWindow(this, bar, "earnings per share", 2, 1))        //ONR upgrade #1
                        SetBackgroundColor(bar, Color.FromArgb(30, Color.Red));
                    else
                    {
                        bool passFilter1 = Date[bar].Date > firstDate.Date             //Assure 6 yr study
                            && closeAdj[bar] > 5                             //core system
                            && Close[bar] > SMA.Series( Close, 200 )[bar]    //core system
                            && SMA.Series( volAdj, 10 )[bar] >= 250000;        //core system
                       
                        if (!passFilter1) continue;
                   
                        if (bar < Bars.Count - 1)
                        {
                            if (Open[bar+1] > (Close[bar] * 0.90) * 1.05)        //ONR upgrade #2
                                BuyAtLimit( bar + 1, Close[bar] * 0.90 );
                        }
                        else
                            BuyAtLimit( bar + 1, Close[bar] * 0.90 );            //core system
                    }
                }
            }

            /* Set the position priorities based on time of day */
            PositionHelper ph = new PositionHelper( this );
            ph.SetTimeOfDayPriority(1);  // 1-minute data referenced to prioritze which trade came first.

            /* Check priority */           
            int j = 0;
            foreach (Position p in Positions)
            {
                j++;
                //PrintDebug(p.Symbol + ":t" + j + "t" + p.Priority + "t" + p.EntryDate.ToShortDateString());
            }   //shows time of day, trade occured & possible momentary spikes
        }
    }
}

Back to top


September 2011

“Bullish price continuation pattern in stock-index futures” By Boris Stein

{Gteen Day by B.Stein}
 

input:TrendPercent(30); {min value of "trendinnes" for the days to take trades}

 
    if (c-o)/(h-l) >= trendpercent/100 {long green day} and
        c[1]            h>h[1] {green's high exceeded red's high} then
                    buy("GreenDayLE") this bar on close;

Back to top

October 2012

"Intraday vs. swing: Adjusting a system" by Donald W. Pendergast Jr. 

Trade Station code (v. 9.0 or higher) for the Pendergast EMA Trigger Strategy.

Optimization and formatting tips: After pasting the Easy Language Document (ELD) code into the editor, set the “Maximum bars back” box to 35 and then verify the ELD before closing it. Now set up a workspace using a five-minute bar chart of AAPL with six months of data.

Select “Trade vol,”“Session hours” and “Exchange” and then click “Properties” to configure the strategy to trade from 0820 to 1315 ET, Monday through Friday. Insert the strategy into the workspace and make sure both long and short trades are enabled; click “Format” and input the parameter ranges shown in Figure A. (Note: If you use trade sizes smaller than 100 shares, the system will take profits at a proportional level – e.g., if the optimization indicates the strategy will work best by closing a trade when open profits have reached $540, a 25-lot trade will actually close out when it reaches $135 in open profits.)

You also need to include commissions and slippage amounts when formatting. Check “Enable look inside bar back testing” and set the “Max bars back” to 35. The test in the main article used a fixed trade size of 25 shares. You’re now ready to test the strategy.

Run an optimization using the “Standard” and “Genetic” options on the most recent six-month set of data for AAPL.

 

//Declaration of user input parameters.

inputs: EMALength(5), MAPrice(close), RoundPrecision(5 {Decimal Places for Price} ), TicksBeyondEntryBar(6), ProfitTarget(1275);

//Declaration of strategy variables.

vars: EMA(0), TradeTrigger(0), PriceOfEntry(0);

///////////////////////////////////////////////////////////////////

//Resets Daily Total Trades variable at the beginning of each day.

///////////////////////////////////////////////////////////////////

inputs: DailyTradesMax(1);

vars: DailyTotalTrades(0), BeginDayTotalTrades(0);

if ( date <> date[1] ) then begin

BeginDayTotalTrades = NumEvenTrades + NumWinTrades + NumLosTrades;

           

end;

DailyTotalTrades = ( NumEvenTrades + NumWinTrades + NumLosTrades ) - BeginDayTotalTrades;

//////////////////////////////////////////////////////

//The following code computes Strategy Entry Signals.

//////////////////////////////////////////////////////

EMA = Round(XAverage(MAPrice, EMALength), RoundPrecision);

/////////////////////////////////////////////////////////////////

//Turns on and off trading depending on certain time conditions.

/////////////////////////////////////////////////////////////////

inputs: TradeTimeStart(0820), TradeTimeEnd(1315);

vars: TradingHours(0);

TradingHours = 0;

If ( ( Time > TradeTimeStart ) and ( Time <= TradeTimeEnd ) ) then

TradingHours = 1;

/////////////////////////////////////////////////////////////////////////////

//Produces a signal for a long trade or short trade depending on Conditions.

/////////////////////////////////////////////////////////////////////////////

//Long Entry Setup.

If ( ( close[1] < EMA[1] ) and ( close > EMA ) and ( TradingHours = 1 ) and ( DailyTotalTrades < DailyTradesMax ) ) then begin

TradeTrigger = 1;

PriceOfEntry = high + ( TicksBeyondEntryBar * ( minmove / pricescale ) );

end;

//Short Entry.

If ( ( close[1] > EMA[1] ) and ( close < EMA ) and ( TradingHours = 1 ) and ( DailyTotalTrades < DailyTradesMax ) ) then begin

TradeTrigger = -1;

PriceOfEntry = low - ( TicksBeyondEntryBar * ( minmove / pricescale ) );

end;

 

//Resets TradeTrigger once trading hours are complete.

if ( time >= TradeTimeEnd ) then

TradeTrigger = 0;

////////////////////////////////////////////////////////////////////////////////

//Opens either a short or long trade if appropriate trading conditions are met.

////////////////////////////////////////////////////////////////////////////////

//Places Market Orders depending on TicksBeyondLastPrice.

If ( TradeTrigger = 1 ) then

buy("L_Entry") next bar at PriceOfEntry stop;

If ( TradeTrigger = -1 ) then

sellshort("S_Entry") next bar at PriceOfEntry stop;

/////////////////////////////////////

// Money Management for Short Trade.

/////////////////////////////////////

if ( MarketPosition = -1 ) then begin

//Resets Entry conditional variables.

TradeTrigger = 0;

//Exits trade at a profit.

buytocover("S_PrftTrgt") next bar at ( EntryPrice - ( ProfitTarget * ( minmove / pricescale ) ) ) limit;

end;

////////////////////////////////////

// Money Management for Long Trade.

////////////////////////////////////

if ( MarketPosition = 1 ) then begin

//Resets Entry conditional variables.

TradeTrigger = 0;

//Exits trade at a profit.

sell("L_PrftTrgt") next bar at ( EntryPrice + ( ProfitTarget * ( minmove / pricescale ) ) ) limit;

end;

///////////////////

//End of Day Exit.

///////////////////

if ( time >= TradeTimeEnd ) then begin

            sell ("L_EOD") this bar on close;

            buytocover ("S_EOD") this bar on close;

end;

 

Swing-trade version: To change the system into a swing-trading strategy, simply delete the final five lines of code:

 

///////////////////

//End of Day Exit.

///////////////////

if ( time >= TradeTimeEnd ) then begin

            sell ("L_EOD") this bar on close;

            buytocover ("S_EOD") this bar on close;

end;

Save the strategy under a new name and verify it before closing it. Now reinstall this version of the strategy into your workspace and go through the same formatting/optimization/back-testing procedure used on the original day-trading version of the system.

 

Optimization settings

These are the optimization ranges and final optimized values for the day trading version of this system:

EMA Length [Start] 5, [Stop] 31, [Increment] 2        Optimized value=5

MA price = close      Optimized value=close

RoundPrecision [Decimal places for price] =5       Optimized value=5

TicksBeyondEntrybar [Start] 1, [Stop] 30, [Increment] 1      Optimized value=6

Profit Target [Start] 200, [Stop] 1500, [Increment [25]           Optimized value=1275 (per 100 share lot traded; in this example, when trading 25-share lots, the system will take profits once $318.75 in open profits is achieved.)

Daily Trades Max [Start] 1, [Stop] 2, [Increment] 1

Trade Time Start = 820 (the trading window times (Eastern Time) were not derived by the optimization, but are simply based on general market behavior observations. They can, however be optimized if so desired).

Trade Time End=1315

These are the optimization ranges and final optimized values for the swing trading version of this system:

EMA Length [Start] 5, [Stop] 31, [Increment] 2        Optimized value=25

MA price = close      Optimized value=close

RoundPrecision [Decimal places for price] =5       Optimized value=5

TicksBeyondEntrybar [Start] 1, [Stop] 30, [Increment] 1      Optimized value=6

Profit Target [Start] 200, [Stop] 1500, [Increment [25]           Optimized value=1040 (per 100 share lot traded; in this example, when trading 25-share lots, the system will take profits once $260 in open profits is achieved.)

Daily Trades Max [Start] 1, [Stop] 2, [Increment] 1

Trade Time Start = 820 (the trading window times (Eastern Time) were not derived by the optimization, but are simply based on general market behavior observations. They can, however be optimized if so desired).

Trade Time End=1315

Back to top

December 2012

Swing trading: ETF vs. component stocks By Donald W. Pendergast Jr.

 

MetaStock Exploration code for the CCI-5 system described in this article:

Column A name: CLOSE
Column A code: CLOSE
Column B name: Long entry
Column B code: (Cross (CCI (5), -100))
Column C name: Long exit
Column C code: (Cross (75, RSI (5)))
Filter: colA>5.00 AND Mov (VOLUME, 50, SIMPLE)>3000

Back to top

March 2013: Riding the E-mini S&P 500 By Andrea Unger

Click here to download a RTF file with the strategy code. 

Back to top 

December 2013: Capitalizing on autocorrelation By Thomas Stridsman

YearlyTarget is a user input, set to 17.5 percent annual target return. BaseRisk is a user input, set to produce annual target return. OnAccount keeps track of account equity adjusted for accrued interest rates and manager’s fees.

//

Dim ThisBar, Div, P, LB As Integer

Dim MonthlyTarget, MonthlyReturn, AdjustST As Double

ThisBar = BarNumber - FirstBar

MonthlyTarget = ((1 + 0.01 * YearlyTarget)^(1/12) - 1) * 100

Div = 0

For P = 1 To 3

LB = 21 * P

If ThisBar > LB Then

MonthlyReturn = MonthlyReturn + ((OnAccount / OnAccount[LB])^(1/P) - 1) * 100

Div = Div + 1

End If

Next

If Div > 0 Then

MonthlyReturn = MonthlyReturn / Div

AdjustST = Min(Max(1 - (MonthlyReturn - MonthlyTarget) / (2 * MonthlyTarget), 0.667), 1.5)

BaseRisk = BaseRisk * AdjustST

End If 

Back to top 

May 2014: Putting two and two together by Thomas Stridsman

TradersStudio (www.tradersstudio.com) code:

Shared declarations:

Dim SlowerLB, FasterLB As Integer

Dim LongBase, ShortBase, LongRisk, ShortRisk, EntryLevel, ExitLevel As Double

For the Bollinger-band system (group A):

SlowerLB = 18 ‘(36, 72)

FasterLB = 12 ‘(24, 48)

LongBase = Average(Close, SlowerLB, 0) + StdDev(Close, SlowerLB, 0) * 2.2

ShortBase = Average(Close, SlowerLB, 0) - StdDev(Close, SlowerLB, 0) * 2.2

LongRisk = LongBase - Average(Close, FasterLB, 0)

ShortRisk = Average(Close, FasterLB, 0) – ShortBase

For the Donchian systems (group B):

SlowerLB = 18 ‘(36, 72)

FasterLB = 12 ‘(24, 48)

LongBase = Highest(High, SlowerLB, 0)

ShortBase = Lowest(Low, SlowerLB, 0)

LongRisk = LongBase - 0.5 * (Highest(High, FasterLB, 0) + Lowest(Low, FasterLB, 0))

ShortRisk = 0.5 * (Highest(High, FasterLB, 0) + Lowest(Low, FasterLB, 0)) – ShortBase

Shared code:

If GetCurrentPosition(TestEntry) < +1 Then

 EntryLevel = LongBase

 ExitLevel = LongBase - LongRisk

Else

 EntryLevel = EntryLevel[1]

 ExitLevel = Max(LongBase - LongRisk, ExitLevel[1])

End If

Back to top 



|
email this story
|
print this story