/// <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 ParseDerivative <T>(SubscriptionDataConfig config, string line, DateTime date) where T : TradeBar, new() { var tradeBar = new T { Period = config.Increment, Symbol = config.Symbol }; var csv = line.ToCsv(6); 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 = config.GetNormalizedPrice(csv[1].ToDecimal() * _scaleFactor); tradeBar.High = config.GetNormalizedPrice(csv[2].ToDecimal() * _scaleFactor); tradeBar.Low = config.GetNormalizedPrice(csv[3].ToDecimal() * _scaleFactor); tradeBar.Close = config.GetNormalizedPrice(csv[4].ToDecimal() * _scaleFactor); tradeBar.Volume = csv[5].ToInt64(); return(tradeBar); }
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 }; var csv = line.ToCsv(6); if (config.Resolution == Resolution.Daily || config.Resolution == Resolution.Hour) { tradeBar.Time = DateTime.ParseExact(csv[0], DateFormat.TwelveCharacter, CultureInfo.InvariantCulture).ConvertTo(config.DataTimeZone, config.ExchangeTimeZone); } else { tradeBar.Time = date.Date.AddMilliseconds(csv[0].ToInt32()).ConvertTo(config.DataTimeZone, config.ExchangeTimeZone); } tradeBar.Open = config.GetNormalizedPrice(csv[1].ToDecimal() * _scaleFactor); tradeBar.High = config.GetNormalizedPrice(csv[2].ToDecimal() * _scaleFactor); tradeBar.Low = config.GetNormalizedPrice(csv[3].ToDecimal() * _scaleFactor); tradeBar.Close = config.GetNormalizedPrice(csv[4].ToDecimal() * _scaleFactor); tradeBar.Volume = csv[5].ToInt64(); return(tradeBar); }
/// <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> protected static T ParseEquity <T>(SubscriptionDataConfig config, string line, DateTime date) where T : TradeBar, new() { var tradeBar = new T { Symbol = config.Symbol, Period = config.Increment }; var csv = line.Split(','); 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); tradeBar.Open = config.GetNormalizedPrice(Convert.ToDecimal(csv[1]) / _scaleFactor); tradeBar.High = config.GetNormalizedPrice(Convert.ToDecimal(csv[2]) / _scaleFactor); tradeBar.Low = config.GetNormalizedPrice(Convert.ToDecimal(csv[3]) / _scaleFactor); tradeBar.Close = config.GetNormalizedPrice(Convert.ToDecimal(csv[4]) / _scaleFactor); } else { // Using custom "ToDecimal" conversion for speed on high resolution data. tradeBar.Time = date.Date.AddMilliseconds(Convert.ToInt32(csv[0])); tradeBar.Open = config.GetNormalizedPrice(csv[1].ToDecimal() / _scaleFactor); tradeBar.High = config.GetNormalizedPrice(csv[2].ToDecimal() / _scaleFactor); tradeBar.Low = config.GetNormalizedPrice(csv[3].ToDecimal() / _scaleFactor); tradeBar.Close = config.GetNormalizedPrice(csv[4].ToDecimal() / _scaleFactor); } tradeBar.Volume = Convert.ToInt64(csv[5]); return(tradeBar); }
/// <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) { var quoteBar = new QuoteBar { Period = config.Increment, Symbol = config.Symbol }; var csv = line.ToCsv(10); 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(csv[0].ToInt32()).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) { quoteBar.Bid = new Bar { Open = config.GetNormalizedPrice(csv[1].ToDecimal() * _scaleFactor), High = config.GetNormalizedPrice(csv[2].ToDecimal() * _scaleFactor), Low = config.GetNormalizedPrice(csv[3].ToDecimal() * _scaleFactor), Close = config.GetNormalizedPrice(csv[4].ToDecimal() * _scaleFactor) }; quoteBar.LastBidSize = csv[5].ToInt64(); } 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) { quoteBar.Ask = new Bar { Open = config.GetNormalizedPrice(csv[6].ToDecimal() * _scaleFactor), High = config.GetNormalizedPrice(csv[7].ToDecimal() * _scaleFactor), Low = config.GetNormalizedPrice(csv[8].ToDecimal() * _scaleFactor), Close = config.GetNormalizedPrice(csv[9].ToDecimal() * _scaleFactor) }; quoteBar.LastAskSize = csv[10].ToInt64(); } else { quoteBar.Ask = null; } quoteBar.Value = quoteBar.Close; return(quoteBar); }
public void NormalizePrice(DataNormalizationMode mode, decimal factor, decimal dividents, decimal expected) { _config.DataNormalizationMode = mode; _config.PriceScaleFactor = factor; _config.SumOfDividends = dividents; Assert.AreEqual(expected, _config.GetNormalizedPrice(100)); }
public override BaseData Reader(SubscriptionDataConfig config, string line, DateTime date, bool isLiveMode) { var quoteBar = new QuoteBar { Period = config.Increment, Symbol = config.Symbol }; var csv = line.ToCsv(10); if (config.Resolution == Resolution.Daily || config.Resolution == Resolution.Hour) { quoteBar.Time = DateTime.ParseExact(csv[0], DateFormat.TwelveCharacter, CultureInfo.InvariantCulture).ConvertTo(config.DataTimeZone, config.ExchangeTimeZone); } else { quoteBar.Time = date.Date.AddMilliseconds(csv[0].ToInt32()).ConvertTo(config.DataTimeZone, config.ExchangeTimeZone); } if (csv[1].Length != 0 || csv[2].Length != 0 || csv[3].Length != 0 || csv[4].Length != 0) { quoteBar.Bid = new Bar { Open = config.GetNormalizedPrice(csv[1].ToDecimal() * _scaleFactor), High = config.GetNormalizedPrice(csv[2].ToDecimal() * _scaleFactor), Low = config.GetNormalizedPrice(csv[3].ToDecimal() * _scaleFactor), Close = config.GetNormalizedPrice(csv[4].ToDecimal() * _scaleFactor) }; quoteBar.LastBidSize = csv[5].ToInt64(); } else { quoteBar.Bid = null; } if (csv[6].Length != 0 || csv[7].Length != 0 || csv[8].Length != 0 || csv[9].Length != 0) { quoteBar.Ask = new Bar { Open = config.GetNormalizedPrice(csv[6].ToDecimal() * _scaleFactor), High = config.GetNormalizedPrice(csv[7].ToDecimal() * _scaleFactor), Low = config.GetNormalizedPrice(csv[8].ToDecimal() * _scaleFactor), Close = config.GetNormalizedPrice(csv[9].ToDecimal() * _scaleFactor) }; quoteBar.LastAskSize = csv[10].ToInt64(); } else { quoteBar.Ask = null; } quoteBar.Value = quoteBar.Close; return(quoteBar); }
/// <summary> /// Parse a line from CSV data sources into our trade bars. /// </summary> /// <param name="config">Configuration class object for this data subscription</param> /// <param name="baseDate">Base date of this tradebar line</param> /// <param name="line">CSV line from source data file</param> /// <param name="datafeed">Datafeed this csv line is sourced from (backtesting or live)</param> public TradeBar(SubscriptionDataConfig config, string line, DateTime baseDate, DataFeedEndpoint datafeed = DataFeedEndpoint.Backtesting) { try { Period = config.Resolution.ToTimeSpan(); //Parse the data into a trade bar: var csv = line.Split(','); const decimal scaleFactor = 10000m; Symbol = config.Symbol; switch (config.SecurityType) { //Equity File Data Format: case SecurityType.Equity: Time = baseDate.Date.AddMilliseconds(Convert.ToInt32(csv[0])); Open = config.GetNormalizedPrice(csv[1].ToDecimal() / scaleFactor); // Convert.ToDecimal(csv[1]) / scaleFactor; High = config.GetNormalizedPrice(csv[2].ToDecimal() / scaleFactor); // Using custom "ToDecimal" conversion for speed. Low = config.GetNormalizedPrice(csv[3].ToDecimal() / scaleFactor); Close = config.GetNormalizedPrice(csv[4].ToDecimal() / scaleFactor); Volume = Convert.ToInt64(csv[5]); break; //FOREX has a different data file format: case SecurityType.Forex: Time = DateTime.ParseExact(csv[0], "yyyyMMdd HH:mm:ss.ffff", CultureInfo.InvariantCulture); Open = csv[1].ToDecimal(); High = csv[2].ToDecimal(); Low = csv[3].ToDecimal(); Close = csv[4].ToDecimal(); break; } //base.Value = Close; } catch (Exception err) { Log.Error("DataModels: TradeBar(): Error Initializing - " + config.SecurityType + " - " + err.Message + " - " + line); } }
/// <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 ParseOption <T>(SubscriptionDataConfig config, string line, DateTime date) where T : TradeBar, new() { var tradeBar = new T { Period = config.Increment }; var csv = line.ToCsv(8); 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 = config.GetNormalizedPrice(csv[4].ToDecimal() * _scaleFactor); tradeBar.High = config.GetNormalizedPrice(csv[5].ToDecimal() * _scaleFactor); tradeBar.Low = config.GetNormalizedPrice(csv[6].ToDecimal() * _scaleFactor); tradeBar.Close = config.GetNormalizedPrice(csv[7].ToDecimal() * _scaleFactor); tradeBar.Volume = csv[8].ToInt64(); var putCall = csv[1] == "P" ? OptionRight.Put : OptionRight.Call; var strike = csv[2].ToDecimal() * _scaleFactor; var expiry = DateTime.ParseExact(csv[3], DateFormat.EightCharacter, null); var symbol = Symbol.CreateOption(config.Symbol.ID.Symbol, config.Market, config.Symbol.ID.OptionStyle, putCall, strike, expiry); tradeBar.Symbol = symbol; return(tradeBar); }
/// <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; // Which security type is this data feed: switch (config.SecurityType) { case SecurityType.Equity: { var csv = line.ToCsv(6); Symbol = config.Symbol; Time = date.Date.AddMilliseconds(csv[0].ToInt64()).ConvertTo(config.DataTimeZone, config.ExchangeTimeZone); Value = config.GetNormalizedPrice(csv[1].ToDecimal() / 10000m); TickType = TickType.Trade; Quantity = csv[2].ToInt32(); if (csv.Count > 3) { Exchange = csv[3]; SaleCondition = csv[4]; Suspicious = (csv[5] == "1"); } break; } case SecurityType.Forex: case SecurityType.Cfd: { var csv = line.ToCsv(3); Symbol = config.Symbol; TickType = TickType.Quote; Time = date.Date.AddMilliseconds(csv[0].ToInt64()).ConvertTo(config.DataTimeZone, config.ExchangeTimeZone); BidPrice = csv[1].ToDecimal(); AskPrice = csv[2].ToDecimal(); Value = (BidPrice + AskPrice) / 2; 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> /// <param name="datafeed">Datafeed for tick - live or backtesting.</param> public Tick(SubscriptionDataConfig config, string line, DateTime date, DataFeedEndpoint datafeed) { try { var csv = line.Split(','); // Which security type is this data feed: switch (config.SecurityType) { case SecurityType.Equity: Symbol = config.Symbol; Time = date.Date.AddMilliseconds(Convert.ToInt64(csv[0])); Value = config.GetNormalizedPrice(csv[1].ToDecimal() / 10000m); DataType = MarketDataType.Tick; TickType = TickType.Trade; Quantity = Convert.ToInt32(csv[2]); if (csv.Length > 3) { Exchange = csv[3]; SaleCondition = csv[4]; Suspicious = (csv[5] == "1"); } break; case SecurityType.Forex: Symbol = config.Symbol; TickType = TickType.Quote; Time = DateTime.ParseExact(csv[0], "yyyyMMdd HH:mm:ss.ffff", CultureInfo.InvariantCulture); BidPrice = csv[1].ToDecimal(); AskPrice = csv[2].ToDecimal(); Value = BidPrice + (AskPrice - BidPrice) / 2; break; } } catch (Exception err) { Log.Error("Error Generating Tick: " + err.Message); } }
/// <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 { var csv = line.Split(','); DataType = MarketDataType.Tick; // Which security type is this data feed: switch (config.SecurityType) { case SecurityType.Equity: Symbol = config.Symbol; Time = date.Date.AddMilliseconds(csv[0].ToInt64()); Value = config.GetNormalizedPrice(csv[1].ToDecimal() / 10000m); TickType = TickType.Trade; Quantity = csv[2].ToInt32(); if (csv.Length > 3) { Exchange = csv[3]; SaleCondition = csv[4]; Suspicious = (csv[5] == "1"); } break; case SecurityType.Forex: Symbol = config.Symbol; TickType = TickType.Quote; Time = date.Date.AddMilliseconds(csv[0].ToInt64()); BidPrice = csv[1].ToDecimal(); AskPrice = csv[2].ToDecimal(); Value = (BidPrice + AskPrice) / 2; break; } } catch (Exception err) { Log.Error("Error Generating Tick: " + err.Message); } }
/// <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) { var quoteBar = new QuoteBar { Period = config.Increment, Symbol = config.Symbol }; var csv = line.ToCsv(10); 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(csv[0].ToInt32()).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) { quoteBar.Bid = new Bar { Open = config.GetNormalizedPrice(csv[1].ToDecimal()*_scaleFactor), High = config.GetNormalizedPrice(csv[2].ToDecimal()*_scaleFactor), Low = config.GetNormalizedPrice(csv[3].ToDecimal()*_scaleFactor), Close = config.GetNormalizedPrice(csv[4].ToDecimal()*_scaleFactor) }; quoteBar.LastBidSize = csv[5].ToInt64(); } 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) { quoteBar.Ask = new Bar { Open = config.GetNormalizedPrice(csv[6].ToDecimal()*_scaleFactor), High = config.GetNormalizedPrice(csv[7].ToDecimal()*_scaleFactor), Low = config.GetNormalizedPrice(csv[8].ToDecimal()*_scaleFactor), Close = config.GetNormalizedPrice(csv[9].ToDecimal()*_scaleFactor) }; quoteBar.LastAskSize = csv[10].ToInt64(); } else { quoteBar.Ask = null; } quoteBar.Value = quoteBar.Close; return quoteBar; }
/// <summary> /// Advances the enumerator to the next element of the collection. /// </summary> /// <returns> /// true if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the collection. /// </returns> /// <exception cref="T:System.InvalidOperationException">The collection was modified after the enumerator was created. </exception><filterpriority>2</filterpriority> public bool MoveNext() { if (_endOfStream) { return(false); } if (Current != null && Current.DataType != MarketDataType.Auxiliary) { // only save previous price data _previous = Current; } if (_subscriptionFactoryEnumerator == null) { // in live mode the trade able dates will eventually advance to the next if (_isLiveMode) { // HACK attack -- we don't want to block in live mode Current = null; return(true); } _endOfStream = true; return(false); } do { // check for aux data first if (HasAuxDataBefore(_lastInstanceBeforeAuxilliaryData)) { // check for any auxilliary data before reading a line, but make sure // it should be going ahead of '_lastInstanceBeforeAuxilliaryData' Current = _auxiliaryData.Dequeue(); return(true); } if (_emittedAuxilliaryData) { _emittedAuxilliaryData = false; Current = _lastInstanceBeforeAuxilliaryData; _lastInstanceBeforeAuxilliaryData = null; return(true); } // keep enumerating until we find something that is within our time frame while (_subscriptionFactoryEnumerator.MoveNext()) { var instance = _subscriptionFactoryEnumerator.Current; if (instance == null) { // keep reading until we get valid data continue; } // prevent emitting past data, this can happen when switching symbols on daily data if (_previous != null && _config.Resolution != Resolution.Tick) { if (_config.IsCustomData) { // Skip the point if time went backwards for custom data? // TODO: Should this be the case for all datapoints? if (instance.EndTime < _previous.EndTime) { continue; } } else { // all other resolutions don't allow duplicate end times if (instance.EndTime <= _previous.EndTime) { continue; } } } if (instance.EndTime < _periodStart) { // keep reading until we get a value on or after the start _previous = instance; continue; } if (instance.Time > _periodFinish) { // stop reading when we get a value after the end _endOfStream = true; return(false); } // if we move past our current 'date' then we need to do daily things, such // as updating factors and symbol mapping as well as detecting aux data if (instance.EndTime.Date > _tradeableDates.Current) { var currentPriceScaleFactor = _config.PriceScaleFactor; // this is fairly hacky and could be solved by removing the aux data from this class // the case is with coarse data files which have many daily sized data points for the // same date, if (!_config.IsInternalFeed) { // this will advance the date enumerator and determine if a new // instance of the subscription enumerator is required _subscriptionFactoryEnumerator = ResolveDataEnumerator(false); } // we produce auxiliary data on date changes, but make sure our current instance // isn't before it in time if (HasAuxDataBefore(instance)) { // since we're emitting this here we need to save off the instance for next time Current = _auxiliaryData.Dequeue(); _emittedAuxilliaryData = true; // with hourly resolution the first bar for the new date is received // before the price scale factor is updated by ResolveDataEnumerator, // so we have to 'rescale' prices before emitting the bar if (_config.Resolution == Resolution.Hour && (_config.SecurityType == SecurityType.Equity || _config.SecurityType == SecurityType.Option)) { var tradeBar = instance as TradeBar; if (tradeBar != null) { var bar = tradeBar; bar.Open = _config.GetNormalizedPrice(GetRawValue(bar.Open, _config.SumOfDividends, currentPriceScaleFactor)); bar.High = _config.GetNormalizedPrice(GetRawValue(bar.High, _config.SumOfDividends, currentPriceScaleFactor)); bar.Low = _config.GetNormalizedPrice(GetRawValue(bar.Low, _config.SumOfDividends, currentPriceScaleFactor)); bar.Close = _config.GetNormalizedPrice(GetRawValue(bar.Close, _config.SumOfDividends, currentPriceScaleFactor)); } } _lastInstanceBeforeAuxilliaryData = instance; return(true); } } // we've made it past all of our filters, we're withing the requested start/end of the subscription, // we've satisfied user and market hour filters, so this data is good to go as current Current = instance; return(true); } // we've ended the enumerator, time to refresh _subscriptionFactoryEnumerator = ResolveDataEnumerator(true); }while (_subscriptionFactoryEnumerator != null); _endOfStream = true; return(false); }
/// <summary> /// Advances the enumerator to the next element of the collection. /// </summary> /// <returns> /// True if the enumerator was successfully advanced to the next element; /// False if the enumerator has passed the end of the collection. /// </returns> public bool MoveNext() { var underlyingReturnValue = _rawDataEnumerator.MoveNext(); Current = _rawDataEnumerator.Current; if (underlyingReturnValue && Current != null && _factorFile != null) { if (Current.Time.Date > _lastTradableDate) { _lastTradableDate = Current.Time.Date; UpdateScaleFactor(_lastTradableDate); } var securityType = Current.Symbol.SecurityType; switch (Current.DataType) { case MarketDataType.TradeBar: var tradeBar = Current as TradeBar; if (tradeBar != null) { tradeBar.Open = _config.GetNormalizedPrice(tradeBar.Open); tradeBar.High = _config.GetNormalizedPrice(tradeBar.High); tradeBar.Low = _config.GetNormalizedPrice(tradeBar.Low); tradeBar.Close = _config.GetNormalizedPrice(tradeBar.Close); } break; case MarketDataType.Tick: var tick = Current as Tick; if (tick != null) { if (securityType == SecurityType.Equity) { tick.Value = _config.GetNormalizedPrice(tick.Value); } if (securityType == SecurityType.Option || securityType == SecurityType.Future) { if (tick.TickType == TickType.Trade) { tick.Value = _config.GetNormalizedPrice(tick.Value); } else if (tick.TickType != TickType.OpenInterest) { tick.BidPrice = tick.BidPrice != 0 ? _config.GetNormalizedPrice(tick.BidPrice) : 0; tick.AskPrice = tick.AskPrice != 0 ?_config.GetNormalizedPrice(tick.AskPrice) : 0; if (tick.BidPrice != 0) { if (tick.AskPrice != 0) { tick.Value = (tick.BidPrice + tick.AskPrice) / 2m; } else { tick.Value = tick.BidPrice; } } else { tick.Value = tick.AskPrice; } } } } break; case MarketDataType.QuoteBar: var quoteBar = Current as QuoteBar; if (quoteBar != null) { if (quoteBar.Ask != null) { quoteBar.Ask.Open = _config.GetNormalizedPrice(quoteBar.Ask.Open); quoteBar.Ask.High = _config.GetNormalizedPrice(quoteBar.Ask.High); quoteBar.Ask.Low = _config.GetNormalizedPrice(quoteBar.Ask.Low); quoteBar.Ask.Close = _config.GetNormalizedPrice(quoteBar.Ask.Close); } if (quoteBar.Bid != null) { quoteBar.Bid.Open = _config.GetNormalizedPrice(quoteBar.Bid.Open); quoteBar.Bid.High = _config.GetNormalizedPrice(quoteBar.Bid.High); quoteBar.Bid.Low = _config.GetNormalizedPrice(quoteBar.Bid.Low); quoteBar.Bid.Close = _config.GetNormalizedPrice(quoteBar.Bid.Close); } quoteBar.Value = quoteBar.Close; } break; case MarketDataType.Auxiliary: case MarketDataType.Base: case MarketDataType.OptionChain: case MarketDataType.FuturesChain: break; default: throw new ArgumentOutOfRangeException(); } } return(underlyingReturnValue); }
/// <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; // Which security type is this data feed: var scaleFactor = GetScaleFactor(config.SecurityType); switch (config.SecurityType) { case SecurityType.Equity: { var csv = line.ToCsv(6); Symbol = config.Symbol; Time = date.Date.AddMilliseconds(csv[0].ToInt64()).ConvertTo(config.DataTimeZone, config.ExchangeTimeZone); Value = config.GetNormalizedPrice(csv[1].ToDecimal() / scaleFactor); TickType = TickType.Trade; Quantity = csv[2].ToDecimal(); if (csv.Count > 3) { Exchange = csv[3]; SaleCondition = csv[4]; Suspicious = (csv[5] == "1"); } break; } case SecurityType.Forex: case SecurityType.Cfd: { var csv = line.ToCsv(3); Symbol = config.Symbol; TickType = TickType.Quote; Time = date.Date.AddMilliseconds(csv[0].ToInt64()).ConvertTo(config.DataTimeZone, config.ExchangeTimeZone); BidPrice = csv[1].ToDecimal(); AskPrice = csv[2].ToDecimal(); Value = (BidPrice + AskPrice) / 2; break; } case SecurityType.Crypto: { TickType = config.TickType; Symbol = config.Symbol; Exchange = config.Market; if (TickType == TickType.Trade) { var csv = line.ToCsv(3); Time = date.Date.AddMilliseconds(csv[0].ToInt64()) .ConvertTo(config.DataTimeZone, config.ExchangeTimeZone); Value = csv[1].ToDecimal(); Quantity = csv[2].ToDecimal(); } if (TickType == TickType.Quote) { var csv = line.ToCsv(6); Time = date.Date.AddMilliseconds(csv[0].ToInt64()) .ConvertTo(config.DataTimeZone, config.ExchangeTimeZone); BidPrice = csv[1].ToDecimal(); BidSize = csv[2].ToDecimal(); AskPrice = csv[3].ToDecimal(); AskSize = csv[4].ToDecimal(); Value = (BidPrice + AskPrice) / 2; } break; } case SecurityType.Future: case SecurityType.Option: { var csv = line.ToCsv(7); TickType = config.TickType; Time = date.Date.AddMilliseconds(csv[0].ToInt64()).ConvertTo(config.DataTimeZone, config.ExchangeTimeZone); Symbol = config.Symbol; if (TickType == TickType.Trade) { Value = config.GetNormalizedPrice(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 = config.GetNormalizedPrice(csv[1].ToDecimal() / scaleFactor); BidSize = csv[2].ToDecimal(); } if (csv[3].Length != 0) { AskPrice = config.GetNormalizedPrice(csv[3].ToDecimal() / scaleFactor); AskSize = csv[4].ToDecimal(); } Exchange = csv[5]; Suspicious = csv[6] == "1"; if (BidPrice != 0) { if (AskPrice != 0) { Value = (BidPrice + AskPrice) / 2m; } else { Value = BidPrice; } } else { Value = AskPrice; } } 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; // Which security type is this data feed: const decimal scaleFactor = 10000m; switch (config.SecurityType) { case SecurityType.Equity: { var csv = line.ToCsv(6); Symbol = config.Symbol; Time = date.Date.AddMilliseconds(csv[0].ToInt64()).ConvertTo(config.DataTimeZone, config.ExchangeTimeZone); Value = config.GetNormalizedPrice(csv[1].ToDecimal() / scaleFactor); TickType = TickType.Trade; Quantity = csv[2].ToInt32(); if (csv.Count > 3) { Exchange = csv[3]; SaleCondition = csv[4]; Suspicious = (csv[5] == "1"); } break; } case SecurityType.Forex: case SecurityType.Cfd: { var csv = line.ToCsv(3); Symbol = config.Symbol; TickType = TickType.Quote; Time = date.Date.AddMilliseconds(csv[0].ToInt64()).ConvertTo(config.DataTimeZone, config.ExchangeTimeZone); BidPrice = csv[1].ToDecimal(); AskPrice = csv[2].ToDecimal(); Value = (BidPrice + AskPrice) / 2; break; } case SecurityType.Option: { var csv = line.ToCsv(7); TickType = config.TickType; Time = date.Date.AddMilliseconds(csv[0].ToInt64()).ConvertTo(config.DataTimeZone, config.ExchangeTimeZone); Symbol = config.Symbol; if (TickType == TickType.Trade) { Value = config.GetNormalizedPrice(csv[1].ToDecimal()/scaleFactor); Quantity = csv[2].ToInt32(); Exchange = csv[3]; SaleCondition = csv[4]; Suspicious = csv[5] == "1"; } else { if (csv[1].Length != 0) { BidPrice = config.GetNormalizedPrice(csv[1].ToDecimal()/scaleFactor); BidSize = csv[2].ToInt32(); } if (csv[3].Length != 0) { AskPrice = config.GetNormalizedPrice(csv[3].ToDecimal()/scaleFactor); AskSize = csv[4].ToInt32(); } Exchange = csv[5]; Suspicious = csv[6] == "1"; if (BidPrice != 0) { if (AskPrice != 0) { Value = (BidPrice + AskPrice)/2m; } else { Value = BidPrice; } } else { Value = AskPrice; } } 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; // Which security type is this data feed: const decimal scaleFactor = 10000m; switch (config.SecurityType) { case SecurityType.Equity: { var csv = line.ToCsv(6); Symbol = config.Symbol; Time = date.Date.AddMilliseconds(csv[0].ToInt64()).ConvertTo(config.DataTimeZone, config.ExchangeTimeZone); Value = config.GetNormalizedPrice(csv[1].ToDecimal() / scaleFactor); TickType = TickType.Trade; Quantity = csv[2].ToInt32(); if (csv.Count > 3) { Exchange = csv[3]; SaleCondition = csv[4]; Suspicious = (csv[5] == "1"); } break; } case SecurityType.Forex: case SecurityType.Cfd: { var csv = line.ToCsv(3); Symbol = config.Symbol; TickType = TickType.Quote; Time = date.Date.AddMilliseconds(csv[0].ToInt64()).ConvertTo(config.DataTimeZone, config.ExchangeTimeZone); BidPrice = csv[1].ToDecimal(); AskPrice = csv[2].ToDecimal(); Value = (BidPrice + AskPrice) / 2; break; } case SecurityType.Option: { var csv = line.ToCsv(10); TickType = csv.Count == 10 ? TickType.Quote : TickType.Trade; Time = date.Date.AddMilliseconds(csv[0].ToInt64()).ConvertTo(config.DataTimeZone, config.ExchangeTimeZone); var putCall = csv[1] == "P" ? OptionRight.Put : OptionRight.Call; var strike = csv[2].ToDecimal() / scaleFactor; var expiry = DateTime.ParseExact(csv[3], DateFormat.EightCharacter, null); Symbol = Symbol.CreateOption(config.Symbol.ID.Symbol, config.Market, config.Symbol.ID.OptionStyle, putCall, strike, expiry); if (TickType == TickType.Trade) { Value = config.GetNormalizedPrice(csv[4].ToDecimal() / scaleFactor); Quantity = csv[5].ToInt32(); Exchange = csv[6]; SaleCondition = csv[7]; Suspicious = csv[8] == "1"; } else { if (csv[4].Length != 0) { BidPrice = config.GetNormalizedPrice(csv[4].ToDecimal() / scaleFactor); BidSize = csv[5].ToInt32(); } if (csv[6].Length != 0) { AskPrice = config.GetNormalizedPrice(csv[6].ToDecimal() / scaleFactor); AskSize = csv[7].ToInt32(); } Exchange = csv[8]; Suspicious = csv[9] == "1"; if (BidPrice != 0) { if (AskPrice != 0) { Value = (BidPrice + AskPrice) / 2m; } else { Value = BidPrice; } } else { Value = AskPrice; } } break; } } } catch (Exception err) { Log.Error(err); } }