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