Amibroker – SMART Trading Strategies https://smarttradingstrategies.com Statistical and Mathematical Approach to Retail Trading Mon, 03 Nov 2025 14:10:06 +0000 en-US hourly 1 https://smarttradingstrategies.com/wp-content/uploads/2021/08/logo-150x150.png Amibroker – SMART Trading Strategies https://smarttradingstrategies.com 32 32 A backtest of the Naïve System in Mean Reversion Trading Systems by Howard Bandy https://smarttradingstrategies.com/naive-system/ https://smarttradingstrategies.com/naive-system/#respond Fri, 10 Jan 2025 13:59:43 +0000 https://smarttradingstrategies.com/?p=1576 This system is taken from Howard Bandy’s Mean Reversion Trading Systems book. It’s a simple system that he presented in one of the earlier chapters (I believe it’s Chapter 3). Note that I have likely altered the code a bit; I’m unable to verify as I do not have the book with me now.

This system is more for exploration than for actual trading; the code includes a lot of variables that you can customize and test.

Regarding the data used

Data used for all backtests below is download from Yahoo Finance (as of 15 Jan 2025). This data is split adjusted but not adjusted for dividends.

The symbols used in all the tests are based on the current S&P 500 components. This list is not ideal, for reasons stated below:

  • Stocks that were in the S&P 500 before today (say in 2001) may no longer be in the current list. These stocks could even have gone bankrupt and may have led to large losses if they were included in the test.
  • Stocks that are currently in the list may have been small companies in the past. The fact that they are now included in the list means they have performed well, which leads to a bullish bias. Hence, results are highly likely to be better than they really are.

For reasons given above, a proper test should be conducted using the component stocks at each point in time. Nonetheless, let’s make do with the data that I have at the moment. In future if I have access to better data, I will update the results here.

Description

Entry rules

  1. A rising day is one where the close is higher than the previous day’s close. Conversely, a falling day is one where the close is lower than the previous day’s close.
  2. Buy at the close if the stock has risen for the past N days (inclusive of today) or fallen for the past N days.

Exit rules

  1. Exit using a profit target
  2. Exit after n days
  3. Exit using a stop loss

Money Management rules:

  1. Risk a fixed dollar amount ($50,000) for each trade
  2. A maximum of 1 trade at any one time
  3. $5 commission per trade

Customization

The following variables are customizable and can be optimized:

  1. Number of rising or falling days required for entry
  2. Percentage of equity to risk
  3. Whether to use stop loss and what percentage for the stop loss
  4. Maximum holding periods (for n-bar exit)
  5. Percentage for profit target
  6. Direction: Buy after N rising days or N falling days

Explorations

Initial Settings

The following initial settings were used

  • Risk Per Trade = 50000
  • Direction = 0
  • N = 3
  • Hold Days = 7
  • Profit Target = 0.4%
  • Stop Loss = 0 (no stop loss), Stop Loss Threshold = 20%

In Sample Data Range: 1 Jan 2000 to 31 Dec 2020

Out of Sample Data Range: 1 Jan 2021 to 31 Dec 2024

Results using Initial Settings

CAGR7.00%
Total Number of Trades2758
Percentage of Winners91.41%
Avg Profit/Avg Loss331.64/2864.46
Max System Drawdown-53.63%

Comparing Direction = 0 vs Direction = 1

Direction = 0Direction = 1
CAGR7.00%-3.03%
Total Number of Trades27582384
Percentage of Winners91.41%88.76%
Avg Profit/Avg Loss331.64/2864.46105.04/918.10
Max System Drawdown-53.63%-81.03

Clearly, the system performs much better when Direction = 0 (i.e. buying after N falling days). In other words, this works better as a mean reversion system.

Subsequent tests will use Direction = 0.

Optimizing N (number of falling days)

N = 10 and 11 produce the best results. However, the number of trades is too low (392 and 207 respectively).

The number of trades drop below 1500 from N = 8 onwards. I prefer to have at least 1500 trades. Therefore, I will choose N = 7 moving forward.

Optimizing Hold Days and Profit Target

Hold Days = 3, 4, 5, 6 appear to work well

Although the CAR/MDD is the highest when profit target is 0.8%, it drops off a lot when the target is changed slightly to 0.6% or 1.0%. A profit target of 1.0% to 1.6% appears to be more robust.

Moving forward, we’ll choose a profit target of 1.4% and hold days of 5 days.

Optimizing Stop Loss Parameters

Applying a stop loss of 10% results in the worst performance (CAGR = 7.39%, Max DD = -30.62%).

With a stop loss of 20%, the CAGR improves to 8.7%, with a max drawdown of -16.69%.

With a stop loss greater than 20%, CAGR and maximum drawdown is the same as without using a stop loss (CAGR = 9.47%, Max DD = -16.69%).

Stop loss tends to result in poorer results, but may be useful psychologically. If stop loss is used, a 20% threshold is suggested.

Final Results

  • Risk Per Trade = 50000
  • Direction = 0
  • N = 7
  • Hold Days = 5
  • Profit Target = 1.4%
  • Stop Loss = 1, Stop Loss Threshold = 20%
In Sample
CAGR8.70%
Total Number of Trades1206
Percentage of Winners77.2%
Avg Profit/Avg Loss837.01/1967.35
Max System Drawdown-16.69%

Results is largely flat from 2014 onwards.

Out of Sample
CAGR5.03%
Total Number of Trades212
Percentage of Winners72.64%
Avg Profit/Avg Loss770.56/1859.50
Max System Drawdown-36.11%

The greatest drawdown occurs in 2022, specifically in Jan and Mar. Nonetheless, due to the rapid recovery of the stock market, the year ended with a positive return of 11.6%.

Code

// BuyAfterAnNDaySequenceMultiPosition.afl
// Taken or adapted from Mean Reversion Trading Systems by Howard Bandy

/*** Options ***/

SetOption("ExtraColumnsLocation", 1);
SetOption("CommissionMode", 2); 	//$ per trade
SetOption("CommissionAmount", 5);
SetOption("InitialEquity", 50000);
SetOption("MaxOpenPositions", 1);
SetBacktestMode(backtestRegularRawMulti);
SetTradeDelays(0,0,0,0);

/*** Position Sizing ***/

percentEQ = Param("Percentage of EQ to risk", 100, 1, 100, 1);
SetPositionSize(percentEQ*0.01*50000, spsValue);

/*** Entry Rules ***/

//Define a day as rising based on the closing price
Rising = C > Ref(C, -1);
Falling = C < Ref(C, -1);

//Direction. 1 == Rising, 0 == Falling
Direction = Param("Direction", 0,0,1,1); 	

//The number of days in the sequence
N = Param("N", 7, 1, 15, 1);

if (Direction == 1)
   NDSequence = Sum(Rising, N) >= N;
else	
   NDSequence = Sum(Falling, N) >= N;

Buy = NDSequence;
Sell = 0;
BuyPrice = SellPrice = Close;		//buy and sell at close

/*** Exit Rules ***/

//Maximum holding period
HoldDays = Param("HoldDays", 5,1,15,1);

//Profit target
ProfitTarget = Param("ProfitTarget", 1.4,0.2,4,0.2);

//Stop loss
SL = Param("Stop Loss", 1, 0, 1, 1);
StopLossThreshold = Param("Stop Loss Threshold", 20, 10, 100, 10);

ApplyStop(stopTypeProfit, stopModePercent, ProfitTarget);
ApplyStop(stopTypeNBar, stopModeBars, HoldDays);
if (SL)
   ApplyStop(stopTypeLoss, stopModePercent, StopLossThreshold);


/*** Plots ***/

SetChartOptions(0,chartShowArrows|chartShowDates);
_N(Title = StrFormat("{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ));
Plot( C, "Close", ParamColor("Color", colorDefault ), styleNoTitle | ParamStyle("Style") | GetPriceStyle() ); 

shapes = IIf(Buy, shapeUpArrow, shapeNone);
shapecolors = IIf(Buy, colorGreen, colorWhite);
PlotShapes(shapes, shapecolors);
]]>
https://smarttradingstrategies.com/naive-system/feed/ 0