CustomMenu

Wednesday, September 28, 2016

Momentum Rotation System AmiBroker Code

I've received several requests for details on the AmiBroker (AB) code and settings used for the backtest shown in my April post: Momentum Rotation 60 Day ROC System Results. That post used the AmiBroker Formula Language (AFL) code from my article in March 2015.  That was a long time ago, so here is the 60 day momentum rotation system AFL again:
SetBacktestMode( backtestRotational );

// 1 ###### BACKTESTER SETTINGS - 1. GENERAL TAB 
SetOption("InitialEquity", 100000);
SetOption("MinShares", 1);
SetOption("MinPosValue", 0);
SetOption("FuturesMode", False);
SetOption("AllowPositionShrinking", False);
SetOption("ActivateStopsImmediately", False);
SetOption("ReverseSignalForcesExit", False);
SetOption("AllowSameBarExit", False);
RoundLotSize = 0;
TickSize = 0;
MarginDeposit = 0;
PointValue = 1;
SetOption("CommissionMode", 2);
SetOption("CommissionAmount", 7.95);
SetOption("InterestRate", 0);
SetOption("AccountMargin", 100);
SetOption("MarginRequirement", 100);

// 2 ###### BACKTESTER SETTINGS - 2. TRADES TAB 
BuyPrice = SellPrice = ShortPrice = CoverPrice = Close;
SetTradeDelays( 1, 1, 1, 1);

// 5 ###### BACKTESTER SETTINGS - 5. PORTFOLIO TAB 
//SetOption("MaxOpenPositions",   1);
// check the box to "Add artificial future bar..."
// Limit trade size as % - use 10 for live trading
// check the box to "Disable trade size limit..."
SetOption("UsePrevBarEquityForPosSizing", False);
SetOption("UseCustomBacktestProc",  False);

// 6 ###### BACKTESTER SETTINGS - 6. WALK FORWARD TAB
//SetOption("WorstRankHeld",    1);


Totalpositions = 1;
SetOption("WorstRankHeld", 1);
SetOption("MaxOpenPositions", Totalpositions );
PositionSize = -100 / Totalpositions ;

LastDayOfMonth = IIf( (Month() == Ref( Month(), 1) AND (Month() != Ref( Month(), 2)) ), 1, 0);
TradeDay = LastDayOfMonth ;

Score = ROC(Close, 60);
PositionScore = IIf(Score < 0, 0, Score ); // Long only
PositionScore = IIf(TradeDay , PositionScore , scoreNoRotate);

//Exploration
Filter = 1;
AddColumn(Score ,"Score",1.1);
AddColumn(PositionScore ,"PositionScore ",1.1);
AddColumn(PositionSize ,"Position Size",1.1);
You can download the AFL code above from my Google Drive: 00_60DayMomentum.afl

It is fairly straight forward AFL code, but I've highlighted four key areas:
  • Line 1 - Rotational trading needs to be activated for this system
  • Line 24 - Trade delays are set to 1, which means trades are entered one day after the signal is generated
  • Line 43 - The LastDayOfMonth variable actually stores the second to last day of the month.  This causes the rotation ranking signal to be calculated on the second to last day of the month.  Since our trade delay is one, the trade occurs the following day, the last day of the month
  • Line 47 - If the ROC(60) is negative, then the PositionScore is set to 0, otherwise the PositionScore is set to the ROC(60)

On the second to last trading day of the month, this strategy calculates the 60 day ROC for each product in the portfolio based on closing prices on that day.  If the 60 day ROC is negative, the system sets the PositionScore to 0 for that product.  It then ranks all of the products in the portfolio, selecting the product with the highest rank.  If all products have a rank of 0, the system will move to cash.  On the last trading day of the month, it executes the buy and sell orders at the close - "market on close" orders in live trading.

In addition to the AFL code above, I used the AB settings shown below.  To replicate my results, you'll need to update your AB settings to match mine.

AmiBroker Backtester Settings - General Tab
AmiBroker Backtester Settings General Tab
(click to enlarge)

AmiBroker Backtester Settings - Trades Tab
AmiBroker Backtester Settings Trades Tab
(click to enlarge)

AmiBroker Backtester Settings - Stops Tab
AmiBroker Backtester Settings Stops Tab
(click to enlarge)

AmiBroker Backtester Settings - Report Tab
AmiBroker Backtester Settings Report Tab
(click to enlarge)

AmiBroker Backtester Settings - Portfolio Tab
AmiBroker Backtester Settings Portfolio Tab
(click to enlarge)

AmiBroker Backtester Settings - Walk Forward Tab
AmiBroker Backtester Settings Walk Forward Tab
(click to enlarge)

AmiBroker Backtester Settings - Monte Carlo Tab
AmiBroker Backtester Settings Monte Carlo Tab
(click to enlarge)

AmiBroker Backtester Filter Settings
AmiBroker Backtester Filter Settings
(click to enlarge)

To run my AFL in your installation of AmiBroker:
  • Download my AFL file
  • Open an AB Analysis tab
  • Select my AFL file in the Formula field on the Analysis tab
  • Update the filter settings (shown above) to only run this strategy against a specific Watch List
  • Change the range to "From-To dates", and then select a date range
  • Finally, select the Backtest button to run the strategy

After you have backtesting configured and running, the next step is to automate quote updates and signal generation.  I use the Windows Task Scheduler utility to call JS scripts, that in turn launch AB and AmiQuote.  This topic is beyond the scope of this article, but I may discuss it in the future.

Also, since my last blog post, there have been several articles on momentum trading, and the poor performance of these systems lately.  Here are a few worth reading:


Follow my blog by email, RSS feed or Twitter (@DTRTrading).  All options are available on the top of the right hand navigation column under the headings "Subscribe To RSS Feed", "Follow By Email", and "Twitter"

5 comments:

Larry P said...

Thanks for sharing, keep up the good work.

Revolver27 said...

Thanks for the great post!

Do you run into any issues with the returns for January each year using the code? I seem to get no returns ever in Jan when looking at the results in the charts/profit table.

Dave said...

I haven't had any issues with returns in January. Just to be sure, I ran this code just now and reviewed the AB report for the run...there were returns for every January from 2006 through this year. Looked pretty similar to the profit table in this post: http://dtr-trading.blogspot.com/search?updated-max=2016-07-06T07:00:00-06:00&max-results=3

Unknown said...

hi wanted to know if we can add a liquidity filter and moving average filer for stock selection

Dave R. said...

You could add filters to this code. The simplest and most straight forward approach would be to add additional PositionScore criteria, similar to how I added in the "Score" and "TradeDay" criteria.

Thanks,
Dave

Post a Comment