Lean  $LEAN_TAG$
Delta.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 Delta indicator that calculate the delta of an option
25  /// </summary>
26  /// <remarks>sensitivity of option price relative to $1 of underlying change</remarks>
28  {
29  /// <summary>
30  /// Initializes a new instance of the Delta 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 Delta</param>
38  /// <param name="ivModel">The option pricing model used to estimate IV</param>
39  public Delta(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 Delta 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 Delta</param>
53  /// <param name="ivModel">The option pricing model used to estimate IV</param>
54  public Delta(Symbol option, IRiskFreeInterestRateModel riskFreeRateModel, IDividendYieldModel dividendYieldModel, Symbol mirrorOption = null,
55  OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null)
56  : this($"Delta({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 Delta 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 Delta</param>
70  /// <param name="ivModel">The option pricing model used to estimate IV</param>
71  public Delta(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 Delta 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 Delta</param>
85  /// <param name="ivModel">The option pricing model used to estimate IV</param>
86  public Delta(Symbol option, PyObject riskFreeRateModel, PyObject dividendYieldModel, Symbol mirrorOption = null,
87  OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null)
88  : this($"Delta({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 Delta 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 Delta</param>
102  /// <param name="ivModel">The option pricing model used to estimate IV</param>
103  public Delta(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 Delta 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 Delta</param>
117  /// <param name="ivModel">The option pricing model used to estimate IV</param>
118  public Delta(Symbol option, IRiskFreeInterestRateModel riskFreeRateModel, decimal dividendYield = 0.0m, Symbol mirrorOption = null,
119  OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null)
120  : this($"Delta({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 Delta 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 Delta</param>
134  /// <param name="ivModel">The option pricing model used to estimate IV</param>
135  public Delta(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 Delta 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 Delta</param>
149  /// <param name="ivModel">The option pricing model used to estimate IV</param>
150  public Delta(Symbol option, PyObject riskFreeRateModel, decimal dividendYield = 0.0m, Symbol mirrorOption = null,
151  OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null)
152  : this($"Delta({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 Delta 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 Delta</param>
166  /// <param name="ivModel">The option pricing model used to estimate IV</param>
167  public Delta(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 Delta 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 Delta</param>
181  /// <param name="ivModel">The option pricing model used to estimate IV</param>
182  public Delta(Symbol option, decimal riskFreeRate = 0.05m, decimal dividendYield = 0.0m, Symbol mirrorOption = null,
183  OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null)
184  : this($"Delta({option},{mirrorOption},{GetOptionModel(optionModel, option.ID.OptionStyle)})", option, riskFreeRate, dividendYield,
185  mirrorOption, optionModel, ivModel)
186  {
187  }
188 
189  /// <summary>
190  /// Calculate the Delta of the option
191  /// </summary>
192  protected override decimal CalculateGreek(decimal timeTillExpiry)
193  {
194  var iv = (double)ImpliedVolatility.Current.Value;
195  var underlyingPrice = (double)UnderlyingPrice.Current.Value;
196  var strike = (double)Strike;
197  var timeTillExpiryDouble = (double)timeTillExpiry;
198  var riskFreeRate = (double)RiskFreeRate.Current.Value;
199  var dividendYield = (double)DividendYield.Current.Value;
200 
201  double result;
202 
203  switch (_optionModel)
204  {
205  case OptionPricingModelType.BinomialCoxRossRubinstein:
206  var upFactor = Math.Exp(iv * Math.Sqrt(timeTillExpiryDouble / OptionGreekIndicatorsHelper.Steps));
207  if (upFactor == 1)
208  {
209  // provide a small step to estimate delta
210  upFactor = 1.00001;
211  }
212 
213  var sU = underlyingPrice * upFactor;
214  var sD = underlyingPrice / upFactor;
215 
216  var fU = OptionGreekIndicatorsHelper.CRRTheoreticalPrice(iv, sU, strike, timeTillExpiryDouble, riskFreeRate, dividendYield, Right);
217  var fD = OptionGreekIndicatorsHelper.CRRTheoreticalPrice(iv, sD, strike, timeTillExpiryDouble, riskFreeRate, dividendYield, Right);
218 
219  result = OptionGreekIndicatorsHelper.Divide(fU - fD, sU - sD);
220  break;
221 
222  case OptionPricingModelType.ForwardTree:
223  var discount = Math.Exp((riskFreeRate - dividendYield) * timeTillExpiryDouble / OptionGreekIndicatorsHelper.Steps);
224  upFactor = Math.Exp(iv * Math.Sqrt(timeTillExpiryDouble / OptionGreekIndicatorsHelper.Steps)) * discount;
225  if (upFactor == 1)
226  {
227  // provide a small step to estimate delta
228  upFactor = 1.00001;
229  }
230  var downFactor = Math.Exp(-iv * Math.Sqrt(timeTillExpiryDouble / OptionGreekIndicatorsHelper.Steps)) * discount;
231  if (downFactor == 1)
232  {
233  // provide a small step to estimate delta
234  downFactor = 0.99999;
235  }
236 
237  sU = underlyingPrice * upFactor;
238  sD = underlyingPrice * downFactor;
239 
240  fU = OptionGreekIndicatorsHelper.ForwardTreeTheoreticalPrice(iv, sU, strike, timeTillExpiryDouble, riskFreeRate, dividendYield, Right);
241  fD = OptionGreekIndicatorsHelper.ForwardTreeTheoreticalPrice(iv, sD, strike, timeTillExpiryDouble, riskFreeRate, dividendYield, Right);
242 
243  result = OptionGreekIndicatorsHelper.Divide(fU - fD, sU - sD);
244  break;
245 
246  case OptionPricingModelType.BlackScholes:
247  default:
248  var norm = new Normal();
249  var d1 = OptionGreekIndicatorsHelper.CalculateD1(underlyingPrice, strike, timeTillExpiryDouble, riskFreeRate, dividendYield, iv);
250 
251  double wholeShareDelta;
252  if (Right == OptionRight.Call)
253  {
254  wholeShareDelta = norm.CumulativeDistribution(d1);
255  }
256  else
257  {
258  wholeShareDelta = -norm.CumulativeDistribution(-d1);
259  }
260 
261  result = wholeShareDelta * Math.Exp(-dividendYield * timeTillExpiryDouble);
262  break;
263  }
264 
265  return Convert.ToDecimal(result);
266  }
267  }
268 }