/* * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections; using System.Collections.Generic; using System.Linq; using Python.Runtime; using QuantConnect.Python; using QuantConnect.Securities.Option; using QuantConnect.Util; namespace QuantConnect.Data.Market { /// /// Base representation of an entire chain of contracts for a single underlying security. /// This type is where T is , , etc. /// public class BaseChain : BaseData, IEnumerable where T : BaseContract where TContractsCollection : DataDictionary, new() { private Dictionary>> _auxiliaryData; private readonly Lazy _dataframe; private readonly bool _flatten; private Dictionary>> AuxiliaryData { get { if (_auxiliaryData == null) { _auxiliaryData = new Dictionary>>(); } return _auxiliaryData; } } /// /// Gets the most recent trade information for the underlying. This may /// be a or a /// [PandasIgnore] public BaseData Underlying { get; internal set; } /// /// Gets all ticks for every option contract in this chain, keyed by option symbol /// [PandasIgnore] public Ticks Ticks { get; protected set; } /// /// Gets all trade bars for every option contract in this chain, keyed by option symbol /// [PandasIgnore] public TradeBars TradeBars { get; protected set; } /// /// Gets all quote bars for every option contract in this chain, keyed by option symbol /// [PandasIgnore] public QuoteBars QuoteBars { get; protected set; } /// /// Gets all contracts in the chain, keyed by option symbol /// public TContractsCollection Contracts { get; private set; } /// /// Gets the set of symbols that passed the /// [PandasIgnore] public HashSet FilteredContracts { get; protected set; } /// /// The data frame representation of the option chain /// [PandasIgnore] public PyObject DataFrame => _dataframe.Value; /// /// The number of contracts in this chain /// public int Count => Contracts.Count; /// /// Checks if the chain contains a contract with the specified symbol /// /// The symbol of the contract to check for /// True if the chain contains a contract with the specified symbol; otherwise, false. public bool ContainsKey(Symbol key) { return Contracts.ContainsKey(key); } /// /// Initializes a new default instance of the class /// protected BaseChain(MarketDataType dataType, bool flatten) { DataType = dataType; _flatten = flatten; _dataframe = new Lazy( () => { if (!PythonEngine.IsInitialized) { return null; } return new PandasConverter().GetDataFrame(new[] { this }, symbolOnlyIndex: true, flatten: _flatten); }, isThreadSafe: false); } /// /// Initializes a new instance of the class /// /// The symbol for this chain. /// The time of this chain /// Whether to flatten the data frame protected BaseChain(Symbol canonicalOptionSymbol, DateTime time, MarketDataType dataType, bool flatten = true) : this(dataType, flatten) { Time = time; Symbol = canonicalOptionSymbol; Ticks = new Ticks(time); TradeBars = new TradeBars(time); QuoteBars = new QuoteBars(time); FilteredContracts = new HashSet(); Underlying = new QuoteBar(); Contracts = new(); Contracts.Time = time; } /// /// Initializes a new instance of the class as a copy of the specified chain /// protected BaseChain(BaseChain other) : this(other.DataType, other._flatten) { Symbol = other.Symbol; Time = other.Time; Value = other.Value; Underlying = other.Underlying; Ticks = other.Ticks; QuoteBars = other.QuoteBars; TradeBars = other.TradeBars; Contracts = other.Contracts; FilteredContracts = other.FilteredContracts; } /// /// Gets the auxiliary data with the specified type and symbol /// /// The type of auxiliary data /// The symbol of the auxiliary data /// The last auxiliary data with the specified type and symbol public TAux GetAux(Symbol symbol) { List list; Dictionary> dictionary; if (!AuxiliaryData.TryGetValue(typeof(TAux), out dictionary) || !dictionary.TryGetValue(symbol, out list)) { return default; } return list.OfType().LastOrDefault(); } /// /// Gets all auxiliary data of the specified type as a dictionary keyed by symbol /// /// The type of auxiliary data /// A dictionary containing all auxiliary data of the specified type public DataDictionary GetAux() { Dictionary> d; if (!AuxiliaryData.TryGetValue(typeof(TAux), out d)) { return new DataDictionary(); } var dictionary = new DataDictionary(); foreach (var kvp in d) { var item = kvp.Value.OfType().LastOrDefault(); if (item != null) { dictionary.Add(kvp.Key, item); } } return dictionary; } /// /// Gets all auxiliary data of the specified type as a dictionary keyed by symbol /// /// The type of auxiliary data /// A dictionary containing all auxiliary data of the specified type public Dictionary> GetAuxList() { Dictionary> dictionary; if (!AuxiliaryData.TryGetValue(typeof(TAux), out dictionary)) { return new Dictionary>(); } return dictionary; } /// /// Gets a list of auxiliary data with the specified type and symbol /// /// The type of auxiliary data /// The symbol of the auxiliary data /// The list of auxiliary data with the specified type and symbol public List GetAuxList(Symbol symbol) { List list; Dictionary> dictionary; if (!AuxiliaryData.TryGetValue(typeof(TAux), out dictionary) || !dictionary.TryGetValue(symbol, out list)) { return new List(); } return list.OfType().ToList(); } /// /// Returns an enumerator that iterates through the collection. /// /// /// An enumerator that can be used to iterate through the collection. /// public IEnumerator GetEnumerator() { return Contracts.Values.GetEnumerator(); } /// /// Returns an enumerator that iterates through a collection. /// /// /// An object that can be used to iterate through the collection. /// IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } /// /// Adds the specified data to this chain /// /// The data to be added internal void AddData(BaseData data) { switch (data) { case Tick tick: Ticks.Add(tick.Symbol, tick); break; case TradeBar tradeBar: TradeBars[tradeBar.Symbol] = tradeBar; break; case QuoteBar quoteBar: QuoteBars[quoteBar.Symbol] = quoteBar; break; default: if (data.DataType == MarketDataType.Base) { AddAuxData(data); } break; } } /// /// Adds the specified auxiliary data to this option chain /// /// The auxiliary data to be added private void AddAuxData(BaseData baseData) { var type = baseData.GetType(); Dictionary> dictionary; if (!AuxiliaryData.TryGetValue(type, out dictionary)) { dictionary = new Dictionary>(); AuxiliaryData[type] = dictionary; } List list; if (!dictionary.TryGetValue(baseData.Symbol, out list)) { list = new List(); dictionary[baseData.Symbol] = list; } list.Add(baseData); } } }