Hello all,
I wanted to share one of the algorithms I have been working on for a while now as I feel it can easily be extended/implemented by other community members. The basic outline of the algorithm is to hedge all of our equity positions (when option data is available) with options of the desired strike and expiration away from the current price and date.
The Universe Selection pulls 25 stocks considered to be stable and the desired put and call options, if available.
The Alpha Model is a simple reversion to the mean strategy which produces insights on the equities then sends market orders on either the put or call option, depending on the equity's insight.
Although the performance of the alpha model is weak, the alpha is not the purpose of this algorithm. The purpose of this algorithm is to create a hedging strategy with options using a dynamic universe.
The reason I think this might be useful is we never have to implement a risk management model that removes options that are expiring too soon or have a strike price( or expiration date) that is no longer desired. With the dynamic universe, the optimal put and call contracts are always returned. Therefore we do not need to build portfolio construction, or risk management models that take into effect options.
Before I go, I wanted to thank both Jovad Uribe and Alex from QuantConnect for working with me on this project.
Jason Bohne :)
Jovad Uribe
Great post! I hope the community utilizes this implementation.
Derek Melchin
Hi Jason,
Interesting algorithm. Thank you for sharing it with the community. There are a few improvements we can make to it though. I've outlined these below, separated by the containing file.
main.py
We can remove the imports of the PCM and execution models. Doing so automatically imports the C# versions, increasing the backtest speed.
OptionsUniverse.py
We can move the static hard-coded values used throughout this class to the constructor's signature. This creates a single place for us to adjust all the parameters of the class.
We can change the if-tree found in SelectFine so that it uses if-elif-else to increase speed. Also, the last if-condition in the original algorithm above was causing bugs.
We can change the construction of `self.contracts` into a convenient one-liner:
self.contract = [self.GetContract(algorithm, stock) for stock in self.stocks]
Doing this requires us to adjust the signature for the GetContract method so it can receive a `stock` argument.
When sorting and filtering the contracts in GetContract, it's best if we perform all the filtering before sorting. This leads to less looping.
OptionsAlpha.py
In the OnSecuritiesChanged method:
In the Update method:
std=symbolData.STD.Current.Value ema=symbolData.EMA.Current.Value
See the attached backtest for reference. All the above modifications have been applied.
Best,
Derek Melchin
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.
Jason
Thank you, Derek.
All of those changes made sense and I will definitely implement those into my program. I appreciate the in-depth assistance.
Jason :)
Rayhan
It would be a great help if anyone explains me this block of code in OptionsUniverse.py inside SelectFine() method :
#Following block of code combines both the symbols of equities and options res = [i for i in self.contract if i] self.result=[] for t in res: for x in t: self.result.append(x) self.newstocks= [x.Symbol for x in self.stocks] #Returns our equities and hedged options return [x for x in self.newstocks + self.result]
Basically i would like to know how does the returned list look like. I presumed that self.contract is a list containing put and call contracts of each underlying stock in portfolio. My confusions are:
what is the reason for using two for loops ?
what is SelectFine returning at the end ? what does the + operator do ?
Hector Barrio
"t in res" is iterating over a list of tuples and "x in t" is unpacking the tuple into a list of individual put and call contract symbols, isn't it? Then the return statement concatenates the lists using the '+' operator: the list of stock symbols and the list of individual options contracts.
Splat operator could be used to remove the internal loop, though it is probably not faster.
for t in res: self.result += [*t]
Rayhan
Hector Barrio , Thank you so much for the explanation. So the returned list from SelectFine() is a list with stock symbols at the beginning and then put and call contracts, right ? What i am thinking , wouldn't it be efficient if we could generate a dictionary of put/call contracts keyed by stock symbols or, returning a pandas dataframe?
Hector Barrio
No problem Rayhan, I don´t think SelectFine return data type can be altered, it has to return a symbol list as it is part of the framework and the symbol list will be used to create the universe object.
https://www.quantconnect.com/docs/algorithm-framework/universe-selectionJason
Hey Rayhan,
Yes, as Hector explained res is the list of tuples containing the selected put and call contracts for each equity in our universe. The loop unpacks it so we can combine it with the list of equities selected. The reasoning for this is so both our equities and put/call contracts can be returned from the universe selection model as the selected assets.
I chose to return both the contracts and equities to keep it in the framework format. In the alpha model, one can generate insights both on the equities and contracts ( which often helps because we would not know whether we should hedge each equity with a put or call contract until we generate our insight on the equity).
By the way, thank you Hector for answering. If anyone has any other questions or suggestions, feel free to let me know.
Jason
Rayhan
So the AlphaModel doesnot work with OptionsChains?
Rayhan
Thank you Jason Bohne first of all for sharing such a nice work. Actually i am having more confusions as i dig deeper, i hope the friendly community is going to clear my confusion :
1. Since the coarse selection is executed once in a month, however, does the finefilter execute with each resolution of the algorithm ? Or the universe selection throws the data to the OptionsAlpha once in a month ?
2. In this tutorial Option Contracts there are two rights on a contract:
x.Right = 0 call option[right to buy] x.Right = 1 put option[right to sell].
which means we can go long on call and write put. Can we not sell call and buy put ?
3. Does the Insight in alphamodel is a prediction for future trend ? How is it useful in the next time step ?
Pardon me i might sound naive because i'm actually a newbee.
Jason
Hey Rayhan,
1). The Fine filter executes as often as the Coarse filter, which is on the first of each month. The universe selection class is called as frequently as the algorithm resolution is set which is minute. However, from the following snippet of code, you can see it will ignore both the coarse and fine filter and return the currently selected universe during the current month.
month= algorithm.Time.month if month == self.lastmonth: return Universe.Unchanged self.lastmonth= month
2). You could sell a call and buy a put however that is doubling your hedge. Additionally, there is always more risk associated with shorting assets. I decided that only longing options was sufficient for my algorithm. Feel free to make this change if you want
3). Insight is the direction in which you think a specific asset will go in some future time period. Check out some more documentation on Insights here https://www.quantconnect.com/docs/algorithm-framework/alpha-creation#Alpha-Creation-Creating-Insights
Jason
Rayhan
I appriciate your answer. I completely get that now.
Moreover, In the following code from OptionAlpha module, we check if we have call contract in the portfolio and then sell the contract right? Since MarketOrder method will sell an asset at the current market price, what will be the selling price of callcontract in this case?
if callcontract is not None and algorithm.Portfolio[callcontract.Symbol].Invested:
algorithm.MarketOrder(callcontract.Symbol,-1,True)
If we were selling the callcontract without the condition, would that be going short on callcontract? Can we do that without a Margin Call account ?
#if algorithm.Portfolio[callcontract.Symbol].Invested:
algorithm.MarketOrder(callcontract.Symbol,-1,True)
Jason
Rayhan
Let's say we originally have a short position on equity XYZ. Then we will also have a call option (if they are available to trade) also in our portfolio. Now let's say we switch our position from a short position to a long position on XYZ. Then we do not want a call contract anymore we would want a put contract. That block of code deals with that scenario. If we are trying to buy a put but we currently have a call contract we will send out a market order to liquidate the call in addition to purchasing the put.
I assume it would sell somewhere in the neighborhood of the current market price but due to slippage, low liquidity this might not always be the case. You can work with reality modeling to try and portray more accurate results in your backtest, found here
https://www.quantconnect.com/docs/algorithm-reference/reality-modelling
I know you can *usually* short call/put contracts however I am not sure whether or not one would need a margin account to do so. I imagine this is a better question for your brokerage.
Jason
Derek Melchin
Hi Rayhan and Jason,
To clarify,
if callcontract is not None and algorithm.Portfolio[callcontract.Symbol].Invested: algorithm.MarketOrder(callcontract.Symbol,-1,True)
will not flip the direction of an option trade when currently long one call contract. To do that, -2 would need to be passed as the quantity argument. See the attached backtest for reference.
Additionally, the universe selection class is not always called as frequently as the algorithm resolution. By default, regardless of the universe resolution, universe selection is performed daily. To call it more frequently, scheduled universe selection can be used.
Best,
Derek Melchin
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.
Rayhan
thanks Derek Melchin . Setting the quantity -2 pretty much makes sense to me as i was thinking that -1 is going to help us to close the position.
Can anyone share a risk model for option trading as a reference ?
Derek Melchin
Hi Rayhan,
We have several example risk management models in the documentation. They are not tailored to options though.
Best,
Derek Melchin
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.
Josh Spivey
Hmmm looks like your universe selection isnt following options alphas method. You need to account for options purchase volume and delta. needs a delta of -20 - 20, Days to exp 30 days volume 500 to 100,00,00 and open interest 1,000 to 345,465
Max Kovalev
Hello all. One comment about frameworks. I do not think that this is a good idea to buy and sell options in Alpha model. Alpha should just produce insights based on some calulations. I think, more proper way to buy and sell options in Risk Mangment model.
Abco Janssens
I'd like to re-use parts of the code provided by Derek Melchin on July 2020 above. But it gives errors when backtesting.
I already corrected below part:
#from QuantConnect.Data.Custom.SEC import *
from QuantConnect.DataSource import *
from AlgorithmImports import *
But still I have below error when executing the backtest:
During the algorithm initialization, the following exception has occurred: TypeError : cannot instantiate abstract class
at Initialize
self.AddUniverseSelection(OptionsUniverse.universe()) #Calls Universe class in main.py: line 15
TypeError : cannot instantiate abstract class
Anybody any idea what is the root cause? Because previously this code must have been fine.
Thanks!
Abco Janssens
Above problem is solved via a support ticket I raised. And solution is as below.
The problem was adding from AlgorithmImports import * at the end of the import statements, since it will pick up the C# version of FundamentalUniverseSelectionModel which is abstract, so if we move it to the top, the problem is solved.
Thanks Alexandre Catarino !
Jason
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.
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!