Lean  $LEAN_TAG$
OptionIndicatorBase.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 QuantConnect.Data;
18 
20 {
21  /// <summary>
22  /// To provide a base class for option indicator
23  /// </summary>
24  public abstract class OptionIndicatorBase : IndicatorBase<IndicatorDataPoint>, IIndicatorWarmUpPeriodProvider
25  {
26  /// <summary>
27  /// Option's symbol object
28  /// </summary>
29  public Symbol OptionSymbol { get; init; }
30 
31  /// <summary>
32  /// Mirror option symbol (by option right), for implied volatility
33  /// </summary>
34  protected Symbol _oppositeOptionSymbol { get; private set; }
35 
36  /// <summary>
37  /// Underlying security's symbol object
38  /// </summary>
40 
41  /// <summary>
42  /// Option pricing model used to calculate indicator
43  /// </summary>
44  protected OptionPricingModelType _optionModel { get; set; }
45 
46  /// <summary>
47  /// Risk-free rate model
48  /// </summary>
50 
51  /// <summary>
52  /// Dividend yield model, for continuous dividend yield
53  /// </summary>
54  protected IDividendYieldModel _dividendYieldModel { get; init; }
55 
56  /// <summary>
57  /// Gets the expiration time of the option
58  /// </summary>
59  public DateTime Expiry => OptionSymbol.ID.Date;
60 
61  /// <summary>
62  /// Gets the option right (call/put) of the option
63  /// </summary>
65 
66  /// <summary>
67  /// Gets the strike price of the option
68  /// </summary>
69  public decimal Strike => OptionSymbol.ID.StrikePrice;
70 
71  /// <summary>
72  /// Gets the option style (European/American) of the option
73  /// </summary>
75 
76  /// <summary>
77  /// Risk Free Rate
78  /// </summary>
79  public Identity RiskFreeRate { get; set; }
80 
81  /// <summary>
82  /// Dividend Yield
83  /// </summary>
84  public Identity DividendYield { get; set; }
85 
86  /// <summary>
87  /// Gets the option price level
88  /// </summary>
90 
91  /// <summary>
92  /// Gets the mirror option price level, for implied volatility
93  /// </summary>
94  public IndicatorBase<IndicatorDataPoint> OppositePrice { get; private set; }
95 
96  /// <summary>
97  /// Gets the underlying's price level
98  /// </summary>
100 
101  /// <summary>
102  /// Flag if mirror option is implemented for parity type calculation
103  /// </summary>
104  public bool UseMirrorContract => _oppositeOptionSymbol != null;
105 
106  /// <summary>
107  /// Initializes a new instance of the OptionIndicatorBase class
108  /// </summary>
109  /// <param name="name">The name of this indicator</param>
110  /// <param name="option">The option to be tracked</param>
111  /// <param name="riskFreeRateModel">Risk-free rate model</param>
112  /// <param name="dividendYieldModel">Dividend yield model</param>
113  /// <param name="mirrorOption">The mirror option for parity calculation</param>
114  /// <param name="period">The lookback period of volatility</param>
115  /// <param name="optionModel">The option pricing model used to estimate the Greek/IV</param>
116  protected OptionIndicatorBase(string name, Symbol option, IRiskFreeInterestRateModel riskFreeRateModel, IDividendYieldModel dividendYieldModel,
117  Symbol mirrorOption = null, OptionPricingModelType? optionModel = null, int period = 2)
118  : base(name)
119  {
120  var sid = option.ID;
121  if (!sid.SecurityType.IsOption())
122  {
123  throw new ArgumentException("OptionIndicatorBase only support SecurityType.Option.");
124  }
125 
126  OptionSymbol = option;
127  _riskFreeInterestRateModel = riskFreeRateModel;
128  _dividendYieldModel = dividendYieldModel;
129  _optionModel = optionModel ?? GetOptionModel(optionModel, sid.OptionStyle);
130 
131  RiskFreeRate = new Identity(name + "_RiskFreeRate");
132  DividendYield = new Identity(name + "_DividendYield");
133  Price = new Identity(name + "_Close");
134  UnderlyingPrice = new Identity(name + "_UnderlyingClose");
135 
136  if (mirrorOption != null)
137  {
138  _oppositeOptionSymbol = mirrorOption;
139  OppositePrice = new Identity(Name + "_OppositeClose");
140  }
141 
142  WarmUpPeriod = period;
143  }
144 
145  /// <summary>
146  /// Required period, in data points, for the indicator to be ready and fully initialized.
147  /// </summary>
148  public int WarmUpPeriod { get; set; }
149 
150  /// <summary>
151  /// Computes the next value of this indicator from the given state.
152  /// This will round the result to 7 decimal places.
153  /// </summary>
154  /// <param name="input">The input given to the indicator</param>
155  /// <returns>A new value for this indicator</returns>
156  protected override decimal ComputeNextValue(IndicatorDataPoint input)
157  {
158  return Math.Round(Calculate(input), 7);
159  }
160 
161  /// <summary>
162  /// Computes the next value of this indicator from the given state.
163  /// </summary>
164  /// <param name="input">The input given to the indicator</param>
165  /// <returns>A new value for this indicator</returns>
166  protected abstract decimal Calculate(IndicatorDataPoint input);
167 
168  /// <summary>
169  /// Resets this indicator and all sub-indicators
170  /// </summary>
171  public override void Reset()
172  {
173  RiskFreeRate.Reset();
174  DividendYield.Reset();
175  Price.Reset();
176  UnderlyingPrice.Reset();
177  base.Reset();
178 
179  if (UseMirrorContract)
180  {
181  OppositePrice.Reset();
182  }
183  }
184 
185  /// <summary>
186  /// Gets the option pricing model based on the option style, if not specified
187  /// </summary>
188  /// <param name="optionModel">The optional option pricing model, which will be returned if not null</param>
189  /// <param name="optionStyle">The option style</param>
190  /// <returns>The option pricing model based on the option style, if not specified</returns>
192  {
193  if (optionModel.HasValue)
194  {
195  return optionModel.Value;
196  }
197 
198  // Default values depend on the option style
199  return optionStyle switch
200  {
201  OptionStyle.European => OptionPricingModelType.BlackScholes,
202  OptionStyle.American => OptionPricingModelType.ForwardTree,
203  _ => throw new ArgumentOutOfRangeException(nameof(optionStyle), optionStyle, null)
204  };
205  }
206  }
207 }