Lean  $LEAN_TAG$
OptionGreekIndicatorBase.cs
1 /*
2  * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
3  * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14 */
15 
16 using System;
17 using Python.Runtime;
18 using QuantConnect.Data;
19 using QuantConnect.Logging;
20 using QuantConnect.Python;
21 
23 {
24  /// <summary>
25  /// To provide a base class for option greeks indicator
26  /// </summary>
28  {
29  private ImpliedVolatility _iv;
30  private bool _userProvidedIv;
31 
32  /// <summary>
33  /// Cache of the current value of the greek
34  /// </summary>
35  protected decimal _greekValue { get; set; }
36 
37  /// <summary>
38  /// Gets the implied volatility of the option
39  /// </summary>
41  {
42  get
43  {
44  return _iv;
45  }
46  set
47  {
48  _iv = value;
49  _userProvidedIv = true;
50  }
51  }
52 
53  /// <summary>
54  /// Initializes a new instance of the OptionGreeksIndicatorBase class
55  /// </summary>
56  /// <param name="name">The name of this indicator</param>
57  /// <param name="option">The option to be tracked</param>
58  /// <param name="riskFreeRateModel">Risk-free rate model</param>
59  /// <param name="dividendYieldModel">Dividend yield model</param>
60  /// <param name="mirrorOption">The mirror option for parity calculation</param>
61  /// <param name="optionModel">The option pricing model used to estimate the Greek</param>
62  /// <param name="ivModel">The option pricing model used to estimate IV</param>
63  protected OptionGreeksIndicatorBase(string name, Symbol option, IRiskFreeInterestRateModel riskFreeRateModel, IDividendYieldModel dividendYieldModel,
64  Symbol mirrorOption = null, OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null)
65  : base(name, option, riskFreeRateModel, dividendYieldModel, mirrorOption, optionModel)
66  {
67  ivModel = GetOptionModel(ivModel, option.ID.OptionStyle);
68  WarmUpPeriod = 1;
69  _iv = new ImpliedVolatility(name + "_IV", option, riskFreeRateModel, dividendYieldModel, mirrorOption, ivModel.Value);
70  }
71 
72  /// <summary>
73  /// Initializes a new instance of the OptionGreeksIndicatorBase class
74  /// </summary>
75  /// <param name="name">The name of this indicator</param>
76  /// <param name="option">The option to be tracked</param>
77  /// <param name="riskFreeRateModel">Risk-free rate model</param>
78  /// <param name="dividendYield">Dividend yield, as a constant</param>
79  /// <param name="mirrorOption">The mirror option for parity calculation</param>
80  /// <param name="optionModel">The option pricing model used to estimate the Greek</param>
81  /// <param name="ivModel">The option pricing model used to estimate IV</param>
82  protected OptionGreeksIndicatorBase(string name, Symbol option, IRiskFreeInterestRateModel riskFreeRateModel, decimal dividendYield = 0.0m,
83  Symbol mirrorOption = null, OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null)
84  : this(name, option, riskFreeRateModel, new ConstantDividendYieldModel(dividendYield), mirrorOption, optionModel, ivModel)
85  {
86  }
87 
88  /// <summary>
89  /// Initializes a new instance of the OptionGreeksIndicatorBase class
90  /// </summary>
91  /// <param name="name">The name of this indicator</param>
92  /// <param name="option">The option to be tracked</param>
93  /// <param name="riskFreeRate">Risk-free rate, as a constant</param>
94  /// <param name="dividendYield">Dividend yield, as a constant</param>
95  /// <param name="mirrorOption">The mirror option for parity calculation</param>
96  /// <param name="optionModel">The option pricing model used to estimate the Greek</param>
97  /// <param name="ivModel">The option pricing model used to estimate IV</param>
98  protected OptionGreeksIndicatorBase(string name, Symbol option, decimal riskFreeRate = 0.05m, decimal dividendYield = 0.0m, Symbol mirrorOption = null,
99  OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null)
100  : this(name, option, new ConstantRiskFreeRateInterestRateModel(riskFreeRate), new ConstantDividendYieldModel(dividendYield),
101  mirrorOption, optionModel, ivModel)
102  {
103  }
104 
105  /// <summary>
106  /// Initializes a new instance of the OptionGreeksIndicatorBase class
107  /// </summary>
108  /// <param name="name">The name of this indicator</param>
109  /// <param name="option">The option to be tracked</param>
110  /// <param name="riskFreeRateModel">Risk-free rate model</param>
111  /// <param name="dividendYieldModel">Dividend yield model</param>
112  /// <param name="mirrorOption">The mirror option for parity calculation</param>
113  /// <param name="optionModel">The option pricing model used to estimate the Greek</param>
114  /// <param name="ivModel">The option pricing model used to estimate IV</param>
115  protected OptionGreeksIndicatorBase(string name, Symbol option, PyObject riskFreeRateModel, PyObject dividendYieldModel, Symbol mirrorOption = null,
116  OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null)
117  : this(name, option, RiskFreeInterestRateModelPythonWrapper.FromPyObject(riskFreeRateModel),
118  DividendYieldModelPythonWrapper.FromPyObject(dividendYieldModel), mirrorOption, optionModel, ivModel)
119  {
120  }
121 
122  /// <summary>
123  /// Initializes a new instance of the OptionGreeksIndicatorBase class
124  /// </summary>
125  /// <param name="name">The name of this indicator</param>
126  /// <param name="option">The option to be tracked</param>
127  /// <param name="riskFreeRateModel">Risk-free rate model</param>
128  /// <param name="dividendYield">Dividend yield, as a constant</param>
129  /// <param name="mirrorOption">The mirror option for parity calculation</param>
130  /// <param name="optionModel">The option pricing model used to estimate the Greek</param>
131  /// <param name="ivModel">The option pricing model used to estimate IV</param>
132  protected OptionGreeksIndicatorBase(string name, Symbol option, PyObject riskFreeRateModel, decimal dividendYield = 0.0m, Symbol mirrorOption = null,
133  OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null)
134  : this(name, option, RiskFreeInterestRateModelPythonWrapper.FromPyObject(riskFreeRateModel),
135  new ConstantDividendYieldModel(dividendYield), mirrorOption, optionModel, ivModel)
136  {
137  }
138 
139  /// <summary>
140  /// Gets a flag indicating when this indicator is ready and fully initialized
141  /// </summary>
142  public override bool IsReady => ImpliedVolatility.IsReady;
143 
144  /// <summary>
145  /// Computes the next value of the option greek indicator
146  /// </summary>
147  /// <param name="input">The input given to the indicator</param>
148  /// <returns>The input is returned unmodified.</returns>
149  protected override decimal Calculate(IndicatorDataPoint input)
150  {
151  var time = input.EndTime;
152  var inputSymbol = input.Symbol;
153 
154  if (inputSymbol == OptionSymbol)
155  {
156  if (!_userProvidedIv) ImpliedVolatility.Update(input);
157  Price.Update(time, input.Price);
158  }
159  else if (inputSymbol == _oppositeOptionSymbol)
160  {
161  if (!_userProvidedIv) ImpliedVolatility.Update(input);
162  OppositePrice.Update(time, input.Price);
163  }
164  else if (inputSymbol == _underlyingSymbol)
165  {
166  if (!_userProvidedIv) ImpliedVolatility.Update(input);
167  UnderlyingPrice.Update(time, input.Price);
168  }
169  else
170  {
171  throw new ArgumentException($"The given symbol was not target, reference or underlying symbol: {inputSymbol}");
172  }
173 
174  if (Price.Current.Time == UnderlyingPrice.Current.Time)
175  {
176  if (UseMirrorContract)
177  {
178  if (Price.Current.Time != OppositePrice.Current.Time)
179  {
180  return _greekValue;
181  }
182  }
183 
185  DividendYield.Update(time, _dividendYieldModel.GetDividendYield(time, UnderlyingPrice.Current.Value));
186 
187  var timeTillExpiry = Convert.ToDecimal(OptionGreekIndicatorsHelper.TimeTillExpiry(Expiry, time));
188  try
189  {
190  _greekValue = timeTillExpiry < 0 ? 0 : CalculateGreek(timeTillExpiry);
191  }
192  catch (OverflowException)
193  {
194  //Log.Error($"OptionGreeksIndicatorBase.Calculate: Decimal overflow detected. The previous greek value will be used.");
195  }
196  }
197 
198  return _greekValue;
199  }
200 
201  /// <summary>
202  /// Calculate the greek of the option
203  /// </summary>
204  protected abstract decimal CalculateGreek(decimal timeTillExpiry);
205 
206  /// <summary>
207  /// Resets this indicator and all sub-indicators
208  /// </summary>
209  public override void Reset()
210  {
212  base.Reset();
213  }
214  }
215 }