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.Python;
20 
22 {
23  /// <summary>
24  /// To provide a base class for option greeks indicator
25  /// </summary>
27  {
28  private ImpliedVolatility _iv;
29  private bool _userProvidedIv;
30 
31  /// <summary>
32  /// Cache of the current value of the greek
33  /// </summary>
34  protected decimal _greekValue { get; set; }
35 
36  /// <summary>
37  /// Gets the implied volatility of the option
38  /// </summary>
40  {
41  get
42  {
43  return _iv;
44  }
45  set
46  {
47  _iv = value;
48  _userProvidedIv = true;
49  }
50  }
51 
52  /// <summary>
53  /// Initializes a new instance of the OptionGreeksIndicatorBase class
54  /// </summary>
55  /// <param name="name">The name of this indicator</param>
56  /// <param name="option">The option to be tracked</param>
57  /// <param name="riskFreeRateModel">Risk-free rate model</param>
58  /// <param name="dividendYieldModel">Dividend yield model</param>
59  /// <param name="mirrorOption">The mirror option for parity calculation</param>
60  /// <param name="optionModel">The option pricing model used to estimate the Greek</param>
61  /// <param name="ivModel">The option pricing model used to estimate IV</param>
62  protected OptionGreeksIndicatorBase(string name, Symbol option, IRiskFreeInterestRateModel riskFreeRateModel, IDividendYieldModel dividendYieldModel,
63  Symbol mirrorOption = null, OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null)
64  : base(name, option, riskFreeRateModel, dividendYieldModel, mirrorOption, optionModel)
65  {
66  ivModel = GetOptionModel(ivModel, option.ID.OptionStyle);
67  WarmUpPeriod = 1;
68  _iv = new ImpliedVolatility(name + "_IV", option, riskFreeRateModel, dividendYieldModel, mirrorOption, ivModel.Value);
69  }
70 
71  /// <summary>
72  /// Initializes a new instance of the OptionGreeksIndicatorBase class
73  /// </summary>
74  /// <param name="name">The name of this indicator</param>
75  /// <param name="option">The option to be tracked</param>
76  /// <param name="riskFreeRateModel">Risk-free rate model</param>
77  /// <param name="dividendYield">Dividend yield, as a constant</param>
78  /// <param name="mirrorOption">The mirror option for parity calculation</param>
79  /// <param name="optionModel">The option pricing model used to estimate the Greek</param>
80  /// <param name="ivModel">The option pricing model used to estimate IV</param>
81  protected OptionGreeksIndicatorBase(string name, Symbol option, IRiskFreeInterestRateModel riskFreeRateModel, decimal dividendYield = 0.0m,
82  Symbol mirrorOption = null, OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null)
83  : this(name, option, riskFreeRateModel, new ConstantDividendYieldModel(dividendYield), mirrorOption, optionModel, ivModel)
84  {
85  }
86 
87  /// <summary>
88  /// Initializes a new instance of the OptionGreeksIndicatorBase class
89  /// </summary>
90  /// <param name="name">The name of this indicator</param>
91  /// <param name="option">The option to be tracked</param>
92  /// <param name="riskFreeRate">Risk-free rate, as a constant</param>
93  /// <param name="dividendYield">Dividend yield, as a constant</param>
94  /// <param name="mirrorOption">The mirror option for parity calculation</param>
95  /// <param name="optionModel">The option pricing model used to estimate the Greek</param>
96  /// <param name="ivModel">The option pricing model used to estimate IV</param>
97  protected OptionGreeksIndicatorBase(string name, Symbol option, decimal riskFreeRate = 0.05m, decimal dividendYield = 0.0m, Symbol mirrorOption = null,
98  OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null)
99  : this(name, option, new ConstantRiskFreeRateInterestRateModel(riskFreeRate), new ConstantDividendYieldModel(dividendYield),
100  mirrorOption, optionModel, ivModel)
101  {
102  }
103 
104  /// <summary>
105  /// Initializes a new instance of the OptionGreeksIndicatorBase class
106  /// </summary>
107  /// <param name="name">The name of this indicator</param>
108  /// <param name="option">The option to be tracked</param>
109  /// <param name="riskFreeRateModel">Risk-free rate model</param>
110  /// <param name="dividendYieldModel">Dividend yield model</param>
111  /// <param name="mirrorOption">The mirror option for parity calculation</param>
112  /// <param name="optionModel">The option pricing model used to estimate the Greek</param>
113  /// <param name="ivModel">The option pricing model used to estimate IV</param>
114  protected OptionGreeksIndicatorBase(string name, Symbol option, PyObject riskFreeRateModel, PyObject dividendYieldModel, Symbol mirrorOption = null,
115  OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null)
116  : this(name, option, RiskFreeInterestRateModelPythonWrapper.FromPyObject(riskFreeRateModel),
117  DividendYieldModelPythonWrapper.FromPyObject(dividendYieldModel), mirrorOption, optionModel, ivModel)
118  {
119  }
120 
121  /// <summary>
122  /// Initializes a new instance of the OptionGreeksIndicatorBase class
123  /// </summary>
124  /// <param name="name">The name of this indicator</param>
125  /// <param name="option">The option to be tracked</param>
126  /// <param name="riskFreeRateModel">Risk-free rate model</param>
127  /// <param name="dividendYield">Dividend yield, as a constant</param>
128  /// <param name="mirrorOption">The mirror option for parity calculation</param>
129  /// <param name="optionModel">The option pricing model used to estimate the Greek</param>
130  /// <param name="ivModel">The option pricing model used to estimate IV</param>
131  protected OptionGreeksIndicatorBase(string name, Symbol option, PyObject riskFreeRateModel, decimal dividendYield = 0.0m, Symbol mirrorOption = null,
132  OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null)
133  : this(name, option, RiskFreeInterestRateModelPythonWrapper.FromPyObject(riskFreeRateModel),
134  new ConstantDividendYieldModel(dividendYield), mirrorOption, optionModel, ivModel)
135  {
136  }
137 
138  /// <summary>
139  /// Gets a flag indicating when this indicator is ready and fully initialized
140  /// </summary>
141  public override bool IsReady => ImpliedVolatility.IsReady;
142 
143  /// <summary>
144  /// Computes the next value of the option greek indicator
145  /// </summary>
146  /// <param name="input">The input given to the indicator</param>
147  /// <returns>The input is returned unmodified.</returns>
148  protected override decimal Calculate(IndicatorDataPoint input)
149  {
150  var time = input.EndTime;
151  var inputSymbol = input.Symbol;
152 
153  if (inputSymbol == OptionSymbol)
154  {
155  if (!_userProvidedIv) ImpliedVolatility.Update(input);
156  Price.Update(time, input.Price);
157  }
158  else if (inputSymbol == _oppositeOptionSymbol)
159  {
160  if (!_userProvidedIv) ImpliedVolatility.Update(input);
161  OppositePrice.Update(time, input.Price);
162  }
163  else if (inputSymbol == _underlyingSymbol)
164  {
165  if (!_userProvidedIv) ImpliedVolatility.Update(input);
166  UnderlyingPrice.Update(time, input.Price);
167  }
168  else
169  {
170  throw new ArgumentException($"The given symbol was not target, reference or underlying symbol: {inputSymbol}");
171  }
172 
173  if (Price.Current.Time == UnderlyingPrice.Current.Time)
174  {
175  if (UseMirrorContract)
176  {
177  if (Price.Current.Time != OppositePrice.Current.Time)
178  {
179  return _greekValue;
180  }
181  }
182 
184  DividendYield.Update(time, _dividendYieldModel.GetDividendYield(time, UnderlyingPrice.Current.Value));
185 
186  var timeTillExpiry = Convert.ToDecimal(OptionGreekIndicatorsHelper.TimeTillExpiry(Expiry, time));
187  try
188  {
189  _greekValue = timeTillExpiry < 0 ? 0 : CalculateGreek(timeTillExpiry);
190  }
191  catch (OverflowException)
192  {
193  //Log.Error($"OptionGreeksIndicatorBase.Calculate: Decimal overflow detected. The previous greek value will be used.");
194  }
195  }
196 
197  return _greekValue;
198  }
199 
200  /// <summary>
201  /// Calculate the greek of the option
202  /// </summary>
203  protected abstract decimal CalculateGreek(decimal timeTillExpiry);
204 
205  /// <summary>
206  /// Resets this indicator and all sub-indicators
207  /// </summary>
208  public override void Reset()
209  {
211  base.Reset();
212  }
213  }
214 }