Tomasz,
Thanks! Also for pointing me towards the "Detailed Log" (forgot it existed - was using Explore only ...).
Tried setting margin to a value other than 100 for a simpler formula, and I still get the use of margin for "SetPositionSize(50,spsPercentOfEquity) and one position only.
Must be doing something wrong ... below is the code, and further below the detailed log message for the first buy.
If you have a second to point me in the right direction, that would be great.
Robert
Code:
/**************************************************************************************************************************
**
** --- Global Equities Momentum (GEM) ---
**
** Designed for daily data
**
** Sources: Dual Momentum Investing (book) by Gary Antonacci
** Risk Premia Harvesting Through Dual Momentum - Gary Antonacci
**
** Website: http://www.optimalmomentum.com/index.html
**
** Notes: The monthly returns posted on Antonacci's site obey the rules of P98. Data used by Antonacci:
** - S&P 500: Ibbotson Large Cap Total Return (all the way to today)
** - ACWI ex US: MSCI ex US until 1987, ACWI ex US afterwards
** - Aggregate Bonds: Ibbotson Intermediate Govt Bond Total Return until Dec 1975, then Barclays US Aggregate Bond Index
**
** The tickers used for this formula use available ETFs (SPY, VEU and AGG) since their start date to better approximate real
** performance
**
****************************************************************************************************************************/
// --- Parameters and initialization ---
USEqu = "SPY";
NonUSEqu = "VEU";
Bonds = "AGG";
TBills = "BIL";
LookBackMonths = Param("LookBack Months",12,1,18,1);
Rules = ParamList("Rules","P98|P101");
SetOption("MaxOpenPositions", 1);
SetOption("AccountMargin", 50);
SetPositionSize(50,spsPercentOfEquity);
SetTradeDelays(0,0,0,0);
// --- Function to calculate ROC based on a variable period (array input) ---
function VarROC( array, periods )
{
prev = Ref( array, -periods );
return 100*(array - prev)/prev;
}
// --- Detect the rebalance day (last trading day of the month) ---
// --- Calculate lookback days ---
// During the month, look back to the month end that will be used on the last day of
// the month, so that in Explore the buy signal converges as the end of the month approaches)
BarNumber = Cum(Status("barinrange"));
LastDayOfMonth = IIf(Month() != Ref(Month(),1), 1 , 0);
LookBackDays = BarNumber - ValueWhen(LastDayOfMonth == 1, BarNumber, LookBackMonths + 1);
LookBackDays2 = BarNumber - ValueWhen(LastDayOfMonth == 1, BarNumber, LookBackMonths);
LookBackDays = IIf(LastDayOfMonth == 1, LookBackDays, LookBackDays2);
// --- Get symbol list ---
wlnum = GetOption( "FilterIncludeWatchlist" );
List = CategoryGetSymbols( categoryWatchlist, wlnum ) ;
// --- Calculate buy signals ---
if ( Status("stocknum") == 0 )
{
StaticVarRemove( "returns*" );
for ( n = 0; ( Symbol = StrExtract( List, n ) ) != ""; n++ )
{
SetForeign ( symbol );
returns = IIf(BarNumber > LookBackDays, VarROC(C,LookBackDays), 0); //Calculated on the close
RestorePriceArrays();
StaticVarSet ( "returns" + symbol, returns );
_TRACE( symbol );
}
returnsBonds = StaticVarGet("returns" + Bonds);
returnsUSEqu = StaticVarGet("returns" + USEqu);
returnsNonUSEqu = StaticVarGet("returns" + NonUSEqu);
returnsTBills = StaticVarGet("returns" + TBills);
buysignal = 0;
for ( n = 0; ( Symbol = StrExtract( List, n ) ) != ""; n++ )
{
switch( Symbol )
{
case Bonds:
if ( rules == "P98" )
buysignal = IIf (returnsUSEqu < returnsTBills, 1, 0);
else
buysignal = IIf ((returnsUSEqu < returnsTBills) AND (returnsNonUSEqu < returnsTBills), 1, 0);
break;
case USEqu:
buysignal = IIf((returnsUSEqu >= returnsNonUSEqu) AND (returnsUSEqu >= returnsTBills), 1, 0);
break;
case NonUSEqu:
if ( rules == "P98" )
buysignal = IIf((returnsNonUSEqu > returnsUSEqu) AND (returnsUSEqu >= returnsTBills), 1, 0);
else
buysignal = IIf((returnsNonUSEqu > returnsUSEqu) AND (returnsNonUSEqu >= returnsTBills), 1, 0);
break;
default: //applied for TBills
buysignal = 0;
break;
}
StaticVarSet("buy" + symbol, buysignal);
}
}
symbol = Name();
buysignal = StaticVarGet("buy" + symbol);
Buy = buysignal AND lastdayofmonth;
Sell = NOT buysignal AND lastdayofmonth;
BuyPrice = Close;
SellPrice = Close;
// --- Exploration ---
ExploreFilter = ParamToggle( "ExploreFilter", "LastBarInTest|All", 1 );
if ( ExploreFilter )
Filter = LastDayOfMonth;
else
Filter = Status( "LastBarInTest" );
if ( Status( "actionex" ) == actionExplore )
{
SetOption( "NoDefaultColumns", True );
AddTextColumn( symbol, "Ticker" );
AddColumn( DateTime(), "Date ", formatDateTime, colorDefault, colorDefault, 135);
SetSortColumns(-2);
bgdcolor = IIf(Buy == 1, colorGreen, colorWhite);
fgdcolor = IIf(Buy == 1, colorWhite, colorDefault);
AddColumn(Buy, "Buy ", -4.0, fgdcolor, bgdcolor , 70);
AddColumn(Close, "Close ");
returns = StaticVarGet("returns" + symbol);
AddColumn(returns, "Return", 1.2, fgdcolor,bgdcolor, 80);
AddColumn(lookbackdays, "Lookback");
}
And the first buy message from the detailed log:
01/31/2008
Entry signals(score):SPY=Buy(1),
Exit signals:
Enter Long, SPY, Price: 107.8685, Shares: 463, Commission: 0, Rank: 1, Equity 100000, Margin Loan: 24971.57, Fx rate: 1
1 Open Positions: , SPY (+463), Market Value: 49943.14, Equity: 100000.00, Cash: 75028.43, Margin: -24971.57, Net Cash Balance: 50056.86,
- adding interest on cash balance: net cash 50056.86, 0% rate, 1 night(s), value = 0.00