protected override void OnSave(BitArrayWriter writer, IEnumerable <ExecutionMessage> messages, TransactionSerializerMetaInfo metaInfo) { if (metaInfo.IsEmpty()) { var msg = messages.First(); metaInfo.FirstOrderId = metaInfo.LastOrderId = msg.OrderId ?? 0; metaInfo.FirstTradeId = metaInfo.LastTradeId = msg.TradeId ?? 0; metaInfo.FirstTransactionId = metaInfo.LastTransactionId = msg.TransactionId; metaInfo.FirstOriginalTransactionId = metaInfo.LastOriginalTransactionId = msg.OriginalTransactionId; metaInfo.FirstCommission = metaInfo.LastCommission = msg.Commission ?? 0; metaInfo.FirstPnL = metaInfo.LastPnL = msg.PnL ?? 0; metaInfo.FirstPosition = metaInfo.LastPosition = msg.Position ?? 0; metaInfo.FirstSlippage = metaInfo.LastSlippage = msg.Slippage ?? 0; metaInfo.FirstItemLocalTime = metaInfo.LastItemLocalTime = msg.LocalTime.UtcDateTime; metaInfo.FirstItemLocalOffset = metaInfo.LastItemLocalOffset = msg.LocalTime.Offset; metaInfo.ServerOffset = msg.ServerTime.Offset; } writer.WriteInt(messages.Count()); var allowNonOrdered = metaInfo.Version >= MarketDataVersions.Version48; var isUtc = metaInfo.Version >= MarketDataVersions.Version51; var allowDiffOffsets = metaInfo.Version >= MarketDataVersions.Version56; var isTickPrecision = metaInfo.Version >= MarketDataVersions.Version60; var buildFrom = metaInfo.Version >= MarketDataVersions.Version67; var leverage = metaInfo.Version >= MarketDataVersions.Version68; foreach (var msg in messages) { if (msg.ExecutionType != ExecutionTypes.Transaction) { throw new ArgumentOutOfRangeException(nameof(messages), msg.ExecutionType, LocalizedStrings.Str1695Params.Put(msg)); } // нулевой номер заявки возможен при сохранении в момент регистрации if (msg.OrderId < 0) { throw new ArgumentOutOfRangeException(nameof(messages), msg.OrderId, LocalizedStrings.Str925); } // нулевая цена возможна, если идет "рыночная" продажа по инструменту без планок if (msg.OrderPrice < 0) { throw new ArgumentOutOfRangeException(nameof(messages), msg.OrderPrice, LocalizedStrings.Str926Params.Put(msg.OrderId == null ? msg.OrderStringId : msg.OrderId.To <string>())); } //var volume = msg.Volume; //if (volume < 0) // throw new ArgumentOutOfRangeException(nameof(messages), volume, LocalizedStrings.Str927Params.Put(msg.OrderId == null ? msg.OrderStringId : msg.OrderId.To<string>())); if (msg.HasTradeInfo()) { //if ((msg.TradeId == null && msg.TradeStringId.IsEmpty()) || msg.TradeId <= 0) // throw new ArgumentOutOfRangeException(nameof(messages), msg.TradeId, LocalizedStrings.Str928Params.Put(msg.TransactionId)); if (msg.TradePrice == null || msg.TradePrice <= 0) { throw new ArgumentOutOfRangeException(nameof(messages), msg.TradePrice, LocalizedStrings.Str929Params.Put(msg.TradeId, msg.OrderId)); } } metaInfo.LastTransactionId = writer.SerializeId(msg.TransactionId, metaInfo.LastTransactionId); metaInfo.LastOriginalTransactionId = writer.SerializeId(msg.OriginalTransactionId, metaInfo.LastOriginalTransactionId); writer.Write(msg.HasOrderInfo); writer.Write(msg.HasTradeInfo); writer.Write(msg.OrderId != null); if (msg.OrderId != null) { metaInfo.LastOrderId = writer.SerializeId(msg.OrderId.Value, metaInfo.LastOrderId); } else { writer.WriteStringEx(msg.OrderStringId); } writer.WriteStringEx(msg.OrderBoardId); writer.Write(msg.TradeId != null); if (msg.TradeId != null) { metaInfo.LastTradeId = writer.SerializeId(msg.TradeId.Value, metaInfo.LastTradeId); } else { writer.WriteStringEx(msg.TradeStringId); } if (msg.OrderPrice != 0) { writer.Write(true); writer.WritePriceEx(msg.OrderPrice, metaInfo, SecurityId); } else { writer.Write(false); } if (msg.TradePrice != null) { writer.Write(true); writer.WritePriceEx(msg.TradePrice.Value, metaInfo, SecurityId); } else { writer.Write(false); } writer.Write(msg.Side == Sides.Buy); writer.Write(msg.OrderVolume != null); if (msg.OrderVolume != null) { writer.WriteVolume(msg.OrderVolume.Value, metaInfo, SecurityId); } writer.Write(msg.TradeVolume != null); if (msg.TradeVolume != null) { writer.WriteVolume(msg.TradeVolume.Value, metaInfo, SecurityId); } writer.Write(msg.VisibleVolume != null); if (msg.VisibleVolume != null) { writer.WriteVolume(msg.VisibleVolume.Value, metaInfo, SecurityId); } writer.Write(msg.Balance != null); if (msg.Balance != null) { writer.WriteVolume(msg.Balance.Value, metaInfo, SecurityId); } var lastOffset = metaInfo.LastServerOffset; metaInfo.LastTime = writer.WriteTime(msg.ServerTime, metaInfo.LastTime, LocalizedStrings.Str930, allowNonOrdered, isUtc, metaInfo.ServerOffset, allowDiffOffsets, isTickPrecision, ref lastOffset); metaInfo.LastServerOffset = lastOffset; writer.WriteNullableInt((int?)msg.OrderType); writer.WriteNullableInt((int?)msg.OrderState); writer.WriteNullableLong(msg.OrderStatus); writer.WriteNullableInt(msg.TradeStatus); writer.WriteNullableInt((int?)msg.TimeInForce); writer.Write(msg.IsSystem != null); if (msg.IsSystem != null) { writer.Write(msg.IsSystem.Value); } writer.Write(msg.IsUpTick != null); if (msg.IsUpTick != null) { writer.Write(msg.IsUpTick.Value); } writer.WriteDto(msg.ExpiryDate); metaInfo.LastCommission = Write(writer, msg.Commission, metaInfo.LastCommission); metaInfo.LastPnL = Write(writer, msg.PnL, metaInfo.LastPnL); metaInfo.LastPosition = Write(writer, msg.Position, metaInfo.LastPosition); metaInfo.LastSlippage = Write(writer, msg.Slippage, metaInfo.LastSlippage); WriteString(writer, metaInfo.Portfolios, msg.PortfolioName); WriteString(writer, metaInfo.ClientCodes, msg.ClientCode); WriteString(writer, metaInfo.BrokerCodes, msg.BrokerCode); WriteString(writer, metaInfo.DepoNames, msg.DepoName); WriteString(writer, metaInfo.UserOrderIds, msg.UserOrderId); WriteString(writer, metaInfo.Comments, msg.Comment); WriteString(writer, metaInfo.SystemComments, msg.SystemComment); WriteString(writer, metaInfo.Errors, msg.Error?.Message); writer.WriteNullableInt((int?)msg.Currency); writer.Write(msg.Latency != null); if (msg.Latency != null) { writer.WriteLong(msg.Latency.Value.Ticks); } writer.Write(msg.OriginSide != null); if (msg.OriginSide != null) { writer.Write(msg.OriginSide.Value == Sides.Buy); } if (metaInfo.Version < MarketDataVersions.Version59) { continue; } WriteItemLocalTime(writer, metaInfo, msg, isTickPrecision); if (metaInfo.Version < MarketDataVersions.Version61) { continue; } writer.Write(msg.IsMarketMaker != null); if (msg.IsMarketMaker != null) { writer.Write(msg.IsMarketMaker.Value); } if (metaInfo.Version < MarketDataVersions.Version62) { continue; } writer.Write(msg.IsMargin != null); if (msg.IsMargin != null) { writer.Write(msg.IsMargin.Value); } if (metaInfo.Version < MarketDataVersions.Version63) { continue; } writer.WriteStringEx(msg.CommissionCurrency); if (metaInfo.Version < MarketDataVersions.Version64) { continue; } writer.Write(msg.IsManual != null); if (msg.IsManual != null) { writer.Write(msg.IsManual.Value); } if (metaInfo.Version < MarketDataVersions.Version65) { continue; } writer.Write(msg.PositionEffect != null); if (msg.PositionEffect != null) { writer.WriteInt((int)msg.PositionEffect.Value); } writer.Write(msg.PostOnly != null); if (msg.PostOnly != null) { writer.Write(msg.PostOnly.Value); } writer.Write(msg.Initiator != null); if (msg.Initiator != null) { writer.Write(msg.Initiator.Value); } if (metaInfo.Version < MarketDataVersions.Version66) { continue; } writer.WriteLong(msg.SeqNum); WriteString(writer, metaInfo.StrategyIds, msg.StrategyId); if (!buildFrom) { continue; } writer.WriteBuildFrom(msg.BuildFrom); if (!leverage) { continue; } writer.WriteNullableInt(msg.Leverage); } }
protected override void OnSave(BitArrayWriter writer, IEnumerable <PositionChangeMessage> messages, PositionMetaInfo metaInfo) { if (metaInfo.IsEmpty()) { var msg = messages.First(); metaInfo.ServerOffset = msg.ServerTime.Offset; } writer.WriteInt(messages.Count()); var buildFrom = metaInfo.Version >= MarketDataVersions.Version35; var side = metaInfo.Version >= MarketDataVersions.Version36; foreach (var message in messages) { var lastOffset = metaInfo.LastServerOffset; metaInfo.LastTime = writer.WriteTime(message.ServerTime, metaInfo.LastTime, "level1", true, true, metaInfo.ServerOffset, true, true, ref lastOffset); metaInfo.LastServerOffset = lastOffset; var hasLocalTime = message.HasLocalTime(message.ServerTime); writer.Write(hasLocalTime); if (hasLocalTime) { lastOffset = metaInfo.LastLocalOffset; metaInfo.LastLocalTime = writer.WriteTime(message.LocalTime, metaInfo.LastLocalTime, LocalizedStrings.Str919, true, true, metaInfo.LocalOffset, true, true, ref lastOffset, true); metaInfo.LastLocalOffset = lastOffset; } metaInfo.Portfolios.TryAdd(message.PortfolioName); writer.WriteInt(metaInfo.Portfolios.IndexOf(message.PortfolioName)); if (message.ClientCode.IsEmpty()) { writer.Write(false); } else { writer.Write(true); metaInfo.ClientCodes.TryAdd(message.ClientCode); writer.WriteInt(metaInfo.ClientCodes.IndexOf(message.ClientCode)); } if (message.DepoName.IsEmpty()) { writer.Write(false); } else { writer.Write(true); metaInfo.DepoNames.TryAdd(message.DepoName); writer.WriteInt(metaInfo.DepoNames.IndexOf(message.DepoName)); } writer.Write(message.LimitType != null); if (message.LimitType != null) { writer.WriteInt((int)message.LimitType.Value); } var count = message.Changes.Count; if (count == 0) { throw new ArgumentException(LocalizedStrings.Str920, nameof(messages)); } writer.WriteInt(count); foreach (var change in message.Changes) { writer.WriteInt((int)change.Key); switch (change.Key) { case PositionChangeTypes.BeginValue: SerializeChange(writer, metaInfo.BeginValue, (decimal)change.Value); break; case PositionChangeTypes.CurrentValue: SerializeChange(writer, metaInfo.CurrentValue, (decimal)change.Value); break; case PositionChangeTypes.BlockedValue: SerializeChange(writer, metaInfo.BlockedValue, (decimal)change.Value); break; case PositionChangeTypes.CurrentPrice: SerializeChange(writer, metaInfo.CurrentPrice, (decimal)change.Value); break; case PositionChangeTypes.AveragePrice: SerializeChange(writer, metaInfo.AveragePrice, (decimal)change.Value); break; case PositionChangeTypes.UnrealizedPnL: SerializeChange(writer, metaInfo.UnrealizedPnL, (decimal)change.Value); break; case PositionChangeTypes.RealizedPnL: SerializeChange(writer, metaInfo.RealizedPnL, (decimal)change.Value); break; case PositionChangeTypes.VariationMargin: SerializeChange(writer, metaInfo.VariationMargin, (decimal)change.Value); break; case PositionChangeTypes.Currency: writer.WriteInt((int)(CurrencyTypes)change.Value); break; case PositionChangeTypes.Leverage: SerializeChange(writer, metaInfo.Leverage, (decimal)change.Value); break; case PositionChangeTypes.Commission: SerializeChange(writer, metaInfo.Commission, (decimal)change.Value); break; case PositionChangeTypes.CurrentValueInLots: SerializeChange(writer, metaInfo.CurrentValueInLots, (decimal)change.Value); break; case PositionChangeTypes.State: writer.WriteInt((int)(PortfolioStates)change.Value); break; case PositionChangeTypes.ExpirationDate: writer.WriteDto((DateTimeOffset)change.Value); break; case PositionChangeTypes.CommissionMaker: case PositionChangeTypes.CommissionTaker: case PositionChangeTypes.BuyOrdersMargin: case PositionChangeTypes.SellOrdersMargin: case PositionChangeTypes.OrdersMargin: writer.WriteDecimal((decimal)change.Value, 0); break; case PositionChangeTypes.SettlementPrice: SerializeChange(writer, metaInfo.SettlementPrice, (decimal)change.Value); break; case PositionChangeTypes.BuyOrdersCount: case PositionChangeTypes.SellOrdersCount: case PositionChangeTypes.OrdersCount: case PositionChangeTypes.TradesCount: writer.WriteInt((int)change.Value); break; default: throw new ArgumentOutOfRangeException(); } } if (metaInfo.Version < MarketDataVersions.Version34) { continue; } writer.WriteStringEx(message.Description); writer.WriteStringEx(message.StrategyId); if (!buildFrom) { continue; } writer.WriteBuildFrom(message.BuildFrom); if (!side) { continue; } writer.WriteNullableSide(message.Side); } }