Backtester Development (Part 6)
Posted by Mark on November 29, 2022 at 07:26 | Last modified: June 22, 2022 08:36Today I will continue discussion of logic for my revamped backtesting program.
The ‘find_spread’ control branch involves one of four paths:
- If DTE > 200 then continue.
- Elif dte_list empty, strike price multiple of 25, and strike price > underlying price by < 26, then store current_date and append option data to respective lists. At the end, the program will select two options for the spread based on available DTE. Since the iteration cannot go in reverse, potentially relevant data must be stored when encountered.
- Elif DTE matches previously-stored DTE then continue (implied is that the lists are no longer empty).
- Elif current_date still matches, then insert option data to beginning of respective lists (implied is that DTE has changed).
- Else update current_date and proceed with spread selection since iteration of all options from previous date is complete.
>
Motivation for requiring 25-point spreads relates to the fact that 5- and 10-point strikes were not available many years ago when option trading volume was much lower.* Even today, 25-point strikes are regarded as having the most volume and best liquidity. If true (this would be exceedingly difficult to test and may require huge amounts of capital to attain large sample sizes of live trades), then this criterion makes good sense.
Requiring 25-point spreads is not without controversy, however. If I include a penalty for slippage regardless of strike-price multiple, then I probably do not need the 25-point limitation. I think a bigger problem is nonuniform strike density, which I discussed in the fourth paragraph here.
Spread selection proceeds as a nested for loop over dte_list, which now has DTE values of matched strike-price options from the same historical date across increasingly farther-out expirations:
- First list position with value > (30 x mte) is the target short option; all related option data corresponding to this list position are now encoded as such.
- Iterate over remainder of dte_list to match first index position with value greater than S_dte + (27 x width)** as target long option; all related option data corresponding to this list position are now encoded as such.
>
These lists are my solution to the problem of dynamic variables described in Part 4. Rather than initializing multiple sets of variables to hold unnecessary data, data is stored in lists with each element corresponding to a particular DTE option. Once the proper DTEs are determined, corresponding values are then assigned to the only set of pre-initialized variables.
I will continue next time with the ‘update_long’ control branch.
>
*—2017 – 2021 option volume is shown here.
>
**—I am using 27 rather than 28 in case of a Friday holiday.