Skip to content

Commit d9085cb

Browse files
committed
Add futures chains DataFrame property
Also, remove IDerivativeSecurity interface from Future
1 parent 99c8b50 commit d9085cb

File tree

865 files changed

+8945
-9092
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

865 files changed

+8945
-9092
lines changed

Common/Data/Market/BaseChain.cs

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

0 commit comments

Comments
 (0)