Back

Theoretical options backtesting framework

In light of the new update, I hereby present my theoretical option backtesting framework which I was working on. This should help, or otherwise speed up, the development of the formal inclusion of options in QuantConnect. Specifically if actual option data is included in QuantConnect, my code could help to derive the option's theoretical properties, such as the greeks. This because I've already implemented all such theoretical formulas in my code (with help from this forum thread).

As the title states, I've tried to create a theoretical option backtesting framework, in which options are calculated using the price of the underlying and the famous Black-Scholes model. Clearly, the greeks do not work if you don't have the actual price of the option, but I've included them anyway (as to help the development of the formal option framework).

In order to use my framework, one must specify how many options you want to use in the algorithm. That is, one must specify how many in-the-money and out-of-money options the algorithm should calculate (these are based on CALLS !!!). Basically, this specifies the depth of options that one will use at any particular moment in the maturity of an option. Note: the depth is based on the current price. Likewise, one must also specify how many maturities in the future the framework should calculate. In a similar manner, one should specify whether the algorithm should use "MONTHLY" options or "WEEKLY" options (yes, both exist!).

Resolution _res = Resolution.Daily;
string[] options = {"CALL", "PUT"};
// type of option maturities (also: "WEEKLY")
string _maturityType = "MONTHLY";
// number of option strikes that you want to include
int _nof_strikes = 3;
// number of option maturities that you want to include
int _nof_maturities = 3;

To give you an example, if you specify "MONTHLY", _nof_strikes = 3, _nof_maturities = 3, the framework will, at each maturity date, calculate the values of 3 in-the-money options and 3 out-of-money options, each for 3 maturities (months!) in the future. So these will be the only options that you can then use in your algorithm.

But how to use any given option? Simple:

Order("SPY.CALL.1.2", 80*100);
This means: buy 80 CALL option contracts on SPY, with the nearest in-the-money strike and the second nearest maturity.

Easy right? In the same manner, Order("SPY.CALL.-1.1", 80*100); buys the nearest out-the-money strike with the nearest maturity.

So, what would a bull spread using CALLS look like?

// buy one call with a low strike (at some maturity)
Order("SPY.CALL.-1.2", 80*100);
// sell (also called "write") calls with a higher strike (at same maturiy)
Order("SPY.CALL.1.2", -80*100);

So, quite straightforward.

I've also included the possibility to make the algorithm download interest rates from QUANDL, to make the theoretical prices more accurate. Likewise, it is also possible to specify a dividend yield for a given stock, as to correct the theoretical prices for that. This goes as follows:

// Second parameter: interest rate. Third parameter: dividend yield
OptionSettings.Initialize(this, 0.05M, 0.01M);

My framework, however, is far from perfect. Actually, I wasn't finished yet but after reading the announcement today I've tried to finish a rough version of it as to help the development of the actual framework. One problem that still exists is that I'm still getting asset price is $0. If using custom data make sure you've set the 'Value' property. errors, although I specifically make sure that my option price is always larger or equal than 0.01. This seems to appear especially when the data 'runs through' periods before the sample period. Apparently the LEAN framework always goes through all data before arriving at the sample period of the algorithm. Clearly, this yields a problem when the asset is theoretical and calculated based on the prices in the sample period. I can't get this error away. However, it still works fine!. The errors appear, but the framework seems to work fine nevertheless.

I hope you guys enjoy. At least, it might help out Jared & team to prep the formal option backtesting framework. Enjoy :)
Update Backtest






The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.



Note: any bought options that are not sold before maturity will automatically be liquidated at maturity by the framework. Just as in real life (options are almost never actually exercised because their value at maturity is equal to their value in the underlying: they are liquidated instead).

Note 2: due to the Time Value of Money, it is often smart to sell your options before maturity. Options lose value as time progresses!

Note 3: I've slightly changed my code. So if you cloned the framework before, clone it again to receive the newest version.
0

Please note, there was a bug in my code for calling the greeks (I was passing the wrong parameters). Below is the updated framework which calculates the greeks correctly. Please clone this one instead of the one above!
0


I also made a mistake in my explanation of how the framework works. I changed this function a while ago and forgot all about it.

Basically, when you specify the maturity, you specify the number of days for which the option should still be alive. The framework will then automatically find the nearest maturity.

So for:

Order("SPY.CALL.1.50", 80*100);

You buy a CALL option at the first in-the-money strike price, that is alive for at least 50 more days. I'm sorry for the ambiguity in my original post. I forgot all about the fact that I changed this function (was already a week ago). But now I understand why I changed it: specifying the number of days for which the option should still be alive makes much more sense than specifying the number of maturities away. So I hope it's clear now.

Order("SPY.CALL.k.m", 80*10)


First parameter k: specifies the k'th nearest in-the-money (when positive) or out-the-money (when negative) strike price.

Second parameter m: specifies the amount of days m for which the option should at least be alive. The framework will automatically find the nearest maturity based on that premise.
0

Hey JP B,
Thanks you so much for putting these extra efforts !!!
Looking forward to your complete version and then to test some algos for Options!
Nik
1

JP, great work.

I am looking forward to this being integrated. Having options in your algo makes so much sense!

Chris
1

Kudos to @JPB, this is absolutely incredible and just goes to show how extremely flexible the LEAN engine can be if you invest a little time. I know you're going off to finish your graduate work but hope to see you back on the forums in the future. Amazing community addition!
1

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


@nik @Christoffer @MichaelH Thank you for the compliments! I'm still not satisfied with the code at all but I feel that it would be a waste of time to try and improve it whereas the developers are actually working on a formal framework for options anyway. I just thought it best to post it in its current state so that the team can take a look at it and borrow ideas from it :)
0

This is a huge step forward for options support in QC, which is awesome!

It might also be a good idea, in terms of extensibility to wrap a standard opensource, library like quantlib (BSD license) that has literally thousands of hours of feature dev and bug fixes and hundreds of eyes on the codebase, so that no one at QC has to spend time maintaining option modeling code.
This would also make it easier to keep the QC codebase for options loosely coupled as well likely make it easier to test... just a thought.
1

@AshleyMesser That seems like a very good idea indeed! It's always better to use a tested library instead of reinventing the wheel.
1

Update Backtest





0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Loading...

This discussion is closed