// Strategy: RSI Selective
// Program control variables
fPort = 1; // 1 = Portfolio, 0 = All Trades
fSameBarExit = 1; // 1 = allow same bar exit (day trades), 0 = disallow
nEntryTiming = 0; // 0 = Same Bar on Close, 1 = Next Bar at Avg Price
nExitTiming = 0; // 0 = Same Bar on Close, 1 = Next Bar at Avg Price
nMaxPos = 2; MaxPos = nMaxPos;
acctMargin = 100;
//pctPosSize = 100/nMaxPos * 100/acctMargin;
////////////////////////////////////////////////////*************************************************************
// Back Test Parameters
minVolume = 250*1000;
nDays = 2;
pctLimit = 1;//FS 4
// SetOption("usecustombacktestproc", True);
// SETUP //
#include_once "Formulas\Norgate Data\Norgate Data Functions.afl"
xMember = NorgateIndexConstituentTimeSeries("$SPX");
//SetBacktestMode(backtestRegularRawMulti); FS
//SetBacktestMode(backtestRegular); FS
SetOption("InitialEquity",IIf(fPort,10000,10000));
SetOption("CommissionMode",3);
SetOption("CommissionAmount",IIf(fPort, 0.01, 0));
SetOption("InterestRate",0);
SetOption("AllowSameBarExit", fSameBarExit);
SetOption("MaxOpenPositions",IIf(fPort,nMaxPos,2500));
SetOption("AccountMargin",IIf(fPort,acctMargin,100));
SetOption("UsePrevBarEquityForPosSizing",IIf(nEntryTiming==0,False,True));
SetOption("AllowPositionShrinking", True);
SetTradeDelays(nEntryTiming,nExitTiming,nEntryTiming,nExitTiming);
SetOption("ActivateStopsImmediately", IIf(nExitTiming==0,False,True));
SetOption("PriceBoundChecking", False); // - if set to False - disables checking and adjusting buyprice/sellprice/coverprice/shortprice arrays to current symbol High-Low range. Bij F, dan ab doet Low
SetOption( "Initialequity", 100000 );
SetOption( "MaxOpenPositions", MaxPos );
SetPositionSize( 100000/nMaxPos, spsValue );
////////////////////////////////////////////////////
// Initialize all arrays so the backtest will always run
Buy = Sell = Short = Cover = 0;
AvgPrice = (O+H+L+C)/4;
BuyPrice = ShortPrice = IIf(nEntryTiming==0,C,AvgPrice);
SellPrice = CoverPrice = IIf(nExitTiming==0,C,AvgPrice);
// Find the last bar where the price actually changed
BarsSinceLastChange = BarsSince(C != Ref(C,-1));
LastGoodBar = IIf(IsEmpty(BarsSinceLastChange), 0, BarCount - LastValue(BarsSinceLastChange) - 1);
fDelisted = LastGoodBar < BarCount -1;
inRange = Status("BarInRange") AND IIf(fDelisted, (LastGoodBar - BarIndex()) >= 3, True);
isLastBar = Status("LastBarInRange");
// Rank trade candidates by lowest RSI
PositionScore = 100 - RSI(2);
fLiquid = C > 5 AND
MA(V, 21) > minVolume;
BuySetup = xMember AND
fLiquid AND
RSI(2)<40 AND
RSI(2) == LLV(RSI(2),2) AND
C > MA(C,200) AND
inRange;
// Determine the limit price now, but allow the CBT to determine whether to enter the trade
pLimit = Ref(C,-1) * (1 - pctLimit/100);
BuyPrice = min(pLimit, O);
Buy = Ref(BuySetup,-1) ;
Sell = RSI(2)>70 OR
BarIndex() == LastGoodBar;
Filter = NorgateIndexConstituentTimeSeries("$SPX") AND BuySetUp ;
AddColumn(BuySetup, "BSetUP");
AddColumn(PositionScore, "PosScore");
AddColumn( (C - Ref(L,1))/C*100>pctLimit ,"hit");
AddColumn( (C - Ref(L,1))/C*100 ,"L.1 % lower than C");
//*
// Basic limit test with limit enforced in CBT
// Limit price should be assigned to the BuyPrice/ShortPrice array
SetBacktestMode(backtestRegularRaw);
SetCustomBacktestProc("");
if (Status("action") == actionPortfolio)
{
// Get backtester object
bo = GetBacktesterObject();
bo.PreProcess();
dn = DateNum();
if (fPort)
{
dailyRiskFreeRtn = Nz((1+(0)/100)^(1/365)-1); //zero interest
nElapsedDays = DaysSince1900()-Ref(DaysSince1900(),-1);
}
rptEquity = 0;
rptExposure = 0;
for (bar=0; bar < BarCount; ++bar)
{
bo.HandleStops(bar);
bo.UpdateStats(bar,1);
if (!fSameBarExit)
{
for (sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar))
{
if (sig.IsExit())
{
bo.ExitTrade(bar, sig.Symbol, sig.Price, sig.Reason);
} // end if Is Exit signal
}
bo.UpdateStats(bar,1);
}
nPos = 0;
for (openPos=bo.GetFirstOpenPos(); openPos; openPos=bo.GetNextOpenPos())
{
++nPos;
}
for (sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar))
{
if (fPort)
fAvailSlots = nPos < nMaxPos;
else
fAvailSlots = True;
if(sig.IsEntry() AND fAvailSlots)
{
trade = bo.FindOpenPos(sig.Symbol);
if (IsNull(trade))
{
++nPos;
SetForeign(sig.Symbol);
pOpen = O;
pHigh = H;
pLow = L;
RestorePriceArrays();
if (sig.IsLong())
fLimit = pLow[bar] < sig.Price;
else
fLimit = pHigh[bar] > sig.Price;
if (fLimit)
{
bo.EnterTrade(bar, sig.Symbol, sig.IsLong(), sig.Price, sig.PosSize, 0, sig.RoundLotSize);
}
}
}
}
bo.UpdateStats(bar,1);
if (fSameBarExit)
{
for (sig = bo.GetFirstSignal(bar); sig; sig = bo.GetNextSignal(bar))
{
if (sig.IsExit())
{
bo.ExitTrade(bar, sig.Symbol, sig.Price, sig.Reason);
}
}
}
bo.UpdateStats(bar,1);
bo.UpdateStats(bar,2);
if (fPort)
{
bo.cash *= ((1 + dailyRiskFreeRtn[bar]) ^ Nz(nElapsedDays[bar]));
}
}
bo.PostProcess();
StaticVarRemove("*");
bo.AddCustomMetric("Max Postions", nMaxPos);
}
//*/
I bought an AB course at trading markets. I understood everything, but by checking results i found wrong results with AB.
Probably I do something wrong, but I donot understand what.
I rebuild the RSI-Selective-Limit-Port met CBT FS201022, code, with a simple RSI, just to test.
When i tested the period 2020.08.01 – 2020.10.01 with
#include_once "Formulas\Norgate Data\Norgate Data Functions.afl"
xMember = NorgateIndexConstituentTimeSeries("$SPX");
maxpos = 2; // not to many symbols, so I can easily understand the portfolio.
pctLimit = 1; // to get more trades
I noticed that AB does not always take the top of the positon score.
Here are the trades of AB 2020.08.01 – 2020.10.01 :
for example, on 2020.09.17 AB bought HSY, while HSY is nr 4 on the positonscore at date 2020.09.16, it
should have tested for KR, this was not hit, so there should not be bought any stock at 2020.09.17 :
for example, on 2020.09.21 AB bought LKQ, while LKQ is nr 17 on the positonscore at date 2020.09.20,
it should have bought BF.B, which is nr 1 and is hit
would someone be so kind to help me and say what i am doing wrong? tanks a lot ! Frans