Lean  $LEAN_TAG$
OptionChain.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 System.Collections;
18 using System.Collections.Generic;
19 using System.Linq;
20 using Python.Runtime;
22 using QuantConnect.Python;
25 using QuantConnect.Util;
26 
28 {
29  /// <summary>
30  /// Represents an entire chain of option contracts for a single underying security.
31  /// This type is <see cref="IEnumerable{OptionContract}"/>
32  /// </summary>
33  public class OptionChain : BaseData, IEnumerable<OptionContract>
34  {
35  private readonly Dictionary<Type, Dictionary<Symbol, List<BaseData>>> _auxiliaryData = new Dictionary<Type, Dictionary<Symbol, List<BaseData>>>();
36  private readonly Lazy<PyObject> _dataframe;
37 
38  /// <summary>
39  /// Gets the most recent trade information for the underlying. This may
40  /// be a <see cref="Tick"/> or a <see cref="TradeBar"/>
41  /// </summary>
42  public BaseData Underlying
43  {
44  get; internal set;
45  }
46 
47  /// <summary>
48  /// Gets all ticks for every option contract in this chain, keyed by option symbol
49  /// </summary>
50  public Ticks Ticks
51  {
52  get; private set;
53  }
54 
55  /// <summary>
56  /// Gets all trade bars for every option contract in this chain, keyed by option symbol
57  /// </summary>
58  public TradeBars TradeBars
59  {
60  get; private set;
61  }
62 
63  /// <summary>
64  /// Gets all quote bars for every option contract in this chain, keyed by option symbol
65  /// </summary>
66  public QuoteBars QuoteBars
67  {
68  get; private set;
69  }
70 
71  /// <summary>
72  /// Gets all contracts in the chain, keyed by option symbol
73  /// </summary>
75  {
76  get; private set;
77  }
78 
79  /// <summary>
80  /// Gets the set of symbols that passed the <see cref="Option.ContractFilter"/>
81  /// </summary>
82  public HashSet<Symbol> FilteredContracts
83  {
84  get; private set;
85  }
86 
87  /// <summary>
88  /// The data frame representation of the option chain
89  /// </summary>
90  public PyObject DataFrame => _dataframe.Value;
91 
92  /// <summary>
93  /// Initializes a new default instance of the <see cref="OptionChain"/> class
94  /// </summary>
95  private OptionChain()
96  {
97  DataType = MarketDataType.OptionChain;
98  _dataframe = new Lazy<PyObject>(() => new PandasConverter().GetDataFrame(this, symbolOnlyIndex: true), isThreadSafe: false);
99  }
100 
101  /// <summary>
102  /// Initializes a new instance of the <see cref="OptionChain"/> class
103  /// </summary>
104  /// <param name="canonicalOptionSymbol">The symbol for this chain.</param>
105  /// <param name="time">The time of this chain</param>
106  public OptionChain(Symbol canonicalOptionSymbol, DateTime time)
107  : this()
108  {
109  Time = time;
110  Symbol = canonicalOptionSymbol;
111  DataType = MarketDataType.OptionChain;
112  Ticks = new Ticks(time);
113  TradeBars = new TradeBars(time);
114  QuoteBars = new QuoteBars(time);
115  Contracts = new OptionContracts(time);
116  FilteredContracts = new HashSet<Symbol>();
117  Underlying = new QuoteBar();
118  }
119 
120  /// <summary>
121  /// Initializes a new instance of the <see cref="OptionChain"/> class
122  /// </summary>
123  /// <param name="canonicalOptionSymbol">The symbol for this chain.</param>
124  /// <param name="time">The time of this chain</param>
125  /// <param name="underlying">The most recent underlying trade data</param>
126  /// <param name="trades">All trade data for the entire option chain</param>
127  /// <param name="quotes">All quote data for the entire option chain</param>
128  /// <param name="contracts">All contracts for this option chain</param>
129  /// <param name="filteredContracts">The filtered list of contracts for this option chain</param>
130  public OptionChain(Symbol canonicalOptionSymbol, DateTime time, BaseData underlying, IEnumerable<BaseData> trades, IEnumerable<BaseData> quotes, IEnumerable<OptionContract> contracts, IEnumerable<Symbol> filteredContracts)
131  : this()
132  {
133  Time = time;
134  Underlying = underlying;
135  Symbol = canonicalOptionSymbol;
136  DataType = MarketDataType.OptionChain;
137  FilteredContracts = filteredContracts.ToHashSet();
138 
139  Ticks = new Ticks(time);
140  TradeBars = new TradeBars(time);
141  QuoteBars = new QuoteBars(time);
142  Contracts = new OptionContracts(time);
143 
144  foreach (var trade in trades)
145  {
146  var tick = trade as Tick;
147  if (tick != null)
148  {
149  List<Tick> ticks;
150  if (!Ticks.TryGetValue(tick.Symbol, out ticks))
151  {
152  ticks = new List<Tick>();
153  Ticks[tick.Symbol] = ticks;
154  }
155  ticks.Add(tick);
156  continue;
157  }
158  var bar = trade as TradeBar;
159  if (bar != null)
160  {
161  TradeBars[trade.Symbol] = bar;
162  }
163  }
164 
165  foreach (var quote in quotes)
166  {
167  var tick = quote as Tick;
168  if (tick != null)
169  {
170  List<Tick> ticks;
171  if (!Ticks.TryGetValue(tick.Symbol, out ticks))
172  {
173  ticks = new List<Tick>();
174  Ticks[tick.Symbol] = ticks;
175  }
176  ticks.Add(tick);
177  continue;
178  }
179  var bar = quote as QuoteBar;
180  if (bar != null)
181  {
182  QuoteBars[quote.Symbol] = bar;
183  }
184  }
185 
186  foreach (var contract in contracts)
187  {
188  Contracts[contract.Symbol] = contract;
189  }
190  }
191 
192  /// <summary>
193  /// Initializes a new option chain for a list of contracts as <see cref="OptionUniverse"/> instances
194  /// </summary>
195  /// <param name="canonicalOptionSymbol">The canonical option symbol</param>
196  /// <param name="time">The time of this chain</param>
197  /// <param name="contracts">The list of contracts data</param>
198  /// <param name="symbolProperties">The option symbol properties</param>
199  public OptionChain(Symbol canonicalOptionSymbol, DateTime time, IEnumerable<OptionUniverse> contracts, SymbolProperties symbolProperties)
200  : this(canonicalOptionSymbol, time)
201  {
202  Time = time;
203  Symbol = canonicalOptionSymbol;
204  DataType = MarketDataType.OptionChain;
205 
206  Ticks = new Ticks(time);
207  TradeBars = new TradeBars(time);
208  QuoteBars = new QuoteBars(time);
209  Contracts = new OptionContracts(time);
210 
211  foreach (var contractData in contracts)
212  {
213  Contracts[contractData.Symbol] = OptionContract.Create(contractData, symbolProperties);
214  Underlying ??= contractData.Underlying;
215  }
216  }
217 
218  /// <summary>
219  /// Gets the auxiliary data with the specified type and symbol
220  /// </summary>
221  /// <typeparam name="T">The type of auxiliary data</typeparam>
222  /// <param name="symbol">The symbol of the auxiliary data</param>
223  /// <returns>The last auxiliary data with the specified type and symbol</returns>
224  public T GetAux<T>(Symbol symbol)
225  {
226  List<BaseData> list;
227  Dictionary<Symbol, List<BaseData>> dictionary;
228  if (!_auxiliaryData.TryGetValue(typeof(T), out dictionary) || !dictionary.TryGetValue(symbol, out list))
229  {
230  return default(T);
231  }
232  return list.OfType<T>().LastOrDefault();
233  }
234 
235  /// <summary>
236  /// Gets all auxiliary data of the specified type as a dictionary keyed by symbol
237  /// </summary>
238  /// <typeparam name="T">The type of auxiliary data</typeparam>
239  /// <returns>A dictionary containing all auxiliary data of the specified type</returns>
241  {
242  Dictionary<Symbol, List<BaseData>> d;
243  if (!_auxiliaryData.TryGetValue(typeof(T), out d))
244  {
245  return new DataDictionary<T>();
246  }
247  var dictionary = new DataDictionary<T>();
248  foreach (var kvp in d)
249  {
250  var item = kvp.Value.OfType<T>().LastOrDefault();
251  if (item != null)
252  {
253  dictionary.Add(kvp.Key, item);
254  }
255  }
256  return dictionary;
257  }
258 
259  /// <summary>
260  /// Gets all auxiliary data of the specified type as a dictionary keyed by symbol
261  /// </summary>
262  /// <typeparam name="T">The type of auxiliary data</typeparam>
263  /// <returns>A dictionary containing all auxiliary data of the specified type</returns>
264  public Dictionary<Symbol, List<BaseData>> GetAuxList<T>()
265  {
266  Dictionary<Symbol, List<BaseData>> dictionary;
267  if (!_auxiliaryData.TryGetValue(typeof(T), out dictionary))
268  {
269  return new Dictionary<Symbol, List<BaseData>>();
270  }
271  return dictionary;
272  }
273 
274  /// <summary>
275  /// Gets a list of auxiliary data with the specified type and symbol
276  /// </summary>
277  /// <typeparam name="T">The type of auxiliary data</typeparam>
278  /// <param name="symbol">The symbol of the auxiliary data</param>
279  /// <returns>The list of auxiliary data with the specified type and symbol</returns>
280  public List<T> GetAuxList<T>(Symbol symbol)
281  {
282  List<BaseData> list;
283  Dictionary<Symbol, List<BaseData>> dictionary;
284  if (!_auxiliaryData.TryGetValue(typeof(T), out dictionary) || !dictionary.TryGetValue(symbol, out list))
285  {
286  return new List<T>();
287  }
288  return list.OfType<T>().ToList();
289  }
290 
291  /// <summary>
292  /// Returns an enumerator that iterates through the collection.
293  /// </summary>
294  /// <returns>
295  /// An enumerator that can be used to iterate through the collection.
296  /// </returns>
297  public IEnumerator<OptionContract> GetEnumerator()
298  {
299  return Contracts.Values.GetEnumerator();
300  }
301 
302  /// <summary>
303  /// Returns an enumerator that iterates through a collection.
304  /// </summary>
305  /// <returns>
306  /// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
307  /// </returns>
308  IEnumerator IEnumerable.GetEnumerator()
309  {
310  return GetEnumerator();
311  }
312 
313  /// <summary>
314  /// Return a new instance clone of this object, used in fill forward
315  /// </summary>
316  /// <returns>A clone of the current object</returns>
317  public override BaseData Clone()
318  {
319  return new OptionChain
320  {
322  Ticks = Ticks,
327  Symbol = Symbol,
328  Time = Time,
329  DataType = DataType,
330  Value = Value
331  };
332  }
333 
334  /// <summary>
335  /// Adds the specified auxiliary data to this option chain
336  /// </summary>
337  /// <param name="baseData">The auxiliary data to be added</param>
338  internal void AddAuxData(BaseData baseData)
339  {
340  var type = baseData.GetType();
341  Dictionary<Symbol, List<BaseData>> dictionary;
342  if (!_auxiliaryData.TryGetValue(type, out dictionary))
343  {
344  dictionary = new Dictionary<Symbol, List<BaseData>>();
345  _auxiliaryData[type] = dictionary;
346  }
347 
348  List<BaseData> list;
349  if (!dictionary.TryGetValue(baseData.Symbol, out list))
350  {
351  list = new List<BaseData>();
352  dictionary[baseData.Symbol] = list;
353  }
354  list.Add(baseData);
355  }
356  }
357 }