Home › Forums › Trading System Mentor Course Community › AmiBroker Coding and AFL › Dual Momentum Code
- This topic is empty.
-
AuthorPosts
-
March 21, 2019 at 11:00 pm #101906MichaelRodwellMember
I came across this code for Dual Momentum Investing. It’s a bit beyond me but thought it might help someone.
Credit to the author in the code and available by request from his website.
Code:/*
** —————————————–
**
** Global Equities Momentum by Gary Antonacci
**
** book : Dual Momentum Investing
** performance: http://www.optimalmomentum.com/trackrecord3.html
**
** rules per page 98 (not the flow chart from page 101):
** 1: when TBILL >= SP500 allocate to U.S. AGG. Bonds (even when ACWI > TBILL)
** 2: when SP500 > TBILL allocate to SP500 or ACWI depending which one has the highest 12-month return
**
** code by TrendXplorer
** [email protected]
** http://www.trendxplorer.info
** version: October 6, 2016
**
** —————————————–
*/// — detect watchlist —
wlnumber = GetOption( “FilterIncludeWatchlist” );
watchlist = GetCategorySymbols( categoryWatchlist, wlnumber );
numberOfAssets = StrCount( watchlist, “,” ) + 1;
N = numberOfAssets;// — backtester settings —
PosQty = 1; // Position Quantity: max number of positions
SetOption( “CommissionAmount”, 0.00 );
SetOption( “InitialEquity”, 100000 );
SetOption( “MaxOpenshort”, 0 );
SetOption( “MaxOpenLong”, PosQty );
SetOption( “MaxOpenPositions”, PosQty );
SetOption( “WorstRankHeld”, PosQty );
SetOption( “AllowPositionShrinking”, True );
SetPositionSize( 100 / PosQty, spsPercentOfEquity );
SetTradeDelays( 0, 0, 0, 0 );
SetOption( “HoldMinBars”, 1 );
SetBacktestMode( backtestRegular );
SetOption(“ExtraColumnsLocation”, 12 );
RoundLotSize = 1;// — inputs —
frequency = ParamToggle( “Rebalance Frequency:”, “Monthly|Quarterly”, 0 );
MomLength = Param( “Momentum Period”, 12, 1, 12, 1 );
_StockSymbol = ParamStr( “US Stock Fund”, “IVV” );
_BondSymbol = ParamStr( “Bond Fund” , “BND” );
_RFsymbol = ParamStr( “RiskFree Fund”, “BIL” );// — init bond switch —
BondSwitch = 0;
SumPos = 0;// — ranking routine —
// based on https://groups.yahoo.com/neo/groups/amibroker/conversations/topics/178791
if ( Status( “stocknum” ) == 0 OR Status( “stocknum” ) == -1 )
{
StaticVarRemove( “Rf*” );
StaticVarRemove( “US*” );
StaticVarRemove( “Ret*” );
StaticVarRemove( “Rank*” );
StaticVarRemove( “Bond*” );
StaticVarRemove( “Pos*” );Data = Foreign( _RFsymbol, “C” );
RfRet = 100 * Nz( -1 + Data / Ref( Data, -MomLength ) );
StaticVarSet( “RfRet”, RfRet );Data = Foreign( _StockSymbol, “C” );
USret = 100 * Nz( -1 + Data / Ref( Data, -MomLength ) );// — determine absolute momentum —
BondSwitch = RfRet >= USret;StaticVarSet( “RfRet” , RfRet );
StaticVarSet( “USret” , USret );
StaticVarSet( “BondSwitch”, BondSwitch );for ( i = 0; ( symbol = StrExtract( watchlist, i ) ) != “”; i++ )
{
SetForeign( symbol );
Ret12m = 100 * Nz( -1 + Close / Ref( Close, -MomLength ) );
RestorePriceArrays();if ( symbol == _BondSymbol ) Ret12m = Null;
StaticVarSet( “Ret12m” + symbol, Ret12m );
}// — generate ranks for slow and fast momentum —
StaticVarGenerateRanks( “Rank”, “Ret12m”, 0, 1234 );for ( i = 0; ( symbol = StrExtract( watchlist, i ) ) != “”; i++ )
{
Ret12m = StaticVarGet( “Ret12m” + symbol );
RankRet12m = StaticVarGet( “RankRet12m” + symbol );
RfRet = StaticVarGet( “RfRet” );
BondSwitch = StaticVarGet( “BondSwitch” );if ( symbol != _RFsymbol )
{
if ( symbol == _BondSymbol )
{
PosSize = IIf( BondSwitch, 100, 0 );
SumPos = SumPos + PosSize;
}
else
{
PosSize = IIf( RankRet12m == 1 AND !BondSwitch, 100, 0 );
SumPos = SumPos + PosSize;
}
}
else
{
PosSize = 0;
}StaticVarSet( “PosSize” + symbol, PosSize );
}StaticVarSet( “SumPos”, SumPos );
}// — get values and ranks for Momentum —
symbol = Name();
RfRet = StaticVarGet( “RfRet” );
USret = StaticVarGet( “USret” );
Ret12m = StaticVarGet( “Ret12m” + symbol );
RankRet12m = StaticVarGet( “RankRet12m” + symbol );
BondSwitch = StaticVarGet( “BondSwitch” );
PosSize = StaticVarGet( “PosSize” + symbol );
ExcRet = IIf( symbol == _BondSymbol, Null, Ret12m – RfRet );
ret1m = 100 * ( Close / Ref( Close, -1 ) – 1 );
RetPf = Ref( Ret1m, 1 );// — detect end of quarter —
QuarterEnd = Month()%3 == 0;// if ( frequency == “Monthly” )
if ( !frequency )
{
rebalance = 1;
holdbars = 1;
}
else
{
rebalance = QuarterEnd;
holdbars = 3;
}// — buy trigger when wi > 0 —
Buy = rebalance AND PosSize;
Sell = 0;
Short = Cover = 0;
BuyPrice = Close;
SellPrice = Close;// — exit at EoM for rebalancing —
ApplyStop( stopTypeNBar, stopModeBars, holdbars, exitatstop = 0 );// — exploration filter —
ExploreFilter = ParamToggle( “ExploreFilter”, “Portfolio|All”, 1 );
if ( ExploreFilter )
Filter = 1;
else
Filter = PosSize > 0; // Status( “LastBarInTest” );// — sort for exploration only (not on backtest) —
if ( Status( “actionex” ) == actionExplore )
{
SetSortColumns( 2, -6, 5 );ColorTopRisk = IIf( RankRet12m == 1 AND Ret12m > RfRet, colorBrightGreen, IIf( RankRet12m == 1, colorRed, colorWhite ) );
ColorPosSize = IIf( PosSize, IIf( symbol == _BondSymbol, colorYellow, colorGold ), colorWhite );AddColumn ( RfRet , “RiskFree (%)” , 3.3 );
AddColumn ( USret , “US Market (%)” , 3.3 );
AddColumn ( Ret12m , “Return 12m (%)” , 3.3, 1, ColorTopRisk );
AddColumn ( ExcRet , “ExcessRet 12m (%)”, 3.3, 1, ColorTopRisk );
AddColumn ( PosSize , “PosSize (%) ” , 1.0, 1, ColorPosSize );
AddTextColumn( Name() , “Tickers” , 1.0, 1, ColorPosSize );
AddColumn ( RetPf , “Portfolio (%)” , 3.3 );//AddColumn ( RankRet12m , “RankMom” , 1.0 );
//AddColumn ( BondSwitch, “BondSwitch” , 1.0 );}
// — initiate custom-backtest procedure —
SetCustomBacktestProc( “” );
//
// — set custom name for portfolio equity —
_PortfolioName = ParamStr( “~~~PortfolioName”, “~~~GEM” );
//
if ( Status( “action” ) == actionPortfolio )
{
bo = GetBacktesterObject();
//
bo.Backtest( 1 );
//
eq = bo.EquityArray;
//
// — iterate through closed trades collect EquityAtExit data —
for ( trade = bo.GetFirstTrade(); trade; trade = bo.GetNextTrade() )
{
EquityAtExit = Lookup( eq, trade.ExitDateTime );
trade.AddCustomMetric( “Equity at exit”, EquityAtExit );
}
bo.ListTrades();
//
// — save equity data to composite symbol —
AddToComposite( bo.EquityArray,
_PortfolioName, “X”,
atcFlagDeleteValues | atcFlagEnableInPortfolio );
//
}
// — end of code — -
AuthorPosts
- You must be logged in to reply to this topic.