I am trying to avoid correlations skipping new trades in the same watchlist (i.e. indices, watchlist number 6) that a position is already open. The code below removes some trades but still keeps trades that should not be kept. See example:
I am not sure if I need to loop through symbols or if it is possible to do it easier.
Many thanks in advance
//BASIC ENTRY (NOT FILTERED)
Short = Cover = 0;
Buy = C > Ref(HHV(C,30),-1);
Sell = C < Ref(LLV(C,20),-1);
PositionSize = MarginDeposit = 1;
//NOW REMOVE NEW TRADES FROM THE SAME WATCHLIST "INDICES"
//IN TRADE LONG
inLong = Flip(Buy,Sell);
//indices full. No more trades until a sell
List = CategoryGetSymbols( categoryWatchlist, 6 );
if ( Status("stocknum") == 0 AND LastValue(StaticVarGet("IND") )==0 )
{
for ( n = 0; ( Symbol = StrExtract( List, n ) ) != ""; n++ )
{
SetForeign ( symbol );
Ind_full = IIf(inlong AND InWatchListName("indices"), 1, 0);
StaticVarSet("IND",Ind_full);
}
}
//Remove correlation trade
Buy = buy and not ref(StaticVarGet("IND"),-1);
you can create a composite ticker which is different from zero when you have a long position in one Index and then use this variable to exclude trades during backtest.
I tried creating a composite using scan and directly in backtest.
I don't get exactly the same results in these two composite tickers (it's something to check why), but you get the idea.
If you prefer you can use StaticVarAdd instead of AddtoComposite.
// run scan on indices watchlist to create composite array which is different from zero when indices are in long position
if ( Status("ActionEx") == actionScan)
{
bir=Status("barinrange");
Short = Cover = 0;
Buy = C > Ref(HHV(C,30),-1);
Sell = C < Ref(LLV(C,20),-1);
inLong = Flip( Buy, Sell )*bir ;
AddToComposite(inLong,"~~~IND","Close", atcFlagDefaults );
}
//create composite in backtest indices watchlist #:6
if ( Status("stocknum") == 0)
{
bir=Status("barinrange");
List = CategoryGetSymbols( categoryWatchlist, 6 );
for( i = 0; ( symbol = StrExtract( List, i ) ) != ""; i++ )
{
_TRACE("#AB: "+symbol);
SetForeign(symbol);
Short = Cover = 0;
Buy = C > Ref(HHV(C,30),-1);
Sell = C < Ref(LLV(C,20),-1);
inLong = Flip( Buy, Sell )*bir ;
AddToComposite(inLong,"~~~INDbt","Close", atcFlagDefaults+atcFlagEnableInBacktest );
RestorePriceArrays();
}
}
Short = Cover = 0;
Buy = C > Ref(HHV(C,30),-1);
Sell = C < Ref(LLV(C,20),-1);
if (InWatchList(6)) inIndices= Foreign("~~~IND","Close"); else inIndices=0;
Buy = Buy AND NOT inIndices ;
PositionSize = MarginDeposit = 1;
The cleaner and more efficient way would be to use the mid-level custom backtester to check if a trade is open in a symbol from the watchlist in question, and if it is then prevent any other symbols from the watchlist that have entry signals from becoming trades while the first trade remains open.
In the mid-level CBT, setting sig.Price = -1; will prevent the entry signal from becoming a trade.
//BASIC ENTRY (NOT FILTERED)
Short = Cover = 0;
Buy = C > Ref(HHV(C,30),-1);
Sell = C < Ref(LLV(C,20),-1);
PositionSize = MarginDeposit = 1;
SetCustomBacktestProc("");
if (Status("action") == actionPortfolio)
{
bo = GetBacktesterObject(); // Get backtester object
bo.PreProcess(); // Do pre-processing (always required)
DetailedLog = GetOption("PortfolioReportMode") == 1;
dt = DateTime();
WatchlistNum = 6;
List = CategoryGetSymbols( categoryWatchlist, WatchlistNum);
for (i = 0; i < BarCount; i++) // Loop through all bars
{
if (DetailedLog) bo.RawTextOutput("Bar Date: " + DateTimeToStr( dt[i] ));
ListTradeOpen = False;
for (trade = bo.GetFirstOpenPos(); trade; trade = bo.GetNextOpenPos())
{
if (StrFind(List, trade.Symbol))
ListTradeOpen = True; // Found an open trade in a symbol from the watchlist
break;
}
if (ListTradeOpen)
{
for (sig = bo.GetFirstSignal( i ); sig; sig = bo.GetNextSignal( i ) )
{
if (sig.IsEntry() AND StrFind(List, sig.Symbol)) // Entry signal for symbol from watchlist
{
sig.Price = -1; // Prevent entry signal becoming a trade
if (DetailedLog) bo.RawTextOutput("\tEntry Prevented in " + sig.Symbol);
}
}
}
bo.ProcessTradeSignals( i ); // Process trades at bar (always required)
}
bo.PostProcess(); // Do post-processing (always required)
}
Using SPY and QQQ as an example, running it without the CBT code, you get an overlapping entry on 19/05/2005:
adding in the CBT code and turning on the Detailed Log, you see that SPY entry signal being ignored.