15
15
16
16
using System ;
17
17
using MathNet . Numerics . RootFinding ;
18
+ using Python . Runtime ;
19
+ using QuantConnect . Data ;
18
20
using QuantConnect . Data . Consolidators ;
19
- using QuantConnect . Data . Market ;
20
21
using QuantConnect . Logging ;
22
+ using QuantConnect . Python ;
21
23
22
24
namespace QuantConnect . Indicators
23
25
{
24
26
/// <summary>
25
27
/// Implied Volatility indicator that calculate the IV of an option using Black-Scholes Model
26
28
/// </summary>
27
- public class ImpliedVolatility : BarIndicator , IIndicatorWarmUpPeriodProvider
29
+ public class ImpliedVolatility : IndicatorBase < IndicatorDataPoint > , IIndicatorWarmUpPeriodProvider
28
30
{
29
31
private readonly Symbol _optionSymbol ;
30
32
private readonly Symbol _underlyingSymbol ;
@@ -34,29 +36,34 @@ public class ImpliedVolatility : BarIndicator, IIndicatorWarmUpPeriodProvider
34
36
private OptionPricingModelType _optionModel ;
35
37
36
38
/// <summary>
37
- /// Gets the expiration time of the option
39
+ /// Risk-free rate model
38
40
/// </summary>
39
- public DateTime Expiry { get ; }
41
+ private readonly IRiskFreeInterestRateModel _riskFreeInterestRateModel ;
40
42
41
43
/// <summary>
42
- /// Gets the option right (call/put) of the option
44
+ /// Gets the expiration time of the option
43
45
/// </summary>
44
- public OptionRight Right { get ; }
46
+ public DateTime Expiry => _optionSymbol . ID . Date ;
45
47
46
48
/// <summary>
47
- /// Risk Free Rate
49
+ /// Gets the option right (call/put) of the option
48
50
/// </summary>
49
- public decimal RiskFreeRate { get ; set ; }
51
+ public OptionRight Right => _optionSymbol . ID . OptionRight ;
50
52
51
53
/// <summary>
52
54
/// Gets the strike price of the option
53
55
/// </summary>
54
- public decimal Strike { get ; }
56
+ public decimal Strike => _optionSymbol . ID . StrikePrice ;
55
57
56
58
/// <summary>
57
59
/// Gets the option style (European/American) of the option
58
60
/// </summary>
59
- public OptionStyle Style { get ; }
61
+ public OptionStyle Style => _optionSymbol . ID . OptionStyle ;
62
+
63
+ /// <summary>
64
+ /// Risk Free Rate
65
+ /// </summary>
66
+ public Identity RiskFreeRate { get ; set ; }
60
67
61
68
/// <summary>
62
69
/// Gets the historical volatility of the underlying
@@ -73,28 +80,15 @@ public class ImpliedVolatility : BarIndicator, IIndicatorWarmUpPeriodProvider
73
80
/// </summary>
74
81
public IndicatorBase < IndicatorDataPoint > UnderlyingPrice { get ; }
75
82
76
- /// <summary>
77
- /// Initializes a new instance of the ImpliedVolatility class
78
- /// </summary>
79
- /// <param name="option">The option to be tracked</param>am>
80
- /// <param name="riskFreeRate">The risk free rate</param>
81
- /// <param name="period">The lookback period of historical volatility</param>
82
- /// <param name="optionModel">The option pricing model used to estimate IV</param>
83
- public ImpliedVolatility ( Symbol option , decimal riskFreeRate = 0.05m , int period = 252 ,
84
- OptionPricingModelType optionModel = OptionPricingModelType . BlackScholes )
85
- : this ( $ "IV({ option . Value } ,{ riskFreeRate } ,{ period } ,{ optionModel } )", option , riskFreeRate , period , optionModel )
86
- {
87
- }
88
-
89
83
/// <summary>
90
84
/// Initializes a new instance of the ImpliedVolatility class
91
85
/// </summary>
92
86
/// <param name="name">The name of this indicator</param>
93
87
/// <param name="option">The option to be tracked</param>
94
- /// <param name="riskFreeRate">The risk free rate</param>
88
+ /// <param name="riskFreeRateModel">Risk- free rate model </param>
95
89
/// <param name="period">The lookback period of historical volatility</param>
96
90
/// <param name="optionModel">The option pricing model used to estimate IV</param>
97
- public ImpliedVolatility ( string name , Symbol option , decimal riskFreeRate = 0.05m , int period = 252 ,
91
+ public ImpliedVolatility ( string name , Symbol option , IRiskFreeInterestRateModel riskFreeRateModel , int period = 252 ,
98
92
OptionPricingModelType optionModel = OptionPricingModelType . BlackScholes )
99
93
: base ( name )
100
94
{
@@ -107,14 +101,10 @@ public ImpliedVolatility(string name, Symbol option, decimal riskFreeRate = 0.05
107
101
_optionSymbol = option ;
108
102
_underlyingSymbol = option . Underlying ;
109
103
_roc = new ( 1 ) ;
104
+ _riskFreeInterestRateModel = riskFreeRateModel ;
110
105
_optionModel = optionModel ;
111
-
112
- Strike = sid . StrikePrice ;
113
- Expiry = sid . Date ;
114
- Right = sid . OptionRight ;
115
- Style = sid . OptionStyle ;
116
- RiskFreeRate = riskFreeRate ;
117
106
107
+ RiskFreeRate = new Identity ( name + "_RiskFreeRate" ) ;
118
108
HistoricalVolatility = IndicatorExtensions . Times (
119
109
IndicatorExtensions . Of (
120
110
new StandardDeviation ( period ) ,
@@ -133,6 +123,75 @@ public ImpliedVolatility(string name, Symbol option, decimal riskFreeRate = 0.05
133
123
WarmUpPeriod = period ;
134
124
}
135
125
126
+ /// <summary>
127
+ /// Initializes a new instance of the ImpliedVolatility class
128
+ /// </summary>
129
+ /// <param name="option">The option to be tracked</param>
130
+ /// <param name="riskFreeRateModel">Risk-free rate model</param>
131
+ /// <param name="period">The lookback period of historical volatility</param>
132
+ /// <param name="optionModel">The option pricing model used to estimate IV</param>
133
+ public ImpliedVolatility ( Symbol option , IRiskFreeInterestRateModel riskFreeRateModel , int period = 252 ,
134
+ OptionPricingModelType optionModel = OptionPricingModelType . BlackScholes )
135
+ : this ( $ "IV({ option . Value } ,{ period } ,{ optionModel } )", option , riskFreeRateModel , period , optionModel )
136
+ {
137
+ }
138
+
139
+ /// <summary>
140
+ /// Initializes a new instance of the ImpliedVolatility class
141
+ /// </summary>
142
+ /// <param name="name">The name of this indicator</param>
143
+ /// <param name="option">The option to be tracked</param>
144
+ /// <param name="riskFreeRateModel">Risk-free rate model</param>
145
+ /// <param name="period">The lookback period of historical volatility</param>
146
+ /// <param name="optionModel">The option pricing model used to estimate IV</param>
147
+ public ImpliedVolatility ( string name , Symbol option , PyObject riskFreeRateModel , int period = 252 ,
148
+ OptionPricingModelType optionModel = OptionPricingModelType . BlackScholes )
149
+ : this ( name , option , RiskFreeInterestRateModelPythonWrapper . FromPyObject ( riskFreeRateModel ) , period , optionModel )
150
+ {
151
+ }
152
+
153
+ /// <summary>
154
+ /// Initializes a new instance of the ImpliedVolatility class
155
+ /// </summary>
156
+ /// <param name="option">The option to be tracked</param>
157
+ /// <param name="riskFreeRateModel">Risk-free rate model</param>
158
+ /// <param name="period">The lookback period of historical volatility</param>
159
+ /// <param name="optionModel">The option pricing model used to estimate IV</param>
160
+ public ImpliedVolatility ( Symbol option , PyObject riskFreeRateModel , int period = 252 ,
161
+ OptionPricingModelType optionModel = OptionPricingModelType . BlackScholes )
162
+ : this ( $ "IV({ option . Value } ,{ period } ,{ optionModel } )", option ,
163
+ RiskFreeInterestRateModelPythonWrapper . FromPyObject ( riskFreeRateModel ) , period , optionModel )
164
+ {
165
+ }
166
+
167
+ /// <summary>
168
+ /// Initializes a new instance of the ImpliedVolatility class
169
+ /// </summary>
170
+ /// <param name="name">The name of this indicator</param>
171
+ /// <param name="option">The option to be tracked</param>
172
+ /// <param name="riskFreeRate">Risk-free rate, as a constant</param>
173
+ /// <param name="period">The lookback period of historical volatility</param>
174
+ /// <param name="optionModel">The option pricing model used to estimate IV</param>
175
+ public ImpliedVolatility ( string name , Symbol option , decimal riskFreeRate = 0.05m , int period = 252 ,
176
+ OptionPricingModelType optionModel = OptionPricingModelType . BlackScholes )
177
+ : this ( name , option , new ConstantRiskFreeRateInterestRateModel ( riskFreeRate ) , period , optionModel )
178
+ {
179
+ }
180
+
181
+ /// <summary>
182
+ /// Initializes a new instance of the ImpliedVolatility class
183
+ /// </summary>
184
+ /// <param name="option">The option to be tracked</param>
185
+ /// <param name="riskFreeRate">Risk-free rate, as a constant</param>
186
+ /// <param name="period">The lookback period of historical volatility</param>
187
+ /// <param name="optionModel">The option pricing model used to estimate IV</param>
188
+ public ImpliedVolatility ( Symbol option , decimal riskFreeRate = 0.05m , int period = 252 ,
189
+ OptionPricingModelType optionModel = OptionPricingModelType . BlackScholes )
190
+ : this ( $ "IV({ option . Value } ,{ period } ,{ riskFreeRate } ,{ optionModel } )", option ,
191
+ new ConstantRiskFreeRateInterestRateModel ( riskFreeRate ) , period , optionModel )
192
+ {
193
+ }
194
+
136
195
/// <summary>
137
196
/// Gets a flag indicating when this indicator is ready and fully initialized
138
197
/// </summary>
@@ -148,17 +207,19 @@ public ImpliedVolatility(string name, Symbol option, decimal riskFreeRate = 0.05
148
207
/// </summary>
149
208
/// <param name="input">The input given to the indicator</param>
150
209
/// <returns>The input is returned unmodified.</returns>
151
- protected override decimal ComputeNextValue ( IBaseDataBar input )
210
+ protected override decimal ComputeNextValue ( IndicatorDataPoint input )
152
211
{
212
+ RiskFreeRate . Update ( input . EndTime , _riskFreeInterestRateModel . GetInterestRate ( input . EndTime ) ) ;
213
+
153
214
var inputSymbol = input . Symbol ;
154
215
if ( inputSymbol == _optionSymbol )
155
216
{
156
- Price . Update ( input . EndTime , input . Close ) ;
217
+ Price . Update ( input . EndTime , input . Price ) ;
157
218
}
158
219
else if ( inputSymbol == _underlyingSymbol )
159
220
{
160
221
_consolidator . Update ( input ) ;
161
- UnderlyingPrice . Update ( input . EndTime , input . Close ) ;
222
+ UnderlyingPrice . Update ( input . EndTime , input . Price ) ;
162
223
}
163
224
else
164
225
{
@@ -194,14 +255,15 @@ private decimal CalculateIV(DateTime time)
194
255
var spotPrice = UnderlyingPrice . Current . Value ;
195
256
var timeToExpiration = Convert . ToDecimal ( ( Expiry - time ) . TotalDays ) / 365m ;
196
257
197
- Func < double , double > f = ( vol ) => ( double ) ( TheoreticalPrice ( Convert . ToDecimal ( vol ) , spotPrice , Strike , timeToExpiration , RiskFreeRate , Right , _optionModel ) - price ) ;
258
+ Func < double , double > f = ( vol ) =>
259
+ ( double ) ( TheoreticalPrice ( Convert . ToDecimal ( vol ) , spotPrice , Strike , timeToExpiration , RiskFreeRate . Current . Value , Right , _optionModel ) - price ) ;
198
260
try
199
261
{
200
262
return Convert . ToDecimal ( Brent . FindRoot ( f , 0.01d , 1.0d , 1e-5d , 20 ) ) ;
201
263
}
202
264
catch
203
265
{
204
- Log . Error ( "Fail to converge, returning 0." ) ;
266
+ Log . Error ( "ImpliedVolatility.CalculateIV(): Fail to converge, returning 0." ) ;
205
267
return 0m ;
206
268
}
207
269
}
@@ -211,12 +273,14 @@ private decimal CalculateIV(DateTime time)
211
273
/// </summary>
212
274
public override void Reset ( )
213
275
{
276
+ _consolidator . Dispose ( ) ;
214
277
_consolidator = new ( TimeSpan . FromDays ( 1 ) ) ;
215
278
_consolidator . DataConsolidated += ( _ , bar ) => {
216
279
_roc . Update ( bar . EndTime , bar . Price ) ;
217
280
} ;
218
281
219
282
_roc . Reset ( ) ;
283
+ RiskFreeRate . Reset ( ) ;
220
284
HistoricalVolatility . Reset ( ) ;
221
285
Price . Reset ( ) ;
222
286
UnderlyingPrice . Reset ( ) ;
0 commit comments