Lean  $LEAN_TAG$
Gamma.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 MathNet.Numerics.Distributions;
18 using Python.Runtime;
19 using QuantConnect.Data;
20 
22 {
23  /// <summary>
24  /// Option Gamma indicator that calculate the gamma of an option
25  /// </summary>
26  /// <remarks>derivative of option price change relative to $1 underlying changes</remarks>
28  {
29  /// <summary>
30  /// Initializes a new instance of the Gamma class
31  /// </summary>
32  /// <param name="name">The name of this indicator</param>
33  /// <param name="option">The option to be tracked</param>
34  /// <param name="riskFreeRateModel">Risk-free rate model</param>
35  /// <param name="dividendYieldModel">Dividend yield model</param>
36  /// <param name="mirrorOption">The mirror option for parity calculation</param>
37  /// <param name="optionModel">The option pricing model used to estimate Gamma</param>
38  /// <param name="ivModel">The option pricing model used to estimate IV</param>
39  public Gamma(string name, Symbol option, IRiskFreeInterestRateModel riskFreeRateModel, IDividendYieldModel dividendYieldModel, Symbol mirrorOption = null,
40  OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null)
41  : base(name, option, riskFreeRateModel, dividendYieldModel, mirrorOption, optionModel, ivModel)
42  {
43  }
44 
45  /// <summary>
46  /// Initializes a new instance of the Gamma class
47  /// </summary>
48  /// <param name="option">The option to be tracked</param>
49  /// <param name="riskFreeRateModel">Risk-free rate model</param>
50  /// <param name="dividendYieldModel">Dividend yield model</param>
51  /// <param name="mirrorOption">The mirror option for parity calculation</param>
52  /// <param name="optionModel">The option pricing model used to estimate Gamma</param>
53  /// <param name="ivModel">The option pricing model used to estimate IV</param>
54  public Gamma(Symbol option, IRiskFreeInterestRateModel riskFreeRateModel, IDividendYieldModel dividendYieldModel, Symbol mirrorOption = null,
55  OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null)
56  : this($"Gamma({option},{mirrorOption},{GetOptionModel(optionModel, option.ID.OptionStyle)})", option, riskFreeRateModel,
57  dividendYieldModel, mirrorOption, optionModel, ivModel)
58  {
59  }
60 
61  /// <summary>
62  /// Initializes a new instance of the Gamma class
63  /// </summary>
64  /// <param name="name">The name of this indicator</param>
65  /// <param name="option">The option to be tracked</param>
66  /// <param name="riskFreeRateModel">Risk-free rate model</param>
67  /// <param name="dividendYieldModel">Dividend yield model</param>
68  /// <param name="mirrorOption">The mirror option for parity calculation</param>
69  /// <param name="optionModel">The option pricing model used to estimate Gamma</param>
70  /// <param name="ivModel">The option pricing model used to estimate IV</param>
71  public Gamma(string name, Symbol option, PyObject riskFreeRateModel, PyObject dividendYieldModel, Symbol mirrorOption = null,
72  OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null)
73  : base(name, option, riskFreeRateModel, dividendYieldModel, mirrorOption, optionModel, ivModel)
74  {
75  }
76 
77  /// <summary>
78  /// Initializes a new instance of the Gamma class
79  /// </summary>
80  /// <param name="option">The option to be tracked</param>
81  /// <param name="riskFreeRateModel">Risk-free rate model</param>
82  /// <param name="dividendYieldModel">Dividend yield model</param>
83  /// <param name="mirrorOption">The mirror option for parity calculation</param>
84  /// <param name="optionModel">The option pricing model used to estimate Gamma</param>
85  /// <param name="ivModel">The option pricing model used to estimate IV</param>
86  public Gamma(Symbol option, PyObject riskFreeRateModel, PyObject dividendYieldModel, Symbol mirrorOption = null,
87  OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null)
88  : this($"Gamma({option},{mirrorOption},{GetOptionModel(optionModel, option.ID.OptionStyle)})", option, riskFreeRateModel,
89  dividendYieldModel, mirrorOption, optionModel, ivModel)
90  {
91  }
92 
93  /// <summary>
94  /// Initializes a new instance of the Gamma class
95  /// </summary>
96  /// <param name="name">The name of this indicator</param>
97  /// <param name="option">The option to be tracked</param>
98  /// <param name="riskFreeRateModel">Risk-free rate model</param>
99  /// <param name="dividendYield">Dividend yield, as a constant</param>
100  /// <param name="mirrorOption">The mirror option for parity calculation</param>
101  /// <param name="optionModel">The option pricing model used to estimate Gamma</param>
102  /// <param name="ivModel">The option pricing model used to estimate IV</param>
103  public Gamma(string name, Symbol option, IRiskFreeInterestRateModel riskFreeRateModel, decimal dividendYield = 0.0m, Symbol mirrorOption = null,
104  OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null)
105  : base(name, option, riskFreeRateModel, dividendYield, mirrorOption, optionModel, ivModel)
106  {
107  }
108 
109  /// <summary>
110  /// Initializes a new instance of the Gamma class
111  /// </summary>
112  /// <param name="option">The option to be tracked</param>
113  /// <param name="riskFreeRateModel">Risk-free rate model</param>
114  /// <param name="dividendYield">Dividend yield, as a constant</param>
115  /// <param name="mirrorOption">The mirror option for parity calculation</param>
116  /// <param name="optionModel">The option pricing model used to estimate Gamma</param>
117  /// <param name="ivModel">The option pricing model used to estimate IV</param>
118  public Gamma(Symbol option, IRiskFreeInterestRateModel riskFreeRateModel, decimal dividendYield = 0.0m, Symbol mirrorOption = null,
119  OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null)
120  : this($"Gamma({option},{mirrorOption},{GetOptionModel(optionModel, option.ID.OptionStyle)})", option, riskFreeRateModel,
121  dividendYield, mirrorOption, optionModel, ivModel)
122  {
123  }
124 
125  /// <summary>
126  /// Initializes a new instance of the Gamma class
127  /// </summary>
128  /// <param name="name">The name of this indicator</param>
129  /// <param name="option">The option to be tracked</param>
130  /// <param name="riskFreeRateModel">Risk-free rate model</param>
131  /// <param name="dividendYield">Dividend yield, as a constant</param>
132  /// <param name="mirrorOption">The mirror option for parity calculation</param>
133  /// <param name="optionModel">The option pricing model used to estimate Gamma</param>
134  /// <param name="ivModel">The option pricing model used to estimate IV</param>
135  public Gamma(string name, Symbol option, PyObject riskFreeRateModel, decimal dividendYield = 0.0m, Symbol mirrorOption = null,
136  OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null)
137  : base(name, option, riskFreeRateModel, dividendYield, mirrorOption, optionModel, ivModel)
138  {
139  }
140 
141  /// <summary>
142  /// Initializes a new instance of the Gamma class
143  /// </summary>
144  /// <param name="option">The option to be tracked</param>
145  /// <param name="riskFreeRateModel">Risk-free rate model</param>
146  /// <param name="dividendYield">Dividend yield, as a constant</param>
147  /// <param name="mirrorOption">The mirror option for parity calculation</param>
148  /// <param name="optionModel">The option pricing model used to estimate Gamma</param>
149  /// <param name="ivModel">The option pricing model used to estimate IV</param>
150  public Gamma(Symbol option, PyObject riskFreeRateModel, decimal dividendYield = 0.0m, Symbol mirrorOption = null,
151  OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null)
152  : this($"Gamma({option},{mirrorOption},{GetOptionModel(optionModel, option.ID.OptionStyle)})", option, riskFreeRateModel,
153  dividendYield, mirrorOption, optionModel, ivModel)
154  {
155  }
156 
157  /// <summary>
158  /// Initializes a new instance of the Gamma class
159  /// </summary>
160  /// <param name="name">The name of this indicator</param>
161  /// <param name="option">The option to be tracked</param>am>
162  /// <param name="riskFreeRate">Risk-free rate, as a constant</param>
163  /// <param name="dividendYield">Dividend yield, as a constant</param>
164  /// <param name="mirrorOption">The mirror option for parity calculation</param>
165  /// <param name="optionModel">The option pricing model used to estimate Gamma</param>
166  /// <param name="ivModel">The option pricing model used to estimate IV</param>
167  public Gamma(string name, Symbol option, decimal riskFreeRate = 0.05m, decimal dividendYield = 0.0m, Symbol mirrorOption = null,
168  OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null)
169  : base(name, option, riskFreeRate, dividendYield, mirrorOption, optionModel, ivModel)
170  {
171  }
172 
173  /// <summary>
174  /// Initializes a new instance of the Gamma class
175  /// </summary>
176  /// <param name="option">The option to be tracked</param>
177  /// <param name="riskFreeRate">Risk-free rate, as a constant</param>
178  /// <param name="dividendYield">Dividend yield, as a constant</param>
179  /// <param name="mirrorOption">The mirror option for parity calculation</param>
180  /// <param name="optionModel">The option pricing model used to estimate Gamma</param>
181  /// <param name="ivModel">The option pricing model used to estimate IV</param>
182  public Gamma(Symbol option, decimal riskFreeRate = 0.05m, decimal dividendYield = 0.0m, Symbol mirrorOption = null,
183  OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null)
184  : this($"Gamma({option},{mirrorOption},{GetOptionModel(optionModel, option.ID.OptionStyle)})", option, riskFreeRate, dividendYield,
185  mirrorOption, optionModel, ivModel)
186  {
187  }
188 
189  /// <summary>
190  /// Calculate the Gamma of the option
191  /// </summary>
192  protected override decimal CalculateGreek(decimal timeTillExpiry)
193  {
194  var underlyingPrice = (double)UnderlyingPrice.Current.Value;
195  var strike = (double)Strike;
196  var timeTillExpiryDouble = (double)timeTillExpiry;
197  var riskFreeRate = (double)RiskFreeRate.Current.Value;
198  var dividendYield = (double)DividendYield.Current.Value;
199  var iv = (double)ImpliedVolatility.Current.Value;
200 
201  double result;
202 
203  switch (_optionModel)
204  {
205  case OptionPricingModelType.BlackScholes:
206  var norm = new Normal();
207  var d1 = OptionGreekIndicatorsHelper.CalculateD1(underlyingPrice, strike, timeTillExpiryDouble, riskFreeRate, dividendYield, iv);
208 
209  // allow at least 1% IV
210  result = norm.Density(-d1) / underlyingPrice / Math.Max(iv, 0.01) / Math.Sqrt(timeTillExpiryDouble);
211  break;
212 
213  case OptionPricingModelType.BinomialCoxRossRubinstein:
214  case OptionPricingModelType.ForwardTree:
215  var upFactor = Math.Exp(iv * Math.Sqrt(timeTillExpiryDouble / OptionGreekIndicatorsHelper.Steps));
216  if (upFactor == 1)
217  {
218  // provide a small step to estimate gamma
219  upFactor = 1.0001;
220  }
221 
222  // Finite differencing approach
223  var sU = underlyingPrice * upFactor * upFactor;
224  var sD = underlyingPrice / upFactor / upFactor;
225 
226  var fU = 0d;
227  var fM = 0d;
228  var fD = 0d;
229  if (_optionModel == OptionPricingModelType.BinomialCoxRossRubinstein)
230  {
231  fU = OptionGreekIndicatorsHelper.CRRTheoreticalPrice(iv, sU, strike, timeTillExpiryDouble, riskFreeRate, dividendYield, Right);
232  fM = OptionGreekIndicatorsHelper.CRRTheoreticalPrice(iv, underlyingPrice, strike, timeTillExpiryDouble, riskFreeRate, dividendYield, Right);
233  fD = OptionGreekIndicatorsHelper.CRRTheoreticalPrice(iv, sD, strike, timeTillExpiryDouble, riskFreeRate, dividendYield, Right);
234  }
235  else if (_optionModel == OptionPricingModelType.ForwardTree)
236  {
237  fU = OptionGreekIndicatorsHelper.ForwardTreeTheoreticalPrice(iv, sU, strike, timeTillExpiryDouble, riskFreeRate, dividendYield, Right);
238  fM = OptionGreekIndicatorsHelper.ForwardTreeTheoreticalPrice(iv, underlyingPrice, strike, timeTillExpiryDouble, riskFreeRate, dividendYield, Right);
239  fD = OptionGreekIndicatorsHelper.ForwardTreeTheoreticalPrice(iv, sD, strike, timeTillExpiryDouble, riskFreeRate, dividendYield, Right);
240  }
241 
242  var gammaU = (fU - fM) / (sU - underlyingPrice);
243  var gammaD = (fM - fD) / (underlyingPrice - sD);
244 
245  result = OptionGreekIndicatorsHelper.Divide((gammaU - gammaD) * 2, sU - sD);
246  break;
247 
248  default:
249  throw new Exception("Unrecognized Option Pricing Model");
250  }
251 
252  return Convert.ToDecimal(result);
253  }
254  }
255 }