chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* 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.Runtime.CompilerServices;
|
||||
using ProtoBuf;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Base Bar Class: Open, High, Low, Close and Period.
|
||||
/// </summary>
|
||||
[ProtoContract(SkipConstructor = true)]
|
||||
public class Bar : IBar
|
||||
{
|
||||
private bool _openSet;
|
||||
|
||||
/// <summary>
|
||||
/// Opening price of the bar: Defined as the price at the start of the time period.
|
||||
/// </summary>
|
||||
[ProtoMember(1)]
|
||||
public virtual decimal Open { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// High price of the bar during the time period.
|
||||
/// </summary>
|
||||
[ProtoMember(2)]
|
||||
public virtual decimal High { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Low price of the bar during the time period.
|
||||
/// </summary>
|
||||
[ProtoMember(3)]
|
||||
public virtual decimal Low { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Closing price of the bar. Defined as the price at Start Time + TimeSpan.
|
||||
/// </summary>
|
||||
[ProtoMember(4)]
|
||||
public virtual decimal Close { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Default initializer to setup an empty bar.
|
||||
/// </summary>
|
||||
public Bar()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializer to setup a bar with a given information.
|
||||
/// </summary>
|
||||
/// <param name="open">Decimal Opening Price</param>
|
||||
/// <param name="high">Decimal High Price of this bar</param>
|
||||
/// <param name="low">Decimal Low Price of this bar</param>
|
||||
/// <param name="close">Decimal Close price of this bar</param>
|
||||
public Bar(decimal open, decimal high, decimal low, decimal close)
|
||||
{
|
||||
_openSet = open != 0;
|
||||
Open = open;
|
||||
High = high;
|
||||
Low = low;
|
||||
Close = close;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the bar with a new value. This will aggregate the OHLC bar
|
||||
/// </summary>
|
||||
/// <param name="value">The new value</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Update(decimal value)
|
||||
{
|
||||
Update(ref value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the bar with a new value. This will aggregate the OHLC bar
|
||||
/// </summary>
|
||||
/// <param name="value">The new value</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Update(ref decimal value)
|
||||
{
|
||||
// Do not accept zero as a new value
|
||||
if (value == 0) return;
|
||||
|
||||
if (!_openSet)
|
||||
{
|
||||
Open = High = Low = Close = value;
|
||||
_openSet = true;
|
||||
}
|
||||
else if (value > High) High = value;
|
||||
else if (value < Low) Low = value;
|
||||
Close = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a clone of this bar
|
||||
/// </summary>
|
||||
public Bar Clone()
|
||||
{
|
||||
return new Bar(Open, High, Low, Close);
|
||||
}
|
||||
|
||||
/// <summary>Returns a string that represents the current object.</summary>
|
||||
/// <returns>A string that represents the current object.</returns>
|
||||
/// <filterpriority>2</filterpriority>
|
||||
public override string ToString()
|
||||
{
|
||||
return $"O: {Open.SmartRounding()} " +
|
||||
$"H: {High.SmartRounding()} " +
|
||||
$"L: {Low.SmartRounding()} " +
|
||||
$"C: {Close.SmartRounding()}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Enum for Bar Direction
|
||||
/// </summary>
|
||||
public enum BarDirection
|
||||
{
|
||||
/// <summary>
|
||||
/// Rising bar (0)
|
||||
/// </summary>
|
||||
Rising,
|
||||
|
||||
/// <summary>
|
||||
/// No change (1)
|
||||
/// </summary>
|
||||
NoDelta,
|
||||
|
||||
/// <summary>
|
||||
/// Falling bar (2)
|
||||
/// </summary>
|
||||
Falling
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,330 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Base representation of an entire chain of contracts for a single underlying security.
|
||||
/// This type is <see cref="IEnumerable{T}"/> where T is <see cref="OptionContract"/>, <see cref="FuturesContract"/>, etc.
|
||||
/// </summary>
|
||||
public class BaseChain<T, TContractsCollection> : BaseData, IEnumerable<T>
|
||||
where T : BaseContract
|
||||
where TContractsCollection : DataDictionary<T>, new()
|
||||
{
|
||||
private Dictionary<Type, Dictionary<Symbol, List<BaseData>>> _auxiliaryData;
|
||||
private readonly Lazy<PyObject> _dataframe;
|
||||
private readonly bool _flatten;
|
||||
|
||||
private Dictionary<Type, Dictionary<Symbol, List<BaseData>>> AuxiliaryData
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_auxiliaryData == null)
|
||||
{
|
||||
_auxiliaryData = new Dictionary<Type, Dictionary<Symbol, List<BaseData>>>();
|
||||
}
|
||||
|
||||
return _auxiliaryData;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the most recent trade information for the underlying. This may
|
||||
/// be a <see cref="Tick"/> or a <see cref="TradeBar"/>
|
||||
/// </summary>
|
||||
[PandasIgnore]
|
||||
public BaseData Underlying
|
||||
{
|
||||
get; internal set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all ticks for every option contract in this chain, keyed by option symbol
|
||||
/// </summary>
|
||||
[PandasIgnore]
|
||||
public Ticks Ticks
|
||||
{
|
||||
get; protected set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all trade bars for every option contract in this chain, keyed by option symbol
|
||||
/// </summary>
|
||||
[PandasIgnore]
|
||||
public TradeBars TradeBars
|
||||
{
|
||||
get; protected set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all quote bars for every option contract in this chain, keyed by option symbol
|
||||
/// </summary>
|
||||
[PandasIgnore]
|
||||
public QuoteBars QuoteBars
|
||||
{
|
||||
get; protected set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all contracts in the chain, keyed by option symbol
|
||||
/// </summary>
|
||||
public TContractsCollection Contracts
|
||||
{
|
||||
get; private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the set of symbols that passed the <see cref="Option.ContractFilter"/>
|
||||
/// </summary>
|
||||
[PandasIgnore]
|
||||
public HashSet<Symbol> FilteredContracts
|
||||
{
|
||||
get; protected set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The data frame representation of the option chain
|
||||
/// </summary>
|
||||
[PandasIgnore]
|
||||
public PyObject DataFrame => _dataframe.Value;
|
||||
|
||||
/// <summary>
|
||||
/// The number of contracts in this chain
|
||||
/// </summary>
|
||||
public int Count => Contracts.Count;
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the chain contains a contract with the specified symbol
|
||||
/// </summary>
|
||||
/// <param name="key">The symbol of the contract to check for</param>
|
||||
/// <returns>True if the chain contains a contract with the specified symbol; otherwise, false.</returns>
|
||||
public bool ContainsKey(Symbol key)
|
||||
{
|
||||
return Contracts.ContainsKey(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new default instance of the <see cref="BaseChain{T, TContractsCollection}"/> class
|
||||
/// </summary>
|
||||
protected BaseChain(MarketDataType dataType, bool flatten)
|
||||
{
|
||||
DataType = dataType;
|
||||
_flatten = flatten;
|
||||
_dataframe = new Lazy<PyObject>(
|
||||
() =>
|
||||
{
|
||||
if (!PythonEngine.IsInitialized)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return new PandasConverter().GetDataFrame(new[] { this }, symbolOnlyIndex: true, flatten: _flatten);
|
||||
},
|
||||
isThreadSafe: false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BaseChain{T, TContractsCollection}"/> class
|
||||
/// </summary>
|
||||
/// <param name="canonicalOptionSymbol">The symbol for this chain.</param>
|
||||
/// <param name="time">The time of this chain</param>
|
||||
/// <param name="flatten">Whether to flatten the data frame</param>
|
||||
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<Symbol>();
|
||||
Underlying = new QuoteBar();
|
||||
Contracts = new();
|
||||
Contracts.Time = time;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BaseChain{T, TContractsCollection}"/> class as a copy of the specified chain
|
||||
/// </summary>
|
||||
protected BaseChain(BaseChain<T, TContractsCollection> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the auxiliary data with the specified type and symbol
|
||||
/// </summary>
|
||||
/// <typeparam name="TAux">The type of auxiliary data</typeparam>
|
||||
/// <param name="symbol">The symbol of the auxiliary data</param>
|
||||
/// <returns>The last auxiliary data with the specified type and symbol</returns>
|
||||
public TAux GetAux<TAux>(Symbol symbol)
|
||||
{
|
||||
List<BaseData> list;
|
||||
Dictionary<Symbol, List<BaseData>> dictionary;
|
||||
if (!AuxiliaryData.TryGetValue(typeof(TAux), out dictionary) || !dictionary.TryGetValue(symbol, out list))
|
||||
{
|
||||
return default;
|
||||
}
|
||||
return list.OfType<TAux>().LastOrDefault();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all auxiliary data of the specified type as a dictionary keyed by symbol
|
||||
/// </summary>
|
||||
/// <typeparam name="TAux">The type of auxiliary data</typeparam>
|
||||
/// <returns>A dictionary containing all auxiliary data of the specified type</returns>
|
||||
public DataDictionary<TAux> GetAux<TAux>()
|
||||
{
|
||||
Dictionary<Symbol, List<BaseData>> d;
|
||||
if (!AuxiliaryData.TryGetValue(typeof(TAux), out d))
|
||||
{
|
||||
return new DataDictionary<TAux>();
|
||||
}
|
||||
var dictionary = new DataDictionary<TAux>();
|
||||
foreach (var kvp in d)
|
||||
{
|
||||
var item = kvp.Value.OfType<TAux>().LastOrDefault();
|
||||
if (item != null)
|
||||
{
|
||||
dictionary.Add(kvp.Key, item);
|
||||
}
|
||||
}
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all auxiliary data of the specified type as a dictionary keyed by symbol
|
||||
/// </summary>
|
||||
/// <typeparam name="TAux">The type of auxiliary data</typeparam>
|
||||
/// <returns>A dictionary containing all auxiliary data of the specified type</returns>
|
||||
public Dictionary<Symbol, List<BaseData>> GetAuxList<TAux>()
|
||||
{
|
||||
Dictionary<Symbol, List<BaseData>> dictionary;
|
||||
if (!AuxiliaryData.TryGetValue(typeof(TAux), out dictionary))
|
||||
{
|
||||
return new Dictionary<Symbol, List<BaseData>>();
|
||||
}
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of auxiliary data with the specified type and symbol
|
||||
/// </summary>
|
||||
/// <typeparam name="TAux">The type of auxiliary data</typeparam>
|
||||
/// <param name="symbol">The symbol of the auxiliary data</param>
|
||||
/// <returns>The list of auxiliary data with the specified type and symbol</returns>
|
||||
public List<TAux> GetAuxList<TAux>(Symbol symbol)
|
||||
{
|
||||
List<BaseData> list;
|
||||
Dictionary<Symbol, List<BaseData>> dictionary;
|
||||
if (!AuxiliaryData.TryGetValue(typeof(TAux), out dictionary) || !dictionary.TryGetValue(symbol, out list))
|
||||
{
|
||||
return new List<TAux>();
|
||||
}
|
||||
return list.OfType<TAux>().ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an enumerator that iterates through the collection.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// An enumerator that can be used to iterate through the collection.
|
||||
/// </returns>
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return Contracts.Values.GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an enumerator that iterates through a collection.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
|
||||
/// </returns>
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the specified data to this chain
|
||||
/// </summary>
|
||||
/// <param name="data">The data to be added</param>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the specified auxiliary data to this option chain
|
||||
/// </summary>
|
||||
/// <param name="baseData">The auxiliary data to be added</param>
|
||||
private void AddAuxData(BaseData baseData)
|
||||
{
|
||||
var type = baseData.GetType();
|
||||
Dictionary<Symbol, List<BaseData>> dictionary;
|
||||
if (!AuxiliaryData.TryGetValue(type, out dictionary))
|
||||
{
|
||||
dictionary = new Dictionary<Symbol, List<BaseData>>();
|
||||
AuxiliaryData[type] = dictionary;
|
||||
}
|
||||
|
||||
List<BaseData> list;
|
||||
if (!dictionary.TryGetValue(baseData.Symbol, out list))
|
||||
{
|
||||
list = new List<BaseData>();
|
||||
dictionary[baseData.Symbol] = list;
|
||||
}
|
||||
list.Add(baseData);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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 Python.Runtime;
|
||||
using QuantConnect.Python;
|
||||
using QuantConnect.Securities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Collection of <see cref="BaseChain{T, TContractsCollection}"/> keyed by canonical option symbol
|
||||
/// </summary>
|
||||
public class BaseChains<T, TContract, TContractsCollection> : DataDictionary<T>
|
||||
where T : BaseChain<TContract, TContractsCollection>
|
||||
where TContract : BaseContract
|
||||
where TContractsCollection : DataDictionary<TContract>, new()
|
||||
{
|
||||
private static readonly IEnumerable<string> _flattenedDfIndexNames = new[] { "canonical", "symbol" };
|
||||
|
||||
private readonly Lazy<PyObject> _dataframe;
|
||||
private readonly bool _flatten;
|
||||
|
||||
/// <summary>
|
||||
/// The data frame representation of the option chains
|
||||
/// </summary>
|
||||
public PyObject DataFrame => _dataframe.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="BaseChains{T, TContract, TContractsCollection}"/> dictionary
|
||||
/// </summary>
|
||||
protected BaseChains()
|
||||
: this(default, true)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="BaseChains{T, TContract, TContractsCollection}"/> dictionary
|
||||
/// </summary>
|
||||
protected BaseChains(bool flatten)
|
||||
: this(default, flatten)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="BaseChains{T, TContract, TContractsCollection}"/> dictionary
|
||||
/// </summary>
|
||||
protected BaseChains(DateTime time, bool flatten)
|
||||
: base(time)
|
||||
{
|
||||
_flatten = flatten;
|
||||
_dataframe = new Lazy<PyObject>(InitializeDataFrame, isThreadSafe: false);
|
||||
}
|
||||
|
||||
private PyObject InitializeDataFrame()
|
||||
{
|
||||
if (!PythonEngine.IsInitialized)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var dataFrames = this.Select(kvp => kvp.Value.DataFrame).ToList();
|
||||
|
||||
if (_flatten)
|
||||
{
|
||||
var canonicalSymbols = this.Select(kvp => kvp.Key);
|
||||
return PandasConverter.ConcatDataFrames(dataFrames, keys: canonicalSymbols, names: _flattenedDfIndexNames, sort: false);
|
||||
}
|
||||
|
||||
return PandasConverter.ConcatDataFrames(dataFrames, sort: false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* 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 QuantConnect.Python;
|
||||
using System;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a base for a single contract, like an option or future contract
|
||||
/// </summary>
|
||||
public abstract class BaseContract : ISymbolProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the contract's symbol
|
||||
/// </summary>
|
||||
[PandasIgnore]
|
||||
public Symbol Symbol
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The security identifier of the symbol
|
||||
/// </summary>
|
||||
[PandasIgnore]
|
||||
public SecurityIdentifier ID => Symbol.ID;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the underlying security's symbol
|
||||
/// </summary>
|
||||
public Symbol UnderlyingSymbol => Symbol.Underlying;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the expiration date
|
||||
/// </summary>
|
||||
public DateTime Expiry => Symbol.ID.Date;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the local date time this contract's data was last updated
|
||||
/// </summary>
|
||||
[PandasIgnore]
|
||||
public DateTime Time
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the open interest
|
||||
/// </summary>
|
||||
public virtual decimal OpenInterest { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the last price this contract traded at
|
||||
/// </summary>
|
||||
public virtual decimal LastPrice { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Value representation of this contract, mimicking <see cref="BaseData.Value"/>.
|
||||
/// Aliases <see cref="LastPrice"/>.
|
||||
/// </summary>
|
||||
[PandasIgnore]
|
||||
public virtual decimal Value => LastPrice;
|
||||
|
||||
/// <summary>
|
||||
/// Alias of value as price, mimicking <see cref="BaseData.Price"/>.
|
||||
/// Aliases <see cref="LastPrice"/>.
|
||||
/// </summary>
|
||||
[PandasIgnore]
|
||||
public virtual decimal Price => LastPrice;
|
||||
|
||||
/// <summary>
|
||||
/// Closing price of this contract, mimicking <see cref="TradeBar.Close"/>.
|
||||
/// Aliases <see cref="LastPrice"/>.
|
||||
/// </summary>
|
||||
[PandasIgnore]
|
||||
public virtual decimal Close => LastPrice;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the last volume this contract traded at
|
||||
/// </summary>
|
||||
public virtual long Volume { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current bid price
|
||||
/// </summary>
|
||||
public virtual decimal BidPrice { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the current bid size
|
||||
/// </summary>
|
||||
public virtual long BidSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ask price
|
||||
/// </summary>
|
||||
public virtual decimal AskPrice { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current ask size
|
||||
/// </summary>
|
||||
public virtual long AskSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BaseContract"/> class
|
||||
/// </summary>
|
||||
/// <param name="symbol">The contract symbol</param>
|
||||
protected BaseContract(Symbol symbol)
|
||||
{
|
||||
Symbol = symbol;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a string that represents the current object.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A string that represents the current object.
|
||||
/// </returns>
|
||||
public override string ToString() => Symbol.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Updates the contract with the new data, which can be a <see cref="Tick"/> or <see cref="TradeBar"/> or <see cref="QuoteBar"/>
|
||||
/// </summary>
|
||||
internal abstract void Update(BaseData data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a bar sectioned not by time, but by some amount of movement in a set field,
|
||||
/// where:
|
||||
/// - Open : Gets the opening value that started this bar
|
||||
/// - Close : Gets the closing value or the current value if the bar has not yet closed.
|
||||
/// - High : Gets the highest value encountered during this bar
|
||||
/// - Low : Gets the lowest value encountered during this bar
|
||||
/// </summary>
|
||||
public abstract class BaseRenkoBar : TradeBar, IBaseDataBar
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the kind of the bar
|
||||
/// </summary>
|
||||
public RenkoType Type { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// The preset size of the consolidated bar
|
||||
/// </summary>
|
||||
public decimal BrickSize { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the end time of this renko bar or the most recent update time if it <see cref="IsClosed"/>
|
||||
/// </summary>
|
||||
public override DateTime EndTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the time this bar started
|
||||
/// </summary>
|
||||
public DateTime Start
|
||||
{
|
||||
get { return Time; }
|
||||
protected set { Time = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not this bar is considered closed.
|
||||
/// </summary>
|
||||
public virtual bool IsClosed { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Reader Method :: using set of arguements we specify read out type. Enumerate
|
||||
/// until the end of the data stream or file. E.g. Read CSV file line by line and convert
|
||||
/// into data types.
|
||||
/// </summary>
|
||||
/// <returns>BaseData type set by Subscription Method.</returns>
|
||||
/// <param name="config">Config.</param>
|
||||
/// <param name="line">Line.</param>
|
||||
/// <param name="date">Date.</param>
|
||||
/// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param>
|
||||
public override BaseData Reader(SubscriptionDataConfig config, string line, DateTime date, bool isLiveMode)
|
||||
{
|
||||
throw new NotSupportedException("RenkoBar does not support the Reader function. This function should never be called on this type.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the URL string source of the file. This will be converted to a stream
|
||||
/// </summary>
|
||||
/// <param name="config">Configuration object</param>
|
||||
/// <param name="date">Date of this source file</param>
|
||||
/// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param>
|
||||
/// <returns>String URL of source file.</returns>
|
||||
public override SubscriptionDataSource GetSource(SubscriptionDataConfig config, DateTime date, bool isLiveMode)
|
||||
{
|
||||
throw new NotSupportedException("RenkoBar does not support the GetSource function. This function should never be called on this type.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* 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 Common.Util;
|
||||
using QuantConnect.Python;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a base class for types holding base data instances keyed by symbol
|
||||
/// </summary>
|
||||
[PandasNonExpandable]
|
||||
public class DataDictionary<T> : BaseExtendedDictionary<Symbol, T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to cache the sorted items in the dictionary.
|
||||
/// We do this instead of using a SortedDictionary to keep the O(1) access time.
|
||||
/// </summary>
|
||||
private List<KeyValuePair<Symbol, T>> _items;
|
||||
private List<Symbol> _keys;
|
||||
private List<T> _values;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the time associated with this collection of data
|
||||
/// </summary>
|
||||
public DateTime Time { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="QuantConnect.Data.Market.DataDictionary{T}"/> class.
|
||||
/// </summary>
|
||||
public DataDictionary() : base()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="QuantConnect.Data.Market.DataDictionary{T}"/> class
|
||||
/// using the specified <paramref name="data"/> as a data source
|
||||
/// </summary>
|
||||
/// <param name="data">The data source for this data dictionary</param>
|
||||
/// <param name="keySelector">Delegate used to select a key from the value</param>
|
||||
public DataDictionary(IEnumerable<T> data, Func<T, Symbol> keySelector)
|
||||
: base(data, keySelector)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="QuantConnect.Data.Market.DataDictionary{T}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="time">The time this data was emitted.</param>
|
||||
public DataDictionary(DateTime time) : base()
|
||||
{
|
||||
Time = time;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the element with the specified key.
|
||||
/// </summary>
|
||||
public override T this[Symbol symbol]
|
||||
{
|
||||
get
|
||||
{
|
||||
T data;
|
||||
if (TryGetValue(symbol, out data))
|
||||
{
|
||||
return data;
|
||||
}
|
||||
CheckForImplicitlyCreatedSymbol(symbol);
|
||||
throw new KeyNotFoundException($"'{symbol}' wasn't found in the {GetType().GetBetterTypeName()} object, likely because there was no-data at this moment in time and it wasn't possible to fillforward historical data. Please check the data exists before accessing it with data.ContainsKey(\"{symbol}\")");
|
||||
}
|
||||
set
|
||||
{
|
||||
_items = null;
|
||||
base[symbol] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value associated with the specified key.
|
||||
/// </summary>
|
||||
public virtual T GetValue(Symbol key)
|
||||
{
|
||||
T value;
|
||||
TryGetValue(key, out value);
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all the items in the dictionary
|
||||
/// </summary>
|
||||
/// <returns>All the items in the dictionary</returns>
|
||||
public override IEnumerable<KeyValuePair<Symbol, T>> GetItems()
|
||||
{
|
||||
if (_items == null)
|
||||
{
|
||||
_items = base.GetItems().OrderBy(x => x.Key).ToList();
|
||||
}
|
||||
return _items;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection containing the keys of the dictionary
|
||||
/// </summary>
|
||||
public override ICollection<Symbol> Keys
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_keys == null)
|
||||
{
|
||||
_keys = (_items == null ? base.Keys.OrderBy(x => x) : _items.Select(x => x.Key)).ToList();
|
||||
}
|
||||
return _keys;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection containing the values of the dictionary
|
||||
/// </summary>
|
||||
public override ICollection<T> Values
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_values == null)
|
||||
{
|
||||
var items = _items == null
|
||||
? base.GetItems().OrderBy(x => x.Key)
|
||||
: (IEnumerable<KeyValuePair<Symbol, T>>)_items;
|
||||
_values = items.Select(x => x.Value).ToList();
|
||||
}
|
||||
return _values;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection containing the keys in the dictionary
|
||||
/// </summary>
|
||||
protected override IEnumerable<Symbol> GetKeys => Keys;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection containing the values in the dictionary
|
||||
/// </summary>
|
||||
protected override IEnumerable<T> GetValues => Values;
|
||||
|
||||
/// <summary>
|
||||
/// Returns an enumerator that iterates through the dictionary
|
||||
/// </summary>
|
||||
/// <returns>An enumerator for the dictionary</returns>
|
||||
public override IEnumerator<KeyValuePair<Symbol, T>> GetEnumerator()
|
||||
{
|
||||
return GetItems().GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all items from the dictionary
|
||||
/// </summary>
|
||||
public override void Clear()
|
||||
{
|
||||
ClearCache();
|
||||
base.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the value with the specified key
|
||||
/// </summary>
|
||||
/// <param name="key">The key of the element to remove</param>
|
||||
/// <returns>true if the element was successfully found and removed; otherwise, false</returns>
|
||||
public override bool Remove(Symbol key)
|
||||
{
|
||||
ClearCache();
|
||||
return base.Remove(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the first occurrence of a specific object from the dictionary
|
||||
/// </summary>
|
||||
/// <param name="item">The key-value pair to remove</param>
|
||||
/// <returns>true if the key-value pair was successfully removed; otherwise, false</returns>
|
||||
public override bool Remove(KeyValuePair<Symbol, T> item)
|
||||
{
|
||||
ClearCache();
|
||||
return base.Remove(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an element with the provided key and value to the dictionary
|
||||
/// </summary>
|
||||
/// <param name="key">The key of the element to add</param>
|
||||
/// <param name="value">The value of the element to add</param>
|
||||
public override void Add(Symbol key, T value)
|
||||
{
|
||||
ClearCache();
|
||||
base.Add(key, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an element with the provided key-value pair to the dictionary
|
||||
/// </summary>
|
||||
/// <param name="item">The key-value pair to add</param>
|
||||
public override void Add(KeyValuePair<Symbol, T> item)
|
||||
{
|
||||
ClearCache();
|
||||
base.Add(item);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void ClearCache()
|
||||
{
|
||||
_items = null;
|
||||
_keys = null;
|
||||
_values = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides extension methods for the DataDictionary class
|
||||
/// </summary>
|
||||
public static class DataDictionaryExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a convenience method for adding a base data instance to our data dictionary
|
||||
/// </summary>
|
||||
public static void Add<T>(this DataDictionary<T> dictionary, T data)
|
||||
where T : BaseData
|
||||
{
|
||||
dictionary.Add(data.Symbol, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* 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 Newtonsoft.Json;
|
||||
using QuantConnect.Orders;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Delisting event of a security
|
||||
/// </summary>
|
||||
public class Delisting : BaseData
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the type of delisting, warning or delisted
|
||||
/// A <see cref="DelistingType.Warning"/> is sent
|
||||
/// </summary>
|
||||
[JsonProperty]
|
||||
public DelistingType Type { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="OrderTicket"/> that was submitted to liquidate this position
|
||||
/// </summary>
|
||||
public OrderTicket Ticket { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Delisting"/> class
|
||||
/// </summary>
|
||||
public Delisting()
|
||||
{
|
||||
DataType = MarketDataType.Auxiliary;
|
||||
Type = DelistingType.Delisted;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Delisting"/> class
|
||||
/// </summary>
|
||||
/// <param name="symbol">The delisted symbol</param>
|
||||
/// <param name="date">The date the symbol was delisted</param>
|
||||
/// <param name="price">The final price before delisting</param>
|
||||
/// <param name="type">The type of delisting event</param>
|
||||
public Delisting(Symbol symbol, DateTime date, decimal price, DelistingType type)
|
||||
: this()
|
||||
{
|
||||
Symbol = symbol;
|
||||
Time = date;
|
||||
Value = price;
|
||||
Type = type;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="OrderTicket"/> used to liquidate this position
|
||||
/// </summary>
|
||||
/// <param name="ticket">The ticket that represents the order to liquidate this position</param>
|
||||
public void SetOrderTicket(OrderTicket ticket)
|
||||
{
|
||||
Ticket = ticket;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reader converts each line of the data source into BaseData objects. Each data type creates its own factory method, and returns a new instance of the object
|
||||
/// each time it is called.
|
||||
/// </summary>
|
||||
/// <param name="config">Subscription data config setup object</param>
|
||||
/// <param name="line">Line of the source document</param>
|
||||
/// <param name="date">Date of the requested data</param>
|
||||
/// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param>
|
||||
/// <returns>Instance of the T:BaseData object generated by this line of the CSV</returns>
|
||||
public override BaseData Reader(SubscriptionDataConfig config, string line, DateTime date, bool isLiveMode)
|
||||
{
|
||||
throw new NotImplementedException("This method is not supposed to be called on the Delisting type.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the URL string source of the file. This will be converted to a stream
|
||||
/// </summary>
|
||||
/// <param name="config">Configuration object</param>
|
||||
/// <param name="date">Date of this source file</param>
|
||||
/// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param>
|
||||
/// <returns>String URL of source file.</returns>
|
||||
public override SubscriptionDataSource GetSource(SubscriptionDataConfig config, DateTime date, bool isLiveMode)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a new instance clone of this object, used in fill forward
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This base implementation uses reflection to copy all public fields and properties
|
||||
/// </remarks>
|
||||
/// <returns>A clone of the current object</returns>
|
||||
public override BaseData Clone()
|
||||
{
|
||||
return new Delisting(Symbol, Time, Price, Type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Formats a string with the symbol and value.
|
||||
/// </summary>
|
||||
/// <returns>string - a string formatted as SPY: 167.753</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
var type = Type == DelistingType.Warning ? "Delisting Warning" : "Delisted";
|
||||
return $"{type}: {Symbol} {EndTime}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Collections of <see cref="Delisting"/> keyed by <see cref="Symbol"/>
|
||||
/// </summary>
|
||||
public class Delistings : DataDictionary<Delisting>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Delistings"/> dictionary
|
||||
/// </summary>
|
||||
public Delistings()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Delistings"/> dictionary
|
||||
/// </summary>
|
||||
/// <param name="frontier">The time associated with the data in this dictionary</param>
|
||||
public Delistings(DateTime frontier)
|
||||
: base(frontier)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* 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 ProtoBuf;
|
||||
using static QuantConnect.StringExtensions;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Dividend event from a security
|
||||
/// </summary>
|
||||
[ProtoContract(SkipConstructor = true)]
|
||||
public class Dividend : BaseData
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the dividend payment
|
||||
/// </summary>
|
||||
[ProtoMember(10)]
|
||||
public decimal Distribution
|
||||
{
|
||||
get { return Value; }
|
||||
set { Value = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the price at which the dividend occurred.
|
||||
/// This is typically the previous day's closing price
|
||||
/// </summary>
|
||||
[ProtoMember(11)]
|
||||
public decimal ReferencePrice
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Dividend class
|
||||
/// </summary>
|
||||
public Dividend()
|
||||
{
|
||||
DataType = MarketDataType.Auxiliary;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Dividend class
|
||||
/// </summary>
|
||||
/// <param name="symbol">The symbol</param>
|
||||
/// <param name="date">The date</param>
|
||||
/// <param name="distribution">The dividend amount</param>
|
||||
/// <param name="referencePrice">The previous day's closing price</param>
|
||||
public Dividend(Symbol symbol, DateTime date, decimal distribution, decimal referencePrice)
|
||||
: this()
|
||||
{
|
||||
Symbol = symbol;
|
||||
Time = date;
|
||||
Distribution = distribution;
|
||||
ReferencePrice = referencePrice;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Dividend class
|
||||
/// </summary>
|
||||
/// <param name="symbol">The symbol</param>
|
||||
/// <param name="date">The date</param>
|
||||
/// <param name="referencePrice">The previous day's closing price</param>
|
||||
/// <param name="priceFactorRatio">The ratio of the price factors, pf_i/pf_i+1</param>
|
||||
/// <param name="decimalPlaces">The number of decimal places to round the dividend's distribution to, defaulting to 2</param>
|
||||
public static Dividend Create(Symbol symbol, DateTime date, decimal referencePrice, decimal priceFactorRatio, int decimalPlaces = 2)
|
||||
{
|
||||
var distribution = ComputeDistribution(referencePrice, priceFactorRatio, decimalPlaces);
|
||||
return new Dividend(symbol, date, distribution, referencePrice);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes the price factor ratio given the previous day's closing price and the p
|
||||
/// </summary>
|
||||
/// <param name="close">Previous day's closing price</param>
|
||||
/// <param name="priceFactorRatio">Price factor ratio pf_i/pf_i+1</param>
|
||||
/// <param name="decimalPlaces">The number of decimal places to round the result to, defaulting to 2</param>
|
||||
/// <returns>The distribution rounded to the specified number of decimal places, defaulting to 2</returns>
|
||||
public static decimal ComputeDistribution(decimal close, decimal priceFactorRatio, int decimalPlaces)
|
||||
{
|
||||
return Math.Round(close - close * priceFactorRatio, decimalPlaces);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reader converts each line of the data source into BaseData objects. Each data type creates its own factory method, and returns a new instance of the object
|
||||
/// each time it is called.
|
||||
/// </summary>
|
||||
/// <param name="config">Subscription data config setup object</param>
|
||||
/// <param name="line">Line of the source document</param>
|
||||
/// <param name="date">Date of the requested data</param>
|
||||
/// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param>
|
||||
/// <returns>Instance of the T:BaseData object generated by this line of the CSV</returns>
|
||||
public override BaseData Reader(SubscriptionDataConfig config, string line, DateTime date, bool isLiveMode)
|
||||
{
|
||||
// this is implemented in the SubscriptionDataReader.CheckForDividend
|
||||
throw new NotImplementedException("This method is not supposed to be called on the Dividend type.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the URL string source of the file. This will be converted to a stream
|
||||
/// </summary>
|
||||
/// <param name="config">Configuration object</param>
|
||||
/// <param name="date">Date of this source file</param>
|
||||
/// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param>
|
||||
/// <returns>String URL of source file.</returns>
|
||||
public override SubscriptionDataSource GetSource(SubscriptionDataConfig config, DateTime date, bool isLiveMode)
|
||||
{
|
||||
// this data is derived from map files and factor files in backtesting
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a new instance clone of this object, used in fill forward
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This base implementation uses reflection to copy all public fields and properties
|
||||
/// </remarks>
|
||||
/// <returns>A clone of the current object</returns>
|
||||
public override BaseData Clone()
|
||||
{
|
||||
return new Dividend
|
||||
{
|
||||
Time = Time,
|
||||
Value = Value,
|
||||
Symbol = Symbol,
|
||||
EndTime = EndTime,
|
||||
DataType = DataType,
|
||||
Distribution = Distribution,
|
||||
ReferencePrice = ReferencePrice
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Formats a string with the symbol and value.
|
||||
/// </summary>
|
||||
/// <returns>string - a string formatted as SPY: 167.753</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return Invariant($"Dividend: {Symbol}: {Distribution} | {ReferencePrice}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Collection of dividends keyed by <see cref="Symbol"/>
|
||||
/// </summary>
|
||||
public class Dividends : DataDictionary<Dividend>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Dividends"/> dictionary
|
||||
/// </summary>
|
||||
public Dividends()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Dividends"/> dictionary
|
||||
/// </summary>
|
||||
/// <param name="frontier">The time associated with the data in this dictionary</param>
|
||||
public Dividends(DateTime frontier)
|
||||
: base(frontier)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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.Generic;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an entire chain of futures contracts for a single underlying
|
||||
/// This type is <see cref="IEnumerable{FuturesContract}"/>
|
||||
/// </summary>
|
||||
public class FuturesChain : BaseChain<FuturesContract, FuturesContracts>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FuturesChain"/> class
|
||||
/// </summary>
|
||||
/// <param name="canonicalFutureSymbol">The symbol for this chain.</param>
|
||||
/// <param name="time">The time of this chain</param>
|
||||
/// <param name="flatten">Whether to flatten the data frame</param>
|
||||
public FuturesChain(Symbol canonicalFutureSymbol, DateTime time, bool flatten = true)
|
||||
: base(canonicalFutureSymbol, time, MarketDataType.FuturesChain, flatten)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FuturesChain"/> class
|
||||
/// </summary>
|
||||
/// <param name="canonicalFutureSymbol">The symbol for this chain.</param>
|
||||
/// <param name="time">The time of this chain</param>
|
||||
/// <param name="contracts">The list of contracts that form this chain</param>
|
||||
/// <param name="flatten">Whether to flatten the data frame</param>
|
||||
public FuturesChain(Symbol canonicalFutureSymbol, DateTime time, IEnumerable<FutureUniverse> contracts, bool flatten = true)
|
||||
: this(canonicalFutureSymbol, time, flatten)
|
||||
{
|
||||
foreach (var contractData in contracts)
|
||||
{
|
||||
if (contractData.Symbol.ID.Date.Date < time.Date) continue;
|
||||
Contracts[contractData.Symbol] = new FuturesContract(contractData);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FuturesChain"/> class as a clone of the specified instance
|
||||
/// </summary>
|
||||
private FuturesChain(FuturesChain other)
|
||||
: base(other)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a new instance clone of this object, used in fill forward
|
||||
/// </summary>
|
||||
/// <returns>A clone of the current object</returns>
|
||||
public override BaseData Clone()
|
||||
{
|
||||
return new FuturesChain(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Collection of <see cref="FuturesChain"/> keyed by canonical futures symbol
|
||||
/// </summary>
|
||||
public class FuturesChains : BaseChains<FuturesChain, FuturesContract, FuturesContracts>
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="FuturesChains"/> dictionary
|
||||
/// </summary>
|
||||
public FuturesChains()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="FuturesChains"/> dictionary
|
||||
/// </summary>
|
||||
public FuturesChains(bool flatten)
|
||||
: base(flatten)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="FuturesChains"/> dictionary
|
||||
/// </summary>
|
||||
public FuturesChains(DateTime time, bool flatten = true)
|
||||
: base(time, flatten)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
* 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 QuantConnect.Data.UniverseSelection;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a single futures contract at a specific expiration
|
||||
/// </summary>
|
||||
public class FuturesContract : BaseContract
|
||||
{
|
||||
private FutureUniverse _universeData;
|
||||
private TradeBar _tradeBar;
|
||||
private QuoteBar _quoteBar;
|
||||
private Tick _tradeTick;
|
||||
private Tick _quoteTick;
|
||||
private Tick _openInterest;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the open interest
|
||||
/// </summary>
|
||||
public override decimal OpenInterest
|
||||
{
|
||||
get
|
||||
{
|
||||
// Contract universe data is prioritized
|
||||
if (_universeData != null)
|
||||
{
|
||||
return _universeData.OpenInterest;
|
||||
}
|
||||
return _openInterest?.Value ?? decimal.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the last price this contract traded at
|
||||
/// </summary>
|
||||
public override decimal LastPrice
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_universeData != null)
|
||||
{
|
||||
return _universeData.Close;
|
||||
}
|
||||
|
||||
if (_tradeBar == null && _tradeTick == null)
|
||||
{
|
||||
return decimal.Zero;
|
||||
}
|
||||
if (_tradeBar != null)
|
||||
{
|
||||
return _tradeTick != null && _tradeTick.EndTime > _tradeBar.EndTime ? _tradeTick.Price : _tradeBar.Close;
|
||||
}
|
||||
return _tradeTick.Price;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the last volume this contract traded at
|
||||
/// </summary>
|
||||
public override long Volume
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_universeData != null)
|
||||
{
|
||||
return (long)_universeData.Volume;
|
||||
}
|
||||
|
||||
if (_tradeBar == null && _tradeTick == null)
|
||||
{
|
||||
return 0L;
|
||||
}
|
||||
if (_tradeBar != null)
|
||||
{
|
||||
return (long)(_tradeTick != null && _tradeTick.EndTime > _tradeBar.EndTime ? _tradeTick.Quantity : _tradeBar.Volume);
|
||||
}
|
||||
return (long)_tradeTick.Quantity;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the current bid price
|
||||
/// </summary>
|
||||
public override decimal BidPrice
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_universeData != null)
|
||||
{
|
||||
return _universeData.Close;
|
||||
}
|
||||
if (_quoteBar == null && _quoteTick == null)
|
||||
{
|
||||
return decimal.Zero;
|
||||
}
|
||||
if (_quoteBar != null)
|
||||
{
|
||||
var quoteBarPrice = _quoteBar.Bid?.Close ?? decimal.Zero;
|
||||
if (_quoteTick != null)
|
||||
{
|
||||
return _quoteTick.EndTime > _quoteBar.EndTime ? _quoteTick.BidPrice : quoteBarPrice;
|
||||
}
|
||||
return quoteBarPrice;
|
||||
}
|
||||
return _quoteTick.BidPrice;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the current bid size
|
||||
/// </summary>
|
||||
public override long BidSize
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_quoteBar == null && _quoteTick == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (_quoteBar != null)
|
||||
{
|
||||
return (long)(_quoteTick != null && _quoteTick.EndTime > _quoteBar.EndTime ? _quoteTick.BidSize : _quoteBar.LastBidSize);
|
||||
}
|
||||
return (long)_quoteTick.BidSize;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current ask price
|
||||
/// </summary>
|
||||
public override decimal AskPrice
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_universeData != null)
|
||||
{
|
||||
return _universeData.Close;
|
||||
}
|
||||
if (_quoteBar == null && _quoteTick == null)
|
||||
{
|
||||
return decimal.Zero;
|
||||
}
|
||||
if (_quoteBar != null)
|
||||
{
|
||||
var quoteBarPrice = _quoteBar.Ask?.Close ?? decimal.Zero;
|
||||
if (_quoteTick != null)
|
||||
{
|
||||
return _quoteTick.EndTime > _quoteBar.EndTime ? _quoteTick.AskPrice : quoteBarPrice;
|
||||
}
|
||||
return quoteBarPrice;
|
||||
}
|
||||
return _quoteTick.AskPrice;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the current ask size
|
||||
/// </summary>
|
||||
public override long AskSize
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_quoteBar == null && _quoteTick == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (_quoteBar != null)
|
||||
{
|
||||
return (long)(_quoteTick != null && _quoteTick.EndTime > _quoteBar.EndTime ? _quoteTick.AskSize : _quoteBar.LastAskSize);
|
||||
}
|
||||
return (long)_quoteTick.AskSize;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FuturesContract"/> class
|
||||
/// </summary>
|
||||
/// <param name="symbol">The futures contract symbol</param>
|
||||
public FuturesContract(Symbol symbol)
|
||||
: base(symbol)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FuturesContract"/> class
|
||||
/// </summary>
|
||||
/// <param name="contractData">The contract universe data</param>
|
||||
public FuturesContract(FutureUniverse contractData)
|
||||
: base(contractData.Symbol)
|
||||
{
|
||||
_universeData = contractData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implicit conversion into <see cref="Symbol"/>
|
||||
/// </summary>
|
||||
/// <param name="contract">The option contract to be converted</param>
|
||||
public static implicit operator Symbol(FuturesContract contract)
|
||||
{
|
||||
return contract.Symbol;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the future contract with the new data, which can be a <see cref="Tick"/> or <see cref="TradeBar"/> or <see cref="QuoteBar"/>
|
||||
/// </summary>
|
||||
internal override void Update(BaseData data)
|
||||
{
|
||||
switch (data)
|
||||
{
|
||||
case TradeBar tradeBar:
|
||||
_tradeBar = tradeBar;
|
||||
break;
|
||||
|
||||
case QuoteBar quoteBar:
|
||||
_quoteBar = quoteBar;
|
||||
break;
|
||||
|
||||
case Tick tick when tick.TickType == TickType.Trade:
|
||||
_tradeTick = tick;
|
||||
break;
|
||||
|
||||
case Tick tick when tick.TickType == TickType.Quote:
|
||||
_quoteTick = tick;
|
||||
break;
|
||||
|
||||
case Tick tick when tick.TickType == TickType.OpenInterest:
|
||||
_openInterest = tick;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Collection of <see cref="FuturesContract"/> keyed by futures symbol
|
||||
/// </summary>
|
||||
public class FuturesContracts : DataDictionary<FuturesContract>
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="FuturesContracts"/> dictionary
|
||||
/// </summary>
|
||||
public FuturesContracts()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="FuturesContracts"/> dictionary
|
||||
/// </summary>
|
||||
public FuturesContracts(DateTime time)
|
||||
: base(time)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* 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 QuantConnect.Python;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the greeks
|
||||
/// </summary>
|
||||
public class Greeks
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the delta.
|
||||
/// <para>
|
||||
/// Delta measures the rate of change of the option value with respect to changes in
|
||||
/// the underlying asset'sprice. (∂V/∂S)
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public virtual decimal Delta { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the gamma.
|
||||
/// <para>
|
||||
/// Gamma measures the rate of change of Delta with respect to changes in
|
||||
/// the underlying asset'sprice. (∂²V/∂S²)
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public virtual decimal Gamma { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the vega.
|
||||
/// <para>
|
||||
/// Vega measures the rate of change of the option value with respect to changes in
|
||||
/// the underlying's volatility. (∂V/∂σ)
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public virtual decimal Vega { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the theta.
|
||||
/// <para>
|
||||
/// Theta measures the rate of change of the option value with respect to changes in
|
||||
/// time. This is commonly known as the 'time decay.' (∂V/∂τ)
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public virtual decimal Theta { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the rho.
|
||||
/// <para>
|
||||
/// Rho measures the rate of change of the option value with respect to changes in
|
||||
/// the risk free interest rate. (∂V/∂r)
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public virtual decimal Rho { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the lambda.
|
||||
/// <para>
|
||||
/// Lambda is the percentage change in option value per percentage change in the
|
||||
/// underlying's price, a measure of leverage. Sometimes referred to as gearing.
|
||||
/// (∂V/∂S ✕ S/V)
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[PandasIgnore]
|
||||
public virtual decimal Lambda { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the lambda.
|
||||
/// <para>
|
||||
/// Lambda is the percentage change in option value per percentage change in the
|
||||
/// underlying's price, a measure of leverage. Sometimes referred to as gearing.
|
||||
/// (∂V/∂S ✕ S/V)
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Alias for <see cref="Lambda"/> required for compatibility with Python when
|
||||
/// PEP8 API is used (lambda is a reserved keyword in Python).
|
||||
/// </remarks>
|
||||
[PandasIgnore]
|
||||
public virtual decimal Lambda_
|
||||
{
|
||||
get { return Lambda; }
|
||||
set { Lambda = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the theta per day.
|
||||
/// <para>
|
||||
/// Theta measures the rate of change of the option value with respect to changes in
|
||||
/// time. This is commonly known as the 'time decay.' (∂V/∂τ)
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[PandasIgnore]
|
||||
public virtual decimal ThetaPerDay
|
||||
{
|
||||
get { return Theta / 365m; }
|
||||
set { Theta = value * 365m; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the annualized theta value based on a daily theta input.
|
||||
/// </summary>
|
||||
/// <param name="thetaPerDay">The theta value per day to be annualized.</param>
|
||||
/// <returns>The annualized theta value, calculated as the daily theta multiplied by 365. Returns decimal.MaxValue or
|
||||
/// decimal.MinValue if the result overflows.</returns>
|
||||
public static decimal GetSafeTheta(decimal thetaPerDay)
|
||||
{
|
||||
try
|
||||
{
|
||||
return thetaPerDay * 365m;
|
||||
}
|
||||
catch (OverflowException)
|
||||
{
|
||||
return thetaPerDay < 0 ? decimal.MinValue : decimal.MaxValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Greeks"/> class.
|
||||
/// </summary>
|
||||
public Greeks()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Greeks"/> class with specified values.
|
||||
/// </summary>
|
||||
public Greeks(decimal delta, decimal gamma, decimal vega, decimal theta, decimal rho, decimal lambda)
|
||||
{
|
||||
Delta = delta;
|
||||
Gamma = gamma;
|
||||
Vega = vega;
|
||||
Theta = theta;
|
||||
Rho = rho;
|
||||
Lambda = lambda;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Generic bar interface with Open, High, Low and Close.
|
||||
/// </summary>
|
||||
public interface IBar
|
||||
{
|
||||
/// <summary>
|
||||
/// Opening price of the bar: Defined as the price at the start of the time period.
|
||||
/// </summary>
|
||||
decimal Open { get; }
|
||||
|
||||
/// <summary>
|
||||
/// High price of the bar during the time period.
|
||||
/// </summary>
|
||||
decimal High { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Low price of the bar during the time period.
|
||||
/// </summary>
|
||||
decimal Low { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Closing price of the bar. Defined as the price at Start Time + TimeSpan.
|
||||
/// </summary>
|
||||
decimal Close { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a type that is both a bar and base data
|
||||
/// </summary>
|
||||
public interface IBaseDataBar : IBaseData, IBar
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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 NodaTime;
|
||||
using System.IO;
|
||||
using QuantConnect.Util;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Margin interest rate data source
|
||||
/// </summary>
|
||||
/// <remarks>This is useful to model margin costs</remarks>
|
||||
public class MarginInterestRate : BaseData
|
||||
{
|
||||
/// <summary>
|
||||
/// The interest rate value
|
||||
/// </summary>
|
||||
public decimal InterestRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance
|
||||
/// </summary>
|
||||
public MarginInterestRate()
|
||||
{
|
||||
DataType = MarketDataType.Auxiliary;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reader converts each line of the data source into BaseData objects. Each data type creates its own factory method, and returns a new instance of the object
|
||||
/// each time it is called. The returned object is assumed to be time stamped in the config.ExchangeTimeZone.
|
||||
/// </summary>
|
||||
/// <param name="config">Subscription data config setup object</param>
|
||||
/// <param name="stream">The data stream</param>
|
||||
/// <param name="date">Date of the requested data</param>
|
||||
/// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param>
|
||||
/// <returns>Instance of the T:BaseData object generated by this line of the CSV</returns>
|
||||
[StubsIgnore]
|
||||
public override BaseData Reader(SubscriptionDataConfig config, StreamReader stream, DateTime date, bool isLiveMode)
|
||||
{
|
||||
var dateTime = stream.GetDateTime("yyyyMMdd HH:mm:ss");
|
||||
var interestRate = stream.GetDecimal();
|
||||
return new MarginInterestRate {
|
||||
Time = dateTime,
|
||||
InterestRate = Value = interestRate,
|
||||
Symbol = config.Symbol
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the URL string source of the file. This will be converted to a stream
|
||||
/// </summary>
|
||||
/// <param name="config">Configuration object</param>
|
||||
/// <param name="date">Date of this source file</param>
|
||||
/// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param>
|
||||
/// <returns>String URL of source file.</returns>
|
||||
public override SubscriptionDataSource GetSource(SubscriptionDataConfig config, DateTime date, bool isLiveMode)
|
||||
{
|
||||
var identifier = config.Symbol.ID;
|
||||
var source = Path.Combine(Globals.DataFolder,
|
||||
identifier.SecurityType.SecurityTypeToLower(),
|
||||
identifier.Market.ToLowerInvariant(),
|
||||
"margin_interest",
|
||||
$"{identifier.Symbol.ToLowerInvariant()}.csv"
|
||||
);
|
||||
|
||||
return new SubscriptionDataSource(source, SubscriptionTransportMedium.LocalFile, FileFormat.Csv);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the data time zone for this data type. This is useful for custom data types
|
||||
/// </summary>
|
||||
public override DateTimeZone DataTimeZone()
|
||||
{
|
||||
return TimeZones.Utc;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Formats a string with the symbol and value.
|
||||
/// </summary>
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Symbol}: Rate {InterestRate}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Collection of dividends keyed by <see cref="Symbol"/>
|
||||
/// </summary>
|
||||
public class MarginInterestRates : DataDictionary<MarginInterestRate>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MarginInterestRate"/> dictionary
|
||||
/// </summary>
|
||||
public MarginInterestRates()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MarginInterestRate"/> dictionary
|
||||
/// </summary>
|
||||
/// <param name="frontier">The time associated with the data in this dictionary</param>
|
||||
public MarginInterestRates(DateTime frontier)
|
||||
: base(frontier)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the greeks
|
||||
/// </summary>
|
||||
internal class ModeledGreeks : Greeks
|
||||
{
|
||||
private Lazy<decimal> _delta;
|
||||
private Lazy<decimal> _gamma;
|
||||
private Lazy<decimal> _vega;
|
||||
private Lazy<decimal> _theta;
|
||||
private Lazy<decimal> _rho;
|
||||
private Lazy<decimal> _lambda;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the delta
|
||||
/// </summary>
|
||||
public override decimal Delta => _delta.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the gamma
|
||||
/// </summary>
|
||||
public override decimal Gamma => _gamma.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the vega
|
||||
/// </summary>
|
||||
public override decimal Vega => _vega.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the theta
|
||||
/// </summary>
|
||||
public override decimal Theta => _theta.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the rho
|
||||
/// </summary>
|
||||
public override decimal Rho => _rho.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the lambda
|
||||
/// </summary>
|
||||
public override decimal Lambda => _lambda.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ModeledGreeks"/> class
|
||||
/// </summary>
|
||||
public ModeledGreeks(Func<decimal> delta, Func<decimal> gamma, Func<decimal> vega, Func<decimal> theta, Func<decimal> rho, Func<decimal> lambda)
|
||||
{
|
||||
_delta = new Lazy<decimal>(delta, isThreadSafe: false);
|
||||
_gamma = new Lazy<decimal>(gamma, isThreadSafe: false);
|
||||
_vega = new Lazy<decimal>(vega, isThreadSafe: false);
|
||||
_theta = new Lazy<decimal>(theta, isThreadSafe: false);
|
||||
_rho = new Lazy<decimal>(rho, isThreadSafe: false);
|
||||
_lambda = new Lazy<decimal>(lambda, isThreadSafe: false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines greeks that are all zero
|
||||
/// </summary>
|
||||
internal class NullGreeks : Greeks
|
||||
{
|
||||
/// <summary>
|
||||
/// Singleton instance of <see cref="NullGreeks"/>
|
||||
/// </summary>
|
||||
public static readonly NullGreeks Instance = new NullGreeks();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the delta
|
||||
/// </summary>
|
||||
public override decimal Delta => decimal.Zero;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the gamma
|
||||
/// </summary>
|
||||
public override decimal Gamma => decimal.Zero;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the vega
|
||||
/// </summary>
|
||||
public override decimal Vega => decimal.Zero;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the theta
|
||||
/// </summary>
|
||||
public override decimal Theta => decimal.Zero;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the rho
|
||||
/// </summary>
|
||||
public override decimal Rho => decimal.Zero;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the lambda
|
||||
/// </summary>
|
||||
public override decimal Lambda => decimal.Zero;
|
||||
|
||||
private NullGreeks()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* 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 QuantConnect.Util;
|
||||
using System;
|
||||
using ProtoBuf;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a data type that represents open interest for given security
|
||||
/// </summary>
|
||||
[ProtoContract(SkipConstructor = true)]
|
||||
public class OpenInterest : Tick
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the OpenInterest class
|
||||
/// </summary>
|
||||
public OpenInterest()
|
||||
{
|
||||
DataType = MarketDataType.Tick;
|
||||
TickType = TickType.OpenInterest;
|
||||
Value = 0;
|
||||
Time = new DateTime();
|
||||
Symbol = Symbol.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cloner constructor for fill forward engine implementation. Clone the original OI into this new one:
|
||||
/// </summary>
|
||||
/// <param name="original">Original OI we're cloning</param>
|
||||
public OpenInterest(OpenInterest original)
|
||||
{
|
||||
DataType = MarketDataType.Tick;
|
||||
TickType = TickType.OpenInterest;
|
||||
Value = original.Value;
|
||||
Time = original.Time;
|
||||
Symbol = original.Symbol;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the OpenInterest class with data
|
||||
/// </summary>
|
||||
/// <param name="time">Full date and time</param>
|
||||
/// <param name="symbol">Underlying equity security symbol</param>
|
||||
/// <param name="openInterest">Open Interest value</param>
|
||||
public OpenInterest(DateTime time, Symbol symbol, decimal openInterest)
|
||||
{
|
||||
DataType = MarketDataType.Tick;
|
||||
TickType = TickType.OpenInterest;
|
||||
Time = time;
|
||||
Symbol = symbol;
|
||||
Value = openInterest;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for QuantConnect open interest data
|
||||
/// </summary>
|
||||
/// <param name="config">Subscription configuration</param>
|
||||
/// <param name="symbol">Symbol for underlying asset</param>
|
||||
/// <param name="line">CSV line of data from QC OI csv</param>
|
||||
/// <param name="baseDate">The base date of the OI</param>
|
||||
public OpenInterest(SubscriptionDataConfig config, Symbol symbol, string line, DateTime baseDate)
|
||||
{
|
||||
var csv = line.Split(',');
|
||||
DataType = MarketDataType.Tick;
|
||||
TickType = TickType.OpenInterest;
|
||||
Symbol = symbol;
|
||||
|
||||
Time = (config.Resolution == Resolution.Daily || config.Resolution == Resolution.Hour) ?
|
||||
// hourly and daily have different time format, and can use slow, robust c# parser.
|
||||
DateTime.ParseExact(csv[0], DateFormat.TwelveCharacter,
|
||||
System.Globalization.CultureInfo.InvariantCulture)
|
||||
.ConvertTo(config.DataTimeZone, config.ExchangeTimeZone)
|
||||
:
|
||||
// Using custom "ToDecimal" conversion for speed on high resolution data.
|
||||
baseDate.Date.AddMilliseconds(csv[0].ToInt32()).ConvertTo(config.DataTimeZone, config.ExchangeTimeZone);
|
||||
|
||||
Value = csv[1].ToDecimal();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse an open interest data line from quantconnect zip source files.
|
||||
/// </summary>
|
||||
/// <param name="line">CSV source line of the compressed source</param>
|
||||
/// <param name="date">Base date for the open interest (date is stored as int milliseconds since midnight)</param>
|
||||
/// <param name="config">Subscription configuration object</param>
|
||||
public OpenInterest(SubscriptionDataConfig config, string line, DateTime date):
|
||||
this(config, config.Symbol, line, date)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tick implementation of reader method: read a line of data from the source and convert it to an open interest object.
|
||||
/// </summary>
|
||||
/// <param name="config">Subscription configuration object for algorithm</param>
|
||||
/// <param name="line">Line from the datafeed source</param>
|
||||
/// <param name="date">Date of this reader request</param>
|
||||
/// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param>
|
||||
/// <returns>New initialized open interest object</returns>
|
||||
public override BaseData Reader(SubscriptionDataConfig config, string line, DateTime date, bool isLiveMode)
|
||||
{
|
||||
if (isLiveMode)
|
||||
{
|
||||
// currently OIs don't come through the reader function
|
||||
return new OpenInterest();
|
||||
}
|
||||
|
||||
return new OpenInterest(config, line, date);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get source for OI data feed - not used with QuantConnect data sources implementation.
|
||||
/// </summary>
|
||||
/// <param name="config">Configuration object</param>
|
||||
/// <param name="date">Date of this source request if source spread across multiple files</param>
|
||||
/// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param>
|
||||
/// <returns>String source location of the file to be opened with a stream</returns>
|
||||
public override SubscriptionDataSource GetSource(SubscriptionDataConfig config, DateTime date, bool isLiveMode)
|
||||
{
|
||||
if (isLiveMode)
|
||||
{
|
||||
// this data type is streamed in live mode
|
||||
return new SubscriptionDataSource(string.Empty, SubscriptionTransportMedium.Streaming);
|
||||
}
|
||||
|
||||
var source = LeanData.GenerateZipFilePath(Globals.DataFolder, config.Symbol, date, config.Resolution, config.TickType);
|
||||
if (config.SecurityType == SecurityType.Future || config.SecurityType.IsOption())
|
||||
{
|
||||
source += "#" + LeanData.GenerateZipEntryName(config.Symbol, date, config.Resolution, config.TickType);
|
||||
}
|
||||
return new SubscriptionDataSource(source, SubscriptionTransportMedium.LocalFile, FileFormat.Csv);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clone implementation for open interest class:
|
||||
/// </summary>
|
||||
/// <returns>New tick object clone of the current class values.</returns>
|
||||
public override BaseData Clone()
|
||||
{
|
||||
return new OpenInterest(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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.Generic;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Securities;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an entire chain of option contracts for a single underlying security.
|
||||
/// This type is <see cref="IEnumerable{OptionContract}"/>
|
||||
/// </summary>
|
||||
public class OptionChain : BaseChain<OptionContract, OptionContracts>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OptionChain"/> class
|
||||
/// </summary>
|
||||
/// <param name="canonicalOptionSymbol">The symbol for this chain.</param>
|
||||
/// <param name="time">The time of this chain</param>
|
||||
/// <param name="flatten">Whether to flatten the data frame</param>
|
||||
public OptionChain(Symbol canonicalOptionSymbol, DateTime time, bool flatten = true)
|
||||
: base(canonicalOptionSymbol, time, MarketDataType.OptionChain, flatten)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new option chain for a list of contracts as <see cref="OptionUniverse"/> instances
|
||||
/// </summary>
|
||||
/// <param name="canonicalOptionSymbol">The canonical option symbol</param>
|
||||
/// <param name="time">The time of this chain</param>
|
||||
/// <param name="contracts">The list of contracts data</param>
|
||||
/// <param name="symbolProperties">The option symbol properties</param>
|
||||
/// <param name="flatten">Whether to flatten the data frame</param>
|
||||
public OptionChain(Symbol canonicalOptionSymbol, DateTime time, IEnumerable<OptionUniverse> contracts, SymbolProperties symbolProperties,
|
||||
bool flatten = true)
|
||||
: this(canonicalOptionSymbol, time, flatten)
|
||||
{
|
||||
foreach (var contractData in contracts)
|
||||
{
|
||||
Underlying ??= contractData.Underlying;
|
||||
if (contractData.Symbol.ID.Date.Date < time.Date) continue;
|
||||
Contracts[contractData.Symbol] = OptionContract.Create(contractData, symbolProperties);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OptionChain"/> class as a clone of the specified instance
|
||||
/// </summary>
|
||||
private OptionChain(OptionChain other)
|
||||
: base(other)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a new instance clone of this object, used in fill forward
|
||||
/// </summary>
|
||||
/// <returns>A clone of the current object</returns>
|
||||
public override BaseData Clone()
|
||||
{
|
||||
return new OptionChain(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* 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.Generic;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Collection of <see cref="OptionChain"/> keyed by canonical option symbol
|
||||
/// </summary>
|
||||
public class OptionChains : BaseChains<OptionChain, OptionContract, OptionContracts>
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="OptionChains"/> dictionary
|
||||
/// </summary>
|
||||
public OptionChains() : base()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="OptionChains"/> dictionary
|
||||
/// </summary>
|
||||
public OptionChains(bool flatten)
|
||||
: base(flatten)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="OptionChains"/> dictionary
|
||||
/// </summary>
|
||||
public OptionChains(DateTime time, bool flatten = true)
|
||||
: base(time, flatten)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="OptionChain"/> for the symbol, converting to canonical if needed.
|
||||
/// </summary>
|
||||
public override OptionChain this[Symbol symbol]
|
||||
{
|
||||
get => base[GetCanonicalOptionSymbol(symbol)];
|
||||
set => base[GetCanonicalOptionSymbol(symbol)] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get the <see cref="OptionChain"/> for the given symbol.
|
||||
/// Converts to the canonical option symbol if needed before attempting retrieval.
|
||||
/// </summary>
|
||||
public override bool TryGetValue(Symbol key, out OptionChain value)
|
||||
{
|
||||
var canonicalSymbol = GetCanonicalOptionSymbol(key);
|
||||
return base.TryGetValue(canonicalSymbol, out value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if an <see cref="OptionChain"/> exists for the given symbol.
|
||||
/// Converts to the canonical option symbol first if needed.
|
||||
/// </summary>
|
||||
public override bool ContainsKey(Symbol key)
|
||||
{
|
||||
var canonicalSymbol = GetCanonicalOptionSymbol(key);
|
||||
return base.ContainsKey(canonicalSymbol);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the specified symbol and chain to the dictionary, converting to canonical if needed.
|
||||
/// </summary>
|
||||
public override void Add(Symbol key, OptionChain value)
|
||||
{
|
||||
var canonicalSymbol = GetCanonicalOptionSymbol(key);
|
||||
base.Add(canonicalSymbol, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the element with the specified key, converting to canonical if needed.
|
||||
/// </summary>
|
||||
public override bool Remove(Symbol key)
|
||||
{
|
||||
var canonicalSymbol = GetCanonicalOptionSymbol(key);
|
||||
return base.Remove(canonicalSymbol);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the dictionary contains the specific key-value pair, converting key to canonical if needed.
|
||||
/// </summary>
|
||||
public override bool Contains(KeyValuePair<Symbol, OptionChain> item)
|
||||
{
|
||||
var canonicalSymbol = GetCanonicalOptionSymbol(item.Key);
|
||||
return base.Contains(new KeyValuePair<Symbol, OptionChain>(canonicalSymbol, item.Value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the specific key-value pair, converting key to canonical if needed.
|
||||
/// </summary>
|
||||
public override bool Remove(KeyValuePair<Symbol, OptionChain> item)
|
||||
{
|
||||
var canonicalSymbol = GetCanonicalOptionSymbol(item.Key);
|
||||
return base.Remove(new KeyValuePair<Symbol, OptionChain>(canonicalSymbol, item.Value));
|
||||
}
|
||||
|
||||
private static Symbol GetCanonicalOptionSymbol(Symbol symbol)
|
||||
{
|
||||
if (symbol.SecurityType.HasOptions())
|
||||
{
|
||||
return Symbol.CreateCanonicalOption(symbol);
|
||||
}
|
||||
|
||||
if (symbol.SecurityType.IsOption())
|
||||
{
|
||||
return symbol.Canonical;
|
||||
}
|
||||
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,344 @@
|
||||
/*
|
||||
* 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 QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Securities.Option;
|
||||
using System;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a single option contract at a specific expiration and strike price
|
||||
/// </summary>
|
||||
public class OptionContract : BaseContract
|
||||
{
|
||||
private IOptionData _optionData = OptionPriceModelResultData.Null;
|
||||
private readonly SymbolProperties _symbolProperties;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the strike price
|
||||
/// </summary>
|
||||
public decimal Strike => Symbol.ID.StrikePrice;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the strike price multiplied by the strike multiplier
|
||||
/// </summary>
|
||||
public decimal ScaledStrike => Strike * _symbolProperties.StrikeMultiplier;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the right being purchased (call [right to buy] or put [right to sell])
|
||||
/// </summary>
|
||||
public OptionRight Right => Symbol.ID.OptionRight;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the option style
|
||||
/// </summary>
|
||||
public OptionStyle Style => Symbol.ID.OptionStyle;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the theoretical price of this option contract as computed by the <see cref="IOptionPriceModel"/>
|
||||
/// </summary>
|
||||
public decimal TheoreticalPrice => _optionData.TheoreticalPrice;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the implied volatility of the option contract as computed by the <see cref="IOptionPriceModel"/>
|
||||
/// </summary>
|
||||
public decimal ImpliedVolatility => _optionData.ImpliedVolatility;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the greeks for this contract
|
||||
/// </summary>
|
||||
public Greeks Greeks => _optionData.Greeks;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the open interest
|
||||
/// </summary>
|
||||
public override decimal OpenInterest => _optionData.OpenInterest;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the last price this contract traded at
|
||||
/// </summary>
|
||||
public override decimal LastPrice => _optionData.LastPrice;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the last volume this contract traded at
|
||||
/// </summary>
|
||||
public override long Volume => _optionData.Volume;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current bid price
|
||||
/// </summary>
|
||||
public override decimal BidPrice => _optionData.BidPrice;
|
||||
|
||||
/// <summary>
|
||||
/// Get the current bid size
|
||||
/// </summary>
|
||||
public override long BidSize => _optionData.BidSize;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ask price
|
||||
/// </summary>
|
||||
public override decimal AskPrice => _optionData.AskPrice;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current ask size
|
||||
/// </summary>
|
||||
public override long AskSize => _optionData.AskSize;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the last price the underlying security traded at
|
||||
/// </summary>
|
||||
public decimal UnderlyingLastPrice => _optionData.UnderlyingLastPrice;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OptionContract"/> class
|
||||
/// </summary>
|
||||
/// <param name="security">The option contract security</param>
|
||||
public OptionContract(ISecurityPrice security)
|
||||
: base(security.Symbol)
|
||||
{
|
||||
_symbolProperties = security.SymbolProperties;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new option contract from a given <see cref="OptionUniverse"/> instance
|
||||
/// </summary>
|
||||
/// <param name="contractData">The option universe contract data to use as source for this contract</param>
|
||||
/// <param name="symbolProperties">The contract symbol properties</param>
|
||||
public OptionContract(OptionUniverse contractData, SymbolProperties symbolProperties)
|
||||
: base(contractData.Symbol)
|
||||
{
|
||||
_symbolProperties = symbolProperties;
|
||||
_optionData = new OptionUniverseData(contractData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the option price model evaluator function to be used for this contract
|
||||
/// </summary>
|
||||
/// <param name="optionPriceModelEvaluator">Function delegate used to evaluate the option price model</param>
|
||||
internal void SetOptionPriceModel(Func<OptionPriceModelResult> optionPriceModelEvaluator)
|
||||
{
|
||||
_optionData = new OptionPriceModelResultData(optionPriceModelEvaluator, _optionData as OptionPriceModelResultData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="OptionContract"/>
|
||||
/// </summary>
|
||||
/// <param name="baseData"></param>
|
||||
/// <param name="security">Provides price properties for a <see cref="Security"/></param>
|
||||
/// <param name="underlying">Last underlying security trade data</param>
|
||||
/// <returns>Option contract</returns>
|
||||
public static OptionContract Create(BaseData baseData, ISecurityPrice security, BaseData underlying)
|
||||
=> Create(baseData.EndTime, security, underlying);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="OptionContract"/>
|
||||
/// </summary>
|
||||
/// <param name="endTime">local date time this contract's data was last updated</param>
|
||||
/// <param name="security">provides price properties for a <see cref="Security"/></param>
|
||||
/// <param name="underlying">last underlying security trade data</param>
|
||||
/// <returns>Option contract</returns>
|
||||
public static OptionContract Create(DateTime endTime, ISecurityPrice security, BaseData underlying)
|
||||
{
|
||||
var contract = new OptionContract(security)
|
||||
{
|
||||
Time = endTime,
|
||||
};
|
||||
contract._optionData.SetUnderlying(underlying);
|
||||
|
||||
return contract;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new option contract from a given <see cref="OptionUniverse"/> instance,
|
||||
/// using its data to form a quote bar to source pricing data
|
||||
/// </summary>
|
||||
/// <param name="contractData">The option universe contract data to use as source for this contract</param>
|
||||
/// <param name="symbolProperties">The contract symbol properties</param>
|
||||
public static OptionContract Create(OptionUniverse contractData, SymbolProperties symbolProperties)
|
||||
{
|
||||
var contract = new OptionContract(contractData, symbolProperties)
|
||||
{
|
||||
Time = contractData.EndTime,
|
||||
};
|
||||
|
||||
return contract;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implicit conversion into <see cref="Symbol"/>
|
||||
/// </summary>
|
||||
/// <param name="contract">The option contract to be converted</param>
|
||||
public static implicit operator Symbol(OptionContract contract)
|
||||
{
|
||||
return contract.Symbol;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the option contract with the new data, which can be a <see cref="Tick"/> or <see cref="TradeBar"/> or <see cref="QuoteBar"/>
|
||||
/// </summary>
|
||||
internal override void Update(BaseData data)
|
||||
{
|
||||
if (data.Symbol.SecurityType.IsOption())
|
||||
{
|
||||
_optionData.Update(data);
|
||||
}
|
||||
else if (data.Symbol.SecurityType == Symbol.GetUnderlyingFromOptionType(Symbol.SecurityType))
|
||||
{
|
||||
_optionData.SetUnderlying(data);
|
||||
}
|
||||
}
|
||||
|
||||
#region Option Contract Data Handlers
|
||||
|
||||
private interface IOptionData
|
||||
{
|
||||
decimal LastPrice { get; }
|
||||
decimal UnderlyingLastPrice { get; }
|
||||
long Volume { get; }
|
||||
decimal BidPrice { get; }
|
||||
long BidSize { get; }
|
||||
decimal AskPrice { get; }
|
||||
long AskSize { get; }
|
||||
decimal OpenInterest { get; }
|
||||
decimal TheoreticalPrice { get; }
|
||||
decimal ImpliedVolatility { get; }
|
||||
Greeks Greeks { get; }
|
||||
|
||||
void Update(BaseData data);
|
||||
|
||||
void SetUnderlying(BaseData data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles option data for a contract from actual price data (trade, quote, open interest) and theoretical price model results
|
||||
/// </summary>
|
||||
private class OptionPriceModelResultData : IOptionData
|
||||
{
|
||||
public static readonly OptionPriceModelResultData Null = new(() => OptionPriceModelResult.None);
|
||||
|
||||
private readonly Lazy<OptionPriceModelResult> _optionPriceModelResult;
|
||||
private TradeBar _tradeBar;
|
||||
private QuoteBar _quoteBar;
|
||||
private OpenInterest _openInterest;
|
||||
private BaseData _underlying;
|
||||
|
||||
public decimal LastPrice => _tradeBar?.Close ?? decimal.Zero;
|
||||
|
||||
public decimal UnderlyingLastPrice => _underlying?.Price ?? decimal.Zero;
|
||||
|
||||
public long Volume => (long)(_tradeBar?.Volume ?? 0L);
|
||||
|
||||
public decimal BidPrice => _quoteBar?.Bid?.Close ?? decimal.Zero;
|
||||
|
||||
public long BidSize => (long)(_quoteBar?.LastBidSize ?? 0L);
|
||||
|
||||
public decimal AskPrice => _quoteBar?.Ask?.Close ?? decimal.Zero;
|
||||
|
||||
public long AskSize => (long)(_quoteBar?.LastAskSize ?? 0L);
|
||||
|
||||
public decimal OpenInterest => _openInterest?.Value ?? decimal.Zero;
|
||||
|
||||
public decimal TheoreticalPrice => _optionPriceModelResult.Value.TheoreticalPrice;
|
||||
public decimal ImpliedVolatility => _optionPriceModelResult.Value.ImpliedVolatility;
|
||||
public Greeks Greeks => _optionPriceModelResult.Value.Greeks;
|
||||
|
||||
public OptionPriceModelResultData(Func<OptionPriceModelResult> optionPriceModelEvaluator,
|
||||
OptionPriceModelResultData previousOptionData = null)
|
||||
{
|
||||
_optionPriceModelResult = new(optionPriceModelEvaluator, isThreadSafe: false);
|
||||
|
||||
if (previousOptionData != null)
|
||||
{
|
||||
_tradeBar = previousOptionData._tradeBar;
|
||||
_quoteBar = previousOptionData._quoteBar;
|
||||
_openInterest = previousOptionData._openInterest;
|
||||
_underlying = previousOptionData._underlying;
|
||||
}
|
||||
}
|
||||
|
||||
public void Update(BaseData data)
|
||||
{
|
||||
switch (data)
|
||||
{
|
||||
case TradeBar tradeBar:
|
||||
_tradeBar = tradeBar;
|
||||
break;
|
||||
case QuoteBar quoteBar:
|
||||
_quoteBar = quoteBar;
|
||||
break;
|
||||
case OpenInterest openInterest:
|
||||
_openInterest = openInterest;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetUnderlying(BaseData data)
|
||||
{
|
||||
_underlying = data;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles option data for a contract from a <see cref="OptionUniverse"/> instance
|
||||
/// </summary>
|
||||
private class OptionUniverseData : IOptionData
|
||||
{
|
||||
private readonly OptionUniverse _contractData;
|
||||
|
||||
public decimal LastPrice => _contractData.Close;
|
||||
|
||||
// TODO: Null check required for FOPs: since OptionUniverse does not support FOPs,
|
||||
// these instances will by "synthetic" and will not have underlying data.
|
||||
// Can be removed after FOPs are supported by OptionUniverse
|
||||
public decimal UnderlyingLastPrice => _contractData?.Underlying?.Price ?? decimal.Zero;
|
||||
|
||||
public long Volume => (long)_contractData.Volume;
|
||||
|
||||
public decimal BidPrice => _contractData.Close;
|
||||
|
||||
public long BidSize => 0;
|
||||
|
||||
public decimal AskPrice => _contractData.Close;
|
||||
|
||||
public long AskSize => 0;
|
||||
|
||||
public decimal OpenInterest => _contractData.OpenInterest;
|
||||
|
||||
public decimal TheoreticalPrice => decimal.Zero;
|
||||
|
||||
public decimal ImpliedVolatility => _contractData.ImpliedVolatility;
|
||||
|
||||
public Greeks Greeks => _contractData.Greeks;
|
||||
|
||||
public OptionUniverseData(OptionUniverse contractData)
|
||||
{
|
||||
_contractData = contractData;
|
||||
}
|
||||
|
||||
public void Update(BaseData data)
|
||||
{
|
||||
}
|
||||
|
||||
public void SetUnderlying(BaseData data)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Collection of <see cref="OptionContract"/> keyed by option symbol
|
||||
/// </summary>
|
||||
public class OptionContracts : DataDictionary<OptionContract>
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="OptionContracts"/> dictionary
|
||||
/// </summary>
|
||||
public OptionContracts()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="OptionContracts"/> dictionary
|
||||
/// </summary>
|
||||
public OptionContracts(DateTime time)
|
||||
: base(time)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,725 @@
|
||||
/*
|
||||
* 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.Globalization;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using ProtoBuf;
|
||||
using QuantConnect.Logging;
|
||||
using QuantConnect.Python;
|
||||
using QuantConnect.Util;
|
||||
using static QuantConnect.StringExtensions;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// QuoteBar class for second and minute resolution data:
|
||||
/// An OHLC implementation of the QuantConnect BaseData class with parameters for candles.
|
||||
/// </summary>
|
||||
[ProtoContract(SkipConstructor = true)]
|
||||
public class QuoteBar : BaseData, IBaseDataBar
|
||||
{
|
||||
// scale factor used in QC equity/option/indexOption data files
|
||||
private const decimal _scaleFactor = 1 / 10000m;
|
||||
|
||||
/// <summary>
|
||||
/// Average bid size
|
||||
/// </summary>
|
||||
[ProtoMember(201)]
|
||||
[PandasColumn("bidsize")]
|
||||
public decimal LastBidSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Average ask size
|
||||
/// </summary>
|
||||
[ProtoMember(202)]
|
||||
[PandasColumn("asksize")]
|
||||
public decimal LastAskSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Bid OHLC
|
||||
/// </summary>
|
||||
[ProtoMember(203)]
|
||||
public Bar Bid { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Ask OHLC
|
||||
/// </summary>
|
||||
[ProtoMember(204)]
|
||||
public Bar Ask { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Opening price of the bar: Defined as the price at the start of the time period.
|
||||
/// </summary>
|
||||
public decimal Open
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Bid != null && Ask != null)
|
||||
{
|
||||
if (Bid.Open != 0m && Ask.Open != 0m)
|
||||
return (Bid.Open + Ask.Open) / 2m;
|
||||
|
||||
if (Bid.Open != 0)
|
||||
return Bid.Open;
|
||||
|
||||
if (Ask.Open != 0)
|
||||
return Ask.Open;
|
||||
|
||||
return 0m;
|
||||
}
|
||||
if (Bid != null)
|
||||
{
|
||||
return Bid.Open;
|
||||
}
|
||||
if (Ask != null)
|
||||
{
|
||||
return Ask.Open;
|
||||
}
|
||||
return 0m;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// High price of the QuoteBar during the time period.
|
||||
/// </summary>
|
||||
public decimal High
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Bid != null && Ask != null)
|
||||
{
|
||||
if (Bid.High != 0m && Ask.High != 0m)
|
||||
return (Bid.High + Ask.High) / 2m;
|
||||
|
||||
if (Bid.High != 0)
|
||||
return Bid.High;
|
||||
|
||||
if (Ask.High != 0)
|
||||
return Ask.High;
|
||||
|
||||
return 0m;
|
||||
}
|
||||
if (Bid != null)
|
||||
{
|
||||
return Bid.High;
|
||||
}
|
||||
if (Ask != null)
|
||||
{
|
||||
return Ask.High;
|
||||
}
|
||||
return 0m;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Low price of the QuoteBar during the time period.
|
||||
/// </summary>
|
||||
public decimal Low
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Bid != null && Ask != null)
|
||||
{
|
||||
if (Bid.Low != 0m && Ask.Low != 0m)
|
||||
return (Bid.Low + Ask.Low) / 2m;
|
||||
|
||||
if (Bid.Low != 0)
|
||||
return Bid.Low;
|
||||
|
||||
if (Ask.Low != 0)
|
||||
return Ask.Low;
|
||||
|
||||
return 0m;
|
||||
}
|
||||
if (Bid != null)
|
||||
{
|
||||
return Bid.Low;
|
||||
}
|
||||
if (Ask != null)
|
||||
{
|
||||
return Ask.Low;
|
||||
}
|
||||
return 0m;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closing price of the QuoteBar. Defined as the price at Start Time + TimeSpan.
|
||||
/// </summary>
|
||||
public decimal Close
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Bid != null && Ask != null)
|
||||
{
|
||||
if (Bid.Close != 0m && Ask.Close != 0m)
|
||||
return (Bid.Close + Ask.Close) / 2m;
|
||||
|
||||
if (Bid.Close != 0)
|
||||
return Bid.Close;
|
||||
|
||||
if (Ask.Close != 0)
|
||||
return Ask.Close;
|
||||
|
||||
return 0m;
|
||||
}
|
||||
if (Bid != null)
|
||||
{
|
||||
return Bid.Close;
|
||||
}
|
||||
if (Ask != null)
|
||||
{
|
||||
return Ask.Close;
|
||||
}
|
||||
return Value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The closing time of this bar, computed via the Time and Period
|
||||
/// </summary>
|
||||
[PandasIgnore]
|
||||
public override DateTime EndTime
|
||||
{
|
||||
get { return Time + Period; }
|
||||
set { Period = value - Time; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The period of this quote bar, (second, minute, daily, ect...)
|
||||
/// </summary>
|
||||
[ProtoMember(205)]
|
||||
[PandasIgnore]
|
||||
public TimeSpan Period { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Default initializer to setup an empty quotebar.
|
||||
/// </summary>
|
||||
public QuoteBar()
|
||||
: this(false)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default initializer to setup an empty quotebar.
|
||||
/// </summary>
|
||||
public QuoteBar(bool empty)
|
||||
{
|
||||
DataType = MarketDataType.QuoteBar;
|
||||
if (empty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Symbol = Symbol.Empty;
|
||||
Time = new DateTime();
|
||||
Bid = new Bar();
|
||||
Ask = new Bar();
|
||||
Value = 0;
|
||||
Period = QuantConnect.Time.OneMinute;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize Quote Bar with Bid(OHLC) and Ask(OHLC) Values:
|
||||
/// </summary>
|
||||
/// <param name="time">DateTime Timestamp of the bar</param>
|
||||
/// <param name="symbol">Market MarketType Symbol</param>
|
||||
/// <param name="bid">Bid OLHC bar</param>
|
||||
/// <param name="lastBidSize">Average bid size over period</param>
|
||||
/// <param name="ask">Ask OLHC bar</param>
|
||||
/// <param name="lastAskSize">Average ask size over period</param>
|
||||
/// <param name="period">The period of this bar, specify null for default of 1 minute</param>
|
||||
public QuoteBar(DateTime time, Symbol symbol, IBar bid, decimal lastBidSize, IBar ask, decimal lastAskSize, TimeSpan? period = null)
|
||||
{
|
||||
Symbol = symbol;
|
||||
Time = time;
|
||||
Bid = bid == null ? null : new Bar(bid.Open, bid.High, bid.Low, bid.Close);
|
||||
Ask = ask == null ? null : new Bar(ask.Open, ask.High, ask.Low, ask.Close);
|
||||
if (Bid != null) LastBidSize = lastBidSize;
|
||||
if (Ask != null) LastAskSize = lastAskSize;
|
||||
Value = Close;
|
||||
Period = period ?? QuantConnect.Time.OneMinute;
|
||||
DataType = MarketDataType.QuoteBar;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the quotebar - build the bar from this pricing information:
|
||||
/// </summary>
|
||||
/// <param name="lastTrade">The last trade price</param>
|
||||
/// <param name="bidPrice">Current bid price</param>
|
||||
/// <param name="askPrice">Current asking price</param>
|
||||
/// <param name="volume">Volume of this trade</param>
|
||||
/// <param name="bidSize">The size of the current bid, if available, if not, pass 0</param>
|
||||
/// <param name="askSize">The size of the current ask, if available, if not, pass 0</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override void Update(decimal lastTrade, decimal bidPrice, decimal askPrice, decimal volume, decimal bidSize, decimal askSize)
|
||||
{
|
||||
// update our bid and ask bars - handle null values, this is to give good values for midpoint OHLC
|
||||
if (Bid == null && bidPrice != 0) Bid = new Bar(bidPrice, bidPrice, bidPrice, bidPrice);
|
||||
else if (Bid != null) Bid.Update(ref bidPrice);
|
||||
|
||||
if (Ask == null && askPrice != 0) Ask = new Bar(askPrice, askPrice, askPrice, askPrice);
|
||||
else if (Ask != null) Ask.Update(ref askPrice);
|
||||
|
||||
if (bidSize > 0)
|
||||
{
|
||||
LastBidSize = bidSize;
|
||||
}
|
||||
|
||||
if (askSize > 0)
|
||||
{
|
||||
LastAskSize = askSize;
|
||||
}
|
||||
|
||||
// be prepared for updates without trades
|
||||
if (lastTrade != 0) Value = lastTrade;
|
||||
else if (askPrice != 0) Value = askPrice;
|
||||
else if (bidPrice != 0) Value = bidPrice;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// QuoteBar Reader: Fetch the data from the QC storage and feed it line by line into the engine.
|
||||
/// </summary>
|
||||
/// <param name="config">Symbols, Resolution, DataType, </param>
|
||||
/// <param name="stream">The file data stream</param>
|
||||
/// <param name="date">Date of this reader request</param>
|
||||
/// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param>
|
||||
/// <returns>Enumerable iterator for returning each line of the required data.</returns>
|
||||
[StubsIgnore]
|
||||
public override BaseData Reader(SubscriptionDataConfig config, StreamReader stream, DateTime date, bool isLiveMode)
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (config.SecurityType)
|
||||
{
|
||||
case SecurityType.Equity:
|
||||
return ParseEquity(config, stream, date);
|
||||
|
||||
case SecurityType.Forex:
|
||||
case SecurityType.Crypto:
|
||||
case SecurityType.CryptoFuture:
|
||||
return ParseForex(config, stream, date);
|
||||
|
||||
case SecurityType.Cfd:
|
||||
return ParseCfd(config, stream, date);
|
||||
|
||||
case SecurityType.Option:
|
||||
case SecurityType.FutureOption:
|
||||
case SecurityType.IndexOption:
|
||||
return ParseOption(config, stream, date);
|
||||
|
||||
case SecurityType.Future:
|
||||
return ParseFuture(config, stream, date);
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
Log.Error(Invariant($"QuoteBar.Reader(): Error parsing stream, Symbol: {config.Symbol.Value}, SecurityType: {config.SecurityType}, ") +
|
||||
Invariant($"Resolution: {config.Resolution}, Date: {date.ToStringInvariant("yyyy-MM-dd")}, Message: {err}")
|
||||
);
|
||||
}
|
||||
|
||||
// we need to consume a line anyway, to advance the stream
|
||||
stream.ReadLine();
|
||||
|
||||
// if we couldn't parse it above return a default instance
|
||||
return new QuoteBar { Symbol = config.Symbol, Period = config.Increment };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// QuoteBar Reader: Fetch the data from the QC storage and feed it line by line into the engine.
|
||||
/// </summary>
|
||||
/// <param name="config">Symbols, Resolution, DataType, </param>
|
||||
/// <param name="line">Line from the data file requested</param>
|
||||
/// <param name="date">Date of this reader request</param>
|
||||
/// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param>
|
||||
/// <returns>Enumerable iterator for returning each line of the required data.</returns>
|
||||
public override BaseData Reader(SubscriptionDataConfig config, string line, DateTime date, bool isLiveMode)
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (config.SecurityType)
|
||||
{
|
||||
case SecurityType.Equity:
|
||||
return ParseEquity(config, line, date);
|
||||
|
||||
case SecurityType.Forex:
|
||||
case SecurityType.Crypto:
|
||||
case SecurityType.CryptoFuture:
|
||||
return ParseForex(config, line, date);
|
||||
|
||||
case SecurityType.Cfd:
|
||||
return ParseCfd(config, line, date);
|
||||
|
||||
case SecurityType.Option:
|
||||
case SecurityType.FutureOption:
|
||||
case SecurityType.IndexOption:
|
||||
return ParseOption(config, line, date);
|
||||
|
||||
case SecurityType.Future:
|
||||
return ParseFuture(config, line, date);
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
Log.Error(Invariant($"QuoteBar.Reader(): Error parsing line: '{line}', Symbol: {config.Symbol.Value}, SecurityType: {config.SecurityType}, ") +
|
||||
Invariant($"Resolution: {config.Resolution}, Date: {date.ToStringInvariant("yyyy-MM-dd")}, Message: {err}")
|
||||
);
|
||||
}
|
||||
|
||||
// if we couldn't parse it above return a default instance
|
||||
return new QuoteBar { Symbol = config.Symbol, Period = config.Increment };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a quotebar representing a future with a scaling factor
|
||||
/// </summary>
|
||||
/// <param name="config">Symbols, Resolution, DataType</param>
|
||||
/// <param name="line">Line from the data file requested</param>
|
||||
/// <param name="date">Date of this reader request</param>
|
||||
/// <returns><see cref="QuoteBar"/> with the bid/ask set to same values</returns>
|
||||
public QuoteBar ParseFuture(SubscriptionDataConfig config, string line, DateTime date)
|
||||
{
|
||||
return ParseQuote(config, date, line, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a quotebar representing a future with a scaling factor
|
||||
/// </summary>
|
||||
/// <param name="config">Symbols, Resolution, DataType</param>
|
||||
/// <param name="streamReader">The data stream of the requested file</param>
|
||||
/// <param name="date">Date of this reader request</param>
|
||||
/// <returns><see cref="QuoteBar"/> with the bid/ask set to same values</returns>
|
||||
public QuoteBar ParseFuture(SubscriptionDataConfig config, StreamReader streamReader, DateTime date)
|
||||
{
|
||||
return ParseQuote(config, date, streamReader, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a quotebar representing an option with a scaling factor
|
||||
/// </summary>
|
||||
/// <param name="config">Symbols, Resolution, DataType</param>
|
||||
/// <param name="line">Line from the data file requested</param>
|
||||
/// <param name="date">Date of this reader request</param>
|
||||
/// <returns><see cref="QuoteBar"/> with the bid/ask set to same values</returns>
|
||||
public QuoteBar ParseOption(SubscriptionDataConfig config, string line, DateTime date)
|
||||
{
|
||||
return ParseQuote(config, date, line, LeanData.OptionUseScaleFactor(config.Symbol));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a quotebar representing an option with a scaling factor
|
||||
/// </summary>
|
||||
/// <param name="config">Symbols, Resolution, DataType</param>
|
||||
/// <param name="streamReader">The data stream of the requested file</param>
|
||||
/// <param name="date">Date of this reader request</param>
|
||||
/// <returns><see cref="QuoteBar"/> with the bid/ask set to same values</returns>
|
||||
public QuoteBar ParseOption(SubscriptionDataConfig config, StreamReader streamReader, DateTime date)
|
||||
{
|
||||
// scale factor only applies for equity and index options
|
||||
return ParseQuote(config, date, streamReader, useScaleFactor: LeanData.OptionUseScaleFactor(config.Symbol));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a quotebar representing a cfd without a scaling factor
|
||||
/// </summary>
|
||||
/// <param name="config">Symbols, Resolution, DataType</param>
|
||||
/// <param name="line">Line from the data file requested</param>
|
||||
/// <param name="date">Date of this reader request</param>
|
||||
/// <returns><see cref="QuoteBar"/> with the bid/ask set to same values</returns>
|
||||
public QuoteBar ParseCfd(SubscriptionDataConfig config, string line, DateTime date)
|
||||
{
|
||||
return ParseQuote(config, date, line, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a quotebar representing a cfd without a scaling factor
|
||||
/// </summary>
|
||||
/// <param name="config">Symbols, Resolution, DataType</param>
|
||||
/// <param name="streamReader">The data stream of the requested file</param>
|
||||
/// <param name="date">Date of this reader request</param>
|
||||
/// <returns><see cref="QuoteBar"/> with the bid/ask set to same values</returns>
|
||||
public QuoteBar ParseCfd(SubscriptionDataConfig config, StreamReader streamReader, DateTime date)
|
||||
{
|
||||
return ParseQuote(config, date, streamReader, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a quotebar representing a forex without a scaling factor
|
||||
/// </summary>
|
||||
/// <param name="config">Symbols, Resolution, DataType</param>
|
||||
/// <param name="line">Line from the data file requested</param>
|
||||
/// <param name="date">Date of this reader request</param>
|
||||
/// <returns><see cref="QuoteBar"/> with the bid/ask set to same values</returns>
|
||||
public QuoteBar ParseForex(SubscriptionDataConfig config, string line, DateTime date)
|
||||
{
|
||||
return ParseQuote(config, date, line, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a quotebar representing a forex without a scaling factor
|
||||
/// </summary>
|
||||
/// <param name="config">Symbols, Resolution, DataType</param>
|
||||
/// <param name="streamReader">The data stream of the requested file</param>
|
||||
/// <param name="date">Date of this reader request</param>
|
||||
/// <returns><see cref="QuoteBar"/> with the bid/ask set to same values</returns>
|
||||
public QuoteBar ParseForex(SubscriptionDataConfig config, StreamReader streamReader, DateTime date)
|
||||
{
|
||||
return ParseQuote(config, date, streamReader, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a quotebar representing an equity with a scaling factor
|
||||
/// </summary>
|
||||
/// <param name="config">Symbols, Resolution, DataType</param>
|
||||
/// <param name="line">Line from the data file requested</param>
|
||||
/// <param name="date">Date of this reader request</param>
|
||||
/// <returns><see cref="QuoteBar"/> with the bid/ask set to same values</returns>
|
||||
public QuoteBar ParseEquity(SubscriptionDataConfig config, string line, DateTime date)
|
||||
{
|
||||
return ParseQuote(config, date, line, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a quotebar representing an equity with a scaling factor
|
||||
/// </summary>
|
||||
/// <param name="config">Symbols, Resolution, DataType</param>
|
||||
/// <param name="streamReader">The data stream of the requested file</param>
|
||||
/// <param name="date">Date of this reader request</param>
|
||||
/// <returns><see cref="QuoteBar"/> with the bid/ask set to same values</returns>
|
||||
public QuoteBar ParseEquity(SubscriptionDataConfig config, StreamReader streamReader, DateTime date)
|
||||
{
|
||||
return ParseQuote(config, date, streamReader, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// "Scaffold" code - If the data being read is formatted as a QuoteBar, use this method to deserialize it
|
||||
/// </summary>
|
||||
/// <param name="config">Symbols, Resolution, DataType, </param>
|
||||
/// <param name="streamReader">The data stream of the requested file</param>
|
||||
/// <param name="date">Date of this reader request</param>
|
||||
/// <param name="useScaleFactor">Whether the data has a scaling factor applied</param>
|
||||
/// <returns><see cref="QuoteBar"/> with the bid/ask prices set appropriately</returns>
|
||||
private QuoteBar ParseQuote(SubscriptionDataConfig config, DateTime date, StreamReader streamReader, bool useScaleFactor)
|
||||
{
|
||||
// Non-equity asset classes will not use scaling, including options that have a non-equity underlying asset class.
|
||||
var scaleFactor = useScaleFactor
|
||||
? _scaleFactor
|
||||
: 1;
|
||||
|
||||
var quoteBar = new QuoteBar
|
||||
{
|
||||
Period = config.Increment,
|
||||
Symbol = config.Symbol
|
||||
};
|
||||
|
||||
if (config.Resolution == Resolution.Daily || config.Resolution == Resolution.Hour)
|
||||
{
|
||||
// hourly and daily have different time format, and can use slow, robust c# parser.
|
||||
quoteBar.Time = streamReader.GetDateTime().ConvertTo(config.DataTimeZone, config.ExchangeTimeZone);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Using custom int conversion for speed on high resolution data.
|
||||
quoteBar.Time = date.Date.AddMilliseconds(streamReader.GetInt32()).ConvertTo(config.DataTimeZone, config.ExchangeTimeZone);
|
||||
}
|
||||
|
||||
var open = streamReader.GetDecimal();
|
||||
var high = streamReader.GetDecimal();
|
||||
var low = streamReader.GetDecimal();
|
||||
var close = streamReader.GetDecimal();
|
||||
var lastSize = streamReader.GetDecimal();
|
||||
// only create the bid if it exists in the file
|
||||
if (open != 0 || high != 0 || low != 0 || close != 0)
|
||||
{
|
||||
// the Bid/Ask bars were already create above, we don't need to recreate them but just set their values
|
||||
quoteBar.Bid.Open = open * scaleFactor;
|
||||
quoteBar.Bid.High = high * scaleFactor;
|
||||
quoteBar.Bid.Low = low * scaleFactor;
|
||||
quoteBar.Bid.Close = close * scaleFactor;
|
||||
quoteBar.LastBidSize = lastSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
quoteBar.Bid = null;
|
||||
}
|
||||
|
||||
open = streamReader.GetDecimal();
|
||||
high = streamReader.GetDecimal();
|
||||
low = streamReader.GetDecimal();
|
||||
close = streamReader.GetDecimal();
|
||||
lastSize = streamReader.GetDecimal();
|
||||
// only create the ask if it exists in the file
|
||||
if (open != 0 || high != 0 || low != 0 || close != 0)
|
||||
{
|
||||
// the Bid/Ask bars were already create above, we don't need to recreate them but just set their values
|
||||
quoteBar.Ask.Open = open * scaleFactor;
|
||||
quoteBar.Ask.High = high * scaleFactor;
|
||||
quoteBar.Ask.Low = low * scaleFactor;
|
||||
quoteBar.Ask.Close = close * scaleFactor;
|
||||
quoteBar.LastAskSize = lastSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
quoteBar.Ask = null;
|
||||
}
|
||||
|
||||
quoteBar.Value = quoteBar.Close;
|
||||
return quoteBar;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// "Scaffold" code - If the data being read is formatted as a QuoteBar, use this method to deserialize it
|
||||
/// TODO: Once all Forex data refactored to use QuoteBar formatted data, use only this method
|
||||
/// </summary>
|
||||
/// <param name="config">Symbols, Resolution, DataType, </param>
|
||||
/// <param name="line">Line from the data file requested</param>
|
||||
/// <param name="date">Date of this reader request</param>
|
||||
/// <param name="useScaleFactor">Whether the data has a scaling factor applied</param>
|
||||
/// <returns><see cref="QuoteBar"/> with the bid/ask prices set appropriately</returns>
|
||||
private QuoteBar ParseQuote(SubscriptionDataConfig config, DateTime date, string line, bool useScaleFactor)
|
||||
{
|
||||
var scaleFactor = useScaleFactor
|
||||
? _scaleFactor
|
||||
: 1;
|
||||
|
||||
var quoteBar = new QuoteBar
|
||||
{
|
||||
Period = config.Increment,
|
||||
Symbol = config.Symbol
|
||||
};
|
||||
|
||||
var csv = line.ToCsv(11);
|
||||
if (config.Resolution == Resolution.Daily || config.Resolution == Resolution.Hour)
|
||||
{
|
||||
// hourly and daily have different time format, and can use slow, robust c# parser.
|
||||
quoteBar.Time = DateTime.ParseExact(csv[0], DateFormat.TwelveCharacter, CultureInfo.InvariantCulture).ConvertTo(config.DataTimeZone, config.ExchangeTimeZone);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Using custom "ToDecimal" conversion for speed on high resolution data.
|
||||
quoteBar.Time = date.Date.AddMilliseconds((double)csv[0].ToDecimal()).ConvertTo(config.DataTimeZone, config.ExchangeTimeZone);
|
||||
}
|
||||
|
||||
// only create the bid if it exists in the file
|
||||
if (csv[1].Length != 0 || csv[2].Length != 0 || csv[3].Length != 0 || csv[4].Length != 0)
|
||||
{
|
||||
// the Bid/Ask bars were already create above, we don't need to recreate them but just set their values
|
||||
quoteBar.Bid.Open = csv[1].ToDecimal() * scaleFactor;
|
||||
quoteBar.Bid.High = csv[2].ToDecimal() * scaleFactor;
|
||||
quoteBar.Bid.Low = csv[3].ToDecimal() * scaleFactor;
|
||||
quoteBar.Bid.Close = csv[4].ToDecimal() * scaleFactor;
|
||||
quoteBar.LastBidSize = csv[5].ToDecimal();
|
||||
}
|
||||
else
|
||||
{
|
||||
quoteBar.Bid = null;
|
||||
}
|
||||
|
||||
// only create the ask if it exists in the file
|
||||
if (csv[6].Length != 0 || csv[7].Length != 0 || csv[8].Length != 0 || csv[9].Length != 0)
|
||||
{
|
||||
// the Bid/Ask bars were already create above, we don't need to recreate them but just set their values
|
||||
quoteBar.Ask.Open = csv[6].ToDecimal() * scaleFactor;
|
||||
quoteBar.Ask.High = csv[7].ToDecimal() * scaleFactor;
|
||||
quoteBar.Ask.Low = csv[8].ToDecimal() * scaleFactor;
|
||||
quoteBar.Ask.Close = csv[9].ToDecimal() * scaleFactor;
|
||||
quoteBar.LastAskSize = csv[10].ToDecimal();
|
||||
}
|
||||
else
|
||||
{
|
||||
quoteBar.Ask = null;
|
||||
}
|
||||
|
||||
quoteBar.Value = quoteBar.Close;
|
||||
return quoteBar;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get Source for Custom Data File
|
||||
/// >> What source file location would you prefer for each type of usage:
|
||||
/// </summary>
|
||||
/// <param name="config">Configuration object</param>
|
||||
/// <param name="date">Date of this source request if source spread across multiple files</param>
|
||||
/// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param>
|
||||
/// <returns>String source location of the file</returns>
|
||||
public override SubscriptionDataSource GetSource(SubscriptionDataConfig config, DateTime date, bool isLiveMode)
|
||||
{
|
||||
if (isLiveMode)
|
||||
{
|
||||
// this data type is streamed in live mode
|
||||
return new SubscriptionDataSource(string.Empty, SubscriptionTransportMedium.Streaming);
|
||||
}
|
||||
|
||||
var source = LeanData.GenerateZipFilePath(Globals.DataFolder, config.Symbol, date, config.Resolution, config.TickType);
|
||||
if (config.SecurityType == SecurityType.Future || config.SecurityType.IsOption())
|
||||
{
|
||||
source += "#" + LeanData.GenerateZipEntryName(config.Symbol, date, config.Resolution, config.TickType);
|
||||
}
|
||||
return new SubscriptionDataSource(source, SubscriptionTransportMedium.LocalFile, FileFormat.Csv);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a new instance clone of this quote bar, used in fill forward
|
||||
/// </summary>
|
||||
/// <returns>A clone of the current quote bar</returns>
|
||||
public override BaseData Clone()
|
||||
{
|
||||
return new QuoteBar
|
||||
{
|
||||
Ask = Ask == null ? null : Ask.Clone(),
|
||||
Bid = Bid == null ? null : Bid.Clone(),
|
||||
LastAskSize = LastAskSize,
|
||||
LastBidSize = LastBidSize,
|
||||
Symbol = Symbol,
|
||||
Time = Time,
|
||||
Period = Period,
|
||||
Value = Value,
|
||||
DataType = DataType
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Collapses QuoteBars into TradeBars object when
|
||||
/// algorithm requires FX data, but calls OnData(<see cref="TradeBars"/>)
|
||||
/// TODO: (2017) Remove this method in favor of using OnData(<see cref="Slice"/>)
|
||||
/// </summary>
|
||||
/// <returns><see cref="TradeBars"/></returns>
|
||||
public TradeBar Collapse()
|
||||
{
|
||||
return new TradeBar(Time, Symbol, Open, High, Low, Close, 0, Period);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert this <see cref="QuoteBar"/> to string form.
|
||||
/// </summary>
|
||||
/// <returns>String representation of the <see cref="QuoteBar"/></returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Symbol}: " +
|
||||
$"Bid: O: {Bid?.Open.SmartRounding()} " +
|
||||
$"Bid: H: {Bid?.High.SmartRounding()} " +
|
||||
$"Bid: L: {Bid?.Low.SmartRounding()} " +
|
||||
$"Bid: C: {Bid?.Close.SmartRounding()} " +
|
||||
$"Ask: O: {Ask?.Open.SmartRounding()} " +
|
||||
$"Ask: H: {Ask?.High.SmartRounding()} " +
|
||||
$"Ask: L: {Ask?.Low.SmartRounding()} " +
|
||||
$"Ask: C: {Ask?.Close.SmartRounding()} ";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Collection of <see cref="QuoteBar"/> keyed by symbol
|
||||
/// </summary>
|
||||
public class QuoteBars : DataDictionary<QuoteBar>
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="QuoteBars"/> dictionary
|
||||
/// </summary>
|
||||
public QuoteBars()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="QuoteBars"/> dictionary
|
||||
/// </summary>
|
||||
public QuoteBars(DateTime time)
|
||||
: base(time)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a bar sectioned not by time, but by some amount of movement in a value (for example, Closing price moving in $10 bar sizes)
|
||||
/// </summary>
|
||||
public class RangeBar: TradeBar
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the range of the bar.
|
||||
/// </summary>
|
||||
public decimal RangeSize { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not this bar is considered closed.
|
||||
/// </summary>
|
||||
public bool IsClosed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initialize a new default instance of <see cref="RangeBar"/> class.
|
||||
/// </summary>
|
||||
public RangeBar()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RangeBar"/> class with the specified values
|
||||
/// </summary>
|
||||
/// <param name="symbol">The symbol of this data</param>
|
||||
/// <param name="endTime">The end time of the bar</param>
|
||||
/// <param name="rangeSize">The size of each range bar</param>
|
||||
/// <param name="open">The opening price for the new bar</param>
|
||||
/// <param name="high">The high price for the new bar</param>
|
||||
/// <param name="low">The low price for the new bar</param>
|
||||
/// <param name="close">The closing price for the new bar</param>
|
||||
/// <param name="volume">The volume value for the new bar</param>
|
||||
public RangeBar(Symbol symbol, DateTime endTime,
|
||||
decimal rangeSize, decimal open, decimal? high = null, decimal? low = null, decimal? close = null, decimal volume = 0)
|
||||
{
|
||||
Symbol = symbol;
|
||||
EndTime = endTime;
|
||||
RangeSize = rangeSize;
|
||||
Open = open;
|
||||
Close = close ?? open;
|
||||
Volume = volume;
|
||||
High = high ?? open;
|
||||
Low = low ?? open;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates this <see cref="RangeBar"/> with the specified values
|
||||
/// </summary>
|
||||
/// <param name="time">The current time</param>
|
||||
/// <param name="currentValue">The current value</param>
|
||||
/// <param name="volumeSinceLastUpdate">The volume since the last update called on this instance</param>
|
||||
public void Update(DateTime time, decimal currentValue, decimal volumeSinceLastUpdate)
|
||||
{
|
||||
EndTime = time;
|
||||
|
||||
if (currentValue < Low)
|
||||
{
|
||||
if ((High - currentValue) > RangeSize)
|
||||
{
|
||||
IsClosed = true;
|
||||
Low = High - RangeSize;
|
||||
Close = Low;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
Low = currentValue;
|
||||
}
|
||||
}
|
||||
else if (currentValue > High)
|
||||
{
|
||||
if ((currentValue - Low) > RangeSize)
|
||||
{
|
||||
IsClosed = true;
|
||||
High = Low + RangeSize;
|
||||
Close = High;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
High = currentValue;
|
||||
}
|
||||
}
|
||||
|
||||
Volume += volumeSinceLastUpdate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a new instance clone of this object, used in fill forward
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This base implementation uses reflection to copy all public fields and properties
|
||||
/// </remarks>
|
||||
/// <returns>A clone of the current object</returns>
|
||||
public override BaseData Clone()
|
||||
{
|
||||
return new RangeBar
|
||||
{
|
||||
RangeSize = RangeSize,
|
||||
Open = Open,
|
||||
Volume = Volume,
|
||||
Close = Close,
|
||||
EndTime = EndTime,
|
||||
High = High,
|
||||
IsClosed = IsClosed,
|
||||
Low = Low,
|
||||
Time = Time,
|
||||
Value = Value,
|
||||
Symbol = Symbol,
|
||||
DataType = DataType
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a bar sectioned not by time, but by some amount of movement in a value (for example, Closing price moving in $10 bar sizes)
|
||||
/// </summary>
|
||||
public class RenkoBar : BaseRenkoBar
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the end time of this renko bar or the most recent update time if it <see cref="BaseRenkoBar.IsClosed"/>
|
||||
/// </summary>
|
||||
[Obsolete("RenkoBar.End is obsolete. Please use RenkoBar.EndTime property instead.")]
|
||||
public DateTime End
|
||||
{
|
||||
get { return EndTime; }
|
||||
set { EndTime = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The trend of the bar (i.e. Rising, Falling or NoDelta)
|
||||
/// </summary>
|
||||
public BarDirection Direction
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Open < Close)
|
||||
return BarDirection.Rising;
|
||||
else if (Open > Close)
|
||||
return BarDirection.Falling;
|
||||
else
|
||||
return BarDirection.NoDelta;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The "spread" of the bar
|
||||
/// </summary>
|
||||
public decimal Spread
|
||||
{
|
||||
get
|
||||
{
|
||||
return Math.Abs(Close - Open);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new default instance of the <see cref="RenkoBar"/> class.
|
||||
/// </summary>
|
||||
public RenkoBar()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RenkoBar"/> class with the specified values
|
||||
/// </summary>
|
||||
/// <param name="symbol">The symbol of this data</param>
|
||||
/// <param name="time">The start time of the bar</param>
|
||||
/// <param name="brickSize">The size of each renko brick</param>
|
||||
/// <param name="open">The opening price for the new bar</param>
|
||||
/// <param name="volume">Any initial volume associated with the data</param>
|
||||
public RenkoBar(Symbol symbol, DateTime time, decimal brickSize,
|
||||
decimal open, decimal volume)
|
||||
{
|
||||
Type = RenkoType.Classic;
|
||||
|
||||
Symbol = symbol;
|
||||
Start = time;
|
||||
EndTime = time;
|
||||
BrickSize = brickSize;
|
||||
Open = open;
|
||||
Close = open;
|
||||
Volume = volume;
|
||||
High = open;
|
||||
Low = open;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RenkoBar"/> class with the specified values
|
||||
/// </summary>
|
||||
/// <param name="symbol">The symbol of this data</param>
|
||||
/// <param name="start">The start time of the bar</param>
|
||||
/// <param name="endTime">The end time of the bar</param>
|
||||
/// <param name="brickSize">The size of each wicko brick</param>
|
||||
/// <param name="open">The opening price for the new bar</param>
|
||||
/// <param name="high">The high price for the new bar</param>
|
||||
/// <param name="low">The low price for the new bar</param>
|
||||
/// <param name="close">The closing price for the new bar</param>
|
||||
public RenkoBar(Symbol symbol, DateTime start, DateTime endTime,
|
||||
decimal brickSize, decimal open, decimal high, decimal low, decimal close)
|
||||
{
|
||||
Type = RenkoType.Wicked;
|
||||
|
||||
Symbol = symbol;
|
||||
Start = start;
|
||||
EndTime = endTime;
|
||||
BrickSize = brickSize;
|
||||
Open = open;
|
||||
Close = close;
|
||||
Volume = 0;
|
||||
High = high;
|
||||
Low = low;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates this <see cref="RenkoBar"/> with the specified values and returns whether or not this bar is closed
|
||||
/// </summary>
|
||||
/// <param name="time">The current time</param>
|
||||
/// <param name="currentValue">The current value</param>
|
||||
/// <param name="volumeSinceLastUpdate">The volume since the last update called on this instance</param>
|
||||
/// <returns>True if this bar <see cref="BaseRenkoBar.IsClosed"/></returns>
|
||||
public bool Update(DateTime time, decimal currentValue, decimal volumeSinceLastUpdate)
|
||||
{
|
||||
if (Type == RenkoType.Wicked)
|
||||
throw new InvalidOperationException("A \"Wicked\" RenkoBar cannot be updated!");
|
||||
|
||||
// can't update a closed renko bar
|
||||
if (IsClosed) return true;
|
||||
if (Start == DateTime.MinValue) Start = time;
|
||||
EndTime = time;
|
||||
|
||||
// compute the min/max closes this renko bar can have
|
||||
decimal lowClose = Open - BrickSize;
|
||||
decimal highClose = Open + BrickSize;
|
||||
|
||||
Close = Math.Min(highClose, Math.Max(lowClose, currentValue));
|
||||
Volume += volumeSinceLastUpdate;
|
||||
|
||||
// determine if this data caused the bar to close
|
||||
if (currentValue <= lowClose || currentValue >= highClose)
|
||||
{
|
||||
IsClosed = true;
|
||||
}
|
||||
|
||||
if (Close > High) High = Close;
|
||||
if (Close < Low) Low = Close;
|
||||
|
||||
return IsClosed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a new instance clone of this object, used in fill forward
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This base implementation uses reflection to copy all public fields and properties
|
||||
/// </remarks>
|
||||
/// <returns>A clone of the current object</returns>
|
||||
public override BaseData Clone()
|
||||
{
|
||||
return new RenkoBar
|
||||
{
|
||||
Type = Type,
|
||||
BrickSize = BrickSize,
|
||||
Open = Open,
|
||||
Volume = Volume,
|
||||
Close = Close,
|
||||
EndTime = EndTime,
|
||||
High = High,
|
||||
IsClosed = IsClosed,
|
||||
Low = Low,
|
||||
Time = Time,
|
||||
Value = Value,
|
||||
Symbol = Symbol,
|
||||
DataType = DataType
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// The type of the RenkoBar being created.
|
||||
/// Used by RenkoConsolidator, ClassicRenkoConsolidator and VolumeRenkoConsolidator
|
||||
/// </summary>
|
||||
/// <remarks>Classic implementation was not entirely accurate for Renko consolidator
|
||||
/// so we have replaced it with a new implementation and maintain the classic
|
||||
/// for backwards compatibility and comparison.</remarks>
|
||||
public enum RenkoType
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates that the RenkoConsolidator works in its
|
||||
/// original implementation; Specifically:
|
||||
/// - It only returns a single bar, at most, irrespective of tick movement
|
||||
/// - It will emit consecutive bars side by side
|
||||
/// - By default even bars are created
|
||||
/// (0)
|
||||
/// </summary>
|
||||
/// <remarks>the Classic mode has only been retained for
|
||||
/// backwards compatibility with existing code.</remarks>
|
||||
Classic,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the RenkoConsolidator works properly;
|
||||
/// Specifically:
|
||||
/// - returns zero or more bars per tick, as appropriate.
|
||||
/// - Will not emit consecutive bars side by side
|
||||
/// - Creates
|
||||
/// (1)
|
||||
/// </summary>
|
||||
Wicked
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* 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 QuantConnect.Indicators;
|
||||
using QuantConnect.Securities;
|
||||
using Common.Data.Consolidators;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a rolling window of <see cref="SessionBar"/> with size 2,
|
||||
/// where [0] contains the current session values in progress (OHLCV + OpenInterest),
|
||||
/// and [1] contains the fully consolidated data of the previous trading day.
|
||||
/// </summary>
|
||||
public class Session : RollingWindow<SessionBar>, IBar
|
||||
{
|
||||
private readonly Symbol _symbol;
|
||||
private readonly TickType _tickType;
|
||||
private readonly SecurityExchangeHours _exchangeHours;
|
||||
private SessionConsolidator _consolidator;
|
||||
|
||||
/// <summary>
|
||||
/// Opening price of the session
|
||||
/// </summary>
|
||||
public decimal Open => _consolidator?.WorkingInstance.Open ?? 0;
|
||||
|
||||
/// <summary>
|
||||
/// High price of the session
|
||||
/// </summary>
|
||||
public decimal High => _consolidator?.WorkingInstance.High ?? 0;
|
||||
|
||||
/// <summary>
|
||||
/// Low price of the session
|
||||
/// </summary>
|
||||
public decimal Low => _consolidator?.WorkingInstance.Low ?? 0;
|
||||
|
||||
/// <summary>
|
||||
/// Closing price of the session
|
||||
/// </summary>
|
||||
public decimal Close => _consolidator?.WorkingInstance.Close ?? 0;
|
||||
|
||||
/// <summary>
|
||||
/// Volume traded during the session
|
||||
/// </summary>
|
||||
public decimal Volume => _consolidator?.WorkingInstance.Volume ?? 0;
|
||||
|
||||
/// <summary>
|
||||
/// Open Interest of the session
|
||||
/// </summary>
|
||||
public decimal OpenInterest => _consolidator?.WorkingInstance.OpenInterest ?? 0;
|
||||
|
||||
/// <summary>
|
||||
/// The symbol of the session
|
||||
/// </summary>
|
||||
public Symbol Symbol => _symbol;
|
||||
|
||||
/// <summary>
|
||||
/// The end time of the session
|
||||
/// </summary>
|
||||
public DateTime EndTime => _consolidator?.WorkingInstance.EndTime ?? default;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of this window
|
||||
/// </summary>
|
||||
public override int Size
|
||||
{
|
||||
set
|
||||
{
|
||||
base.Size = value;
|
||||
TryInitialize();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Session"/> class
|
||||
/// </summary>
|
||||
/// <param name="tickType">The tick type to use</param>
|
||||
/// <param name="exchangeHours">The exchange hours</param>
|
||||
/// <param name="symbol">The symbol</param>
|
||||
/// <param name="size">The number of items to hold</param>
|
||||
public Session(TickType tickType, SecurityExchangeHours exchangeHours, Symbol symbol, int size = 0)
|
||||
: base(size)
|
||||
{
|
||||
_symbol = symbol;
|
||||
_tickType = tickType;
|
||||
_exchangeHours = exchangeHours;
|
||||
TryInitialize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the session with new market data
|
||||
/// </summary>
|
||||
/// <param name="data">The new data to update the session with</param>
|
||||
public void Update(BaseData data)
|
||||
{
|
||||
_consolidator?.Update(data);
|
||||
}
|
||||
|
||||
private void OnConsolidated(object sender, IBaseData consolidated)
|
||||
{
|
||||
// Finished current trading day
|
||||
// Add the new working session bar at [0], this will shift the previous trading day's bar to [1]
|
||||
Add(_consolidator.WorkingInstance);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scans the consolidator to see if it should emit a bar due to time passing
|
||||
/// </summary>
|
||||
public void Scan(DateTime currentLocalTime)
|
||||
{
|
||||
// Delegates the scan decision to the underlying consolidator.
|
||||
_consolidator?.ValidateAndScan(currentLocalTime);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the session
|
||||
/// </summary>
|
||||
public override void Reset()
|
||||
{
|
||||
if (_consolidator != null)
|
||||
{
|
||||
base.Reset();
|
||||
_consolidator.Reset();
|
||||
// We need to add the working session bar at [0]
|
||||
Add(_consolidator.WorkingInstance);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a string representation of current session bar with OHLCV and OpenInterest values formatted.
|
||||
/// Example: "O: 101.00 H: 112.00 L: 95.00 C: 110.00 V: 1005.00 OI: 12"
|
||||
/// </summary>
|
||||
public override string ToString()
|
||||
{
|
||||
if (_consolidator != null)
|
||||
{
|
||||
return _consolidator.WorkingInstance.ToString();
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
private void TryInitialize()
|
||||
{
|
||||
if (base.Size > 0 && _consolidator == null)
|
||||
{
|
||||
_consolidator = new SessionConsolidator(_exchangeHours, _tickType, _symbol);
|
||||
_consolidator.DataConsolidated += OnConsolidated;
|
||||
Add(_consolidator.WorkingInstance);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains OHLCV data for a single session
|
||||
/// </summary>
|
||||
public class SessionBar : TradeBar
|
||||
{
|
||||
private DateTime _lastVolumeTime = DateTime.MinValue;
|
||||
private QuoteBar _bar;
|
||||
private readonly TickType _sourceTickType;
|
||||
|
||||
/// <summary>
|
||||
/// Open Interest:
|
||||
/// </summary>
|
||||
public decimal OpenInterest { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Opening price of the bar: Defined as the price at the start of the time period.
|
||||
/// </summary>
|
||||
public override decimal Open => _bar?.Open ?? 0m;
|
||||
|
||||
/// <summary>
|
||||
/// High price of the TradeBar during the time period.
|
||||
/// </summary>
|
||||
public override decimal High => _bar?.High ?? 0m;
|
||||
|
||||
/// <summary>
|
||||
/// Low price of the TradeBar during the time period.
|
||||
/// </summary>
|
||||
public override decimal Low => _bar?.Low ?? 0m;
|
||||
|
||||
/// <summary>
|
||||
/// Closing price of the TradeBar. Defined as the price at Start Time + TimeSpan.
|
||||
/// </summary>
|
||||
public override decimal Close => _bar?.Close ?? 0m;
|
||||
|
||||
/// <summary>
|
||||
/// The closing time of this bar, computed via the Time and Period
|
||||
/// </summary>
|
||||
public override DateTime EndTime
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Time == DateTime.MaxValue)
|
||||
{
|
||||
// Prevent overflow from Time + Period when Time is DateTime.MaxValue
|
||||
return Time;
|
||||
}
|
||||
|
||||
return base.EndTime;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The period of this session bar
|
||||
/// </summary>
|
||||
public override TimeSpan Period { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of SessionBar with default values
|
||||
/// </summary>
|
||||
public SessionBar()
|
||||
{
|
||||
Period = QuantConnect.Time.OneDay;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of SessionBar with a specific tick type
|
||||
/// </summary>
|
||||
public SessionBar(TickType sourceTickType)
|
||||
{
|
||||
_sourceTickType = sourceTickType;
|
||||
Period = QuantConnect.Time.OneDay;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the session bar with new market data and initializes the first bar if needed
|
||||
/// </summary>
|
||||
/// <param name="data">The new data to update the session with</param>
|
||||
/// <param name="consolidated">The current consolidated session bar</param>
|
||||
public void Update(BaseData data, IBaseData consolidated)
|
||||
{
|
||||
InitializeBar(data, consolidated);
|
||||
if (data.Time < _bar.Time)
|
||||
{
|
||||
// This will prevent overlapping
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.DataType == MarketDataType.TradeBar && data is TradeBar tradeBar)
|
||||
{
|
||||
if (_lastVolumeTime <= tradeBar.Time)
|
||||
{
|
||||
_lastVolumeTime = tradeBar.EndTime;
|
||||
Volume += tradeBar.Volume;
|
||||
}
|
||||
|
||||
if (_sourceTickType == TickType.Trade)
|
||||
{
|
||||
if (Initialized == 0)
|
||||
{
|
||||
Initialized = 1;
|
||||
_bar.Bid.Open = tradeBar.Open;
|
||||
}
|
||||
_bar.Bid.Close = tradeBar.Close;
|
||||
if (tradeBar.Low < _bar.Bid.Low) _bar.Bid.Low = tradeBar.Low;
|
||||
if (tradeBar.High > _bar.Bid.High) _bar.Bid.High = tradeBar.High;
|
||||
|
||||
_bar.Time = tradeBar.EndTime;
|
||||
}
|
||||
}
|
||||
else if (_sourceTickType == TickType.Quote && data.DataType == MarketDataType.QuoteBar)
|
||||
{
|
||||
var quoteBar = (QuoteBar)data;
|
||||
var bid = quoteBar.Bid;
|
||||
var ask = quoteBar.Ask;
|
||||
|
||||
// update the bid and ask
|
||||
if (bid != null)
|
||||
{
|
||||
if (_bar.Bid == null)
|
||||
{
|
||||
_bar.Bid = bid.Clone();
|
||||
}
|
||||
else
|
||||
{
|
||||
_bar.Bid.Close = bid.Close;
|
||||
if (_bar.Bid.High < bid.High) _bar.Bid.High = bid.High;
|
||||
if (_bar.Bid.Low > bid.Low) _bar.Bid.Low = bid.Low;
|
||||
}
|
||||
}
|
||||
if (ask != null)
|
||||
{
|
||||
if (_bar.Ask == null)
|
||||
{
|
||||
_bar.Ask = ask.Clone();
|
||||
}
|
||||
else
|
||||
{
|
||||
_bar.Ask.Close = ask.Close;
|
||||
if (_bar.Ask.High < ask.High) _bar.Ask.High = ask.High;
|
||||
if (_bar.Ask.Low > ask.Low) _bar.Ask.Low = ask.Low;
|
||||
}
|
||||
}
|
||||
|
||||
_bar.Value = data.Value;
|
||||
_bar.Time = data.EndTime;
|
||||
}
|
||||
else if (data.DataType == MarketDataType.Tick)
|
||||
{
|
||||
var tick = (Tick)data;
|
||||
if (_lastVolumeTime <= data.Time)
|
||||
{
|
||||
_lastVolumeTime = data.EndTime;
|
||||
Volume += tick.Quantity;
|
||||
}
|
||||
|
||||
// update the bid and ask
|
||||
if (_sourceTickType == tick.TickType)
|
||||
{
|
||||
if (tick.TickType == TickType.Trade)
|
||||
{
|
||||
if (Initialized == 0)
|
||||
{
|
||||
Initialized = 1;
|
||||
_bar.Bid.Open = tick.Value;
|
||||
}
|
||||
_bar.Bid.Close = tick.Value;
|
||||
if (tick.Value < _bar.Bid.Low) _bar.Bid.Low = tick.Value;
|
||||
if (tick.Value > _bar.Bid.High) _bar.Bid.High = tick.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
_bar.Update(decimal.Zero, tick.BidPrice, tick.AskPrice, decimal.Zero, tick.BidSize, tick.AskSize);
|
||||
}
|
||||
_bar.Time = data.EndTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeBar(BaseData data, IBaseData consolidated)
|
||||
{
|
||||
if (_bar == null)
|
||||
{
|
||||
_bar = new QuoteBar(data.Time.Date, data.Symbol, null, 0, null, 0, Period);
|
||||
if (_sourceTickType == TickType.Trade)
|
||||
{
|
||||
_bar.Bid = new Bar(0, 0, decimal.MaxValue, 0);
|
||||
}
|
||||
else if (consolidated != null)
|
||||
{
|
||||
var previousBar = ((SessionBar)consolidated)._bar;
|
||||
_bar.Update(decimal.Zero, previousBar?.Bid?.Close ?? decimal.Zero, previousBar?.Ask?.Close ?? decimal.Zero, decimal.Zero, decimal.Zero, decimal.Zero);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a string representation of the session bar with OHLCV and OpenInterest values formatted.
|
||||
/// Example: "O: 101.00 H: 112.00 L: 95.00 C: 110.00 V: 1005.00 OI: 12"
|
||||
/// </summary>
|
||||
public override string ToString()
|
||||
{
|
||||
return $"O: {Open.SmartRounding()} " +
|
||||
$"H: {High.SmartRounding()} " +
|
||||
$"L: {Low.SmartRounding()} " +
|
||||
$"C: {Close.SmartRounding()} " +
|
||||
$"V: {Volume.SmartRounding()} " +
|
||||
$"OI: {OpenInterest}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* 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 Newtonsoft.Json;
|
||||
using ProtoBuf;
|
||||
using static QuantConnect.StringExtensions;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Split event from a security
|
||||
/// </summary>
|
||||
[ProtoContract(SkipConstructor = true)]
|
||||
public class Split : BaseData
|
||||
{
|
||||
/// <summary>
|
||||
///Gets the type of split event, warning or split.
|
||||
/// </summary>
|
||||
[JsonProperty]
|
||||
[ProtoMember(10)]
|
||||
public SplitType Type
|
||||
{
|
||||
get; private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the split factor
|
||||
/// </summary>
|
||||
[JsonProperty]
|
||||
[ProtoMember(11)]
|
||||
public decimal SplitFactor
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the price at which the split occurred
|
||||
/// This is typically the previous day's closing price
|
||||
/// </summary>
|
||||
[ProtoMember(12)]
|
||||
public decimal ReferencePrice
|
||||
{
|
||||
get { return Value; }
|
||||
set { Value = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Split class
|
||||
/// </summary>
|
||||
public Split()
|
||||
{
|
||||
Type = SplitType.SplitOccurred;
|
||||
DataType = MarketDataType.Auxiliary;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Split class
|
||||
/// </summary>
|
||||
/// <param name="symbol">The symbol</param>
|
||||
/// <param name="date">The date</param>
|
||||
/// <param name="price">The price at the time of the split</param>
|
||||
/// <param name="splitFactor">The split factor to be applied to current holdings</param>
|
||||
/// <param name="type">The type of split event, warning or split occurred</param>
|
||||
public Split(Symbol symbol, DateTime date, decimal price, decimal splitFactor, SplitType type)
|
||||
: this()
|
||||
{
|
||||
Type = type;
|
||||
Time = date;
|
||||
Symbol = symbol;
|
||||
ReferencePrice = price;
|
||||
SplitFactor = splitFactor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reader converts each line of the data source into BaseData objects. Each data type creates its own factory method, and returns a new instance of the object
|
||||
/// each time it is called.
|
||||
/// </summary>
|
||||
/// <param name="config">Subscription data config setup object</param>
|
||||
/// <param name="line">Line of the source document</param>
|
||||
/// <param name="date">Date of the requested data</param>
|
||||
/// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param>
|
||||
/// <returns>Instance of the T:BaseData object generated by this line of the CSV</returns>
|
||||
public override BaseData Reader(SubscriptionDataConfig config, string line, DateTime date, bool isLiveMode)
|
||||
{
|
||||
// this is implemented in the SubscriptionDataReader.CheckForSplit
|
||||
throw new NotImplementedException("This method is not supposed to be called on the Split type.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the URL string source of the file. This will be converted to a stream
|
||||
/// </summary>
|
||||
/// <param name="config">Configuration object</param>
|
||||
/// <param name="date">Date of this source file</param>
|
||||
/// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param>
|
||||
/// <returns>String URL of source file.</returns>
|
||||
public override SubscriptionDataSource GetSource(SubscriptionDataConfig config, DateTime date, bool isLiveMode)
|
||||
{
|
||||
// this data is derived from map files and factor files in backtesting
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Formats a string with the symbol and value.
|
||||
/// </summary>
|
||||
/// <returns>string - a string formatted as SPY: 167.753</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
var type = Type == SplitType.Warning ? "Split Warning" : "Split";
|
||||
return Invariant($"{type}: {Symbol}: {SplitFactor} | {ReferencePrice}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a new instance clone of this object, used in fill forward
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This base implementation uses reflection to copy all public fields and properties
|
||||
/// </remarks>
|
||||
/// <returns>A clone of the current object</returns>
|
||||
public override BaseData Clone()
|
||||
{
|
||||
return new Split(Symbol, Time, Price, SplitFactor, Type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Collection of splits keyed by <see cref="Symbol"/>
|
||||
/// </summary>
|
||||
public class Splits : DataDictionary<Split>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Splits"/> dictionary
|
||||
/// </summary>
|
||||
public Splits()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Splits"/> dictionary
|
||||
/// </summary>
|
||||
/// <param name="frontier">The time associated with the data in this dictionary</param>
|
||||
public Splits(DateTime frontier)
|
||||
: base(frontier)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Symbol changed event of a security. This is generated when a symbol is remapped for a given
|
||||
/// security, for example, at EOD 2014.04.02 GOOG turned into GOOGL, but are the same
|
||||
/// </summary>
|
||||
public class SymbolChangedEvent : BaseData
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the symbol before the change
|
||||
/// </summary>
|
||||
public string OldSymbol { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the symbol after the change
|
||||
/// </summary>
|
||||
public string NewSymbol { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new default instance of the <see cref="SymbolChangedEvent"/> class
|
||||
/// </summary>
|
||||
public SymbolChangedEvent()
|
||||
{
|
||||
DataType = MarketDataType.Auxiliary;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SymbolChangedEvent"/>
|
||||
/// </summary>
|
||||
/// <param name="requestedSymbol">The symbol that was originally requested</param>
|
||||
/// <param name="date">The date/time this symbol remapping took place</param>
|
||||
/// <param name="oldSymbol">The old symbol mapping</param>
|
||||
/// <param name="newSymbol">The new symbol mapping</param>
|
||||
public SymbolChangedEvent(Symbol requestedSymbol, DateTime date, string oldSymbol, string newSymbol)
|
||||
: this()
|
||||
{
|
||||
Time = date;
|
||||
Symbol = requestedSymbol;
|
||||
OldSymbol = oldSymbol;
|
||||
NewSymbol = newSymbol;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the URL string source of the file. This will be converted to a stream
|
||||
/// </summary>
|
||||
/// <param name="config">Configuration object</param>
|
||||
/// <param name="date">Date of this source file</param>
|
||||
/// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param>
|
||||
/// <returns>String URL of source file.</returns>
|
||||
public override SubscriptionDataSource GetSource(SubscriptionDataConfig config, DateTime date, bool isLiveMode)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a new instance clone of this object, used in fill forward
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This base implementation uses reflection to copy all public fields and properties
|
||||
/// </remarks>
|
||||
/// <returns>A clone of the current object</returns>
|
||||
public override BaseData Clone()
|
||||
{
|
||||
return new SymbolChangedEvent(Symbol, Time, OldSymbol, NewSymbol);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Friendly string representation of this symbol changed event
|
||||
/// </summary>
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Time} {OldSymbol}->{NewSymbol}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Collection of <see cref="SymbolChangedEvent"/> keyed by the original, requested symbol
|
||||
/// </summary>
|
||||
public class SymbolChangedEvents : DataDictionary<SymbolChangedEvent>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SymbolChangedEvent"/> dictionary
|
||||
/// </summary>
|
||||
public SymbolChangedEvents()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SymbolChangedEvent"/> dictionary
|
||||
/// </summary>
|
||||
/// <param name="frontier">The time associated with the data in this dictionary</param>
|
||||
public SymbolChangedEvents(DateTime frontier)
|
||||
: base(frontier)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,855 @@
|
||||
/*
|
||||
* 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 ProtoBuf;
|
||||
using System.IO;
|
||||
using Newtonsoft.Json;
|
||||
using QuantConnect.Util;
|
||||
using QuantConnect.Logging;
|
||||
using System.Globalization;
|
||||
using System.Runtime.CompilerServices;
|
||||
using QuantConnect.Python;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Tick class is the base representation for tick data. It is grouped into a Ticks object
|
||||
/// which implements IDictionary and passed into an OnData event handler.
|
||||
/// </summary>
|
||||
[ProtoContract(SkipConstructor = true)]
|
||||
[ProtoInclude(1000, typeof(OpenInterest))]
|
||||
public class Tick : BaseData
|
||||
{
|
||||
private Exchange _exchange = QuantConnect.Exchange.UNKNOWN;
|
||||
private string _exchangeValue;
|
||||
private uint? _parsedSaleCondition;
|
||||
|
||||
/// <summary>
|
||||
/// Type of the Tick: Trade or Quote.
|
||||
/// </summary>
|
||||
[ProtoMember(10)]
|
||||
[PandasIgnore]
|
||||
public TickType TickType { get; set; } = TickType.Trade;
|
||||
|
||||
/// <summary>
|
||||
/// Quantity exchanged in a trade.
|
||||
/// </summary>
|
||||
[ProtoMember(11)]
|
||||
public decimal Quantity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Exchange code this tick came from <see cref="Exchanges"/>
|
||||
/// </summary>
|
||||
[PandasIgnore]
|
||||
public string ExchangeCode
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_exchange == null)
|
||||
{
|
||||
_exchange = Symbol != null
|
||||
? _exchangeValue.GetPrimaryExchange(Symbol.SecurityType, Symbol.ID.Market) : _exchangeValue.GetPrimaryExchange();
|
||||
}
|
||||
return _exchange.Code;
|
||||
}
|
||||
set
|
||||
{
|
||||
_exchangeValue = value;
|
||||
_exchange = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exchange name this tick came from <see cref="Exchanges"/>
|
||||
/// </summary>
|
||||
[ProtoMember(12)]
|
||||
public string Exchange
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_exchange == null)
|
||||
{
|
||||
_exchange = Symbol != null
|
||||
? _exchangeValue.GetPrimaryExchange(Symbol.SecurityType, Symbol.ID.Market) : _exchangeValue.GetPrimaryExchange();
|
||||
}
|
||||
return _exchange;
|
||||
}
|
||||
set
|
||||
{
|
||||
_exchangeValue = value;
|
||||
_exchange = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sale condition for the tick.
|
||||
/// </summary>
|
||||
[PandasIgnore]
|
||||
[ProtoMember(13)]
|
||||
public string SaleCondition { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// For performance parsed sale condition for the tick.
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[PandasIgnore]
|
||||
public uint ParsedSaleCondition
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(SaleCondition))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_parsedSaleCondition.HasValue)
|
||||
{
|
||||
_parsedSaleCondition = uint.Parse(SaleCondition, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
|
||||
}
|
||||
return _parsedSaleCondition.Value;
|
||||
}
|
||||
set
|
||||
{
|
||||
_parsedSaleCondition = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bool whether this is a suspicious tick
|
||||
/// </summary>
|
||||
[ProtoMember(14)]
|
||||
public bool Suspicious { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Bid Price for Tick
|
||||
/// </summary>
|
||||
[ProtoMember(15)]
|
||||
public decimal BidPrice { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Asking price for the Tick quote.
|
||||
/// </summary>
|
||||
[ProtoMember(16)]
|
||||
public decimal AskPrice { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Alias for "Value" - the last sale for this asset.
|
||||
/// </summary>
|
||||
public decimal LastPrice
|
||||
{
|
||||
get
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Size of bid quote.
|
||||
/// </summary>
|
||||
[ProtoMember(17)]
|
||||
public decimal BidSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Size of ask quote.
|
||||
/// </summary>
|
||||
[ProtoMember(18)]
|
||||
public decimal AskSize { get; set; }
|
||||
|
||||
//In Base Class: Alias of Closing:
|
||||
//public decimal Price;
|
||||
|
||||
//Symbol of Asset.
|
||||
//In Base Class: public Symbol Symbol;
|
||||
|
||||
//In Base Class: DateTime Of this TradeBar
|
||||
//public DateTime Time;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize tick class with a default constructor.
|
||||
/// </summary>
|
||||
public Tick()
|
||||
{
|
||||
Value = 0;
|
||||
Time = new DateTime();
|
||||
DataType = MarketDataType.Tick;
|
||||
Symbol = Symbol.Empty;
|
||||
TickType = TickType.Trade;
|
||||
Quantity = 0;
|
||||
_exchange = QuantConnect.Exchange.UNKNOWN;
|
||||
SaleCondition = string.Empty;
|
||||
Suspicious = false;
|
||||
BidSize = 0;
|
||||
AskSize = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cloner constructor for fill forward engine implementation. Clone the original tick into this new tick:
|
||||
/// </summary>
|
||||
/// <param name="original">Original tick we're cloning</param>
|
||||
public Tick(Tick original)
|
||||
{
|
||||
Symbol = original.Symbol;
|
||||
Time = new DateTime(original.Time.Ticks);
|
||||
Value = original.Value;
|
||||
BidPrice = original.BidPrice;
|
||||
AskPrice = original.AskPrice;
|
||||
// directly set privates so we don't parse the exchange
|
||||
_exchange = original._exchange;
|
||||
_exchangeValue = original._exchangeValue;
|
||||
SaleCondition = original.SaleCondition;
|
||||
_parsedSaleCondition = original._parsedSaleCondition;
|
||||
Quantity = original.Quantity;
|
||||
Suspicious = original.Suspicious;
|
||||
DataType = MarketDataType.Tick;
|
||||
TickType = original.TickType;
|
||||
BidSize = original.BidSize;
|
||||
AskSize = original.AskSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for a FOREX tick where there is no last sale price. The volume in FX is so high its rare to find FX trade data.
|
||||
/// To fake this the tick contains bid-ask prices and the last price is the midpoint.
|
||||
/// </summary>
|
||||
/// <param name="time">Full date and time</param>
|
||||
/// <param name="symbol">Underlying currency pair we're trading</param>
|
||||
/// <param name="bid">FX tick bid value</param>
|
||||
/// <param name="ask">FX tick ask value</param>
|
||||
public Tick(DateTime time, Symbol symbol, decimal bid, decimal ask)
|
||||
{
|
||||
DataType = MarketDataType.Tick;
|
||||
Time = time;
|
||||
Symbol = symbol;
|
||||
Value = (bid + ask) / 2;
|
||||
TickType = TickType.Quote;
|
||||
BidPrice = bid;
|
||||
AskPrice = ask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Tick"/> class to <see cref="TickType.OpenInterest"/>.
|
||||
/// </summary>
|
||||
/// <param name="time">The time at which the open interest tick occurred.</param>
|
||||
/// <param name="symbol">The symbol associated with the open interest tick.</param>
|
||||
/// <param name="openInterest">The value of the open interest for the specified symbol.</param>
|
||||
public Tick(DateTime time, Symbol symbol, decimal openInterest)
|
||||
{
|
||||
Time = time;
|
||||
Symbol = symbol;
|
||||
Value = openInterest;
|
||||
DataType = MarketDataType.Tick;
|
||||
TickType = TickType.OpenInterest;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializer for a last-trade equity tick with bid or ask prices.
|
||||
/// </summary>
|
||||
/// <param name="time">Full date and time</param>
|
||||
/// <param name="symbol">Underlying equity security symbol</param>
|
||||
/// <param name="bid">Bid value</param>
|
||||
/// <param name="ask">Ask value</param>
|
||||
/// <param name="last">Last trade price</param>
|
||||
public Tick(DateTime time, Symbol symbol, decimal last, decimal bid, decimal ask)
|
||||
{
|
||||
DataType = MarketDataType.Tick;
|
||||
Time = time;
|
||||
Symbol = symbol;
|
||||
Value = last;
|
||||
TickType = TickType.Quote;
|
||||
BidPrice = bid;
|
||||
AskPrice = ask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Trade tick type constructor
|
||||
/// </summary>
|
||||
/// <param name="time">Full date and time</param>
|
||||
/// <param name="symbol">Underlying equity security symbol</param>
|
||||
/// <param name="saleCondition">The ticks sale condition</param>
|
||||
/// <param name="exchange">The ticks exchange</param>
|
||||
/// <param name="quantity">The quantity traded</param>
|
||||
/// <param name="price">The price of the trade</param>
|
||||
public Tick(DateTime time, Symbol symbol, string saleCondition, string exchange, decimal quantity, decimal price)
|
||||
{
|
||||
Value = price;
|
||||
Time = time;
|
||||
DataType = MarketDataType.Tick;
|
||||
Symbol = symbol;
|
||||
TickType = TickType.Trade;
|
||||
Quantity = quantity;
|
||||
Exchange = exchange;
|
||||
SaleCondition = saleCondition;
|
||||
Suspicious = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Trade tick type constructor
|
||||
/// </summary>
|
||||
/// <param name="time">Full date and time</param>
|
||||
/// <param name="symbol">Underlying equity security symbol</param>
|
||||
/// <param name="saleCondition">The ticks sale condition</param>
|
||||
/// <param name="exchange">The ticks exchange</param>
|
||||
/// <param name="quantity">The quantity traded</param>
|
||||
/// <param name="price">The price of the trade</param>
|
||||
public Tick(DateTime time, Symbol symbol, string saleCondition, Exchange exchange, decimal quantity, decimal price)
|
||||
: this(time, symbol, saleCondition, string.Empty, quantity, price)
|
||||
{
|
||||
// we were giving the exchange, set it directly
|
||||
_exchange = exchange;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Quote tick type constructor
|
||||
/// </summary>
|
||||
/// <param name="time">Full date and time</param>
|
||||
/// <param name="symbol">Underlying equity security symbol</param>
|
||||
/// <param name="saleCondition">The ticks sale condition</param>
|
||||
/// <param name="exchange">The ticks exchange</param>
|
||||
/// <param name="bidSize">The bid size</param>
|
||||
/// <param name="bidPrice">The bid price</param>
|
||||
/// <param name="askSize">The ask size</param>
|
||||
/// <param name="askPrice">The ask price</param>
|
||||
public Tick(DateTime time, Symbol symbol, string saleCondition, string exchange, decimal bidSize, decimal bidPrice, decimal askSize, decimal askPrice)
|
||||
{
|
||||
Time = time;
|
||||
DataType = MarketDataType.Tick;
|
||||
Symbol = symbol;
|
||||
TickType = TickType.Quote;
|
||||
Exchange = exchange;
|
||||
SaleCondition = saleCondition;
|
||||
Suspicious = false;
|
||||
AskPrice = askPrice;
|
||||
AskSize = askSize;
|
||||
BidPrice = bidPrice;
|
||||
BidSize = bidSize;
|
||||
SetValue();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Quote tick type constructor
|
||||
/// </summary>
|
||||
/// <param name="time">Full date and time</param>
|
||||
/// <param name="symbol">Underlying equity security symbol</param>
|
||||
/// <param name="bidSize">The bid size</param>
|
||||
/// <param name="bidPrice">The bid price</param>
|
||||
/// <param name="askSize">The ask size</param>
|
||||
/// <param name="askPrice">The ask price</param>
|
||||
public Tick(DateTime time, Symbol symbol, decimal bidSize, decimal bidPrice, decimal askSize, decimal askPrice)
|
||||
: this(time, symbol, string.Empty, string.Empty, bidSize, bidPrice, askSize, askPrice)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Quote tick type constructor
|
||||
/// </summary>
|
||||
/// <param name="time">Full date and time</param>
|
||||
/// <param name="symbol">Underlying equity security symbol</param>
|
||||
/// <param name="saleCondition">The ticks sale condition</param>
|
||||
/// <param name="exchange">The ticks exchange</param>
|
||||
/// <param name="bidSize">The bid size</param>
|
||||
/// <param name="bidPrice">The bid price</param>
|
||||
/// <param name="askSize">The ask size</param>
|
||||
/// <param name="askPrice">The ask price</param>
|
||||
public Tick(DateTime time, Symbol symbol, string saleCondition, Exchange exchange, decimal bidSize, decimal bidPrice, decimal askSize, decimal askPrice)
|
||||
: this(time, symbol, saleCondition, string.Empty, bidSize, bidPrice, askSize, askPrice)
|
||||
{
|
||||
// we were giving the exchange, set it directly
|
||||
_exchange = exchange;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for QuantConnect FXCM Data source:
|
||||
/// </summary>
|
||||
/// <param name="symbol">Symbol for underlying asset</param>
|
||||
/// <param name="line">CSV line of data from FXCM</param>
|
||||
public Tick(Symbol symbol, string line)
|
||||
{
|
||||
var csv = line.Split(',');
|
||||
DataType = MarketDataType.Tick;
|
||||
Symbol = symbol;
|
||||
Time = DateTime.ParseExact(csv[0], DateFormat.Forex, CultureInfo.InvariantCulture);
|
||||
Value = (BidPrice + AskPrice) / 2;
|
||||
TickType = TickType.Quote;
|
||||
BidPrice = Convert.ToDecimal(csv[1], CultureInfo.InvariantCulture);
|
||||
AskPrice = Convert.ToDecimal(csv[2], CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for QuantConnect tick data
|
||||
/// </summary>
|
||||
/// <param name="symbol">Symbol for underlying asset</param>
|
||||
/// <param name="line">CSV line of data from QC tick csv</param>
|
||||
/// <param name="baseDate">The base date of the tick</param>
|
||||
public Tick(Symbol symbol, string line, DateTime baseDate)
|
||||
{
|
||||
var csv = line.Split(',');
|
||||
DataType = MarketDataType.Tick;
|
||||
Symbol = symbol;
|
||||
Time = baseDate.Date.AddTicks(Convert.ToInt64(10000 * csv[0].ToDecimal()));
|
||||
Value = csv[1].ToDecimal() / GetScaleFactor(symbol);
|
||||
TickType = TickType.Trade;
|
||||
Quantity = csv[2].ToDecimal();
|
||||
Exchange = csv[3].Trim();
|
||||
SaleCondition = csv[4];
|
||||
Suspicious = csv[5].ToInt32() == 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a tick data line from quantconnect zip source files.
|
||||
/// </summary>
|
||||
/// <param name="reader">The source stream reader</param>
|
||||
/// <param name="date">Base date for the tick (ticks date is stored as int milliseconds since midnight)</param>
|
||||
/// <param name="config">Subscription configuration object</param>
|
||||
public Tick(SubscriptionDataConfig config, StreamReader reader, DateTime date)
|
||||
{
|
||||
try
|
||||
{
|
||||
DataType = MarketDataType.Tick;
|
||||
Symbol = config.Symbol;
|
||||
|
||||
// Which security type is this data feed:
|
||||
var scaleFactor = GetScaleFactor(config.Symbol);
|
||||
|
||||
switch (config.SecurityType)
|
||||
{
|
||||
case SecurityType.Equity:
|
||||
{
|
||||
TickType = config.TickType;
|
||||
Time = date.Date.AddTicks(Convert.ToInt64(10000 * reader.GetDecimal())).ConvertTo(config.DataTimeZone, config.ExchangeTimeZone);
|
||||
|
||||
bool pastLineEnd;
|
||||
if (TickType == TickType.Trade)
|
||||
{
|
||||
Value = reader.GetDecimal() / scaleFactor;
|
||||
Quantity = reader.GetDecimal(out pastLineEnd);
|
||||
if (!pastLineEnd)
|
||||
{
|
||||
Exchange = reader.GetString();
|
||||
SaleCondition = reader.GetString();
|
||||
Suspicious = reader.GetInt32() == 1;
|
||||
}
|
||||
}
|
||||
else if (TickType == TickType.Quote)
|
||||
{
|
||||
BidPrice = reader.GetDecimal() / scaleFactor;
|
||||
BidSize = reader.GetDecimal();
|
||||
AskPrice = reader.GetDecimal() / scaleFactor;
|
||||
AskSize = reader.GetDecimal(out pastLineEnd);
|
||||
|
||||
SetValue();
|
||||
|
||||
if (!pastLineEnd)
|
||||
{
|
||||
Exchange = reader.GetString();
|
||||
SaleCondition = reader.GetString();
|
||||
Suspicious = reader.GetInt32() == 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException($"Tick(): Unexpected tick type {TickType}");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SecurityType.Forex:
|
||||
case SecurityType.Cfd:
|
||||
{
|
||||
TickType = TickType.Quote;
|
||||
Time = date.Date.AddTicks(Convert.ToInt64(10000 * reader.GetDecimal()))
|
||||
.ConvertTo(config.DataTimeZone, config.ExchangeTimeZone);
|
||||
BidPrice = reader.GetDecimal();
|
||||
AskPrice = reader.GetDecimal();
|
||||
|
||||
SetValue();
|
||||
break;
|
||||
}
|
||||
|
||||
case SecurityType.CryptoFuture:
|
||||
case SecurityType.Crypto:
|
||||
{
|
||||
TickType = config.TickType;
|
||||
Exchange = config.Market;
|
||||
Time = date.Date.AddTicks(Convert.ToInt64(10000 * reader.GetDecimal()))
|
||||
.ConvertTo(config.DataTimeZone, config.ExchangeTimeZone);
|
||||
|
||||
if (TickType == TickType.Trade)
|
||||
{
|
||||
Value = reader.GetDecimal();
|
||||
Quantity = reader.GetDecimal(out var endOfLine);
|
||||
Suspicious = !endOfLine && reader.GetInt32() == 1;
|
||||
}
|
||||
else if(TickType == TickType.Quote)
|
||||
{
|
||||
BidPrice = reader.GetDecimal();
|
||||
BidSize = reader.GetDecimal();
|
||||
AskPrice = reader.GetDecimal();
|
||||
AskSize = reader.GetDecimal(out var endOfLine);
|
||||
Suspicious = !endOfLine && reader.GetInt32() == 1;
|
||||
|
||||
SetValue();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SecurityType.Future:
|
||||
case SecurityType.Option:
|
||||
case SecurityType.FutureOption:
|
||||
case SecurityType.IndexOption:
|
||||
{
|
||||
TickType = config.TickType;
|
||||
Time = date.Date.AddTicks(Convert.ToInt64(10000 * reader.GetDecimal()))
|
||||
.ConvertTo(config.DataTimeZone, config.ExchangeTimeZone);
|
||||
|
||||
if (TickType == TickType.Trade)
|
||||
{
|
||||
Value = reader.GetDecimal() / scaleFactor;
|
||||
Quantity = reader.GetDecimal();
|
||||
Exchange = reader.GetString();
|
||||
SaleCondition = reader.GetString();
|
||||
Suspicious = reader.GetInt32() == 1;
|
||||
}
|
||||
else if (TickType == TickType.OpenInterest)
|
||||
{
|
||||
Value = reader.GetDecimal();
|
||||
}
|
||||
else
|
||||
{
|
||||
BidPrice = reader.GetDecimal() / scaleFactor;
|
||||
BidSize = reader.GetDecimal();
|
||||
AskPrice = reader.GetDecimal() / scaleFactor;
|
||||
AskSize = reader.GetDecimal();
|
||||
Exchange = reader.GetString();
|
||||
Suspicious = reader.GetInt32() == 1;
|
||||
|
||||
SetValue();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
Log.Error(err);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a tick data line from quantconnect zip source files.
|
||||
/// </summary>
|
||||
/// <param name="line">CSV source line of the compressed source</param>
|
||||
/// <param name="date">Base date for the tick (ticks date is stored as int milliseconds since midnight)</param>
|
||||
/// <param name="config">Subscription configuration object</param>
|
||||
public Tick(SubscriptionDataConfig config, string line, DateTime date)
|
||||
{
|
||||
try
|
||||
{
|
||||
DataType = MarketDataType.Tick;
|
||||
Symbol = config.Symbol;
|
||||
|
||||
// Which security type is this data feed:
|
||||
var scaleFactor = GetScaleFactor(config.Symbol);
|
||||
|
||||
switch (config.SecurityType)
|
||||
{
|
||||
case SecurityType.Equity:
|
||||
{
|
||||
var index = 0;
|
||||
TickType = config.TickType;
|
||||
var csv = line.ToCsv(TickType == TickType.Trade ? 6 : 8);
|
||||
Time = date.Date.AddTicks(Convert.ToInt64(10000 * csv[index++].ToDecimal())).ConvertTo(config.DataTimeZone, config.ExchangeTimeZone);
|
||||
|
||||
if (TickType == TickType.Trade)
|
||||
{
|
||||
Value = csv[index++].ToDecimal() / scaleFactor;
|
||||
Quantity = csv[index++].ToDecimal();
|
||||
if (csv.Count > index)
|
||||
{
|
||||
Exchange = csv[index++];
|
||||
SaleCondition = csv[index++];
|
||||
Suspicious = (csv[index++] == "1");
|
||||
}
|
||||
}
|
||||
else if (TickType == TickType.Quote)
|
||||
{
|
||||
BidPrice = csv[index++].ToDecimal() / scaleFactor;
|
||||
BidSize = csv[index++].ToDecimal();
|
||||
AskPrice = csv[index++].ToDecimal() / scaleFactor;
|
||||
AskSize = csv[index++].ToDecimal();
|
||||
|
||||
SetValue();
|
||||
|
||||
if (csv.Count > index)
|
||||
{
|
||||
Exchange = csv[index++];
|
||||
SaleCondition = csv[index++];
|
||||
Suspicious = (csv[index++] == "1");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException($"Tick(): Unexpected tick type {TickType}");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SecurityType.Forex:
|
||||
case SecurityType.Cfd:
|
||||
{
|
||||
var csv = line.ToCsv(3);
|
||||
TickType = TickType.Quote;
|
||||
var ticks = (long)(csv[0].ToDecimal() * TimeSpan.TicksPerMillisecond);
|
||||
Time = date.Date.AddTicks(ticks)
|
||||
.ConvertTo(config.DataTimeZone, config.ExchangeTimeZone);
|
||||
BidPrice = csv[1].ToDecimal();
|
||||
AskPrice = csv[2].ToDecimal();
|
||||
|
||||
SetValue();
|
||||
break;
|
||||
}
|
||||
|
||||
case SecurityType.Crypto:
|
||||
case SecurityType.CryptoFuture:
|
||||
{
|
||||
TickType = config.TickType;
|
||||
Exchange = config.Market;
|
||||
|
||||
if (TickType == TickType.Trade)
|
||||
{
|
||||
var csv = line.ToCsv(3);
|
||||
Time = date.Date.AddTicks(Convert.ToInt64(10000 * csv[0].ToDecimal()))
|
||||
.ConvertTo(config.DataTimeZone, config.ExchangeTimeZone);
|
||||
Value = csv[1].ToDecimal();
|
||||
Quantity = csv[2].ToDecimal();
|
||||
Suspicious = csv.Count >= 4 && csv[3] == "1";
|
||||
}
|
||||
|
||||
if (TickType == TickType.Quote)
|
||||
{
|
||||
var csv = line.ToCsv(6);
|
||||
Time = date.Date.AddTicks(Convert.ToInt64(10000 * csv[0].ToDecimal()))
|
||||
.ConvertTo(config.DataTimeZone, config.ExchangeTimeZone);
|
||||
BidPrice = csv[1].ToDecimal();
|
||||
BidSize = csv[2].ToDecimal();
|
||||
AskPrice = csv[3].ToDecimal();
|
||||
AskSize = csv[4].ToDecimal();
|
||||
Suspicious = csv.Count >= 6 && csv[5] == "1";
|
||||
|
||||
SetValue();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SecurityType.Future:
|
||||
case SecurityType.Option:
|
||||
case SecurityType.FutureOption:
|
||||
case SecurityType.IndexOption:
|
||||
{
|
||||
var csv = line.ToCsv(7);
|
||||
TickType = config.TickType;
|
||||
Time = date.Date.AddTicks(Convert.ToInt64(10000 * csv[0].ToDecimal()))
|
||||
.ConvertTo(config.DataTimeZone, config.ExchangeTimeZone);
|
||||
|
||||
if (TickType == TickType.Trade)
|
||||
{
|
||||
Value = csv[1].ToDecimal()/scaleFactor;
|
||||
Quantity = csv[2].ToDecimal();
|
||||
Exchange = csv[3];
|
||||
SaleCondition = csv[4];
|
||||
Suspicious = csv[5] == "1";
|
||||
}
|
||||
else if (TickType == TickType.OpenInterest)
|
||||
{
|
||||
Value = csv[1].ToDecimal();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (csv[1].Length != 0)
|
||||
{
|
||||
BidPrice = csv[1].ToDecimal()/scaleFactor;
|
||||
BidSize = csv[2].ToDecimal();
|
||||
}
|
||||
if (csv[3].Length != 0)
|
||||
{
|
||||
AskPrice = csv[3].ToDecimal()/scaleFactor;
|
||||
AskSize = csv[4].ToDecimal();
|
||||
}
|
||||
Exchange = csv[5];
|
||||
Suspicious = csv[6] == "1";
|
||||
|
||||
SetValue();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
Log.Error(err);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tick implementation of reader method: read a line of data from the source and convert it to a tick object.
|
||||
/// </summary>
|
||||
/// <param name="config">Subscription configuration object for algorithm</param>
|
||||
/// <param name="line">Line from the datafeed source</param>
|
||||
/// <param name="date">Date of this reader request</param>
|
||||
/// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param>
|
||||
/// <returns>New Initialized tick</returns>
|
||||
public override BaseData Reader(SubscriptionDataConfig config, string line, DateTime date, bool isLiveMode)
|
||||
{
|
||||
if (isLiveMode)
|
||||
{
|
||||
// currently ticks don't come through the reader function
|
||||
return new Tick();
|
||||
}
|
||||
|
||||
return new Tick(config, line, date);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tick implementation of reader method: read a line of data from the source and convert it to a tick object.
|
||||
/// </summary>
|
||||
/// <param name="config">Subscription configuration object for algorithm</param>
|
||||
/// <param name="stream">The source stream reader</param>
|
||||
/// <param name="date">Date of this reader request</param>
|
||||
/// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param>
|
||||
/// <returns>New Initialized tick</returns>
|
||||
[StubsIgnore]
|
||||
public override BaseData Reader(SubscriptionDataConfig config, StreamReader stream, DateTime date, bool isLiveMode)
|
||||
{
|
||||
if (isLiveMode)
|
||||
{
|
||||
// currently ticks don't come through the reader function
|
||||
return new Tick();
|
||||
}
|
||||
|
||||
return new Tick(config, stream, date);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get source for tick data feed - not used with QuantConnect data sources implementation.
|
||||
/// </summary>
|
||||
/// <param name="config">Configuration object</param>
|
||||
/// <param name="date">Date of this source request if source spread across multiple files</param>
|
||||
/// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param>
|
||||
/// <returns>String source location of the file to be opened with a stream</returns>
|
||||
public override SubscriptionDataSource GetSource(SubscriptionDataConfig config, DateTime date, bool isLiveMode)
|
||||
{
|
||||
if (isLiveMode)
|
||||
{
|
||||
// this data type is streamed in live mode
|
||||
return new SubscriptionDataSource(string.Empty, SubscriptionTransportMedium.Streaming);
|
||||
}
|
||||
|
||||
var source = LeanData.GenerateZipFilePath(Globals.DataFolder, config.Symbol, date, config.Resolution, config.TickType);
|
||||
if (config.SecurityType == SecurityType.Future || config.SecurityType.IsOption())
|
||||
{
|
||||
source += "#" + LeanData.GenerateZipEntryName(config.Symbol, date, config.Resolution, config.TickType);
|
||||
}
|
||||
return new SubscriptionDataSource(source, SubscriptionTransportMedium.LocalFile, FileFormat.Csv);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the tick price information - not used.
|
||||
/// </summary>
|
||||
/// <param name="lastTrade">This trade price</param>
|
||||
/// <param name="bidPrice">Current bid price</param>
|
||||
/// <param name="askPrice">Current asking price</param>
|
||||
/// <param name="volume">Volume of this trade</param>
|
||||
/// <param name="bidSize">The size of the current bid, if available</param>
|
||||
/// <param name="askSize">The size of the current ask, if available</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override void Update(decimal lastTrade, decimal bidPrice, decimal askPrice, decimal volume, decimal bidSize, decimal askSize)
|
||||
{
|
||||
Value = lastTrade;
|
||||
BidPrice = bidPrice;
|
||||
AskPrice = askPrice;
|
||||
BidSize = bidSize;
|
||||
AskSize = askSize;
|
||||
Quantity = Convert.ToDecimal(volume);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if tick contains valid data (either a trade, or a bid or ask)
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool IsValid()
|
||||
{
|
||||
// Indexes have zero volume in live trading, but is still a valid tick.
|
||||
return (TickType == TickType.Trade && (LastPrice > 0.0m && (Quantity > 0 || Symbol.SecurityType == SecurityType.Index))) ||
|
||||
(TickType == TickType.Quote && AskPrice > 0.0m && AskSize > 0) ||
|
||||
(TickType == TickType.Quote && BidPrice > 0.0m && BidSize > 0) ||
|
||||
(TickType == TickType.OpenInterest && Value > 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clone implementation for tick class:
|
||||
/// </summary>
|
||||
/// <returns>New tick object clone of the current class values.</returns>
|
||||
public override BaseData Clone()
|
||||
{
|
||||
return new Tick(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Formats a string with the symbol and value.
|
||||
/// </summary>
|
||||
/// <returns>string - a string formatted as SPY: 167.753</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
switch (TickType)
|
||||
{
|
||||
case TickType.Trade:
|
||||
return $"{Symbol}: Price: {Price} Quantity: {Quantity}";
|
||||
|
||||
case TickType.Quote:
|
||||
return $"{Symbol}: Bid: {BidSize}@{BidPrice} Ask: {AskSize}@{AskPrice}";
|
||||
|
||||
case TickType.OpenInterest:
|
||||
return $"{Symbol}: OpenInterest: {Value}";
|
||||
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the tick Value based on ask and bid price
|
||||
/// </summary>
|
||||
public void SetValue()
|
||||
{
|
||||
Value = BidPrice + AskPrice;
|
||||
if (BidPrice * AskPrice != 0)
|
||||
{
|
||||
Value /= 2m;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the scaling factor according to the <see cref="SecurityType"/> of the <see cref="Symbol"/> provided.
|
||||
/// Non-equity data will not be scaled, including options with an underlying non-equity asset class.
|
||||
/// </summary>
|
||||
/// <param name="symbol">Symbol to get scaling factor for</param>
|
||||
/// <returns>Scaling factor</returns>
|
||||
private static decimal GetScaleFactor(Symbol symbol)
|
||||
{
|
||||
return symbol.SecurityType == SecurityType.Equity || symbol.SecurityType == SecurityType.Option ? 10000m : 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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.Generic;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Ticks collection which implements an IDictionary-string-list of ticks. This way users can iterate over the string indexed ticks of the requested symbol.
|
||||
/// </summary>
|
||||
/// <remarks>Ticks are timestamped to the nearest second in QuantConnect</remarks>
|
||||
public class Ticks : DataDictionary<List<Tick>>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Ticks"/> dictionary
|
||||
/// </summary>
|
||||
public Ticks()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Ticks"/> dictionary
|
||||
/// </summary>
|
||||
/// <param name="frontier">The time associated with the data in this dictionary</param>
|
||||
public Ticks(DateTime frontier)
|
||||
: base(frontier)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,883 @@
|
||||
/*
|
||||
* 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 ProtoBuf;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using QuantConnect.Util;
|
||||
using System.Globalization;
|
||||
using QuantConnect.Logging;
|
||||
using static QuantConnect.StringExtensions;
|
||||
using QuantConnect.Python;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// TradeBar class for second and minute resolution data:
|
||||
/// An OHLC implementation of the QuantConnect BaseData class with parameters for candles.
|
||||
/// </summary>
|
||||
[ProtoContract(SkipConstructor = true)]
|
||||
public class TradeBar : BaseData, IBaseDataBar
|
||||
{
|
||||
// scale factor used in QC equity/forex data files
|
||||
private const decimal _scaleFactor = 1 / 10000m;
|
||||
|
||||
protected int Initialized;
|
||||
private decimal _open;
|
||||
private decimal _high;
|
||||
private decimal _low;
|
||||
|
||||
/// <summary>
|
||||
/// Volume:
|
||||
/// </summary>
|
||||
[ProtoMember(101)]
|
||||
public virtual decimal Volume { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Opening price of the bar: Defined as the price at the start of the time period.
|
||||
/// </summary>
|
||||
[ProtoMember(102)]
|
||||
public virtual decimal Open
|
||||
{
|
||||
get { return _open; }
|
||||
set
|
||||
{
|
||||
Initialize(value);
|
||||
_open = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// High price of the TradeBar during the time period.
|
||||
/// </summary>
|
||||
[ProtoMember(103)]
|
||||
public virtual decimal High
|
||||
{
|
||||
get { return _high; }
|
||||
set
|
||||
{
|
||||
Initialize(value);
|
||||
_high = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Low price of the TradeBar during the time period.
|
||||
/// </summary>
|
||||
[ProtoMember(104)]
|
||||
public virtual decimal Low
|
||||
{
|
||||
get { return _low; }
|
||||
set
|
||||
{
|
||||
Initialize(value);
|
||||
_low = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closing price of the TradeBar. Defined as the price at Start Time + TimeSpan.
|
||||
/// </summary>
|
||||
[ProtoMember(105)]
|
||||
public virtual decimal Close
|
||||
{
|
||||
get { return Value; }
|
||||
set
|
||||
{
|
||||
Initialize(value);
|
||||
Value = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The closing time of this bar, computed via the Time and Period
|
||||
/// </summary>
|
||||
[PandasIgnore]
|
||||
public override DateTime EndTime
|
||||
{
|
||||
get { return Time + Period; }
|
||||
set { Period = value - Time; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The period of this trade bar, (second, minute, daily, ect...)
|
||||
/// </summary>
|
||||
[ProtoMember(106)]
|
||||
[PandasIgnore]
|
||||
public virtual TimeSpan Period { get; set; }
|
||||
|
||||
//In Base Class: Alias of Closing:
|
||||
//public decimal Price;
|
||||
|
||||
//Symbol of Asset.
|
||||
//In Base Class: public Symbol Symbol;
|
||||
|
||||
//In Base Class: DateTime Of this TradeBar
|
||||
//public DateTime Time;
|
||||
|
||||
/// <summary>
|
||||
/// Default initializer to setup an empty tradebar.
|
||||
/// </summary>
|
||||
public TradeBar()
|
||||
{
|
||||
Symbol = Symbol.Empty;
|
||||
DataType = MarketDataType.TradeBar;
|
||||
Period = QuantConnect.Time.OneMinute;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cloner constructor for implementing fill forward.
|
||||
/// Return a new instance with the same values as this original.
|
||||
/// </summary>
|
||||
/// <param name="original">Original tradebar object we seek to clone</param>
|
||||
public TradeBar(TradeBar original)
|
||||
{
|
||||
DataType = MarketDataType.TradeBar;
|
||||
Time = new DateTime(original.Time.Ticks);
|
||||
Symbol = original.Symbol;
|
||||
Value = original.Close;
|
||||
Open = original.Open;
|
||||
High = original.High;
|
||||
Low = original.Low;
|
||||
Close = original.Close;
|
||||
Volume = original.Volume;
|
||||
Period = original.Period;
|
||||
Initialized = 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize Trade Bar with OHLC Values:
|
||||
/// </summary>
|
||||
/// <param name="time">DateTime Timestamp of the bar</param>
|
||||
/// <param name="symbol">Market MarketType Symbol</param>
|
||||
/// <param name="open">Decimal Opening Price</param>
|
||||
/// <param name="high">Decimal High Price of this bar</param>
|
||||
/// <param name="low">Decimal Low Price of this bar</param>
|
||||
/// <param name="close">Decimal Close price of this bar</param>
|
||||
/// <param name="volume">Volume sum over day</param>
|
||||
/// <param name="period">The period of this bar, specify null for default of 1 minute</param>
|
||||
public TradeBar(DateTime time, Symbol symbol, decimal open, decimal high, decimal low, decimal close, decimal volume, TimeSpan? period = null)
|
||||
{
|
||||
Time = time;
|
||||
Symbol = symbol;
|
||||
Value = close;
|
||||
Open = open;
|
||||
High = high;
|
||||
Low = low;
|
||||
Close = close;
|
||||
Volume = volume;
|
||||
Period = period ?? QuantConnect.Time.OneMinute;
|
||||
DataType = MarketDataType.TradeBar;
|
||||
Initialized = 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TradeBar Reader: Fetch the data from the QC storage and feed it line by line into the engine.
|
||||
/// </summary>
|
||||
/// <param name="config">Symbols, Resolution, DataType, </param>
|
||||
/// <param name="line">Line from the data file requested</param>
|
||||
/// <param name="date">Date of this reader request</param>
|
||||
/// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param>
|
||||
/// <returns>Enumerable iterator for returning each line of the required data.</returns>
|
||||
public override BaseData Reader(SubscriptionDataConfig config, string line, DateTime date, bool isLiveMode)
|
||||
{
|
||||
//Handle end of file:
|
||||
if (line == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isLiveMode)
|
||||
{
|
||||
return new TradeBar();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
switch (config.SecurityType)
|
||||
{
|
||||
//Equity File Data Format:
|
||||
case SecurityType.Equity:
|
||||
return ParseEquity(config, line, date);
|
||||
|
||||
//FOREX has a different data file format:
|
||||
case SecurityType.Forex:
|
||||
return ParseForex(config, line, date);
|
||||
|
||||
case SecurityType.Crypto:
|
||||
case SecurityType.CryptoFuture:
|
||||
return ParseCrypto(config, line, date);
|
||||
|
||||
case SecurityType.Cfd:
|
||||
return ParseCfd(config, line, date);
|
||||
|
||||
case SecurityType.Index:
|
||||
return ParseIndex(config, line, date);
|
||||
|
||||
case SecurityType.Option:
|
||||
case SecurityType.FutureOption:
|
||||
case SecurityType.IndexOption:
|
||||
return ParseOption(config, line, date);
|
||||
|
||||
case SecurityType.Future:
|
||||
return ParseFuture(config, line, date);
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
Log.Error(Invariant($"TradeBar.Reader(): Error parsing line: '{line}', Symbol: {config.Symbol.Value}, SecurityType: ") +
|
||||
Invariant($"{config.SecurityType}, Resolution: {config.Resolution}, Date: {date:yyyy-MM-dd}, Message: {err}")
|
||||
);
|
||||
}
|
||||
|
||||
// if we couldn't parse it above return a default instance
|
||||
return new TradeBar { Symbol = config.Symbol, Period = config.Increment };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TradeBar Reader: Fetch the data from the QC storage and feed it directly from the stream into the engine.
|
||||
/// </summary>
|
||||
/// <param name="config">Symbols, Resolution, DataType, </param>
|
||||
/// <param name="stream">The file data stream</param>
|
||||
/// <param name="date">Date of this reader request</param>
|
||||
/// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param>
|
||||
/// <returns>Enumerable iterator for returning each line of the required data.</returns>
|
||||
[StubsIgnore]
|
||||
public override BaseData Reader(SubscriptionDataConfig config, StreamReader stream, DateTime date, bool isLiveMode)
|
||||
{
|
||||
//Handle end of file:
|
||||
if (stream == null || stream.EndOfStream)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (isLiveMode)
|
||||
{
|
||||
return new TradeBar();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
switch (config.SecurityType)
|
||||
{
|
||||
//Equity File Data Format:
|
||||
case SecurityType.Equity:
|
||||
return ParseEquity(config, stream, date);
|
||||
|
||||
//FOREX has a different data file format:
|
||||
case SecurityType.Forex:
|
||||
return ParseForex(config, stream, date);
|
||||
|
||||
case SecurityType.Crypto:
|
||||
case SecurityType.CryptoFuture:
|
||||
return ParseCrypto(config, stream, date);
|
||||
|
||||
case SecurityType.Index:
|
||||
return ParseIndex(config, stream, date);
|
||||
|
||||
case SecurityType.Cfd:
|
||||
return ParseCfd(config, stream, date);
|
||||
|
||||
case SecurityType.Option:
|
||||
case SecurityType.FutureOption:
|
||||
case SecurityType.IndexOption:
|
||||
return ParseOption(config, stream, date);
|
||||
|
||||
case SecurityType.Future:
|
||||
return ParseFuture(config, stream, date);
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
Log.Error(Invariant($"TradeBar.Reader(): Error parsing stream, Symbol: {config.Symbol.Value}, SecurityType: ") +
|
||||
Invariant($"{config.SecurityType}, Resolution: {config.Resolution}, Date: {date:yyyy-MM-dd}, Message: {err}")
|
||||
);
|
||||
}
|
||||
|
||||
// we need to consume a line anyway, to advance the stream
|
||||
stream.ReadLine();
|
||||
|
||||
// if we couldn't parse it above return a default instance
|
||||
return new TradeBar { Symbol = config.Symbol, Period = config.Increment };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses the trade bar data line assuming QC data formats
|
||||
/// </summary>
|
||||
public static TradeBar Parse(SubscriptionDataConfig config, string line, DateTime baseDate)
|
||||
{
|
||||
switch (config.SecurityType)
|
||||
{
|
||||
case SecurityType.Equity:
|
||||
return ParseEquity(config, line, baseDate);
|
||||
|
||||
case SecurityType.Forex:
|
||||
case SecurityType.Crypto:
|
||||
case SecurityType.CryptoFuture:
|
||||
return ParseForex(config, line, baseDate);
|
||||
|
||||
case SecurityType.Cfd:
|
||||
return ParseCfd(config, line, baseDate);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses equity trade bar data into the specified tradebar type, useful for custom types with OHLCV data deriving from TradeBar
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The requested output type, must derive from TradeBar</typeparam>
|
||||
/// <param name="config">Symbols, Resolution, DataType, </param>
|
||||
/// <param name="line">Line from the data file requested</param>
|
||||
/// <param name="date">Date of this reader request</param>
|
||||
/// <returns></returns>
|
||||
public static T ParseEquity<T>(SubscriptionDataConfig config, string line, DateTime date)
|
||||
where T : TradeBar, new()
|
||||
{
|
||||
var tradeBar = new T
|
||||
{
|
||||
Symbol = config.Symbol,
|
||||
Period = config.Increment
|
||||
};
|
||||
|
||||
ParseEquity(tradeBar, config, line, date);
|
||||
|
||||
return tradeBar;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses equity trade bar data into the specified tradebar type, useful for custom types with OHLCV data deriving from TradeBar
|
||||
/// </summary>
|
||||
/// <param name="config">Symbols, Resolution, DataType, </param>
|
||||
/// <param name="streamReader">The data stream of the requested file</param>
|
||||
/// <param name="date">Date of this reader request</param>
|
||||
/// <returns></returns>
|
||||
public static TradeBar ParseEquity(SubscriptionDataConfig config, StreamReader streamReader, DateTime date)
|
||||
{
|
||||
var tradeBar = new TradeBar
|
||||
{
|
||||
Symbol = config.Symbol,
|
||||
Period = config.Increment
|
||||
};
|
||||
StreamParseScale(config, streamReader, date, useScaleFactor: true, tradeBar, true);
|
||||
|
||||
return tradeBar;
|
||||
}
|
||||
|
||||
private static void ParseEquity(TradeBar tradeBar, SubscriptionDataConfig config, string line, DateTime date)
|
||||
{
|
||||
LineParseScale(config, line, date, useScaleFactor: true, tradeBar, hasVolume: true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses equity trade bar data into the specified tradebar type, useful for custom types with OHLCV data deriving from TradeBar
|
||||
/// </summary>
|
||||
/// <param name="config">Symbols, Resolution, DataType, </param>
|
||||
/// <param name="line">Line from the data file requested</param>
|
||||
/// <param name="date">Date of this reader request</param>
|
||||
/// <returns></returns>
|
||||
public static TradeBar ParseEquity(SubscriptionDataConfig config, string line, DateTime date)
|
||||
{
|
||||
var tradeBar = new TradeBar
|
||||
{
|
||||
Symbol = config.Symbol,
|
||||
Period = config.Increment
|
||||
};
|
||||
ParseEquity(tradeBar, config, line, date);
|
||||
return tradeBar;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses forex trade bar data into the specified tradebar type, useful for custom types with OHLCV data deriving from TradeBar
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The requested output type, must derive from TradeBar</typeparam>
|
||||
/// <param name="config">Symbols, Resolution, DataType, </param>
|
||||
/// <param name="line">Line from the data file requested</param>
|
||||
/// <param name="date">The base data used to compute the time of the bar since the line specifies a milliseconds since midnight</param>
|
||||
/// <returns></returns>
|
||||
public static T ParseForex<T>(SubscriptionDataConfig config, string line, DateTime date)
|
||||
where T : TradeBar, new()
|
||||
{
|
||||
var tradeBar = new T
|
||||
{
|
||||
Symbol = config.Symbol,
|
||||
Period = config.Increment
|
||||
};
|
||||
LineParseNoScale(config, line, date, tradeBar, hasVolume: false);
|
||||
|
||||
return tradeBar;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses crypto trade bar data into the specified tradebar type, useful for custom types with OHLCV data deriving from TradeBar
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The requested output type, must derive from TradeBar</typeparam>
|
||||
/// <param name="config">Symbols, Resolution, DataType, </param>
|
||||
/// <param name="line">Line from the data file requested</param>
|
||||
/// <param name="date">The base data used to compute the time of the bar since the line specifies a milliseconds since midnight</param>
|
||||
public static T ParseCrypto<T>(SubscriptionDataConfig config, string line, DateTime date)
|
||||
where T : TradeBar, new()
|
||||
{
|
||||
var tradeBar = new T
|
||||
{
|
||||
Symbol = config.Symbol,
|
||||
Period = config.Increment
|
||||
};
|
||||
LineParseNoScale(config, line, date, tradeBar);
|
||||
|
||||
return tradeBar;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses crypto trade bar data into the specified tradebar type, useful for custom types with OHLCV data deriving from TradeBar
|
||||
/// </summary>
|
||||
/// <param name="config">Symbols, Resolution, DataType, </param>
|
||||
/// <param name="line">Line from the data file requested</param>
|
||||
/// <param name="date">The base data used to compute the time of the bar since the line specifies a milliseconds since midnight</param>
|
||||
public static TradeBar ParseCrypto(SubscriptionDataConfig config, string line, DateTime date)
|
||||
{
|
||||
return LineParseNoScale(config, line, date);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses crypto trade bar data into the specified tradebar type, useful for custom types with OHLCV data deriving from TradeBar
|
||||
/// </summary>
|
||||
/// <param name="config">Symbols, Resolution, DataType, </param>
|
||||
/// <param name="streamReader">The data stream of the requested file</param>
|
||||
/// <param name="date">The base data used to compute the time of the bar since the line specifies a milliseconds since midnight</param>
|
||||
public static TradeBar ParseCrypto(SubscriptionDataConfig config, StreamReader streamReader, DateTime date)
|
||||
{
|
||||
return StreamParseNoScale(config, streamReader, date);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses forex trade bar data into the specified tradebar type, useful for custom types with OHLCV data deriving from TradeBar
|
||||
/// </summary>
|
||||
/// <param name="config">Symbols, Resolution, DataType, </param>
|
||||
/// <param name="line">Line from the data file requested</param>
|
||||
/// <param name="date">The base data used to compute the time of the bar since the line specifies a milliseconds since midnight</param>
|
||||
/// <returns></returns>
|
||||
public static TradeBar ParseForex(SubscriptionDataConfig config, string line, DateTime date)
|
||||
{
|
||||
return LineParseNoScale(config, line, date, hasVolume: false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses forex trade bar data into the specified tradebar type, useful for custom types with OHLCV data deriving from TradeBar
|
||||
/// </summary>
|
||||
/// <param name="config">Symbols, Resolution, DataType, </param>
|
||||
/// <param name="streamReader">The data stream of the requested file</param>
|
||||
/// <param name="date">The base data used to compute the time of the bar since the line specifies a milliseconds since midnight</param>
|
||||
/// <returns></returns>
|
||||
public static TradeBar ParseForex(SubscriptionDataConfig config, StreamReader streamReader, DateTime date)
|
||||
{
|
||||
return StreamParseNoScale(config, streamReader, date, hasVolume: false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses CFD trade bar data into the specified tradebar type, useful for custom types with OHLCV data deriving from TradeBar
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The requested output type, must derive from TradeBar</typeparam>
|
||||
/// <param name="config">Symbols, Resolution, DataType, </param>
|
||||
/// <param name="line">Line from the data file requested</param>
|
||||
/// <param name="date">The base data used to compute the time of the bar since the line specifies a milliseconds since midnight</param>
|
||||
/// <returns></returns>
|
||||
public static T ParseCfd<T>(SubscriptionDataConfig config, string line, DateTime date)
|
||||
where T : TradeBar, new()
|
||||
{
|
||||
// CFD has the same data format as Forex
|
||||
return ParseForex<T>(config, line, date);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses CFD trade bar data into the specified tradebar type, useful for custom types with OHLCV data deriving from TradeBar
|
||||
/// </summary>
|
||||
/// <param name="config">Symbols, Resolution, DataType, </param>
|
||||
/// <param name="line">Line from the data file requested</param>
|
||||
/// <param name="date">The base data used to compute the time of the bar since the line specifies a milliseconds since midnight</param>
|
||||
/// <returns></returns>
|
||||
public static TradeBar ParseCfd(SubscriptionDataConfig config, string line, DateTime date)
|
||||
{
|
||||
// CFD has the same data format as Forex
|
||||
return ParseForex(config, line, date);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses CFD trade bar data into the specified tradebar type, useful for custom types with OHLCV data deriving from TradeBar
|
||||
/// </summary>
|
||||
/// <param name="config">Symbols, Resolution, DataType, </param>
|
||||
/// <param name="streamReader">The data stream of the requested file</param>
|
||||
/// <param name="date">The base data used to compute the time of the bar since the line specifies a milliseconds since midnight</param>
|
||||
/// <returns></returns>
|
||||
public static TradeBar ParseCfd(SubscriptionDataConfig config, StreamReader streamReader, DateTime date)
|
||||
{
|
||||
// CFD has the same data format as Forex
|
||||
return ParseForex(config, streamReader, date);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses Option trade bar data into the specified tradebar type, useful for custom types with OHLCV data deriving from TradeBar
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The requested output type, must derive from TradeBar</typeparam>
|
||||
/// <param name="config">Symbols, Resolution, DataType, </param>
|
||||
/// <param name="line">Line from the data file requested</param>
|
||||
/// <param name="date">The base data used to compute the time of the bar since the line specifies a milliseconds since midnight</param>
|
||||
/// <returns></returns>
|
||||
public static T ParseOption<T>(SubscriptionDataConfig config, string line, DateTime date)
|
||||
where T : TradeBar, new()
|
||||
{
|
||||
var tradeBar = new T
|
||||
{
|
||||
Period = config.Increment,
|
||||
Symbol = config.Symbol
|
||||
};
|
||||
LineParseScale(config, line, date, useScaleFactor: LeanData.OptionUseScaleFactor(config.Symbol), tradeBar, hasVolume: true);
|
||||
|
||||
return tradeBar;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses Option trade bar data into the specified tradebar type, useful for custom types with OHLCV data deriving from TradeBar
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The requested output type, must derive from TradeBar</typeparam>
|
||||
/// <param name="config">Symbols, Resolution, DataType, </param>
|
||||
/// <param name="streamReader">The data stream of the requested file</param>
|
||||
/// <param name="date">The base data used to compute the time of the bar since the line specifies a milliseconds since midnight</param>
|
||||
/// <returns></returns>
|
||||
public static T ParseOption<T>(SubscriptionDataConfig config, StreamReader streamReader, DateTime date)
|
||||
where T : TradeBar, new()
|
||||
{
|
||||
var tradeBar = new T
|
||||
{
|
||||
Period = config.Increment,
|
||||
Symbol = config.Symbol
|
||||
};
|
||||
StreamParseScale(config, streamReader, date, useScaleFactor: LeanData.OptionUseScaleFactor(config.Symbol), tradeBar, true);
|
||||
|
||||
return tradeBar;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses Future trade bar data into the specified tradebar type, useful for custom types with OHLCV data deriving from TradeBar
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The requested output type, must derive from TradeBar</typeparam>
|
||||
/// <param name="config">Symbols, Resolution, DataType, </param>
|
||||
/// <param name="streamReader">The data stream of the requested file</param>
|
||||
/// <param name="date">The base data used to compute the time of the bar since the line specifies a milliseconds since midnight</param>
|
||||
/// <returns></returns>
|
||||
public static T ParseFuture<T>(SubscriptionDataConfig config, StreamReader streamReader, DateTime date)
|
||||
where T : TradeBar, new()
|
||||
{
|
||||
var tradeBar = new T
|
||||
{
|
||||
Period = config.Increment,
|
||||
Symbol = config.Symbol
|
||||
};
|
||||
StreamParseNoScale(config, streamReader, date, tradeBar);
|
||||
|
||||
return tradeBar;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses Future trade bar data into the specified tradebar type, useful for custom types with OHLCV data deriving from TradeBar
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The requested output type, must derive from TradeBar</typeparam>
|
||||
/// <param name="config">Symbols, Resolution, DataType, </param>
|
||||
/// <param name="line">Line from the data file requested</param>
|
||||
/// <param name="date">The base data used to compute the time of the bar since the line specifies a milliseconds since midnight</param>
|
||||
/// <returns></returns>
|
||||
public static T ParseFuture<T>(SubscriptionDataConfig config, string line, DateTime date)
|
||||
where T : TradeBar, new()
|
||||
{
|
||||
var tradeBar = new T
|
||||
{
|
||||
Period = config.Increment,
|
||||
Symbol = config.Symbol
|
||||
};
|
||||
LineParseNoScale(config, line, date, tradeBar);
|
||||
|
||||
return tradeBar;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse an index bar from the LEAN disk format
|
||||
/// </summary>
|
||||
public static TradeBar ParseIndex(SubscriptionDataConfig config, string line, DateTime date)
|
||||
{
|
||||
return LineParseNoScale(config, line, date);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse an index bar from the LEAN disk format
|
||||
/// </summary>
|
||||
private static TradeBar LineParseNoScale(SubscriptionDataConfig config, string line, DateTime date, TradeBar bar = null, bool hasVolume = true)
|
||||
{
|
||||
var tradeBar = bar ?? new TradeBar
|
||||
{
|
||||
Period = config.Increment,
|
||||
Symbol = config.Symbol
|
||||
};
|
||||
|
||||
var csv = line.ToCsv(hasVolume ? 6 : 5);
|
||||
if (config.Resolution == Resolution.Daily || config.Resolution == Resolution.Hour)
|
||||
{
|
||||
// hourly and daily have different time format, and can use slow, robust c# parser.
|
||||
tradeBar.Time = DateTime.ParseExact(csv[0], DateFormat.TwelveCharacter, CultureInfo.InvariantCulture).ConvertTo(config.DataTimeZone, config.ExchangeTimeZone);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Using custom "ToDecimal" conversion for speed on high resolution data.
|
||||
tradeBar.Time = date.Date.AddMilliseconds(csv[0].ToInt32()).ConvertTo(config.DataTimeZone, config.ExchangeTimeZone);
|
||||
}
|
||||
tradeBar.Open = csv[1].ToDecimal();
|
||||
tradeBar.High = csv[2].ToDecimal();
|
||||
tradeBar.Low = csv[3].ToDecimal();
|
||||
tradeBar.Close = csv[4].ToDecimal();
|
||||
if (hasVolume)
|
||||
{
|
||||
tradeBar.Volume = csv[5].ToDecimal();
|
||||
}
|
||||
return tradeBar;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse an index bar from the LEAN disk format
|
||||
/// </summary>
|
||||
private static TradeBar StreamParseNoScale(SubscriptionDataConfig config, StreamReader streamReader, DateTime date, TradeBar bar = null, bool hasVolume = true)
|
||||
{
|
||||
var tradeBar = bar ?? new TradeBar
|
||||
{
|
||||
Period = config.Increment,
|
||||
Symbol = config.Symbol
|
||||
};
|
||||
|
||||
if (config.Resolution == Resolution.Daily || config.Resolution == Resolution.Hour)
|
||||
{
|
||||
// hourly and daily have different time format, and can use slow, robust c# parser.
|
||||
tradeBar.Time = streamReader.GetDateTime().ConvertTo(config.DataTimeZone, config.ExchangeTimeZone);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Using custom "ToDecimal" conversion for speed on high resolution data.
|
||||
tradeBar.Time = date.Date.AddMilliseconds(streamReader.GetInt32()).ConvertTo(config.DataTimeZone, config.ExchangeTimeZone);
|
||||
}
|
||||
tradeBar.Open = streamReader.GetDecimal();
|
||||
tradeBar.High = streamReader.GetDecimal();
|
||||
tradeBar.Low = streamReader.GetDecimal();
|
||||
tradeBar.Close = streamReader.GetDecimal();
|
||||
if (hasVolume)
|
||||
{
|
||||
tradeBar.Volume = streamReader.GetDecimal();
|
||||
}
|
||||
return tradeBar;
|
||||
}
|
||||
|
||||
private static TradeBar LineParseScale(SubscriptionDataConfig config, string line, DateTime date, bool useScaleFactor, TradeBar bar = null, bool hasVolume = true)
|
||||
{
|
||||
var tradeBar = bar ?? new TradeBar
|
||||
{
|
||||
Period = config.Increment,
|
||||
Symbol = config.Symbol
|
||||
};
|
||||
|
||||
LineParseNoScale(config, line, date, tradeBar, hasVolume);
|
||||
if (useScaleFactor)
|
||||
{
|
||||
tradeBar.Open *= _scaleFactor;
|
||||
tradeBar.High *= _scaleFactor;
|
||||
tradeBar.Low *= _scaleFactor;
|
||||
tradeBar.Close *= _scaleFactor;
|
||||
}
|
||||
|
||||
return tradeBar;
|
||||
}
|
||||
|
||||
private static TradeBar StreamParseScale(SubscriptionDataConfig config, StreamReader streamReader, DateTime date, bool useScaleFactor, TradeBar bar = null, bool hasVolume = true)
|
||||
{
|
||||
var tradeBar = bar ?? new TradeBar
|
||||
{
|
||||
Period = config.Increment,
|
||||
Symbol = config.Symbol
|
||||
};
|
||||
|
||||
StreamParseNoScale(config, streamReader, date, tradeBar, hasVolume);
|
||||
if (useScaleFactor)
|
||||
{
|
||||
tradeBar.Open *= _scaleFactor;
|
||||
tradeBar.High *= _scaleFactor;
|
||||
tradeBar.Low *= _scaleFactor;
|
||||
tradeBar.Close *= _scaleFactor;
|
||||
}
|
||||
|
||||
return tradeBar;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse an index bar from the LEAN disk format
|
||||
/// </summary>
|
||||
public static TradeBar ParseIndex(SubscriptionDataConfig config, StreamReader streamReader, DateTime date)
|
||||
{
|
||||
return StreamParseNoScale(config, streamReader, date);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses Option trade bar data into the specified tradebar type, useful for custom types with OHLCV data deriving from TradeBar
|
||||
/// </summary>
|
||||
/// <param name="config">Symbols, Resolution, DataType, </param>
|
||||
/// <param name="line">Line from the data file requested</param>
|
||||
/// <param name="date">The base data used to compute the time of the bar since the line specifies a milliseconds since midnight</param>
|
||||
/// <returns></returns>
|
||||
public static TradeBar ParseOption(SubscriptionDataConfig config, string line, DateTime date)
|
||||
{
|
||||
return ParseOption<TradeBar>(config, line, date);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses Option trade bar data into the specified tradebar type, useful for custom types with OHLCV data deriving from TradeBar
|
||||
/// </summary>
|
||||
/// <param name="config">Symbols, Resolution, DataType, </param>
|
||||
/// <param name="streamReader">The data stream of the requested file</param>
|
||||
/// <param name="date">The base data used to compute the time of the bar since the line specifies a milliseconds since midnight</param>
|
||||
/// <returns></returns>
|
||||
public static TradeBar ParseOption(SubscriptionDataConfig config, StreamReader streamReader, DateTime date)
|
||||
{
|
||||
return ParseOption<TradeBar>(config, streamReader, date);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses Future trade bar data into the specified tradebar type, useful for custom types with OHLCV data deriving from TradeBar
|
||||
/// </summary>
|
||||
/// <param name="config">Symbols, Resolution, DataType, </param>
|
||||
/// <param name="line">Line from the data file requested</param>
|
||||
/// <param name="date">The base data used to compute the time of the bar since the line specifies a milliseconds since midnight</param>
|
||||
/// <returns></returns>
|
||||
public static TradeBar ParseFuture(SubscriptionDataConfig config, string line, DateTime date)
|
||||
{
|
||||
return ParseFuture<TradeBar>(config, line, date);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses Future trade bar data into the specified tradebar type, useful for custom types with OHLCV data deriving from TradeBar
|
||||
/// </summary>
|
||||
/// <param name="config">Symbols, Resolution, DataType, </param>
|
||||
/// <param name="streamReader">The data stream of the requested file</param>
|
||||
/// <param name="date">The base data used to compute the time of the bar since the line specifies a milliseconds since midnight</param>
|
||||
/// <returns></returns>
|
||||
public static TradeBar ParseFuture(SubscriptionDataConfig config, StreamReader streamReader, DateTime date)
|
||||
{
|
||||
return ParseFuture<TradeBar>(config, streamReader, date);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the tradebar - build the bar from this pricing information:
|
||||
/// </summary>
|
||||
/// <param name="lastTrade">This trade price</param>
|
||||
/// <param name="bidPrice">Current bid price (not used) </param>
|
||||
/// <param name="askPrice">Current asking price (not used) </param>
|
||||
/// <param name="volume">Volume of this trade</param>
|
||||
/// <param name="bidSize">The size of the current bid, if available</param>
|
||||
/// <param name="askSize">The size of the current ask, if available</param>
|
||||
public override void Update(decimal lastTrade, decimal bidPrice, decimal askPrice, decimal volume, decimal bidSize, decimal askSize)
|
||||
{
|
||||
Initialize(lastTrade);
|
||||
if (lastTrade > High) High = lastTrade;
|
||||
if (lastTrade < Low) Low = lastTrade;
|
||||
//Volume is the total summed volume of trades in this bar:
|
||||
Volume += volume;
|
||||
//Always set the closing price;
|
||||
Close = lastTrade;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get Source for Custom Data File
|
||||
/// >> What source file location would you prefer for each type of usage:
|
||||
/// </summary>
|
||||
/// <param name="config">Configuration object</param>
|
||||
/// <param name="date">Date of this source request if source spread across multiple files</param>
|
||||
/// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param>
|
||||
/// <returns>String source location of the file</returns>
|
||||
public override SubscriptionDataSource GetSource(SubscriptionDataConfig config, DateTime date, bool isLiveMode)
|
||||
{
|
||||
if (isLiveMode)
|
||||
{
|
||||
// this data type is streamed in live mode
|
||||
return new SubscriptionDataSource(string.Empty, SubscriptionTransportMedium.Streaming);
|
||||
}
|
||||
|
||||
var source = LeanData.GenerateZipFilePath(Globals.DataFolder, config.Symbol, date, config.Resolution, config.TickType);
|
||||
if (config.SecurityType == SecurityType.Future || config.SecurityType.IsOption())
|
||||
{
|
||||
source += "#" + LeanData.GenerateZipEntryName(config.Symbol, date, config.Resolution, config.TickType);
|
||||
}
|
||||
return new SubscriptionDataSource(source, SubscriptionTransportMedium.LocalFile, FileFormat.Csv);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a new instance clone of this object, used in fill forward
|
||||
/// </summary>
|
||||
/// <param name="fillForward">True if this is a fill forward clone</param>
|
||||
/// <returns>A clone of the current object</returns>
|
||||
public override BaseData Clone(bool fillForward)
|
||||
{
|
||||
var clone = base.Clone(fillForward);
|
||||
|
||||
if (fillForward)
|
||||
{
|
||||
// zero volume out, since it would skew calculations in volume-based indicators
|
||||
((TradeBar)clone).Volume = 0;
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a new instance clone of this object
|
||||
/// </summary>
|
||||
public override BaseData Clone()
|
||||
{
|
||||
return (BaseData)MemberwiseClone();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Formats a string with the symbol and value.
|
||||
/// </summary>
|
||||
/// <returns>string - a string formatted as SPY: 167.753</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Symbol}: " +
|
||||
$"O: {Open.SmartRounding()} " +
|
||||
$"H: {High.SmartRounding()} " +
|
||||
$"L: {Low.SmartRounding()} " +
|
||||
$"C: {Close.SmartRounding()} " +
|
||||
$"V: {Volume.SmartRounding()}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes this bar with a first data point
|
||||
/// </summary>
|
||||
/// <param name="value">The seed value for this bar</param>
|
||||
private void Initialize(decimal value)
|
||||
{
|
||||
if (Interlocked.CompareExchange(ref Initialized, 1, 0) == 0)
|
||||
{
|
||||
_open = value;
|
||||
_low = value;
|
||||
_high = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Collection of TradeBars to create a data type for generic data handler:
|
||||
/// </summary>
|
||||
public class TradeBars : DataDictionary<TradeBar>
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="TradeBars"/> dictionary
|
||||
/// </summary>
|
||||
public TradeBars()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="TradeBars"/> dictionary
|
||||
/// </summary>
|
||||
/// <param name="frontier">The time associated with the data in this dictionary</param>
|
||||
public TradeBars(DateTime frontier)
|
||||
: base(frontier)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
namespace QuantConnect.Data.Market
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a bar sectioned not by time, but by some amount of movement in volume
|
||||
/// </summary>
|
||||
public class VolumeRenkoBar : BaseRenkoBar
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets whether or not this bar is considered closed.
|
||||
/// </summary>
|
||||
public override bool IsClosed => Volume >= BrickSize;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new default instance of the <see cref="RenkoBar"/> class.
|
||||
/// </summary>
|
||||
public VolumeRenkoBar()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="VolumeRenkoBar"/> class with the specified values
|
||||
/// </summary>
|
||||
/// <param name="symbol">symbol of the data</param>
|
||||
/// <param name="start">The current data start time</param>
|
||||
/// <param name="endTime">The current data end time</param>
|
||||
/// <param name="brickSize">The preset volume capacity of this bar</param>
|
||||
/// <param name="open">The current data open value</param>
|
||||
/// <param name="high">The current data high value</param>
|
||||
/// <param name="low">The current data low value</param>
|
||||
/// <param name="close">The current data close value</param>
|
||||
/// <param name="volume">The current data volume</param>
|
||||
public VolumeRenkoBar(Symbol symbol, DateTime start, DateTime endTime, decimal brickSize, decimal open, decimal high, decimal low, decimal close, decimal volume)
|
||||
{
|
||||
Type = RenkoType.Classic;
|
||||
BrickSize = brickSize;
|
||||
|
||||
Symbol = symbol;
|
||||
Start = start;
|
||||
EndTime = endTime;
|
||||
Open = open;
|
||||
Close = close;
|
||||
Volume = volume;
|
||||
High = high;
|
||||
Low = low;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates this <see cref="VolumeRenkoBar"/> with the specified values and returns whether or not this bar is closed
|
||||
/// </summary>
|
||||
/// <param name="time">The current data end time</param>
|
||||
/// <param name="high">The current data high value</param>
|
||||
/// <param name="low">The current data low value</param>
|
||||
/// <param name="close">The current data close value</param>
|
||||
/// <param name="volume">The current data volume</param>
|
||||
/// <returns>The excess volume that the current bar cannot absorb</returns>
|
||||
public decimal Update(DateTime time, decimal high, decimal low, decimal close, decimal volume)
|
||||
{
|
||||
// can't update a closed renko bar
|
||||
if (IsClosed) return 0m;
|
||||
EndTime = time;
|
||||
|
||||
var excessVolume = Volume + volume - BrickSize;
|
||||
if (excessVolume > 0)
|
||||
{
|
||||
Volume = BrickSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
Volume += volume;
|
||||
}
|
||||
|
||||
Close = close;
|
||||
if (high > High) High = high;
|
||||
if (low < Low) Low = low;
|
||||
|
||||
return excessVolume;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="VolumeRenkoBar"/> with previous information rollover
|
||||
/// </summary>
|
||||
public VolumeRenkoBar Rollover()
|
||||
{
|
||||
return new VolumeRenkoBar
|
||||
{
|
||||
Type = Type,
|
||||
BrickSize = BrickSize,
|
||||
Symbol = Symbol,
|
||||
Open = Close, // rollover open is the previous close
|
||||
High = Close,
|
||||
Low = Close,
|
||||
Close = Close,
|
||||
Start = EndTime, // rollover start time is the previous end time
|
||||
EndTime = EndTime,
|
||||
Volume = 0m
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user