public void ProcessMarketData(DepthMarketDataField field) { if (field == null) { return; } if (_provider.EnableMarketLog) { //_provider.Logger.Debug($"{field.InstrumentID},{field.UpdateTime},{field.Bids[0].Price},{field.Bids[0].Size},{field.Asks[0].Price},{field.Asks[0].Size},{field.LastPrice},{field.Volume}."); _provider.Logger.Debug($"{field.InstrumentID},{field.UpdateTime},{field.LastPrice},{field.Volume}."); } _instruments.TryGetValue(field.InstrumentID, out var inst); if (inst == null) { if (_provider.EnableMarketLog) { _provider.Logger.Debug($"unsubscribed tick: {field.InstrumentID}."); } return; } var instId = inst.Id; var localTime = DateTime.Now; var exchangeTime = field.ExchangeDateTime(); if (exchangeTime.Year == DateTime.MaxValue.Year) { if (_provider.EnableMarketLog) { _provider.Logger.Debug($"empty trading time, {field.InstrumentID}"); } exchangeTime = localTime; } else { if (_provider.NightTradingTimeCorrection) { exchangeTime = Helper.CorrectionActionDay(localTime, exchangeTime); } } var time = exchangeTime.TimeOfDay; if (_provider.MaxTimeDiffExchangeLocal > 0) { var diff = Math.Abs((localTime.TimeOfDay - time).TotalMinutes); if (diff > _provider.MaxTimeDiffExchangeLocal) { if (_provider.EnableMarketLog) { _provider.Logger.Debug($"time diff ={diff},{field.InstrumentID}"); } return; } } var range = _timeRanges[instId]; if (!_instOpenFlag[instId]) { if (range.InRange(time)) { if (_instCloseFlag[instId] && range.IsClose(time)) { if (_provider.EnableMarketLog) { _provider.Logger.Debug($"already closed, {field.InstrumentID}."); } return; } inst.SetMarketData(field); _instOpenFlag[instId] = true; _instCloseFlag[instId] = false; if (_provider.EnableMarketLog) { _provider.Logger.Debug($"market open, {field.InstrumentID}."); } } else { if (_provider.EnableMarketLog) { _provider.Logger.Debug($"market no open, {field.InstrumentID}."); } return; } } var last = _marketData[instId]; if (field.ClosePrice > 0 && range.IsClose(time)) { inst.SetMarketData(field); _instCloseFlag[instId] = true; _instOpenFlag[instId] = false; _marketData[instId] = EmptyMarketData; if (_provider.EnableMarketLog) { _provider.Logger.Debug($"market close, {field.InstrumentID}."); } } else { if (_czceInstFlag[inst.Id]) { field.ClosePrice = 0; } _marketData[instId] = field; } if (field.Asks?.Length > 0 && field.Asks[0].Size > 0) { var ask = OpenQuant.Helper.NewTick <Ask>(localTime, exchangeTime, _provider.Id, instId, field.Asks[0].Price, field.Asks[0].Size); _provider.ProcessMarketData(ask); } if (field.Bids?.Length > 0 && field.Bids[0].Size > 0) { var bid = OpenQuant.Helper.NewTick <Bid>(localTime, exchangeTime, _provider.Id, instId, field.Bids[0].Price, field.Bids[0].Size); _provider.ProcessMarketData(bid); } if (!(field.LastPrice > double.Epsilon)) { if (_provider.EnableMarketLog) { _provider.Logger.Debug($"empty price, {field.InstrumentID}."); } return; } var size = _provider.VolumeIsAccumulated ? field.Volume - last.Volume : field.Volume; if (_provider.DiscardEmptyTrade && _provider.VolumeIsAccumulated && Math.Abs(size) < double.Epsilon && _instOpenFlag[instId]) { if (_provider.EnableMarketLog) { _provider.Logger.Debug($"empty trade, {field.InstrumentID}."); } return; } double openInterest, turnover; var trade = OpenQuant.Helper.NewTick <Trade>(localTime, exchangeTime, _provider.Id, instId, field.LastPrice, size); if (_provider.VolumeIsAccumulated) { openInterest = field.OpenInterest - last.OpenInterest; turnover = field.Turnover - last.Turnover; } else { openInterest = field.OpenInterest; turnover = field.Turnover; } trade.SetMarketData(field); trade.SetMarketData(openInterest, turnover); _provider.ProcessMarketData(trade); }
private void _OnRtnDepthMarketData(IntPtr ptr1) { DepthMarketDataField obj = (DepthMarketDataField)Marshal.PtrToStructure(ptr1, typeof(DepthMarketDataField)); OnRtnDepthMarketData(this, ref obj); }
private static void OnRtnDepthMarketData(DepthMarketDataField DepthMarketData) { Console.WriteLine(DepthMarketData.InstrumentID + ":" + DepthMarketData.LastPrice); }
public void ProcessMarketData(DepthMarketDataField field) { if (field == null) { return; } if (_provider.EnableMarketLog) { //_provider.Logger.Debug($"{field.InstrumentID},{field.UpdateTime},{field.Bids[0].Price},{field.Bids[0].Size},{field.Asks[0].Price},{field.Asks[0].Size},{field.LastPrice},{field.Volume}."); _provider.logger.Debug($"{field.InstrumentID},{field.UpdateTime},{field.LastPrice},{field.Volume}."); } _instDictCache.TryGetValue(field.InstrumentID, out var inst); if (inst == null) { if (_provider.EnableMarketLog) { _provider.logger.Debug($"unsubscribed tick: {field.InstrumentID}."); } return; } field.ExchangeID = inst.Exchange; var instId = inst.Id; var localTime = DateTime.Now; var exchangeTime = field.ExchangeDateTime(); if (exchangeTime.Year == DateTime.MaxValue.Year) { if (_provider.EnableMarketLog) { _provider.logger.Debug($"empty trading time, {field.InstrumentID}"); } exchangeTime = localTime; } else { if (_provider.NightTradingTimeCorrection) { exchangeTime = QBHelper.CorrectionActionDay(localTime, exchangeTime); } } var time = exchangeTime.TimeOfDay; if (_provider.MaxTimeDiffExchangeLocal > 0) { var diff = Math.Abs((localTime.TimeOfDay - time).TotalMinutes); if (diff > _provider.MaxTimeDiffExchangeLocal) { if (_provider.EnableMarketLog) { _provider.logger.Debug($"time diff ={diff},{field.InstrumentID}"); } return; } } var range = _timeRanges[instId]; if (!_instOpenFlag[instId]) { if (range.InRange(time)) { if (_instCloseFlag[instId] && range.IsClose(time)) { if (_provider.EnableMarketLog) { _provider.logger.Debug($"already closed, {field.InstrumentID}."); } return; } inst.SetMarketData(field); _instOpenFlag[instId] = true; _instCloseFlag[instId] = false; if (_provider.EnableMarketLog) { _provider.logger.Debug($"market open, {field.InstrumentID}."); } } else { if (_provider.EnableMarketLog) { _provider.logger.Debug($"market no open, {field.InstrumentID}."); } return; } } var last = _marketData[instId]; if (range.IsClose(time) && field.ClosePrice > 0) { inst.SetMarketData(field); _instCloseFlag[instId] = true; _instOpenFlag[instId] = false; _marketData[instId] = EmptyMarketData; if (_provider.EnableMarketLog) { _provider.logger.Debug($"market close, {field.InstrumentID}."); } } else { if (_czceInstFlag[inst.Id]) { field.ClosePrice = 0; } _marketData[instId] = field; } Ask ask = null; if (field.Asks?.Length > 0 && field.Asks[0].Size > 0) { #if Compatibility ask = OpenQuant.Helper.NewTick <Ask>(localTime, exchangeTime, _provider.Id, instId, field.Asks[0].Price, field.Asks[0].Size); #else ask = new Ask(localTime, exchangeTime, _provider.Id, instId, field.Asks[0].Price, field.Asks[0].Size); #endif //_provider.ProcessMarketData(ask); } else { ask = new Ask(localTime, exchangeTime, _provider.Id, instId, 0, 0); } Bid bid = null; if (field.Bids?.Length > 0 && field.Bids[0].Size > 0) { #if Compatibility bid = OpenQuant.Helper.NewTick <Bid>(localTime, exchangeTime, _provider.Id, instId, field.Bids[0].Price, field.Bids[0].Size); #else bid = new Bid(localTime, exchangeTime, _provider.Id, instId, field.Bids[0].Price, field.Bids[0].Size); #endif //_provider.ProcessMarketData(bid); } else { bid = new Bid(localTime, exchangeTime, _provider.Id, instId, 0, 0); } if (!(field.LastPrice > double.Epsilon)) { if (_provider.EnableMarketLog) { _provider.logger.Debug($"empty price, {field.InstrumentID}."); } return; } var size = _provider.volumeIsAccumulated ? field.Volume - last.Volume : field.Volume; if (_provider.DiscardEmptyTrade && _provider.volumeIsAccumulated && Math.Abs(size) < double.Epsilon && _instOpenFlag[instId]) { if (_provider.EnableMarketLog) { _provider.logger.Debug($"empty trade, {field.InstrumentID}."); } return; } #if Compatibility var trade = OpenQuant.Helper.NewTick <Trade>(localTime, exchangeTime, _provider.Id, instId, field.LastPrice, size); #else var trade = new Trade(localTime, exchangeTime, _provider.Id, instId, field.LastPrice, (int)size); #endif var turnover = double.NaN; if (_provider.volumeIsAccumulated) { if (field.Turnover > last.Turnover) { turnover = field.Turnover - last.Turnover; } else { turnover = field.Turnover / field.Volume * size; } } else { turnover = field.Turnover; } if (!_czceInstFlag[instId]) { turnover /= inst.Factor; } trade.SetMarketData(field); trade.SetMarketData(turnover, field.OpenInterest); if (_provider.RaiseOnTradeFirst) { _provider.ProcessMarketData(trade); if (bid != null) { _provider.ProcessMarketData(bid); } if (ask != null) { _provider.ProcessMarketData(ask); } } else { if (bid != null) { _provider.ProcessMarketData(bid); } if (ask != null) { _provider.ProcessMarketData(ask); } _provider.ProcessMarketData(trade); } }
private DepthMarketDataField PbTick2DepthMarketDataField(PbTickCodec codec, PbTick tick) { PbTickView tickView = codec.Data2View(tick, false); DepthMarketDataField marketData = default(DepthMarketDataField); codec.GetUpdateTime(tick, out marketData.UpdateTime, out marketData.UpdateMillisec); marketData.TradingDay = tickView.TradingDay; marketData.ActionDay = tickView.ActionDay; marketData.LastPrice = tickView.LastPrice; marketData.Volume = tickView.Volume; marketData.Turnover = tickView.Turnover; marketData.OpenInterest = tickView.OpenInterest; marketData.AveragePrice = tickView.AveragePrice; if (tickView.Bar != null) { marketData.OpenPrice = tickView.Bar.Open; marketData.HighestPrice = tickView.Bar.High; marketData.LowestPrice = tickView.Bar.Low; marketData.ClosePrice = tickView.Bar.Close; } if (tickView.Static != null) { marketData.LowerLimitPrice = tickView.Static.LowerLimitPrice; marketData.UpperLimitPrice = tickView.Static.UpperLimitPrice; marketData.SettlementPrice = tickView.Static.SettlementPrice; marketData.Symbol = tickView.Static.Symbol; if (!string.IsNullOrWhiteSpace(tickView.Static.Exchange)) { marketData.Exchange = Enum <ExchangeType> .Parse(tickView.Static.Exchange); } } int count = tickView.DepthList == null ? 0 : tickView.DepthList.Count; if (count > 0) { int AskPos = DepthListHelper.FindAsk1Position(tickView.DepthList, tickView.AskPrice1); int BidPos = AskPos - 1; int _BidPos = BidPos; if (_BidPos >= 0) { marketData.BidPrice1 = tickView.DepthList[_BidPos].Price; marketData.BidVolume1 = tickView.DepthList[_BidPos].Size; --_BidPos; if (_BidPos >= 0) { marketData.BidPrice2 = tickView.DepthList[_BidPos].Price; marketData.BidVolume2 = tickView.DepthList[_BidPos].Size; --_BidPos; if (_BidPos >= 0) { marketData.BidPrice3 = tickView.DepthList[_BidPos].Price; marketData.BidVolume3 = tickView.DepthList[_BidPos].Size; --_BidPos; if (_BidPos >= 0) { marketData.BidPrice4 = tickView.DepthList[_BidPos].Price; marketData.BidVolume4 = tickView.DepthList[_BidPos].Size; --_BidPos; if (_BidPos >= 0) { marketData.BidPrice5 = tickView.DepthList[_BidPos].Price; marketData.BidVolume5 = tickView.DepthList[_BidPos].Size; } } } } } int _AskPos = AskPos; if (_AskPos < count) { marketData.AskPrice1 = tickView.DepthList[_AskPos].Price; marketData.AskVolume1 = tickView.DepthList[_AskPos].Size; ++_AskPos; if (_AskPos < count) { marketData.AskPrice2 = tickView.DepthList[_AskPos].Price; marketData.AskVolume2 = tickView.DepthList[_AskPos].Size; ++_AskPos; if (_AskPos < count) { marketData.AskPrice3 = tickView.DepthList[_AskPos].Price; marketData.AskVolume3 = tickView.DepthList[_AskPos].Size; ++_AskPos; if (_AskPos < count) { marketData.AskPrice4 = tickView.DepthList[_AskPos].Price; marketData.AskVolume4 = tickView.DepthList[_AskPos].Size; ++_AskPos; if (_AskPos < count) { marketData.AskPrice5 = tickView.DepthList[_AskPos].Price; marketData.AskVolume5 = tickView.DepthList[_AskPos].Size; } } } } } } return(marketData); }
// 目前先不处理港股的tickSize变化的那种行情 PbTick CreateTick(ref DepthMarketDataField pDepthMarketData, PbTickCodec codec) { var tick = new PbTick(); tick.DepthList = new List <DepthItem>(); tick.Config = codec.Config; tick.TradingDay = pDepthMarketData.TradingDay; tick.ActionDay = pDepthMarketData.ActionDay; tick.Time_HHmm = pDepthMarketData.UpdateTime / 100; tick.Time_____ssf__ = pDepthMarketData.UpdateTime % 100 * 10 + pDepthMarketData.UpdateMillisec / 100; tick.Time________ff = pDepthMarketData.UpdateMillisec % 100; // 数据接收器时计算本地与交易所的行情时间差 // 1.这个地方是否保存? // 2.到底是XAPI中提供还是由接收器提供? //tick.LocalTime_Msec = (int)(DateTime.Now - codec.GetActionDayDateTime(tick)).TotalMilliseconds; codec.SetSymbol(tick, pDepthMarketData.Symbol); if (pDepthMarketData.Exchange != ExchangeType.Undefined) { codec.SetExchange(tick, Enum <ExchangeType> .ToString(pDepthMarketData.Exchange)); } codec.SetLowerLimitPrice(tick, pDepthMarketData.LowerLimitPrice); codec.SetUpperLimitPrice(tick, pDepthMarketData.UpperLimitPrice); codec.SetOpen(tick, pDepthMarketData.OpenPrice); codec.SetHigh(tick, pDepthMarketData.HighestPrice); codec.SetLow(tick, pDepthMarketData.LowestPrice); codec.SetClose(tick, pDepthMarketData.ClosePrice); codec.SetVolume(tick, (long)pDepthMarketData.Volume); codec.SetOpenInterest(tick, (long)pDepthMarketData.OpenInterest); codec.SetTurnover(tick, pDepthMarketData.Turnover);//一定要设置合约乘数才能最优保存 codec.SetAveragePrice(tick, pDepthMarketData.AveragePrice); codec.SetLastPrice(tick, pDepthMarketData.LastPrice); codec.SetSettlementPrice(tick, pDepthMarketData.SettlementPrice); do { if (pDepthMarketData.BidVolume1 == 0) { break; } tick.DepthList.Insert(0, new DepthItem(codec.PriceToTick(pDepthMarketData.BidPrice1), pDepthMarketData.BidVolume1, 0)); // 先记录一个假的,防止只有买价没有卖价的情况 codec.SetAskPrice1(tick, pDepthMarketData.BidPrice1); tick.AskPrice1 += 1; if (pDepthMarketData.BidVolume2 == 0) { break; } tick.DepthList.Insert(0, new DepthItem(codec.PriceToTick(pDepthMarketData.BidPrice2), pDepthMarketData.BidVolume2, 0)); if (pDepthMarketData.BidVolume3 == 0) { break; } tick.DepthList.Insert(0, new DepthItem(codec.PriceToTick(pDepthMarketData.BidPrice3), pDepthMarketData.BidVolume3, 0)); if (pDepthMarketData.BidVolume4 == 0) { break; } tick.DepthList.Insert(0, new DepthItem(codec.PriceToTick(pDepthMarketData.BidPrice4), pDepthMarketData.BidVolume4, 0)); if (pDepthMarketData.BidVolume5 == 0) { break; } tick.DepthList.Insert(0, new DepthItem(codec.PriceToTick(pDepthMarketData.BidPrice5), pDepthMarketData.BidVolume5, 0)); } while (false); do { if (pDepthMarketData.AskVolume1 == 0) { break; } tick.DepthList.Add(new DepthItem(codec.PriceToTick(pDepthMarketData.AskPrice1), pDepthMarketData.AskVolume1, 0)); // 记录卖一价 codec.SetAskPrice1(tick, pDepthMarketData.AskPrice1); if (pDepthMarketData.AskVolume2 == 0) { break; } tick.DepthList.Add(new DepthItem(codec.PriceToTick(pDepthMarketData.AskPrice2), pDepthMarketData.AskVolume2, 0)); if (pDepthMarketData.AskVolume3 == 0) { break; } tick.DepthList.Add(new DepthItem(codec.PriceToTick(pDepthMarketData.AskPrice3), pDepthMarketData.AskVolume3, 0)); if (pDepthMarketData.AskVolume4 == 0) { break; } tick.DepthList.Add(new DepthItem(codec.PriceToTick(pDepthMarketData.AskPrice4), pDepthMarketData.AskVolume4, 0)); if (pDepthMarketData.AskVolume5 == 0) { break; } tick.DepthList.Add(new DepthItem(codec.PriceToTick(pDepthMarketData.AskPrice5), pDepthMarketData.AskVolume5, 0)); } while (false); return(tick); }
public OnRtnDepthMarketDataEventArgs(ref DepthMarketDataField marketData) { this.marketData = marketData; }
public static void SetMarketData(this Instrument inst, DepthMarketDataField field) { inst.Fields[QuantBoxConst.InstrumentMarketDataOffset] = field; }
protected virtual void OnMarketDataReceived(object sender, DepthMarketDataField field) { Provider.OnMessage(field); }
public static void SetMarketData(this Trade trade, DepthMarketDataField field) { trade.Fields[QuantBoxConst.TradeMarketDataOffset] = field; trade.Fields[QuantBoxConst.TradeClosePriceOffset] = field.ClosePrice; }
private USeMarketData DepthMarketDataFieldToUSeFuture(DepthMarketDataField field) { USeMarketData marketData = new USeMarketData(); try { marketData.AskPrice = field.AskPrice1.ToDecimal(); marketData.AskSize = field.AskVolume1; marketData.BidPrice = field.BidPrice1.ToDecimal(); marketData.BidSize = field.BidVolume1; marketData.ClosePrice = field.ClosePrice.ToDecimal(); marketData.AvgPrice = field.AveragePrice; if (m_instrumentDic.ContainsKey(field.InstrumentID)) { marketData.Instrument = m_instrumentDic[field.InstrumentID].Clone(); } else { marketData.Instrument = new USeInstrument(field.InstrumentID, field.InstrumentID, USeMarket.Unknown); } marketData.LastPrice = field.LastPrice.ToDecimal(); marketData.LowerLimitPrice = field.LowerLimitPrice.ToDecimal(); marketData.OpenPrice = field.OpenPrice.ToDecimal(); marketData.PreClosePrice = field.PreClosePrice.ToDecimal(); marketData.PreSettlementPrice = field.PreSettlementPrice.ToDecimal(); marketData.SettlementPrice = field.SettlementPrice.ToDecimal(); marketData.Turnover = field.Turnover.ToDecimal(); DateTime updateTime = DateTime.Now; if (string.IsNullOrWhiteSpace(field.TradingDay) && string.IsNullOrWhiteSpace(field.UpdateTime)) { Debug.Assert(false); updateTime = DateTime.Now; } else if (string.IsNullOrWhiteSpace(field.TradingDay)) { if (DateTime.TryParseExact(DateTime.Today.ToString("yyyyMMdd") + field.UpdateTime.Trim(), "yyyyMMddHH:mm:ss", null, System.Globalization.DateTimeStyles.None, out updateTime) == false) { Debug.Assert(false); updateTime = DateTime.Now; } else { marketData.QuoteTime = updateTime.TimeOfDay; } } else { if (DateTime.TryParseExact(field.TradingDay.Trim() + field.UpdateTime.Trim(), "yyyyMMddHH:mm:ss", null, System.Globalization.DateTimeStyles.None, out updateTime) == false) { Debug.Assert(false); updateTime = DateTime.Now; } else { marketData.QuoteDay = updateTime.Date; marketData.QuoteTime = updateTime.TimeOfDay; } } marketData.UpdateTime = updateTime; marketData.UpperLimitPrice = field.UpperLimitPrice.ToDecimal(); marketData.Volume = field.Volume; marketData.HighPrice = field.HighestPrice.ToDecimal(); marketData.LowPrice = field.LowestPrice.ToDecimal(); marketData.OpenInterest = field.OpenInterest.ToDecimal(); //marketData.PreOpenInterest = field.PreOpenInterest.ToDecimal(); } catch (Exception ex) { m_logger.WriteError(string.Format("{0} DepthMarketDataFieldToUSeFuture() convet failed ,Error:{1}.", ToString(), ex.Message)); Debug.Assert(false, "DepthMarketDataFieldToUSeFuture() convet failed," + ex.Message); } return(marketData); }
public void OnInputMarketData(DepthMarketDataField pDepthMarketData) { TickWriter.Write(ref pDepthMarketData); }
private void OnRtnDepthMarketData(object sender, ref DepthMarketDataField marketData) { Input.Post(marketData); }
public void ProcessMarketData(DepthMarketDataField field) { if (field == null) { return; } if (_provider.EnableMarketLog) { _provider.Logger.Debug($"{field.InstrumentID},{field.UpdateTime},{field.LastPrice},{field.Volume},{field.OpenPrice},{field.ClosePrice}."); } _instruments.TryGetValue(field.InstrumentID, out var inst); if (inst == null) { inst = _provider.InstrumentManager.Get(field.InstrumentID); if (inst == null) { if (_provider.EnableMarketLog) { _provider.Logger.Debug($"not found {field.InstrumentID}."); } return; } InitInstrument(inst); if (_provider.EnableMarketLog) { _provider.Logger.Debug($"{inst.Symbol}, init."); } } var instId = inst.Id; var datetime = DateTime.Now; var exchangeTime = field.ExchangeDateTime(); if (exchangeTime.Year == DateTime.MaxValue.Year) { if (_provider.EnableMarketLog) { _provider.Logger.Debug($"empty trading time,{field.InstrumentID}"); } exchangeTime = datetime; } else { if (_provider.NightTradingTimeCorrection) { exchangeTime = Helper.CorrectionActionDay(datetime, exchangeTime); } } var time = exchangeTime.TimeOfDay; var range = _timeRanges[instId]; if (!_instOpenFlag[instId]) { if (field.OpenPrice > 0 && range.InRange(time) && !range.IsClose(time) && (DateTime.Now.TimeOfDay - time).Hours < 1) { inst.SetMarketData(field); _instOpenFlag[instId] = true; if (_provider.EnableMarketLog) { _provider.Logger.Debug($"market open, {field.InstrumentID}."); } } else { if (_provider.EnableMarketLog) { _provider.Logger.Debug($"market no open, {field.InstrumentID}."); } return; } } var last = _marketData[instId]; if (field.ClosePrice > 0 && range.IsClose(time)) { inst.SetMarketData(field); _instOpenFlag[instId] = false; _marketData[instId] = EmptyMarketData; if (_provider.EnableMarketLog) { _provider.Logger.Debug($"market close, {field.InstrumentID}."); } } else { _marketData[instId] = field; } if (field.Asks?.Length > 0) { var ask = new Ask(datetime, exchangeTime, _provider.Id, instId, field.Asks[0].Price, field.Asks[0].Size); _provider.ProcessMarketData(ask); } if (field.Bids?.Length > 0) { var bid = new Bid(datetime, exchangeTime, _provider.Id, instId, field.Bids[0].Price, field.Bids[0].Size); _provider.ProcessMarketData(bid); } if (!(field.LastPrice > double.Epsilon)) { if (_provider.EnableMarketLog) { _provider.Logger.Debug($"empty price, {field.InstrumentID}."); } return; } var size = (int)(field.Volume - last.Volume); if (_provider.DiscardEmptyTrade && size == 0 && _instOpenFlag[instId]) { if (_provider.EnableMarketLog) { _provider.Logger.Debug($"empty trade, {field.InstrumentID}."); } return; } var trade = new QBTrade(datetime, exchangeTime, _provider.Id, instId, field.LastPrice, 0); if (_provider.VolumeIsAccumulated) { trade.Size = size; trade.OpenInterest = field.OpenInterest - last.OpenInterest; trade.Turnover = field.Turnover - last.Turnover; } else { trade.Size = (int)field.Volume; trade.OpenInterest = field.OpenInterest; trade.Turnover = field.Turnover; } trade.Field = field; _provider.ProcessMarketData(trade); }