Using MA function

Hi All,
I am trying to backtest a system. It includes simple Moving average function (MA). The system runs on hourly data. For a candle of a particular hour if I want to calculate Moving average of close of last 5 hours then what should I use

MA(Close,5)

Or

MA( Ref(Close,-1),5)

I am afraid that if I use MA(Close,5) , it may pick the close value of the present hourly candle also which will skew the backtest results.

For example, at 3pm candle I want to calculate the moving average using the close of 10am, 11am, 12 noon, 1pm and 2pm candle.

If Data is updating then the most recent bar will vary.

ma5 = MA( C, 5);
prevBar = Ref( ma5, -1);    // -x for x bars ago

// I'd prefer shifting the ma5 variable instead of Close like you
// although it would be the same values

This is how you should reference the previous bar(s) MA.

MA will not change for all completed bars, it will change only for most recent bar if data is streaming.

When you are testing, you should not be afraid. Instead, you should analyze all the results from all the scenarios including frozen data from the cold storage.

1 Like

Thanks for the explanation.
I am backtesting on the historical data so although the data is not updating but I want to mimick the scenario of live trading and in that case it will up updating.
So what I understand is that using MA(close,5) will be forward looking in backtesting
Please correct me if I am wrong.

There are many scenarios, and you have to choose what is appropriate.

If you operate on current bar, there can be room for signal repainting, whereas if you operate on a completed bar you are certain.
I'd rather have my stop hit on current bar then to wait till close, often these are key zones of support or resistance, if you wait till close, you end up paying an extra amount for loss.

So if my system only trades at close of each hourly candle then even if I use MA(close,5) in my bactesting then it should not be forward looking in backtesting and should be similar to what it will be like when the system is trading live , correct?

yes, pretty much so.

It is not forward looking to do something like in following example:

SetTradeDelays( 0, 0, 0, 0 );

myma = MA( Close, 20 );

BuyPrice = Close;
Buy = Cross( Close, myma );

Signal occurs at Close of bar and close of bar is used as trade price. Both are present at same time.
But it is just unrealistic/unlikely that you would get trade entry/exit at close of bar in realtime.

So a more realistic approach in backtesting is doing this -> adding a bar entry delay and entering next bar at open price of bar:

SetTradeDelays( 1, 1, 1, 1 );

myma = MA( Close, 20 );

BuyPrice = Open;
Buy = Cross( Close, myma );

BTW, MA( Close, 20 ) price is known at close of bar only.


On the other hand a future leak would be this example:

SetTradeDelays( 0, 0, 0, 0 );

myma = MA( Close, 20 );

BuyPrice = Open;
Buy = Cross( Close, myma );

Trade price at open but a signal occurring at close of same bar (since there isn't any bar delay there).


As for adding bar delays.... either by using backtester function SetTradeDelays or by using Ref() function.

Using SetTradeDelays:

SetTradeDelays( 1, 1, 1, 1 );// one bar delay for all entries and exits

myma = MA( Close, 20 );

BuyPrice = Open;
Buy = Cross( Close, myma );

Using Ref():

SetTradeDelays( 0, 0, 0, 0 );// overriding analysis settings' delays of trades tab ensuring it is zero

myma = MA( Close, 20 );

BuyPrice = Open;
Buy = Ref(Cross( Close, myma ), -1);// one bar entry delay

Both upper two examples do the same thing.

3 Likes

@fxshrat,
Thanks for the tutorial. Your examples and explanations are well crafted and very instructive.

1 Like