/// <summary> /// Get GetATM options for nearest available expiration. /// </summary> protected Tuple <OptionContract, OptionContract> GetATM(QCAlgorithmFramework algorithim, Symbol underlyingSymbol, int expiryDistance = 0) { IOrderedEnumerable <OptionContract> selected = OptionTools.GetOptionsForExpiry(algorithim, underlyingSymbol, expiryDistance); if (selected == null) { return(null); } var put = selected .Where(o => o.Right == OptionRight.Put && o.Strike - 0.5m < o.UnderlyingLastPrice) //sort by distance from atm .OrderBy(o => Math.Abs(o.UnderlyingLastPrice - o.Strike)).FirstOrDefault(); if (put == null) { return(null); } var call = selected .Where(o => o.Right == OptionRight.Call && o.Strike == put.Strike).FirstOrDefault(); if (call == null) { return(null); } return(new Tuple <OptionContract, OptionContract>(call, put)); }
/// <summary> /// Updates this alpha model with the latest data from the algorithm. /// This is called each time the algorithm receives data for subscribed securities /// </summary> /// <param name="algorithm">The algorithm instance</param> /// <param name="data">The new data available</param> /// <returns>The new insights generated</returns> public override IEnumerable <Insight> Update(QCAlgorithmFramework algorithm, Slice data) { var insights = new List <Insight>(); foreach (var kvp in _symbolDataBySymbol) { var symbol = kvp.Key; try { var frontOptions = OptionTools.GetOptionsForExpiry(algorithm, symbol, 0); var backOptions = OptionTools.GetOptionsForExpiry(algorithm, symbol, 1); var frontiv = AverageIV(algorithm, frontOptions); var backiv = AverageIV(algorithm, backOptions); kvp.Value.Update(data.Time, frontiv, backiv); } catch (Exception ex) { algorithm.Log("Failed to compute IV!"); continue; } var std = kvp.Value.STD; var previousState = kvp.Value.State; var previousMag = kvp.Value.Mag; double mag; var state = GetState(std, out mag); if ((state != previousState || mag > previousMag) && std.IsReady) { var insightPeriod = _resolution.Multiply(_period); switch (state) { case State.Neutral: insights.Add(Insight.Price(symbol, insightPeriod, InsightDirection.Flat)); break; case State.TrippedHigh: insights.Add(Insight.Price(symbol, insightPeriod, _inverted ? InsightDirection.Up : InsightDirection.Down, mag)); break; case State.TrippedLow: insights.Add(Insight.Price(symbol, insightPeriod, _inverted ? InsightDirection.Down : InsightDirection.Up, mag)); break; } kvp.Value.State = state; kvp.Value.Mag = mag; } } return(insights); }
/// <summary> /// Get OTM options for nearest available expiration. /// </summary> protected IOrderedEnumerable <OptionContract> GetOTM(QCAlgorithmFramework algorithim, Symbol underlyingSymbol, OptionRight right, int expiryDistance = 0) { IOrderedEnumerable <OptionContract> selected = OptionTools.GetOptionsForExpiry(algorithim, underlyingSymbol, expiryDistance); if (selected == null) { return(null); } return(selected .Where(o => o.Right == right) //check if OTM .Where(o => (right == OptionRight.Put ? o.Strike <o.UnderlyingLastPrice : o.Strike> o.UnderlyingLastPrice)) //sort by distance from atm .OrderBy(o => Math.Abs(o.UnderlyingLastPrice - o.Strike))); }
/// <summary> /// Updates this alpha model with the latest data from the algorithm. /// This is called each time the algorithm receives data for subscribed securities /// </summary> /// <param name="algorithm">The algorithm instance</param> /// <param name="data">The new data available</param> /// <returns>The new insights generated</returns> public override IEnumerable <Insight> Update(QCAlgorithmFramework algorithm, Slice data) { if (data == null || data.OptionChains == null || data.OptionChains.Count() < 1) { return(new List <Insight>()); } var chainItem = data.OptionChains.First(); var symbol = chainItem.Key.Underlying; var options = OptionTools.GetOptionsForExpiry(algorithm, symbol, 0); var count = options.Where((o) => (o.Expiry - data.Time).TotalDays <= _daysOpenBegin && (o.Expiry - data.Time).TotalDays >= _daysOpenEnd) .Count(); if (count > 0) { return(new List <Insight>() { Insight.Price(chainItem.Key.Underlying, TimeSpan.FromDays(1), InsightDirection.Up) }); } count = options.Where((o) => Math.Abs((o.Expiry - data.Time).TotalDays) <= _daysCloseBegin && Math.Abs((o.Expiry - data.Time).TotalDays) >= _daysCloseEnd) .Count(); if (count > 0) { return(new List <Insight>() { Insight.Price(chainItem.Key.Underlying, TimeSpan.FromDays(1), InsightDirection.Down) }); } return(new List <Insight>()); }