Option Contract Re-Selection and Arbitrary Legs
In the previous lecture, we employed abstraction to write out a fairly acceptable backtest engine for testing out the variance premium.
As we mentioned, there are still alot of points worth working on, so we want to address those issues. We improve our code base to vastly enhance it.
The code is attached, so we are only going to make comments at the central points that I want to highlight - for the implementation details, please peruse the code on your own. The final product and detailed walkthrough of the programming is recorded in our quant lectures:
https://hangukquant.thinkific.com/courses/qt202-quantitative-options-testing
From this abstracted code base, let’s argue some limitations.
First, we assume that the contracts were continuously rebalanced. However, in practical settings, this is often not true. We set up some initial position, such as a straddle, and as the underlying moves, our delta exposure changes, and rather than rebalancing out of those contracts into a new delta-neutral structures, we would either bear the delta risk or employ some discrete hedging. Either way, we are not that likely to do continuous rebalancing, unless we are doing something with 0dtes and holding them to expiry.
Rebalancing however, is still important. Delta hedging allows us to manage delta risk, but our gamma exposure is unchanged. Gamma measures the option price convexity, and can be said to be the option-ness of the option. When the underlying moves, away from the ATM strike, then the gamma exposure falls…suppose an extreme scenario where you are holding a long straddle/strangle, and the underlying increases so far to the extent that your call is near delta one and put is near delta zero. Your, originally delta neutral option structure, now behaves like a delta one position, and your hedge would be a one-for-one offsetting position. This is no longer even a volatility position, and you would want to rebalance the contracts so that you can pick up the gamma.
So we want to implement a rebalancing feature.
Another thing we want to improve is having an automated option selector. Right now, we manually select a straddle with arduous Python code. What if we want a strangle, or a bull call spread, an iron condor, or calendar spread instead?
We might just want to write something like this for a calendar spread:
strategy={
"legs":{
"0":{
"type":"call",
"selector":[
(OPTION_SELECTOR.STRIKE.ATM_REFERENCE_JUMP,1),
(OPTION_SELECTOR.EXPIRY.NEAREST,20)
],
"contracts":1
},
"1":{
"type":"call",
"selector":[
(OPTION_SELECTOR.STRIKE.ATM_REFERENCE_JUMP,1),
(OPTION_SELECTOR.EXPIRY.NEAREST,50)
],
"contracts":-1
},
},
"underlying":0
},
or a bull call spread:
strategy={
"legs":{
"0":{
"type":"call",
"selector":[
(OPTION_SELECTOR.STRIKE.ATM_REFERENCE_JUMP,1),
(OPTION_SELECTOR.EXPIRY.NEAREST,20)
],
"contracts":1
},
"1":{
"type":"call",
"selector":[
(OPTION_SELECTOR.STRIKE.ATM_REFERENCE_JUMP,2),
(OPTION_SELECTOR.EXPIRY.NEAREST,20)
],
"contracts":-1
},
},
"underlying":0
},
or a strangle:
strategy={
"legs":{
"0":{
"type":"call",
"selector":[
(OPTION_SELECTOR.STRIKE.DELTA_NEAREST,0.40),
(OPTION_SELECTOR.EXPIRY.NEAREST,20)
],
"contracts":1
},
"1":{
"type":"put",
"selector":[
(OPTION_SELECTOR.STRIKE.DELTA_NEAREST,-0.40),
(OPTION_SELECTOR.EXPIRY.NEAREST,20)
],
"contracts":1
},
},
"underlying":0
},
or a covered call:
strategy={
"legs":{
"0":{
"type":"call",
"selector":[
(OPTION_SELECTOR.STRIKE.DELTA_NEAREST,0.40),
(OPTION_SELECTOR.EXPIRY.NEAREST,20)
],
"contracts":-1
},
},
"underlying":1
},
that way we don’t have to write additional code each time we want to test a new option structure. But more importantly, not writing new code means not introducing new bugs, which means less operational risk, which means less trading risk.
Last but not least, we want to introduce vectorization. This just makes everything cleaner and more efficient.
See how we tackle this problems in our improved code base, which evolves the abstracted options backtester.
Code files (paid):