Hi All,
As you read you will likely identify some holes in my understanding of AmiBroker and AFL. I'm not asking for explicit answers to my questions, moreso links to resources or explanations of concepts I'm missing. The goal is AmiBroker mastery. While it may take more time to figure out the issues with a little direction (instead of handing me the answer), I find that learning process tends to stick better. So please dive on in and any help you can provide I will greatly appreciate.
Intended Function
- A signal is generated using 1-min candles when the EMA(C, 20) crosses above the EMA(C, 50)
- Entry and exit are monitored using 1-sec candles (price occasionally hits a profitable exit and a stop loss in a one-minute time frame, thus I need that resolution to understand which occurs first)
- After the signal occurs an entry price is calculated. It's the signal bar's close minus some multiple of the ATR
- Price needs to come down and hit our entry before a minute transpires (I think this is what my code does, but not 100% sure)
- After the signal occurs a stop price is calculated. Initially it's entry price minus 5.25 points
- If price exceeds entry by 2.75 points, we lock in 0.5 points profit, if price exceeds entry by 5.25 points we lock in 3.25 points profit (there are two more levels, but you get the idea, click here to see)
- When price touches the stop price, we exit the trade at the stop price
If I look at my chart, everything looks like it works, however, I'm still lacking sufficient understanding of how the back tester works. While I see a trade on 12/28/2022 on my chart, it does no appear on my back test trade report.
For reference
- Trade on 1-minute chart
- Same trade on 1-second chart
- Back test report lacks the 12/28 trade. This is not the only one
Running a back test I get the following: Error 15. Endless loop detected in FOR loop
I don't have a FOR loop in my code. I'm assuming it resides somewhere in the back testing. Currently I'm trying to run the test for 3 years of data. That's 31.5M+ bars. Inside Database Settings the largest allowable value is 1,000,000. That's less than 31.5M. Is this an issue?
My next point of investigation was Tools > Preferences > AFL Tab. There I maxed out the Endless Loop Threshold to 999999999. I still get the Error 15, however, I do not have a FOR loop in my code... what am I missing?
So after reading all this... please tell me what concepts I am missing? What resources should I study to fill in the blanks? Any and all assistance will be greatly appreciated. I went ahead and posted my code below.
Code for Price Chart
SetChartOptions(2,chartWrapTitle);
_SECTION_BEGIN("Price");
SetChartOptions(0,chartShowArrows|chartShowDates);
SetChartOptions(2,chartWrapTitle);
_N(Title = StrFormat("{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ));
Plot( C, "Close", ParamColor("Color", colorDefault ), styleNoTitle | ParamStyle("Style") | GetPriceStyle() );
_SECTION_END();
SetTradeDelays(0,0,0,0);
SetOption("FuturesMode", True);
SetOption("InitialEquity", 10000);
SetOption("MaxOpenPositions", 100);
SetOption("CommissionMode", 3 );
SetOption("CommissionAmount", 0.56);
SetOption("AllowSameBarExit", True);
MarginDeposit = 50;
RoundLotSize = 1;
TickSize = 0.25;
PointValue = 5.0;
SetPositionSize( 10, spsPercentOfEquity );
//SetPositionSize( 100, spsShares);
//SetBarsRequired(2400);
function RoundToTick(Value){
integral = Prec(Value,0);
decimal = Value - integral;
newDec = IIf(decimal < 0.125,0.00,
IIf(decimal >= 0.125 && decimal < 0.375,0.25,
IIf(decimal >= 0.375 && decimal < 0.625,0.50,
IIf(decimal >= 0.625 && decimal < 0.875,0.75,
IIf(decimal >= 0.875,1.00,0)))));
return integral + newDec;
}
/* Check for entry
*/
TimeFrameSet(in1Minute);
AtrPeriod = 14;
TradeCooldown = 14;
Ema20 = EMA(C, 20);
Ema50 = EMA(C, 50);
BuySignal = Ref(Cross(Ema20, Ema50), -1);
EntryOffset = -.85 * ATR(AtrPeriod);
EntryPrice = RoundToTick(ValueWhen(BuySignal, C + EntryOffset));
TimeFrameRestore();
BuySignal = TimeFrameExpand(BuySignal, in1Minute);
EntryPrice = TimeFrameExpand(EntryPrice, in1Minute);
TradeCoolDown = TimeFrameExpand(TradeCoolDown, in1Minute) * 60;
Buy = Ref(BuySignal, -1) && L < EntryPrice;
Buy = ExRem(Buy, BarsSince(Buy) == TradeCoolDown);
//BuyPrice = IIf(Buy, EntryPrice, Null);
BuyPrice = RoundToTick(ValueWhen(Buy, EntryPrice));
/* Trailing Stop (expand for notes)
1) Initial StopLength = 10 ticks (2.5 points)
2) Trigger0 = EntryPrice + 10 ticks (2.5 points)
Stop0 = Entry + 4 ticks (1 point)
3) Trigger1 = EntryPrice + 20 ticks (5 points)
Stop1 = HighSinceEntry - 15 ticks (3.75 points)
4) Trigger2 = EntryPrice + 35 ticks (8.75 points)
Stop2 = HighSinceEntry - 10 ticks (2.5 points)
5) Trigger3 = EntryPrice + 50 ticks (12.5 points)
Stop3 = HighSinceEntry - 4 ticks (1.0 point)
*/
ProfitTrigger = EntryPrice + 2.75; // i think this is OK... but double check --> i keep taking this down and profits keep going up... not sure if this is behaving correctly
Trigger01 = EntryPrice + 5.25;
Trigger02 = EntryPrice + 7.5;
Trigger03 = EntryPrice + 9.75;
StopInit = EntryPrice - 5.25;
ProfitLock = EntryPrice + 0.5;
Trail01 = 3.25;
Trail02 = 2.0;
Trail03 = 1.0;
HighSinceBuy = IIf(Buy, H, HighestSince(Buy, H));
LowSinceBuy = IIf(Buy, L, LowestSince(Buy, L));
Trail = IIf(HighSinceBuy >= Trigger03, Trail03, IIf(HighSinceBuy >= Trigger02, Trail02, IIf(HighSinceBuy >= Trigger01, Trail01, Null)));
StopLong = IIf(Buy, StopInit, IIf(IsEmpty(Trail), IIf(HighSinceBuy >= ProfitTrigger, ProfitLock, StopInit), HighSinceBuy - Trail));
StopLong = IIf(!Buy && Ref(BarsSince(L <= StopLong), -1) < BarsSince(Buy), Null, StopLong);
Sell = L <= StopLong;
Sell = ExRem(Sell, Ref(Buy, 1));
SellPrice = RoundToTick(StopLong);
BuySignal = ExRem(BuySignal, Sell);
BarsSinceBuy = BarsSince(Buy);
BarsSinceSell = BarsSince(Sell);
IsLong = Buy && Sell || (BarsSinceBuy < Ref(BarsSinceSell,-1)) || (BarsSinceBuy >=0 && IsEmpty(Ref(BarsSinceSell, -1)));
Profit = IIf(Ref(Sell, -1) && Ref(SellPrice > BuyPrice, -1), Ref(SellPrice - BuyPrice, -1), Null);
Loss = IIf(Ref(Sell, -1) && Ref(SellPrice < BuyPrice, -1), Ref(SellPrice - BuyPrice, -1), Null);
BuyPrice = IIf(IsLong, BuyPrice, Null);
ProfitTrigger = IIf(IsLong, ProfitTrigger, Null);
Trigger01 = IIf(IsLong, Trigger01, Null);
Trigger02 = IIf(IsLong, Trigger02, Null);
Trigger03 = IIf(IsLong, Trigger03, Null);
ProfitLock = IIf(IsLong, ProfitLock, Null);
Trail01 = IIf(IsLong, Trail01, Null);
Trail02 = IIf(IsLong, Trail02, Null);
Trail03 = IIf(IsLong, Trail03, Null);
/* Plot Charty Thingers
Plot(BuyLimitPrice,"BuyLimitPrice",IIf(Low < BuyLimitPrice - 0.01,colorGrey50,colorGrey50),styleDashed|styleThick);
*/
Plot(Ema20, "EMA(20)", ColorRGB(255,0,255));
Plot(Ema50, "EMA(50)", ColorRGB(180,180,180));
Plot(StopLong, "StopLong", ColorRGB(255,0,255), styleStaircase | styleThick);
Plot(ProfitTrigger, "ProfitTrigger", colorDarkRed, styleStaircase | styleThick);
Plot(Trigger01, "Trigger01", colorOrange, styleStaircase | styleThick);
Plot(Trigger02, "Trigger02", colorGreen, styleStaircase | styleThick);
Plot(Trigger03, "Trigger03", colorIndigo, styleStaircase | styleThick);
Plot(IIf(BarsSince(Ref(BuySignal, -1)) < 3,EntryPrice,Null), "PotentialEntryPrice",colorLightBlue, styleDots | styleNoLine);
Plot(BuyPrice, "BuyPrice", colorBlue, styleDots | styleNoLine | styleThick);
Plot(SellPrice, "SellPrice", colorBlack, styleStaircase | styleThick);
PlotShapes(BuySignal * shapeHollowUpArrow, colorGreen, 0, Low);
PlotShapes(Buy * shapeUpArrow, colorGreen, 0, Low);
PlotShapes(Sell * shapeDownArrow, colorRed, 0, High);
Code for Separate Panel
SetTradeDelays(0,0,0,0);
SetOption("FuturesMode", True);
SetOption("InitialEquity", 10000);
SetOption("MaxOpenPositions", 100);
SetOption("CommissionMode", 3 );
SetOption("CommissionAmount", 0.56);
SetOption("AllowSameBarExit", True);
MarginDeposit = 50;
RoundLotSize = 1;
TickSize = 0.25;
PointValue = 5.0;
SetPositionSize( 10, spsPercentOfEquity );
//SetPositionSize( 100, spsShares);
//SetBarsRequired(2400);
function RoundToTick(Value){
integral = Prec(Value,0);
decimal = Value - integral;
newDec = IIf(decimal < 0.125,0.00,
IIf(decimal >= 0.125 && decimal < 0.375,0.25,
IIf(decimal >= 0.375 && decimal < 0.625,0.50,
IIf(decimal >= 0.625 && decimal < 0.875,0.75,
IIf(decimal >= 0.875,1.00,0)))));
return integral + newDec;
}
/* Check for entry
*/
TimeFrameSet(in1Minute);
AtrPeriod = 14;
TradeCooldown = 14;
Ema20 = EMA(C, 20);
Ema50 = EMA(C, 50);
BuySignal = Ref(Cross(Ema20, Ema50), -1);
EntryOffset = -.85 * ATR(AtrPeriod);
EntryPrice = RoundToTick(ValueWhen(BuySignal, C + EntryOffset));
TimeFrameRestore();
BuySignal = TimeFrameExpand(BuySignal, in1Minute);
EntryPrice = TimeFrameExpand(EntryPrice, in1Minute);
TradeCoolDown = TimeFrameExpand(TradeCoolDown, in1Minute) * 60;
Buy = Ref(BuySignal, -1) && L < EntryPrice;
Buy = ExRem(Buy, BarsSince(Buy) == TradeCoolDown);
//BuyPrice = IIf(Buy, EntryPrice, Null);
BuyPrice = RoundToTick(ValueWhen(Buy, EntryPrice));
/* Trailing Stop (expand for notes)
1) Initial StopLength = 10 ticks (2.5 points)
2) Trigger0 = EntryPrice + 10 ticks (2.5 points)
Stop0 = Entry + 4 ticks (1 point)
3) Trigger1 = EntryPrice + 20 ticks (5 points)
Stop1 = HighSinceEntry - 15 ticks (3.75 points)
4) Trigger2 = EntryPrice + 35 ticks (8.75 points)
Stop2 = HighSinceEntry - 10 ticks (2.5 points)
5) Trigger3 = EntryPrice + 50 ticks (12.5 points)
Stop3 = HighSinceEntry - 4 ticks (1.0 point)
*/
ProfitTrigger = EntryPrice + 2.75; // i think this is OK... but double check --> i keep taking this down and profits keep going up... not sure if this is behaving correctly
Trigger01 = EntryPrice + 5.25;
Trigger02 = EntryPrice + 7.5;
Trigger03 = EntryPrice + 9.75;
StopInit = EntryPrice - 5.25;
ProfitLock = EntryPrice + 0.5;
Trail01 = 3.25;
Trail02 = 2.0;
Trail03 = 1.0;
HighSinceBuy = IIf(Buy, H, HighestSince(Buy, H));
LowSinceBuy = IIf(Buy, L, LowestSince(Buy, L));
Trail = IIf(HighSinceBuy >= Trigger03, Trail03, IIf(HighSinceBuy >= Trigger02, Trail02, IIf(HighSinceBuy >= Trigger01, Trail01, Null)));
StopLong = IIf(Buy, StopInit, IIf(IsEmpty(Trail), IIf(HighSinceBuy >= ProfitTrigger, ProfitLock, StopInit), HighSinceBuy - Trail));
StopLong = IIf(!Buy && Ref(BarsSince(L < StopLong), -1) < BarsSince(Buy), Null, StopLong);
Sell = L <= StopLong;
Sell = ExRem(Sell, Ref(Buy, 1));
SellPrice = RoundToTick(StopLong);
BarsSinceBuy = BarsSince(Buy);
BarsSinceSell = BarsSince(Sell);
IsLong = Buy && Sell || (BarsSinceBuy < Ref(BarsSinceSell,-1)) || (BarsSinceBuy >=0 && IsEmpty(Ref(BarsSinceSell, -1)));
Profit = IIf(Ref(Sell, -1) && Ref(SellPrice > BuyPrice, -1), Ref(SellPrice - BuyPrice, -1), Null);
Loss = IIf(Ref(Sell, -1) && Ref(SellPrice < BuyPrice, -1), Ref(SellPrice - BuyPrice, -1), Null);
BuyPrice = IIf(IsLong, BuyPrice, Null);
ProfitTrigger = IIf(IsLong, ProfitTrigger, Null);
Trigger01 = IIf(IsLong, Trigger01, Null);
Trigger02 = IIf(IsLong, Trigger02, Null);
Trigger03 = IIf(IsLong, Trigger03, Null);
ProfitLock = IIf(IsLong, ProfitLock, Null);
Trail01 = IIf(IsLong, Trail01, Null);
Trail02 = IIf(IsLong, Trail02, Null);
Trail03 = IIf(IsLong, Trail03, Null);
/* Plot Sector Omega (Sub-Panel Plots)
*/
Plot(Profit, "Profit", colorLime, styleArea);
Plot(IsLong, "IsLong", colorGrey50, styleArea);
Plot(Loss, "Loss", colorRed, styleArea);
Plot(0,"0",colorBlack,styleThick);
Plot (2 * Buy, "Buy", colorBlue, styleThick | styleArea);
//Plot(ATR(AtrPeriod)*AtrCheck,"AtrCheck",ColorRGB(222,222,222), styleArea);
//Plot(TradeAge, "TradeAge", colorBlack);