Hi there,
I'm trying to create code that identifies those underlyings that are having earnings days in 7 days, add them to my universe to buy a long straddle, then sell those positions on earnings day.
With my code it seems to be identifying those items in the universe that are having earnings days in 7 days and adding them, however:
if (data.OptionChains.TryGetValue(OptionSymbol, out chain))
this is never evaluating to true (and I'm thus never executing a trade). I've debuged the OptionSymbol object and it's not undefined or anything, thoughts? According to this file: http://data.quantconnect.com/option/usa/options.txt 'fb,' for instance, should have options data.
My code is attached.
Thanks for the help!
Jarett Dunn
As a note,
public override void OnData(Slice data) { ... }
was originally
public override void OnData(TradeBars data) { ... }
in the example for coarse/fine universe filtering I stole. Is my Slice data incorrect in my code?
Moreover, is there a way to build an OptionChains chain other than:
if (data.OptionChains.TryGetValue(OptionSymbol, out chain))
which could be the answer that'll work in my case?
Jarett Dunn
After I get this entering orders, I'll need to fix a few other things I would need help with, too:
1) Get it to buy chains that are 30-45 days out from today;
2) Get it to buy a % of the buying power in the account's worth of straddles at a time (instead of just 1).
Alexandre Catarino
We are attaching an example that may put you in the right direction.
We limit it to only trade SPY options:
public IEnumerable<Symbol> FineSelectionFunction(IEnumerable<FineFundamental> fine) { // Only return SPY for testing purposes return fine.Where(x=> x.Symbol.Value == "SPY").Select(x => x.Symbol); }
Once the symbols are added to the universe, you should use OnSecuritiesChanged to add the options:
public override void OnSecuritiesChanged(SecurityChanges changes) { // Add option for every added security foreach (var security in changes.AddedSecurities) { if (security is Option) continue; var option = AddOption(security.Symbol); option.SetFilter(-2, 2, TimeSpan.Zero, TimeSpan.FromDays(45)); } }
And the trading logic will remain in the OnData event handler like it would if you had used AddOption in Initialize.
Now you will have to add logic to avoid buying straddles when you already have one in your portfolio. After that, you can modify the Fine Universe Selection to allow more symbols.
Jarett Dunn
Thanks for your help!
I can't seem to attach a new backtest because of the below error. If I remove:
// Add option for every added security
foreach (var security in changes.AddedSecurities) {
if (security is Option) continue;
var option = AddOption(security.Symbol);
option.SetFilter(-2, 2, TimeSpan.Zero, TimeSpan.FromDays(45));
}
from 'OnSecuritiesChanged,' the backtest appears to work and consider multiple securities and also doesn't give the error.
I see the occasional error `Runtime Error: System.InvalidCastException: Specified cast is not valid` in OnSecuritiesChanged, thoughts?
When I switched back to universe selection, the code seems to only be considering SPY, here's some output from the line:
Debug("Securities added: " + string.Join(",", changes.AddedSecurities.Select(x => x.Symbol.Value)));
973 | 20:03:35: Securities added: SPY
974 | 20:03:39: Securities added: SPY 160318C00194500, SPY 160318C00195000, SPY 160318C00195500,SPY 160318C00196000,SPY 160318P00194500, SPY 160318P00195000, SPY 160318P00195500,SPY 160318P00196000,SPY ...
975 | 20:03:39: Securities added: SPY 160318C00194000, SPY 160318P00194000, SPY 160415C00194000,SPY 160415P00194000
976 | 20:03:40: Securities added: SPY 160318C00196500, SPY 160318P00196500
977 | 20:03:40: Securities added: SPY 160318C00197000, SPY 160318P00197000, SPY 160415C00197000, SPY 160415P00197000
978 | 20:03:41: Securities added: SPY 160318C00197500, SPY 160318P00197500
979 | 20:03:42: Securities added: SPY 160318C00198000, SPY 160318P00198000, SPY 160415C00198000, SPY 160415P00198000
980 | 20:03:43: Securities added: SPY 160318C00198500, SPY 160318P00198500
Alexandre Catarino
Please checkout the attached project, where we use buy straddles of 5 stocks that fall under our universe selection criteria. The algorithm is explained in my previous commment. We only added a List of Symbols to keep track of straddles that were bought.
The "Runtime Error: System.InvalidCastException: Specified cast is not valid" was due to using a wrong value for the first parameter of AddOption:
var option = AddOption(security.Symbol); // Wrong var option = AddOption(security.Symbol.Value); // Right
Jarett Dunn
Great!
That's helpful.
I've added in the Liquidate code for when the equities leave the universe - which I hoped would be 7 days later, according to:
Time >= x.EarningReports.FileDate.AddDays(-7) &&
Time >= x.EarningReports.FileDate.AddDays(0) &&
However it seems my straddles are being immediately resold back to market :(
Thanks for all your help so far!
Jarett Dunn
I've implemented a SL/TP on my trades instead of trying to resell the straddles on earnings days, but it appears my fine universe selection is adding way more securities than I would have wanted :(
How can I get it to add just those equities who have earnings days in exactly 7 days to the universe?
Also, is there a way to define this behavior in the coarse universe selection (so that we're not always dealing with the same underlyings)?
In the same month they're re-entering straddles for multiple stocks mulitple times (ie. immediately after reselling those straddles). The intended effect is that it only enters a straddle 9 days before the earnings date, as defined by:
return fine
.Where(x =>
Time >= x.EarningReports.FileDate.AddDays(-9) &&
Time >= x.EarningReports.FileDate.AddDays(0) &&
x.EarningReports.FileDate != new DateTime())
.Select(x => x.Symbol).Take(5);
Jarett Dunn
Here's the backtest:
Jarett Dunn
Moreover, is there a way to enable intraday trading for options? that would have avoideded that enormous pitfall in the recent backtest with a smaller SL.
Jarett Dunn
The problem lies within the data :) EarningsDate is the most recent earnings date before the Time, which means we can't use it (as I thought it was the next earnings date). The best I can hope for is to add a quarter's worth of time to PeriodEndingDate (then 20-30 days for them to release earnings).
Can we somehow allow it for next earnings date to be available to be pulled, if available?
Alexandre Catarino
Unfortunatelly the next earnings data is not available. Please checkout the available Fundamentals data here.
Maybe you could make some research to determine whether earnings file dates are consistent (they don't vart much, e.g., always the second Monday of the quarter). It may be a good estimate for backtesting. For live trading, you will be able to rely on Nasdaq's Earnings Calendar.
Jarett Dunn
Hey Bao,
I ended up coding this entire algorithm using a Questrade API demo account (using live data from the day before):
The issue is that sometimes the code would buy some straddles that would then have both the call and the put turn worthless - which broke the strategy :( from what I understand you can still sell them to market by setting a limit price you 'think' might be acceptable, but given the automated nature I'm unsure how to calculate that - I'm sure I could create a limit order in a live environment and then if it doesn't sell, update the order to be less advantageous? But altogether the uncertainty made it not worth the effort in the end.
I'd still very much like to be able to backtest the strategy, though. 5 month's data isn't necessarily ideal... all you'd need to do is do some math on the current date (somehow in C#)
Bao Huynh
Jarett Dunn ,
I crawled the earning report data from nasdaq which goes back from 2012-Now. I didn't clean the data so some discrepancy in Symbols & Company Name but it seems 99% accurate. Definitely needs some cleaning still. I'll take it down the link after today.
Thanks for the tip! Let me know if the data helps.
Edited by Jared: Cannot share data obtained illegally.
JayJayD
Hey Bao Huynh,
I think a simple implementation will be something like this:
In the Initialize method:
public override void Initialize() { List<Tuple<DateTime, string>> earnings = ReadEarningData(); Schedule.On(DateRules.EveryDay(), TimeRules.At(9, 0), () => { // Check the next earnings. var nextEarnings = earnings.Where(x => x.Item1.Date == Time.Date.AddDays(7)).ToArray(); foreach (var nextEarning in nextEarnings) { // Just an example, implement your logic here. MarketOrder(nextEarning.Item2, 100); } } ); }
Hope it helps.
Jarett Dunn
Hey,
Thanksf for the help.
Anyone know why the attached backtest is only working with SPY?
Log(nextEarning.ticker); is logging:
2012-02-01 09:00:00 EGHT
2012-02-01 09:00:00 APH
2012-02-01 09:00:00 ASML
2012-02-01 09:00:00 The
2012-02-01 09:00:00 CTBI
2012-02-01 09:00:00 CVBF
2012-02-01 09:00:00 EBAY
2012-02-01 09:00:00 FFIV
2012-02-01 09:00:00 FFKT
2012-02-01 09:00:00 FAST
2012-02-01 09:00:00 ME
2012-02-01 09:00:00 FCCO
etc...
Jared Broad
This line tells it to add daily data. Is this what you intended? "UniverseSettings.Resolution = Resolution.Daily;"
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.
Jarett Dunn
I believe so :) I'm no pro at QuantConnect or even C#.
In FineSelectionFunction I was trying to load the CSV, load next earners via Schedule.On(DateRules.EveryDay(), TimeRules.At(9, 0), () => (which I think is working, as I have logs from Log(nextEarning.ticker); in my output log) . . . I'm just unsure why that fine universe isn't being picked up on by OnSecuritiesChanged?
Jarett Dunn
Got it :) You can call 'AddSecurity' anywhere and it triggers OnSecuritiesChanged.
Issue is I'm breaking the emulator :)
Memory Usage Maxed Out - 1024MB max, with last sample of 2012MB.
Can I clone QuantConnect via GitHub and run it on one of my servers in Ubuntu?
Jared Broad
You can if you buy your own financial data ($'000) -- or you can increase your backtesting RAM allocation through the subscription page.
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.
Jarett Dunn
Thanks Jared.
Can you or someone review my code and figure out where the memory leak is, or why it seems to stop processing the backtest after the 16th or so of Jan? It just comes to a dead halt. I put in a limit to not have more than 3 options open at a given point in time, and the last time I tried to run the backtest from Jan - May it gave me an error akin to 'maximum execution time of (however many) seconds has occured, look for any recursive for loops.' Also, where does it get the idea to buy SPY straddle immediately upon launch? Backtest attached.
Jarett Dunn
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!