/// <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> /// 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> public OptionChain(Symbol canonicalOptionSymbol, DateTime time) { Time = time; Symbol = canonicalOptionSymbol; DataType = MarketDataType.OptionChain; Ticks = new Ticks(time); TradeBars = new TradeBars(time); QuoteBars = new QuoteBars(time); Contracts = new OptionContracts(time); FilteredContracts = new HashSet <Symbol>(); Underlying = new QuoteBar(); }
/// <summary> /// Cloner constructor for implementing fill forward. /// Return a new instance with the same values as this original. /// </summary> /// <param name="original">Original quotebar object we seek to clone</param> public QuoteBar(QuoteBar original) { Symbol = original.Symbol; Time = new DateTime(original.Time.Ticks); var bid = original.Bid; Bid = bid == null ? null : new Bar(bid.Open, bid.High, bid.Low, bid.Close); var ask = original.Ask; Ask = ask == null ? null : new Bar(ask.Open, ask.High, ask.Low, ask.Close); AvgBidSize = original.AvgBidSize; AvgAskSize = original.AvgAskSize; Value = original.Close; Period = original.Period; DataType = MarketDataType.QuoteBar; }
private QuoteBar ParseTradeAsQuoteBar(SubscriptionDataConfig config, DateTime date, string line) { if (!HasShownWarning) { Logging.Log.Error("QuoteBar.ParseTradeAsQuoteBar(): Data formatted as Trade when Quote format was expected. Support for this will disappear June 2017."); HasShownWarning = true; } var quoteBar = new QuoteBar { Period = config.Increment, Symbol = config.Symbol }; var csv = line.ToCsv(5); 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 { //Fast decimal conversion quoteBar.Time = date.Date.AddMilliseconds(csv[0].ToInt32()).ConvertTo(config.DataTimeZone, config.ExchangeTimeZone); } var bid = new Bar { Open = csv[1].ToDecimal(), High = csv[2].ToDecimal(), Low = csv[3].ToDecimal(), Close = csv[4].ToDecimal() }; var ask = new Bar { Open = csv[1].ToDecimal(), High = csv[2].ToDecimal(), Low = csv[3].ToDecimal(), Close = csv[4].ToDecimal() }; quoteBar.Ask = ask; quoteBar.Bid = bid; quoteBar.Value = quoteBar.Close; return(quoteBar); }
public void AggregatesNewQuoteBarProperly() { QuoteBar quoteBar = null; var creator = new QuoteBarConsolidator(4); creator.DataConsolidated += (sender, args) => { quoteBar = args; }; var time = DateTime.Today; var bar1 = new QuoteBar { Time = time, Symbol = Symbols.SPY, Bid = new Bar(1, 2, 0.75m, 1.25m), LastBidSize = 3, Ask = null, LastAskSize = 0 }; creator.Update(bar1); Assert.IsNull(quoteBar); var bar2 = new QuoteBar { Time = time, Symbol = Symbols.SPY, Bid = new Bar(1.1m, 2.2m, 0.9m, 2.1m), LastBidSize = 3, Ask = new Bar(2.2m, 4.4m, 3.3m, 3.3m), LastAskSize = 0 }; creator.Update(bar2); Assert.IsNull(quoteBar); var bar3 = new QuoteBar { Time = time, Symbol = Symbols.SPY, Bid = new Bar(1, 2, 0.5m, 1.75m), LastBidSize = 3, Ask = null, LastAskSize = 0 }; creator.Update(bar3); Assert.IsNull(quoteBar); var bar4 = new QuoteBar { Time = time, Symbol = Symbols.SPY, Bid = null, LastBidSize = 0, Ask = new Bar(1, 7, 0.5m, 4.4m), LastAskSize = 4 }; creator.Update(bar4); Assert.IsNotNull(quoteBar); Assert.AreEqual(bar1.Symbol, quoteBar.Symbol); Assert.AreEqual(bar1.Bid.Open, quoteBar.Bid.Open); Assert.AreEqual(bar2.Ask.Open, quoteBar.Ask.Open); Assert.AreEqual(bar2.Bid.High, quoteBar.Bid.High); Assert.AreEqual(bar4.Ask.High, quoteBar.Ask.High); Assert.AreEqual(bar3.Bid.Low, quoteBar.Bid.Low); Assert.AreEqual(bar4.Ask.Low, quoteBar.Ask.Low); Assert.AreEqual(bar3.Bid.Close, quoteBar.Bid.Close); Assert.AreEqual(bar4.Ask.Close, quoteBar.Ask.Close); Assert.AreEqual(bar3.LastBidSize, quoteBar.LastBidSize); Assert.AreEqual(bar4.LastAskSize, quoteBar.LastAskSize); }
/// <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) { quoteBar.Bid = new Bar { Open = open * scaleFactor, High = high * scaleFactor, Low = low * scaleFactor, 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) { quoteBar.Ask = new Bar { Open = open * scaleFactor, High = high * scaleFactor, Low = low * scaleFactor, Close = close * scaleFactor }; quoteBar.LastAskSize = lastSize; } else { quoteBar.Ask = null; } quoteBar.Value = quoteBar.Close; return(quoteBar); }
private static void UpdateContract(OptionContract contract, QuoteBar quote) { if (quote.Ask != null && quote.Ask.Close != 0m) { contract.AskPrice = quote.Ask.Close; contract.AskSize = quote.LastAskSize; } if (quote.Bid != null && quote.Bid.Close != 0m) { contract.BidPrice = quote.Bid.Close; contract.BidSize = quote.LastBidSize; } }
/// <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; }