Hi I am having a problem with passing my metrics to StaticVarGenerateRanks.
Part of my code (my metrics, is just n example to shown that I need a loop to calculate it):
//This sets the Static Metrics
for (y=ymin; y<=ymax; y++)
{ StaticVarSet( "Rocs"+Name() + y, IIf( var == y, Rocs, 0 ),persistent =True );// ROC at each variable Var
count= Cum(IIF(var ==y AND NumOfBars>0, 1,0)) ;// Number of occurrency per each case
StaticVarSet("Count"+Name()+y, count,persistent =True);
for( i = 1; i < BarCount; i++ )
{ if (var[i]==y AND NumOfBars[i]>=1+lag)
eq[i]=eq[i-1] *(1+Rocs[i]/100);
else
eq[i]= eq[i-1];
}
StaticVarSet("EQ"+Name()+y, eq,persistent =True);
geteq = StaticVarGet( "EQ"+Name()+y);
FValueEQ= LastValue(ValueWhen (fbr==1,geteq,1));
LValueEQ= geteq;
getcount=StaticVarGet("Count"+Name()+y);
addval=1e-20; //
CAR=((LValueEQ/FValueEQ)^(1/(getcount/12+addval))-1)*100;//*100;
StaticVarSet( "CAR"+Name()+y, CAR,persistent =True);
GETCAR=StaticVarGet( "CAR"+Name()+y);
for (i=1; i<BarCount; i++)
{ if(refvar[i]==y)
{ AGGCAR[i]= GETCAR[i];
StaticVarSet( "AGGCAR"+Name(), AGGCAR,persistent =True);
}
}
}
generates AGGCAR and stores it in a Static Variable which should then be used with StaticVarGenerateRanks.
My problem is that AGGCAR is not passes to StaticVarGenerateRanks because StaticVarGenerateRanks is computed if ( Status( "stocknum" ) == 0 )
When I run explorer (see attached file) AGGCAR is calculated correctly (AGGCAR column) but not passed to the StaticVarGenerateRanks calculation (RankMet column) . If I run the exploration twice I can see that (RankMet column) gets the right value from AGGCAR.
Rotational_with_rank_light_v1.afl (14.3 KB)
I guess the problem lays with the order of execution, basically I suspect that AGGCAR is calculated at each bar for each ticker, while StaticVarGenerateRanks (RankMet column) is generated when Status( "stocknum" ) == 0 ) only, therefore it misses all the AGGCAR because at Status( "stocknum" ) == 0 ) RankMet is not know for all tickers > 0.
I ve been trying to solve this issue for a while and cannot find a solution.
Any help would be very welcome.
JB
the whole code
//==========================================================================
// Source: Amibroker forum, from various sorces and my own contribution
//==========================================================================
// Settings and Options
SetOption("ExtraColumnsLocation",2);
// Watchlist // Backtester Settings //
wlnumber = GetOption( "FilterIncludeWatchlist" );
watchlist = GetCategorySymbols( categoryWatchlist, wlnumber );
NumTickers = StrCount( watchlist, "," ) + 1;
SetOption( "MaxOpenPositions", NumTickers );
SetOption( "CommissionMode", 1 ); // 1 = PeTickerRocent 0 = Dollars
SetOption("InitialEquity", 10000 ); // Initial Portfolio Equity
SetTradeDelays(0,0,0,0);
SetOption("AllowSameBarExit", True );
//=======================================================
lag=1;
Index= Foreign( ".SPX","C");
Var=IIf (Index>MA(C,12),1,0);
_SECTION_BEGIN("Action Type and Time Series");
ExploreFilter = ParamToggle("Explore","Last_Bar|All_Bars",1);
if ( ExploreFilter ) Filter = 1;
else Filter = Status( "lastbarinrange" );
// Run on all times or on First Visible Bar FVB
TimeSeriesSel=ParamList("Time Series From","All Series|First Visible Bar",0);
//DebugToggle=ParamToggle("Debug","NO|YES",1);
//HideToggle= ParamToggle("Hide","NO|YES",0);
_SECTION_END();
//=======================================================
//
_SECTION_BEGIN("Positions");
// Number of max open positions
PosQtyOptTog= ParamList( "PosQtyOpt:","NO|YES", Defaultval=0);
if (PosQtyOptTog=="NO")
PosQty = Param( "Number of Positions", 3, 1, NumTickers, 1) ;
if (PosQtyOptTog=="YES")
{ PosQtyMin = Param("PosQtyMin",1, 1, NumTickers, 1);
PosQtyMax = Param("PosQtyMax",NumTickers, 1, NumTickers, 1);
PosQtyOpt = Optimize( "Pos Qty Optimaser", 1, PosQtyMin, PosQtyMax, 1);
PosQty = PosQtyOpt;
}
URankNum = 1; // rank has to be be >URankNum
LRankNum= PosQty; // rank has to be be <=LRankNum
ExcTopRankTog= ParamList( "Exc Top Rank Optimiser:","NO|YES", Defaultval=0);
if (ExcTopRankTog=="YES")
{ ExcMin = Param("ExcTopPosMin",0, 1, NumTickers, 1);
ExcMax = Param("ExcTopPosMax",5, 1, NumTickers, 1);
ExcMaxRank = Optimize( "ExcPosQtyOpt", 1, ExcMin, ExcMax, 1);
URankNum = ExcMaxRank +1; // rank has to be be >=URankNum
LRankNum= URankNum + PosQty -1;
} // rank has to be be <= LRankNum
InEquity=Param("Initial Equity",1000,1,100,1000,10);
MinBars= Param("Min Bars",1,1,100,1);
CommPct=Param("% Commission", 0,0,5,0.01); // This set the value for the commissions
SetOption( "CommissionAmount", CommPct);
SetOption("HoldMinBars", MinBars );
_SECTION_END();
//=======================================================
_SECTION_BEGIN("In/Out market and cash");
// Choose if you want an In/Out Market filter
InOutTog=ParamToggle( "In/Out Market","NO|YES",Defaultval=1);
// If In/Out Market filter is (NO)
if( InOutTog==0)
{ InOut= 1; // This means that the Market Filter is always OFF
SPX=999; SPXMA=888;
}
// If In/Out Market filter is (YES)
if(InOutTog==1)// Filter ON
{ // Select a Ticker if In/Out Market filter is (YES)
MarInd= ParamList( "In/Out Market Ticker:",".SPX|Name()",Defaultval=0);
SPX=Foreign(MarInd,"C");
/// Choseee if Optimaze or Not the MA for the Ticker of In/Out Market filter
MarIndMAOptTog=ParamToggle( "In/Out MA Optimizer:","NO|YES",Defaultval=0);
// If Optimaze MA is (NO) the select teh MA Periods Manually
if(MarIndMAOptTog==0)
{ SPXMAPDS= Param("In/out MA periods",12, 1, 100, 1);
SPXMA=MA(SPX,SpxMAPds);
InOut= SPX>=SPXMA ;
}
// If Optimaze MA is (YES) this optimaze the MA Periods
if(MarIndMAOptTog==1)
{ // If Optimaze MA is (YES) this selects Min and Max MA Periods
SpxMaMin= Param("MA Min Pds",6, 1, 100, 1); //choose Min
SpxMaMax= Param("MA Max Pds",18, 1, 500, 1); //choose Max
SpxMaSte= Param("MA Ste Pds",1, 1, 100, 1); //choose Steps
SPXMAPds= Optimize("MA Pds",1,SpxMaMin, SpxMaMax,SpxMaSte); // optimizer
SPXMA=MA(SPX,SpxMAPds);
InOut= SPX>=SPXMA;
}
}
TickerMaTog=ParamToggle( "Ticker Moving Average","NO|YES",Defaultval=0);
if(TickerMaTog==0)
TickerMa=C; UpDown = 1;
if(TickerMaTog==1)
{ TickerMaOptTog=ParamToggle( "Opt Ticker Moving Av.","NO|YES",Defaultval=0);
if(TickerMaOptTog==0)
{ TickerMaPds= Param("Ticker Ma",12, 1, 100, 1);//Choose Moving Average
TickerMa=MA(C,TickerMaPds);
}
if(TickerMaOptTog==1)
{ TickerMaMin= Param("Min Ticker Ma",1, 1, 100, 1); //choose Min
TickerMaMax= Param("Max Ticker Ma",18, 1, 500, 1); //choose Max
TickerMaSte= Param("Step Ticker Ma",1, 1, 100, 1); //choose Steps
TickerMaPds= Optimize( "Ticker Ma Pds", 1, TickerMaMin, TickerMaMax, TickerMaSte); //Optimize Moving Average
TickerMa=MA(C,TickerMaPds);
}
}
CashTR = ParamList( "Cash Ticker:","$CASHTR|.SPX|#IND",Defaultval=0); // Ticker for cash
_SECTION_END();
//=======================================================
_SECTION_BEGIN("System Optimizer and Reports");
// This code sets if the system optimazer is OFF or ON (default=OFF)
OptTog= Paramtoggle("System Optimizer:", "OFF|ON",Defaultval=0);
if( OptTog==1 )
{ OptimizerSetEngine("cmae"); OptimizerSetOption("MaxEval", 10000000 ); }
// Report to be switched ON because of portfolio report
Report= ParamToggle("Report:","OFF|ON",DefaultVal=1);// 0 suppresses report; 1 foTickerRoces generation of full report;
SetOption("GenerateReport", report);
// This code sets if the type of report
ReportModetog=ParamList( "Report Mode:","Trade list|Detailed log|Summary|No output", Defaultval=2);
if(ReportModeTog=="Trade list") ReportMode= 0; if(ReportModeTog=="Detailed log") ReportMode= 1;
if(ReportModeTog=="Summary") ReportMode= 2; if(ReportModeTog=="No output") ReportMode= 3;
SetOption("PortfolioReportMode",ReportMode);
_SECTION_END();
//=========================================================
// ALL METRICS HERE
//=========================================================
eq=InEquity; // this comes from above settings
Rocs = ROC( C, 1 );
RefVar = Ref(Var,-lag);
YMin= 0;//LastValue( Lowest(Var) ); // Minimum for IND/Y/M/Other
YMax= 1;// LastValue( Highest(Var) ); // Maximum for IND/Y/M/Other
Car =InCount = PosSize = AGGCAR=0;
BI=BarIndex();
fbr = IIf(Status( "FirstBarInRange" ),1,Null) ;
lbr = IIf(Status( "LastBarInRange" ),1,Null) ;
NumOfBars= BI-ValueWhen (fbr==1,BI,1);
BuyPrice=Close; SellPrice=Close;
// Remove StaticVar at first symbol
if ( Status( "stocknum" ) == 0 )
{StaticVarRemove( "Rocs*" );
StaticVarRemove( "Count*" ); StaticVarRemove( "EQ*" );
}
//This sets the Static Metrics
for (y=ymin; y<=ymax; y++) if(y!=0)
{ StaticVarSet( "Rocs"+Name() + y, IIf( var == y, Rocs, 0 ),persistent =True );// ROC at each variable Var
count= Cum(IIF(var ==y AND NumOfBars>0, 1,0)) ;// Number of occurrency per each case
StaticVarSet("Count"+Name()+y, count,persistent =True);
for( i = 1; i < BarCount; i++ )
{ if (var[i]==y AND NumOfBars[i]>=1+lag)
eq[i]=eq[i-1] *(1+Rocs[i]/100);
else
eq[i]= eq[i-1];
}
StaticVarSet("EQ"+Name()+y, eq,persistent =True);
geteq = StaticVarGet( "EQ"+Name()+y);
FValueEQ= LastValue(ValueWhen (fbr==1,geteq,1));
LValueEQ= geteq;
getcount=StaticVarGet("Count"+Name()+y);
addval=1e-20; //
CAR=((LValueEQ/FValueEQ)^(1/(getcount/12+addval))-1)*100;//*100;
StaticVarSet( "CAR"+Name()+y, CAR,persistent =True);
GETCAR=StaticVarGet( "CAR"+Name()+y);
for (i=1; i<BarCount; i++)
{ if(refvar[i]==y)
{ AGGCAR[i]= GETCAR[i];
StaticVarSet( "AGGCAR"+Name(), AGGCAR,persistent =True);
}
}
}
//=========================================================
// Scenarios Metrics END
//=========================================================
// --- metrics ranking routine ---
if ( Status( "stocknum" ) == 0 )
{
StaticVarRemove( "RankMet*"); StaticVarRemove( "ActMet*");
StaticVarRemove( "RankRank*"); StaticVarRemove( "PosSize*");
StaticVarRemove( "UpDown*");
//This sets the Static Metrics
for ( i = 0; ( symbol = StrExtract( watchlist, i ) ) != ""; i++ )
{ SetForeign( symbol );
////==============================================
//// Metrics for ticker ranking values STARTS HERE
UpDown = 1; //
CARG=StaticVarGet( "AGGCAR"+Symbol);
RankMet = CARG ;// Actual value used for the ranking !!
////==============================================
//// Metrics for ticker ranking values ENDS HERE
if ( symbol == CashTR )
{RankMet = -999;} // force lowest rank for cash ticker
if(TickerMaTog==1)
UpDown = C>= MA( C, TickerMaPds );
ActMet= RankMet; // This is the Actual Metrics before * UpDown
// Used for Ranking, If UpDown=0 the RankMet=0
RestorePriceArrays();
StaticVarSet( "RankMet" + symbol , RankMet,persistent =True);
StaticVarSet( "ActMet" + symbol , ActMet ,persistent =True);
StaticVarSet( "UpDown" + symbol , UpDown,persistent =True );
}
// This generates rank for "RankMet" the actual Metrics used for the Ranking
StaticVarGenerateRanks( "Rank", "RankMet", 0, 1224 );
//This gets the Static Metrics Variables
for ( i = 0; ( symbol = StrExtract( watchlist, i ) ) != ""; i++ )
{ if(TickerMaTog==1)
{UpDown = StaticVarGet( "UpDown" + symbol);
RankNum = StaticVarGet( "RankRankMet" + symbol ) ;
// n. top ranked symbols above their MA filter
InCount = IIf( RankNum <= PosQty AND UpDown==1, InCount + 1, InCount );}
if(TickerMaTog==0)
{ RankNum = StaticVarGet( "RankRankMet" + symbol );
// n. top ranked symbols above their MA filter
InCount = IIf( RankNum <= PosQty AND UpDown==1, InCount + 1, InCount );}
}
//This sets the PosSize
for ( i = 0; ( symbol = StrExtract( watchlist, i ) ) != ""; i++ )
{ RankNum = StaticVarGet( "RankRankMet" + symbol );
UpDown = StaticVarGet( "UpDown" + symbol);
if(symbol==CashTR) // this apply to cash
{ PosSize= IIF(INOUT==0,100,(PosQty-InCount) * 100 / PosQty);
}
else // this apply to any other symbol
{ PosSize = IIf( RankNum <= LRankNum AND RankNum >= URankNum AND UpDown==1 AND INOUT==1, 100 / PosQty, 0 );
}
StaticVarSet( "PosSize" + symbol, PosSize ,persistent =True);
}
}
// --- get values and ranks for Momentum ---
symbol = Name();
RankMet = StaticVarGet( "RankMet" + symbol );
ActMet = StaticVarGet( "ActMet" + symbol );
RankNum = StaticVarGet( "RankRankMet" + symbol );
PosSize = StaticVarGet( "PosSize" + symbol );
UpDown = StaticVarGet( "UpDown" + symbol );
// --- re-balance at the end/close of every month ---
//M=Month(); LDM= M!=Ref(M,1); // This is the last day of the month
Buy = PosSize > 0 ;
Sell = 1;
// --- set position sizes ---
PositionSize = -PosSize; // "-" sign for spsPercentOfEquity
// --- set stop in number of bars ---
//=========================================================
// Exploration //
//=========================================================
if ( Status( "actionex" ) == actionExplore )
{
SetSortColumns( 2,3);
// --- columns for exploration ---
SetOption( "NoDefaultColumns", True );
AddTextColumn( Name() , "Ticker" );
AddColumn( DateTime(), "Date", formatDateTime );
ColorRank = IIf( RankNum <= PosQty AND PosSize, ColorGold, colorWhite );
ColorPos = IIf( PosSize > 0, IIf( Name() == CashTR, colorYellow, colorGold ), colorWhite );
ColorInOut= IIF( InOut ==0, colorYellow, colorWhite);
ColorUpDown= IIF( UpDown ==0, coloryellow, colorWhite);
ColorInCount=IIF( InCount >0, ColorGold, colorWhite);
AddColumn( RankNum , "RankNum" , 1.0, 1, ColorRank );
AddColumn( RankMet , "RankMet" , 3.3 );
AddColumn( ActMet , "ActMet" , 3.3 );
AddColumn( PosSize, "PosSize(%)", 3.3, 1, ColorPos );
AddColumn( InCount, "InCount", 3.0, 1, ColorInCount );
AddColumn( C , "Close" , 1.2);
AddColumn( TickerMa , " Ticker MA" , 1.2);
AddColumn( UpDown , "UpDown" , 1.0,1 ,ColorUpDown);
AddColumn( InOut , "InOut" , 1.0,1, ColorInOut);
AddTextColumn( MarInd , "MarInd");
AddColumn( SPX , "SPX" , 1.2);
AddColumn( SPXMA , "SPXMA" , 1.2);
AddColumn( NumOfBars, "Bars",1);
AddColumn(AGGCAR,"AGGCAR",1.3);
for (y=ymin; y<=ymax; y++)
{ gettroc = StaticVarGet( "Rocs"+Name()+y);
geteq= StaticVarGet( "EQ"+Name()+y);
getcar= StaticVarGet( "CAR"+Name()+y);
getcount= StaticVarGet( "count"+Name()+y);
AddColumn(IIf(Var==y,getTRoc,Null), "Roc_"+y ,1.2);
AddColumn(IIf(Var==y,geteq,Null) , "EQ_"+y ,1.2);
AddColumn(IIf(Var==y,getcar,Null) , "CAR_"+y ,1.2);
AddColumn(IIf(Var==y,getcount,Null) , "count_"+y ,1);
}
}
//=========================================================
// Backtesting Stats
//=========================================================
function GetFormulaName()
{ return StrExtract( StrExtract( GetFormulaPath(), -1, '\\' ), -2, '.' ); }
FileName=GetFormulaName();
SetCustomBacktestProc(""); // Now custom-backtest procedure follows
if( Status("action") == actionPortfolio )
{
bo = GetBacktesterObject();
bo.Backtest(); // run default backtest procedure
st = bo.GetPerformanceStats(0); // get stats for all trades
// Here we add custom metric to backtest report
//Weigthed Reward/Risk Ratio
WRR = st.GetValue("WinnersAvgProfitPercent")*st.GetValue("WinnersPercent")/
abs(st.GetValue("LosersAvgLossPercent")*st.GetValue("LosersPercent"));
bo.AddCustomMetric( "W R/R ", WRR );
e = bo.EquityArray();
StaticVarset( "EQ", e, persistent = True );
ModelType=StaticVarGetText("Model");
AddToComposite( e, "~~EQ_"+FileName + ModelType, "X", atcFlagDefaults |atcFlagEnableInPortfolio);
// Here we add custom metric at trade level
SumMAE = SumMFE= NumTrades = 0;
// iterate through closed trades first
for( trade = bo.GetFirstTrade(); trade; trade = bo.GetNextTrade() )
{ // here we sum up maximum adverse excursions
SumMFE= SumMFE + trade.GetMFE();
SumMAE = SumMAE + trade.GetMAE();
NumTrades++;
}
// iterate through eventually still open positions
for( trade = bo.GetFirstOpenPos(); trade; trade = bo.GetNextOpenPos() )
{
SumMFE = SumMFE + trade.GetMFE();
SumMAE = SumMAE + trade.GetMAE();
NumTrades++;
}
averageMFE = SumMFE / NumTrades;
bo.AddCustomMetric( "Av.MFE ", averageMFE );
averageMAE = SumMAE / NumTrades;
bo.AddCustomMetric( "Av.MAE ", averageMAE );
MFEMAE=abs(averageMFE)/abs(averageMAE);
bo.AddCustomMetric( "MFE/MAE", MFEMAE );
}
// --- end of code ---