ExecutionMessage ISnapshotSerializer <string, ExecutionMessage> .Deserialize(Version version, byte[] buffer)
        {
            if (version == null)
            {
                throw new ArgumentNullException(nameof(version));
            }

            using (var handle = new GCHandle <byte[]>(buffer))
            {
                var ptr = handle.CreatePointer();

                var snapshot = ptr.ToStruct <TransactionSnapshot>(true);

                var execMsg = new ExecutionMessage
                {
                    SecurityId    = snapshot.SecurityId.ToSecurityId(),
                    PortfolioName = snapshot.PortfolioName,
                    ServerTime    = snapshot.LastChangeServerTime.To <DateTimeOffset>(),
                    LocalTime     = snapshot.LastChangeLocalTime.To <DateTimeOffset>(),

                    ExecutionType = ExecutionTypes.Transaction,

                    //OriginalTransactionId = snapshot.OriginalTransactionId,
                    TransactionId = snapshot.TransactionId,

                    HasOrderInfo = snapshot.HasOrderInfo,
                    HasTradeInfo = snapshot.HasTradeInfo,

                    BrokerCode = snapshot.BrokerCode,
                    ClientCode = snapshot.ClientCode,

                    Comment       = snapshot.Comment,
                    SystemComment = snapshot.SystemComment,

                    Currency = snapshot.Currency == null ? (CurrencyTypes?)null : (CurrencyTypes)snapshot.Currency.Value,
                    DepoName = snapshot.DepoName,
                    Error    = snapshot.Error.IsEmpty() ? null : new InvalidOperationException(snapshot.Error),

                    ExpiryDate    = snapshot.ExpiryDate?.To <DateTimeOffset>(),
                    IsMarketMaker = snapshot.IsMarketMaker == null ? (bool?)null : (snapshot.IsMarketMaker.Value == 1),
                    IsMargin      = snapshot.IsMargin == null ? (bool?)null : (snapshot.IsMargin.Value == 1),
                    IsManual      = snapshot.IsManual == null ? (bool?)null : (snapshot.IsManual.Value == 1),
                    Side          = (Sides)snapshot.Side,
                    OrderId       = snapshot.OrderId,
                    OrderStringId = snapshot.OrderStringId,
                    OrderBoardId  = snapshot.OrderBoardId,
                    OrderPrice    = snapshot.OrderPrice,
                    OrderVolume   = snapshot.OrderVolume,
                    VisibleVolume = snapshot.VisibleVolume,
                    OrderType     = snapshot.OrderType == null ? (OrderTypes?)null : (OrderTypes)snapshot.OrderType.Value,
                    OrderState    = snapshot.OrderState == null ? (OrderStates?)null : (OrderStates)snapshot.OrderState.Value,
                    OrderStatus   = snapshot.OrderStatus,
                    Balance       = snapshot.Balance,
                    UserOrderId   = snapshot.UserOrderId,
                    OriginSide    = snapshot.OriginSide == null ? (Sides?)null : (Sides)snapshot.OriginSide.Value,
                    Latency       = snapshot.Latency == null ? (TimeSpan?)null : TimeSpan.FromTicks(snapshot.Latency.Value),
                    PnL           = snapshot.PnL,
                    Position      = snapshot.Position,
                    Slippage      = snapshot.Slippage,
                    Commission    = snapshot.Commission,
                    TradePrice    = snapshot.TradePrice,
                    TradeVolume   = snapshot.TradeVolume,
                    TradeStatus   = snapshot.TradeStatus,
                    TradeId       = snapshot.TradeId,
                    TradeStringId = snapshot.TradeStringId,
                    OpenInterest  = snapshot.OpenInterest,
                    IsSystem      = snapshot.IsSystem == null ? (bool?)null : (snapshot.IsSystem.Value == 1),
                    TimeInForce   = snapshot.OrderTif == null ? (TimeInForce?)null : (TimeInForce)snapshot.OrderTif.Value,
                };

                //var paramSize = (version > SnapshotVersions.V20 ? typeof(TransactionConditionParamV21) : typeof(TransactionConditionParamV20)).SizeOf();

                if (!snapshot.ConditionType.IsEmpty())
                {
                    execMsg.Condition = snapshot.ConditionType.To <Type>().CreateInstance <OrderCondition>();
                    execMsg.Condition.Parameters.Clear();                     // removing pre-defined values
                }

                for (var i = 0; i < snapshot.ConditionParamsCount; i++)
                {
                    var param = ptr.ToStruct <TransactionConditionParamV21>(true);

                    var typeBuffer = new byte[param.ValueTypeLen];
                    ptr.CopyTo(typeBuffer, true);

                    var paramTypeName = typeBuffer.UTF8();

                    try
                    {
                        var paramType = paramTypeName.To <Type>();

                        object value;

                        if (param.NumValue != null)
                        {
                            value = (long)param.NumValue;
                        }
                        else if (param.DecimalValue != null)
                        {
                            value = (decimal)param.DecimalValue;
                        }
                        else if (param.BoolValue != null)
                        {
                            value = (bool)param.BoolValue;
                        }
                        //else if (paramType == typeof(Unit))
                        //	value = param.StringValue.ToUnit();
                        else if (param.StringValueLen > 0)
                        {
                            var strBuffer = new byte[param.StringValueLen];
                            ptr.CopyTo(strBuffer, true);

                            if (typeof(IPersistable).IsAssignableFrom(paramType))
                            {
                                var persistable = paramType.CreateInstance <IPersistable>();
                                persistable.Load(new XmlSerializer <SettingsStorage>().Deserialize(strBuffer));
                                value = persistable;
                            }
                            else if (typeof(IRange).IsAssignableFrom(paramType))
                            {
                                var range = paramType.CreateInstance <IRange>();

                                var storage = new XmlSerializer <SettingsStorage>().Deserialize(strBuffer);

                                if (storage.ContainsKey(nameof(range.Min)))
                                {
                                    range.Min = storage.GetValue <object>(nameof(range.Min));
                                }

                                if (storage.ContainsKey(nameof(range.Max)))
                                {
                                    range.Max = storage.GetValue <object>(nameof(range.Max));
                                }

                                value = range;
                            }
                            else
                            {
                                value = typeof(XmlSerializer <>).Make(paramType).CreateInstance <ISerializer>().Deserialize(strBuffer);
                            }
                        }
                        else
                        {
                            value = null;
                        }

                        value = value.To(paramType);
                        execMsg.Condition.Parameters.Add(param.Name, value);
                    }
                    catch (Exception ex)
                    {
                        ex.LogError();
                    }
                }

                return(execMsg);
            }
        }