How to set open positions at the start of a backtest? (Starting Positions)
Author: ronc
Creation Date: 5/18/2013 12:36 AM
profile picture

ronc

#1
Is there a way to set open positions at the start of a backtest? In other words, rather than have the backtest begin with no open positions, I want to set specific symbols to have specific open positions at the start of the backtest.

Thanks
Ron
profile picture

Eugene

#2
Well, you can establish the position(s) by issuing regular BuyAt*/ShortAt* commands for your stocks on bar 1 or later (buying on bar 0 is impossible due to the absense of the data required to calculate the basis price for the order). Check this Q&D example out:

CODE:
Please log in to see this code.


P.S. Note that it's impossible by modifying the Positions collection directly (unsupported):

CODE:
Please log in to see this code.
profile picture

Panache

#3
In order to get accurate back testing results, especially over relatively small data ranges, I want to have my strategy purchase all the positions on the first day of the back test that it would have had open if it had been started at an earlier date.

Initially, I started the strategy trading a couple of periods before the actual period I wanted to back test. I then did some math on the By Period metrics to get the performance during the actual back test period.

What I'm now doing is to run the strategy once with the ending date on the day before the beginning date of the back test I want to run, and write the open positions to a file. I then read the file and buy those position on the first date of the "real" back test. Obviously, this takes twice as long to run a back test, but it does allow me to utilize the Performance metrics directly.

Is there a better way to do this?

Concretely, let's assume I am using the Moving Average Crossover strategy applied to the S&P 500 with a maximum of 20 open positions and want to back test it over a period of 6 months. Depending on the beginning date, it may take some time before the strategy opens it's first position. Therefore, the performance metrics for the 6 month period may be very different from what they would be if I had been trading the strategy for some time, and the back test was just one of the 6 month periods during which I had been trading the strategy.
profile picture

Eugene

#4
QUOTE:
Therefore, the performance metrics for the 6 month period may be very different from what they would be if I had been trading the strategy for some time, and the back test was just one of the 6 month periods during which I had been trading the strategy.

Hope this helps:

FAQ: How to start Buy&Hold from specific bar (not at bar #0)?
profile picture

Panache

#5
Thanks, but unless I'm missing something, that doesn't tell me which positions would be open on bar 1. I use my own version of GetAllDataForSymbol to load sufficient data to have the moving average up and running at bar 1. However, some how the strategy has to start "trading" before bar 1 in order to determine the initial positions.

Let's say my strategy is limited to one open position and A crossed over at bar -15, but crossed back under at bar -5, AA crossed over at bar -10 and AAPL crossed over at bar -4. If I had been trading the strategy for the 15 previous days, it would have purchased A at bar -15, not purchased AA, because there was already one open position, sold A at bar -5 and purchased AAPL at bar -4.

Therefore, I'd like to have my back test start on bar 1 by buying AAPL, but not A or AA, which is the position that would have been open if I had been trading the strategy 15 days earlier.
profile picture

Panache

#6
What would really be useful for me is if you could add a drop down box for the date range over which the performance of the strategy and the benchmark is calculated, rather than using the Data Range for that. That way people could load and run their strategies on whatever data they needed and evaluate the performance of the strategy over specific periods.

Let's say I want to see the performance of a strategy over rolling 3 year periods. Currently, I need to set the Data Range for each 3 year period, run the strategy and look at the performance. With my suggestion, I could simply run the strategy once against All Data (or some subset specified in Data Range) and then change the performance date range to each of the 3 year periods I wanted to see. If I also wanted to see the results over 5 year periods, I could again change the performance date range without having to rerun the strategy.

Moreover, it would completely eliminate the lead bars issue, since I could load as much data as I wanted (and even run the strategy against what are now negative bar numbers) and see only the performance for the period I was interested in.

Currently, I use sliders to determine when the strategy starts trading, which can be independent of the Data Range. Therefore, I only use the Data Range to determine how much data to load. The performance is calculated correctly, except for the Benchmark, which is no longer useful, since it is tied to the beginning of the Data Range. Unfortunately, as highlighted above, my slider solution doesn't solve the problem of a strategy which needs to begin trading before the beginning of the period over which I want to evaluate the performance.

I know you guys are reluctant to add to the GUI, but I really think making the Data Range only be about how much data is loaded and adding a performance range would be worthwhile.
profile picture

Panache

#7
It occurs to me that I may be able to get what I'm looking for with a custom Visualizer that only uses the trades beginning on a certain date. (For now, I can just use the By Period information.) The more important question for me is whether I could optimize a strategy based on a custom parameter such as Net Profit after a certain date. I realize that this would require a custom Optimizer.

Before I spend a lot of time on this, I wanted to get your impression about whether this sounds feasible.

profile picture

Eugene

#8
Re: Visualizer. I don't think it's going to be easy. The built-in SystemPerformance and SystemResults objects (which contain backtest results generated by WL) automatically cover the entire backtest range. If you plan on using any metrics based on system's equity and performance, you may have to do all the TradingSystemExecutor's job from scratch.

EDIT: On a second thought, it may be easier than I initially thought because WFO (being a performance visualizer) already does something like that internally. It has to create Bars objects for different in/out of sample ranges and then applies the undocumented TradingSystemExecutor.
profile picture

Panache

#9
Not being a fan of trying to figure out undocumented commands, I decided the best way to accomplish what I wanted was by writing it into the Strategy. The Strategy uses a list to keep track of the positions beginning at the start of the Data Range and only generates buy and sell signals beginning with the last trading day of the year prior to January 1 of the Strategy Parameter Start Year. Therefore, the Data Range controls how much data is analyzed and the Start Year to the end of the Data Range controls how much of the data is included in the performance metrics. (Note that some performance metrics are not accurate with the Strategy, such as Annualized Gain % and Benchmark Buy & Hold, since they are calculated over the entire Data Range, rather than beginning on January 1 of the Start Year.) Doing it this way also results in a Strategy that can be optimized over January 1 of the Start Year to the end of the Data Range. (Don't include Start Year as one of the parameters to be optimized.)

Unless your Strategy requires a large number of lead bars or trades very infrequently, I suggest beginning the Data Range one year prior to the Start Year. That should give it ample time to get up and running to establish positions very much like what it would have had you been trading it for some time.

I welcome any suggestions for improvements and specifically for making the code more efficient.

For demonstration purposes, following is a Strategy for a simple SMA Crossover. To use it, run it against only ONE symbol in the DataSet. The
CODE:
Please log in to see this code.
causes it to check every other symbol in your DataSet.

CODE:
Please log in to see this code.
profile picture

Panache

#10
One correction to the above code:

CODE:
Please log in to see this code.


needs to be replaced with:

CODE:
Please log in to see this code.


Otherwise, it sells the most recently purchased position, regardless of whether or not it is the symbol specified in the SetContext statement.
profile picture

Eugene

#11
QUOTE:
One correction to the above code:

I've updated your code.