private static string MyTradeToString(ExecutionMessage trade) { return string.Format("{0};{1};{2};{3};{4};{5};{6}", trade.SecurityId.SecurityCode, trade.TradeId, trade.ServerTime, trade.TradePrice, trade.Volume, trade.Side, trade.OrderId); }
private static string TradeToString(ExecutionMessage tick) { //securityId;tradeId;time;price;volume;orderdirection return string.Format("{0};{1};{2};{3};{4};{5}", tick.SecurityId.SecurityCode, tick.TradeId, tick.ServerTime, tick.TradePrice, tick.Volume, tick.Side); }
public Tuple <Trade, bool> ProcessTradeMessage(Security security, ExecutionMessage message) { if (security == null) { throw new ArgumentNullException(nameof(security)); } if (message == null) { throw new ArgumentNullException(nameof(message)); } var trade = GetTrade(security, message.TradeId, message.TradeStringId, (id, stringId) => { var t = message.ToTrade(EntityFactory.CreateTrade(security, id, stringId)); t.LocalTime = message.LocalTime; t.Time = message.ServerTime; message.CopyExtensionInfo(t); return(t); }); return(trade); }
/// <summary> /// To calculate trade profitability. If the trade was already processed earlier, previous information returns. /// </summary> /// <param name="trade">Trade.</param> /// <param name="info">Information on new trade.</param> /// <returns><see langword="true" />, if new trade received, otherwise, <see langword="false" />.</returns> public bool ProcessMyTrade(ExecutionMessage trade, out PnLInfo info) { if (trade == null) { throw new ArgumentNullException(nameof(trade)); } var tradeId = trade.GetTradeId(); if (_tradeInfos.TryGetValue(tradeId, out info)) { return(false); } var queue = _securityPnLs.SafeAdd(trade.SecurityId, security => new PnLQueue(security)); info = queue.Process(trade); _tradeInfos.Add(tradeId, info); _realizedPnL += info.PnL; return(true); }
public void StartExport() { MarketDataAdapter.SendInMessage(new PortfolioLookupMessage { TransactionId = TransactionIdGenerator.GetNextId() }); var exm = new ExecutionMessage { ExtensionInfo = new Dictionary <object, object>() }; exm.ExtensionInfo.Add(new KeyValuePair <object, object>("GetMyTrades", null)); exm.ExtensionInfo.Add(new KeyValuePair <object, object>("GetOrders", null)); MarketDataAdapter.SendInMessage(exm); var posm = new PositionMessage { ExtensionInfo = new Dictionary <object, object>() }; posm.ExtensionInfo.Add(new KeyValuePair <object, object>("GetPositions", null)); MarketDataAdapter.SendInMessage(posm); }
private static void SaveTransaction(ISnapshotStorage snapshotStorage, ExecutionMessage message) { ExecutionMessage sepTrade = null; if (message.HasOrderInfo && message.HasTradeInfo) { sepTrade = new ExecutionMessage { HasTradeInfo = true, SecurityId = message.SecurityId, ServerTime = message.ServerTime, TransactionId = message.TransactionId, ExecutionType = message.ExecutionType, TradeId = message.TradeId, TradeVolume = message.TradeVolume, TradePrice = message.TradePrice, TradeStatus = message.TradeStatus, TradeStringId = message.TradeStringId, OriginSide = message.OriginSide, Commission = message.Commission, IsSystem = message.IsSystem, }; message.HasTradeInfo = false; message.TradeId = null; message.TradeVolume = null; message.TradePrice = null; message.TradeStatus = null; message.TradeStringId = null; message.OriginSide = null; } snapshotStorage.Update(message); if (sepTrade != null) snapshotStorage.Update(sepTrade); }
private void ProcessLevel1Trade(Level1ChangeMessage message, decimal lastTradePrice, decimal lastTradeVolume, List <ExecutionMessage> retVal) { if (message.LocalTime.Date == _lastTradeDate) { return; } if (lastTradePrice == 0 || lastTradeVolume == 0) { return; } var exec = new ExecutionMessage { LocalTime = message.LocalTime, ServerTime = message.ServerTime, SecurityId = message.SecurityId, ExecutionType = ExecutionTypes.Tick, TradePrice = lastTradePrice, Volume = lastTradeVolume, }; retVal.AddRange(ProcessExecution(exec)); }
private static string TradeToString(ExecutionMessage tick) { //securityId;tradeId;time;price;volume;orderdirection return $"{tick.SecurityId.SecurityCode};{tick.TradeId};{tick.ServerTime};{tick.TradePrice};{tick.TradeVolume};{tick.Side}"; }
private void OnMessageReported(FileBasedProject project, ExecutionMessage executionMessage) { MessageReported?.Invoke(this, new ProjectMessageEventArgs { Project = project, Message = executionMessage.Level + ": " + executionMessage.Message }); }
private void ProcessOrderMessage(Order o, Security security, ExecutionMessage message, long transactionId) { if (message.OrderState != OrderStates.Failed) { Tuple<Portfolio, bool, bool> pfInfo; var tuples = _entityCache.ProcessOrderMessage(o, security, message, transactionId, out pfInfo); if (tuples == null) { this.AddWarningLog(LocalizedStrings.Str1156Params, message.OrderId.To<string>() ?? message.OrderStringId); return; } if (pfInfo != null) ProcessPortfolio(pfInfo); foreach (var tuple in tuples) { var order = tuple.Item1; var isNew = tuple.Item2; var isChanged = tuple.Item3; if (message.OrderType == OrderTypes.Conditional && (message.DerivedOrderId != null || !message.DerivedOrderStringId.IsEmpty())) { var derivedOrder = _entityCache.GetOrder(order.Security, 0L, message.DerivedOrderId ?? 0, message.DerivedOrderStringId); if (derivedOrder == null) _orderStopOrderAssociations.Add(Tuple.Create(message.DerivedOrderId, message.DerivedOrderStringId), new RefPair<Order, Action<Order, Order>>(order, (s, o1) => s.DerivedOrder = o1)); else order.DerivedOrder = derivedOrder; } if (message.OrderState == OrderStates.Active || message.OrderState == OrderStates.Done) { var info = _filteredMarketDepths.TryGetValue(order.Security); info?.Process(message); } if (isNew) { this.AddOrderInfoLog(order, "New order"); if (order.Type == OrderTypes.Conditional) RaiseNewStopOrders(new[] { order }); else RaiseNewOrder(order); } else if (isChanged) { this.AddOrderInfoLog(order, "Order changed"); if (order.Type == OrderTypes.Conditional) RaiseStopOrdersChanged(new[] { order }); else RaiseOrderChanged(order); } if (order.Id != null) ProcessMyTrades(order, order.Id.Value, _nonAssociatedByIdMyTrades); ProcessMyTrades(order, order.TransactionId, _nonAssociatedByTransactionIdMyTrades); if (!order.StringId.IsEmpty()) ProcessMyTrades(order, order.StringId, _nonAssociatedByStringIdMyTrades); ProcessConditionOrders(order); } } else { foreach (var tuple in _entityCache.ProcessOrderFailMessage(o, security, message)) { var fail = tuple.Item1; //TryProcessFilteredMarketDepth(fail.Order.Security, message); //var isRegisterFail = (fail.Order.Id == null && fail.Order.StringId.IsEmpty()) || fail.Order.Status == OrderStatus.RejectedBySystem; var isCancelTransaction = tuple.Item2; this.AddErrorLog(() => (isCancelTransaction ? "OrderCancelFailed" : "OrderRegisterFailed") + Environment.NewLine + fail.Order + Environment.NewLine + fail.Error); var isStop = fail.Order.Type == OrderTypes.Conditional; if (!isCancelTransaction) { _entityCache.AddRegisterFail(fail); if (isStop) RaiseStopOrdersRegisterFailed(new[] { fail }); else RaiseOrderRegisterFailed(fail); } else { _entityCache.AddCancelFail(fail); if (isStop) RaiseStopOrdersCancelFailed(new[] { fail }); else RaiseOrderCancelFailed(fail); } } } }
protected override void WriterFixOrderCondition(IFixWriter writer, ExecutionMessage message) { writer.WriteOrderCondition((QuikOrderCondition)message.Condition, TransactionSession.DateTimeFormat); }
private void OnSessionOrderChanged(LmaxOrder lmaxOrder) { var transactionId = TryParseTransactionId(lmaxOrder.InstructionId); if (transactionId == null) { return; } LmaxOrderCondition condition = null; decimal price = 0; OrderTypes orderType; switch (lmaxOrder.OrderType) { case OrderType.MARKET: orderType = OrderTypes.Market; break; case OrderType.LIMIT: orderType = OrderTypes.Limit; if (lmaxOrder.LimitPrice == null) { throw new ArgumentException(LocalizedStrings.Str3394Params.Put(transactionId), nameof(lmaxOrder)); } price = (decimal)lmaxOrder.LimitPrice; break; case OrderType.STOP_ORDER: case OrderType.STOP_LOSS_MARKET_ORDER: case OrderType.STOP_PROFIT_LIMIT_ORDER: orderType = OrderTypes.Conditional; if (lmaxOrder.StopPrice == null) { throw new ArgumentException(LocalizedStrings.Str3395Params.Put(transactionId), nameof(lmaxOrder)); } price = (decimal)lmaxOrder.StopPrice; condition = new LmaxOrderCondition { StopLossOffset = lmaxOrder.StopLossOffset, TakeProfitOffset = lmaxOrder.StopProfitOffset, }; break; case OrderType.CLOSE_OUT_ORDER_POSITION: case OrderType.CLOSE_OUT_POSITION: case OrderType.SETTLEMENT_ORDER: case OrderType.OFF_ORDERBOOK: case OrderType.REVERSAL: case OrderType.UNKNOWN: orderType = OrderTypes.Execute; break; default: throw new ArgumentOutOfRangeException(); } DateTimeOffset?expiryDate = null; var tif = StockSharpTimeInForce.PutInQueue; switch (lmaxOrder.TimeInForce) { case LmaxTimeInForce.FillOrKill: tif = StockSharpTimeInForce.MatchOrCancel; break; case LmaxTimeInForce.ImmediateOrCancel: tif = StockSharpTimeInForce.CancelBalance; break; case LmaxTimeInForce.GoodForDay: expiryDate = DateTime.Today.ApplyTimeZone(TimeZoneInfo.Utc); break; case LmaxTimeInForce.GoodTilCancelled: break; case LmaxTimeInForce.Unknown: throw new NotSupportedException(LocalizedStrings.Str3396Params.Put(lmaxOrder.TimeInForce, transactionId.Value, lmaxOrder.OrderId)); default: throw new InvalidOperationException(LocalizedStrings.Str3397Params.Put(lmaxOrder.TimeInForce, transactionId.Value, lmaxOrder.OrderId)); } var msg = new ExecutionMessage { SecurityId = new SecurityId { Native = lmaxOrder.InstrumentId }, OriginalTransactionId = transactionId.Value, OrderType = orderType, OrderPrice = price, Condition = condition, OrderVolume = lmaxOrder.Quantity.Abs(), Side = lmaxOrder.Quantity > 0 ? Sides.Buy : Sides.Sell, Balance = lmaxOrder.Quantity - lmaxOrder.FilledQuantity, PortfolioName = lmaxOrder.AccountId.To <string>(), TimeInForce = tif, ExpiryDate = expiryDate, OrderStringId = lmaxOrder.OrderId, ExecutionType = ExecutionTypes.Transaction, Commission = lmaxOrder.Commission, ServerTime = CurrentTime.Convert(TimeZoneInfo.Utc), HasOrderInfo = true, }; msg.OrderState = lmaxOrder.CancelledQuantity > 0 ? OrderStates.Done : (msg.Balance == 0 ? OrderStates.Done : OrderStates.Active); //msg.Action = lmaxOrder.CancelledQuantity > 0 // ? ExecutionActions.Canceled // : (lmaxOrder.FilledQuantity == 0 ? ExecutionActions.Registered : ExecutionActions.Matched); SendOutMessage(msg); }
public Tuple <OrderFail, bool> ProcessOrderFailMessage(Security security, ExecutionMessage message) { if (security == null) { throw new ArgumentNullException("security"); } if (message == null) { throw new ArgumentNullException("message"); } var data = _cache.GetData(security); Order order = null; if (!message.OrderStringId.IsEmpty()) { order = data.OrdersByStringId.TryGetValue(message.OrderStringId); } bool isCancelled; if (order == null) { if (message.OriginalTransactionId == 0) { throw new ArgumentOutOfRangeException("message", message.OriginalTransactionId, LocalizedStrings.Str715); } var orders = data.Orders; order = (Order)orders.TryGetValue(CreateOrderKey(message.OrderType, message.OriginalTransactionId, true)); if (order != null && order.Id == message.OrderId) { isCancelled = true; } else { order = (Order)orders.TryGetValue(CreateOrderKey(message.OrderType, message.OriginalTransactionId, false)); isCancelled = false; } if (order == null) { return(null); } } else { var pair = data.Orders.LastOrDefault(p => p.Value.Order == order); isCancelled = pair.Key.Item3; } // ServerTime для заявки - это время регистрации order.LastChangeTime = message.LocalTime; order.LocalTime = message.LocalTime; if (message.OrderStatus != null) { order.Status = message.OrderStatus; } //для ошибок снятия не надо менять состояние заявки if (!isCancelled) { order.State = OrderStates.Failed; } if (message.Commission != null) { order.Commission = message.Commission; } message.CopyExtensionInfo(order); var error = message.Error ?? new InvalidOperationException( isCancelled ? LocalizedStrings.Str716 : LocalizedStrings.Str717); var fail = EntityFactory.CreateOrderFail(order, error); fail.ServerTime = message.ServerTime; fail.LocalTime = message.LocalTime; return(Tuple.Create(fail, isCancelled)); }
public static string PrintExecutionMsg(ExecutionMessage msg) { Execution exe = msg.Execution; return(string.Format("executioID {0}, orderID {1}, side {2}, price {3}, qty {4}, reqeustID {5}.", exe.ExecId, exe.OrderId, exe.Side, exe.Price, exe.Shares, msg.ReqId)); }
/// <summary> /// Обработать сообщение. /// </summary> /// <param name="message">Сообщение.</param> /// <returns>Результат обработки. Если будет возрвщено <see langword="null"/>, /// то генератору пока недостаточно данных для генерации нового сообщения.</returns> protected override Message OnProcess(Message message) { DateTimeOffset time; switch (message.Type) { case MessageTypes.Level1Change: { var l1Msg = (Level1ChangeMessage)message; var value = l1Msg.Changes.TryGetValue(Level1Fields.LastTradePrice); if (value != null) { _lastOrderPrice = (decimal)value; } TradeGenerator.Process(message); time = l1Msg.ServerTime; break; } case MessageTypes.Execution: { var execMsg = (ExecutionMessage)message; switch (execMsg.ExecutionType) { case ExecutionTypes.Tick: _lastOrderPrice = execMsg.GetTradePrice(); break; default: return(null); } time = execMsg.ServerTime; break; } case MessageTypes.Time: { var timeMsg = (TimeMessage)message; time = timeMsg.ServerTime; break; } default: return(null); } if (!IsTimeToGenerate(time)) { return(null); } // TODO более реалистичную генерацию, так как сейчас объемы, цены и сделки c потолка var action = RandomGen.GetInt(0, 5); var isNew = action < 3 || _activeOrders.IsEmpty(); ExecutionMessage item; if (isNew) { var priceStep = SecurityDefinition.PriceStep ?? 0.01m; _lastOrderPrice += RandomGen.GetInt(-MaxPriceStepCount, MaxPriceStepCount) * priceStep; if (_lastOrderPrice <= 0) { _lastOrderPrice = priceStep; } item = new ExecutionMessage { OrderId = IdGenerator.GetNextId(), SecurityId = SecurityId, ServerTime = time, OrderState = OrderStates.Active, Volume = Volumes.Next(), Side = RandomGen.GetEnum <Sides>(), Price = _lastOrderPrice, ExecutionType = ExecutionTypes.OrderLog, }; _activeOrders.Enqueue((ExecutionMessage)item.Clone()); } else { var activeOrder = _activeOrders.Peek(); item = (ExecutionMessage)activeOrder.Clone(); item.ServerTime = time; var isMatched = action == 5; ExecutionMessage trade = null; if (isMatched) { trade = (ExecutionMessage)TradeGenerator.Process(message); } if (isMatched && trade != null) { item.Volume = RandomGen.GetInt(1, (int)activeOrder.GetVolume()); item.TradeId = trade.TradeId; item.TradePrice = trade.TradePrice; item.TradeStatus = trade.TradeStatus; // TODO //quote.Trade = TradeGenerator.Generate(time); //item.Volume = activeOrder.Volume; //if (item.Side == Sides.Buy && quote.Trade.Price > quote.Order.Price) // item.TradePrice = item.Price; //else if (item.Side == Sides.Sell && quote.Trade.Price < quote.Order.Price) // item.TradePrice = item.Price; activeOrder.Volume -= item.Volume; if (activeOrder.Volume == 0) { item.OrderState = OrderStates.Done; _activeOrders.Dequeue(); } else { item.OrderState = OrderStates.Active; } } else { item.OrderState = OrderStates.Done; item.IsCancelled = true; _activeOrders.Dequeue(); } } LastGenerationTime = time; return(item); }
private ExecutionMessage getExeMessage_for_Sell3Contract() { ExecutionMessage message = new ExecutionMessage(3001, getContract(), getExecution_for_Sell3Contract()); return(message); }
private Message ProcessBuilders(ExecutionMessage execMsg) { List <long> nonBuilderIds = null; foreach (var subscriptionId in execMsg.GetSubscriptionIds()) { if (!_subscriptionIds.TryGetValue(subscriptionId, out var info)) { if (nonBuilderIds == null) { nonBuilderIds = new List <long>(); } nonBuilderIds.Add(subscriptionId); // can be non OL->MB subscription //this.AddDebugLog("OL processing {0}/{1} not found.", execMsg.SecurityId, subscriptionId); continue; } if (!info.IsTicks) { try { QuoteChangeMessage depth; lock (info.Lock) { depth = info.Builder.Update(execMsg); if (info.State != SubscriptionStates.Online) { depth = null; } else { depth = depth?.TypedClone(); } } this.AddDebugLog("OL->MD processing {0}={1}.", execMsg.SecurityId, depth != null); if (depth != null) { depth.SetSubscriptionIds(subscriptionId: subscriptionId); base.OnInnerAdapterNewOutMessage(depth); } } catch (Exception ex) { // если ОЛ поврежден, то не нарушаем весь цикл обработки сообщения // а только выводим сообщение в лог base.OnInnerAdapterNewOutMessage(ex.ToErrorMessage()); } } else { this.AddDebugLog("OL->TICK processing {0}.", execMsg.SecurityId); base.OnInnerAdapterNewOutMessage(execMsg.ToTick()); } } if (nonBuilderIds is null) { return(null); } execMsg.SetSubscriptionIds(nonBuilderIds.ToArray()); return(execMsg); }
private static string OrderToString(ExecutionMessage order) { return string.Format("{0};{1};{2};{3};{4};{5};{6};{7};{8};{9};{10};{11};{12}", order.OrderId, order.OriginalTransactionId, order.ServerTime, order.SecurityId.SecurityCode, order.PortfolioName, order.Volume, order.Balance, order.Price, order.OriginSide, order.OrderType, order.OrderState, order.IsCancelled, order.LocalTime); }
private static string MyTradeToString(ExecutionMessage trade) { return $"{trade.SecurityId.SecurityCode};{trade.TradeId};{trade.ServerTime};{trade.TradePrice};{trade.TradeVolume};{trade.Side};{trade.OrderId}"; }
private static string OrderToString(ExecutionMessage order) { return $"{order.OrderId};{order.OriginalTransactionId};{order.ServerTime};{order.SecurityId.SecurityCode};{order.PortfolioName};{order.OrderVolume};{order.Balance};{order.OrderPrice};{order.OriginSide};{order.OrderType};{order.OrderState};{order.IsCancelled};{order.LocalTime}"; }
/// <summary> /// To convert the tick trade. /// </summary> /// <param name="tick">Tick trade.</param> /// <returns>Stream <see cref="ExecutionMessage"/>.</returns> public IEnumerable <ExecutionMessage> ToExecutionLog(ExecutionMessage tick) { if (tick == null) { throw new ArgumentNullException(nameof(tick)); } if (!_priceStepUpdated) { _securityDefinition.PriceStep = tick.GetTradePrice().GetDecimalInfo().EffectiveScale.GetPriceStep(); _priceStepUpdated = true; } if (!_volumeStepUpdated) { var tickVolume = tick.TradeVolume; if (tickVolume != null) { _securityDefinition.VolumeStep = tickVolume.Value.GetDecimalInfo().EffectiveScale.GetPriceStep(); _volumeStepUpdated = true; } } //if (tick.ExecutionType != ExecutionTypes.Tick) // throw new ArgumentOutOfRangeException(nameof(tick), tick.ExecutionType, LocalizedStrings.Str1655); //_lastTradeDate = message.LocalTime.Date; var retVal = new List <ExecutionMessage>(); var bestBid = _bids.FirstOrDefault(); var bestAsk = _asks.FirstOrDefault(); var tradePrice = tick.GetTradePrice(); var volume = tick.TradeVolume ?? 1; var time = tick.LocalTime; if (bestBid.Value != null && tradePrice <= bestBid.Key) { // тик попал в биды, значит была крупная заявка по рынку на продажу, // которая возможна исполнила наши заявки ProcessMarketOrder(retVal, _bids, tick.ServerTime, tick.LocalTime, Sides.Sell, tradePrice, volume); // подтягиваем противоположные котировки и снимаем лишние заявки TryCreateOppositeOrder(retVal, _asks, time, tick.ServerTime, tradePrice, volume, Sides.Buy); } else if (bestAsk.Value != null && tradePrice >= bestAsk.Key) { // тик попал в аски, значит была крупная заявка по рынку на покупку, // которая возможна исполнила наши заявки ProcessMarketOrder(retVal, _asks, tick.ServerTime, tick.LocalTime, Sides.Buy, tradePrice, volume); TryCreateOppositeOrder(retVal, _bids, time, tick.ServerTime, tradePrice, volume, Sides.Sell); } else if (bestBid.Value != null && bestAsk.Value != null && bestBid.Key < tradePrice && tradePrice < bestAsk.Key) { // тик попал в спред, значит в спреде до сделки была заявка. // создаем две лимитки с разных сторон, но одинаковой ценой. // если в эмуляторе есть наша заявка на этом уровне, то она исполниться. // если нет, то эмулятор взаимно исполнит эти заявки друг об друга var originSide = GetOrderSide(tick); retVal.Add(CreateMessage(time, tick.ServerTime, originSide, tradePrice, volume + (_securityDefinition.VolumeStep ?? 1 * _settings.VolumeMultiplier), tif: TimeInForce.MatchOrCancel)); var spreadStep = _settings.SpreadSize * GetPriceStep(); // try to fill depth gaps var newBestPrice = tradePrice + spreadStep; var depth = _settings.MaxDepth; while (--depth > 0) { var diff = bestAsk.Key - newBestPrice; if (diff > 0) { retVal.Add(CreateMessage(time, tick.ServerTime, Sides.Sell, newBestPrice, 0)); newBestPrice += spreadStep * _priceRandom.Next(1, _settings.SpreadSize); } else { break; } } newBestPrice = tradePrice - spreadStep; depth = _settings.MaxDepth; while (--depth > 0) { var diff = newBestPrice - bestBid.Key; if (diff > 0) { retVal.Add(CreateMessage(time, tick.ServerTime, Sides.Buy, newBestPrice, 0)); newBestPrice -= spreadStep * _priceRandom.Next(1, _settings.SpreadSize); } else { break; } } retVal.Add(CreateMessage(time, tick.ServerTime, originSide.Invert(), tradePrice, volume, tif: TimeInForce.MatchOrCancel)); } else { // если у нас стакан был полу пустой, то тик формирует некий ценовой уровень в стакана, // так как прошедщая заявка должна была обо что-то удариться. допускаем, что после // прохождения сделки на этом ценовом уровне остался объем равный тиковой сделки var hasOpposite = true; Sides originSide; // определяем направление псевдо-ранее существовавшей заявки, из которой получился тик if (bestBid.Value != null) { originSide = Sides.Sell; } else if (bestAsk.Value != null) { originSide = Sides.Buy; } else { originSide = GetOrderSide(tick); hasOpposite = false; } retVal.Add(CreateMessage(time, tick.ServerTime, originSide, tradePrice, volume)); // если стакан был полностью пустой, то формируем сразу уровень с противоположной стороны if (!hasOpposite) { var oppositePrice = tradePrice + _settings.SpreadSize * GetPriceStep() * (originSide == Sides.Buy ? 1 : -1); if (oppositePrice > 0) { retVal.Add(CreateMessage(time, tick.ServerTime, originSide.Invert(), oppositePrice, volume)); } } } if (!HasDepth(time)) { // если стакан слишком разросся, то удаляем его хвосты (не удаляя пользовательские заявки) CancelWorstQuote(retVal, time, tick.ServerTime, Sides.Buy, _bids); CancelWorstQuote(retVal, time, tick.ServerTime, Sides.Sell, _asks); } _prevTickPrice = tradePrice; return(retVal); }
//public static int GetPermId(this MyTrade trade) //{ // return trade.GetValue<int>(_permId); //} internal static void SetPermId(this ExecutionMessage trade, int permId) { trade.AddValue(_permId, permId); }
public OrderChangeInfo ApplyChanges(ExecutionMessage message, bool isCancel) { var order = Order; OrderChangeInfo retVal; if (order.State == OrderStates.Done) { // данные о заявке могут приходить из маркет-дата и транзакционного адаптеров retVal = OrderChangeInfo.Create(order, _raiseNewOrder, false); _raiseNewOrder = false; return(retVal); //throw new InvalidOperationException("Изменение заявки в состоянии Done невозможно."); } else if (order.State == OrderStates.Failed) { // some adapters can resend order's info //throw new InvalidOperationException(); return(null); } var isPending = order.State == OrderStates.Pending; if (message.OrderId != null) { order.Id = message.OrderId.Value; } if (!message.OrderStringId.IsEmpty()) { order.StringId = message.OrderStringId; } if (!message.OrderBoardId.IsEmpty()) { order.BoardId = message.OrderBoardId; } //// некоторые коннекторы не транслируют при отмене отмененный объем //// esper. при перерегистрации заявок необходимо обновлять баланс //if (message.Balance > 0 || !isCancelled || isReRegisterCancelled) //{ // // BTCE коннектор не транслирует баланс заявки // if (!(message.OrderState == OrderStates.Active && message.Balance == 0)) // order.Balance = message.Balance; //} if (message.Balance != null) { order.Balance = message.Balance.Value; } // IB коннектор не транслирует состояние заявки в одном из своих сообщений if (message.OrderState != null) { order.State = order.State.CheckModification(message.OrderState.Value); } if (order.Time == DateTimeOffset.MinValue) { order.Time = message.ServerTime; } // для новых заявок используем серверное время, // т.к. заявка получена первый раз и не менялась // ServerTime для заявки - это время регистрации order.LastChangeTime = _raiseNewOrder ? message.ServerTime : message.LocalTime; order.LocalTime = message.LocalTime; //нулевой объем может быть при перерегистрации if (order.Volume == 0 && message.OrderVolume != null) { order.Volume = message.OrderVolume.Value; } if (message.Commission != null) { order.Commission = message.Commission; } if (!message.CommissionCurrency.IsEmpty()) { order.CommissionCurrency = message.CommissionCurrency; } if (message.TimeInForce != null) { order.TimeInForce = message.TimeInForce.Value; } if (message.Latency != null) { if (isCancel) { order.LatencyCancellation = message.Latency.Value; } else if (isPending) { if (order.State != OrderStates.Pending) { order.LatencyRegistration = message.Latency.Value; } } } if (message.AveragePrice != null) { order.AveragePrice = message.AveragePrice; } if (message.Yield != null) { order.Yield = message.Yield; } message.CopyExtensionInfo(order); retVal = OrderChangeInfo.Create(order, _raiseNewOrder, true); _raiseNewOrder = false; return(retVal); }
internal static void SetCumulativeQuantity(this ExecutionMessage trade, int cummVolume) { trade.AddValue(_cumulativeQuantity, cummVolume); }
protected override void WriterFixOrderCondition(IFixWriter writer, ExecutionMessage message) { writer.WriteOrderCondition((QuikOrderCondition)message.Condition); }
internal static void SetAveragePrice(this ExecutionMessage trade, decimal price) { trade.AddValue(_averagePrice, price); }
private void OnOrdersResponse(OrdersResponse response) { foreach (var order in response.Orders.Cast <TransaqBaseOrder>().Concat(response.StopOrders)) { var stockSharpTransactionId = _orders.TryGetValue(order.TransactionId); if (stockSharpTransactionId == 0) { stockSharpTransactionId = order.TransactionId; // если заявка пришла от терминала, то просто идентификатор транзакции ассоциируем как стокшарповский _orders.Add(order.TransactionId, order.TransactionId); _ordersTypes.Add(order.TransactionId, order is TransaqStopOrder ? OrderTypes.Conditional : OrderTypes.Limit); } var execMsg = new ExecutionMessage { SecurityId = new SecurityId { Native = order.SecId }, Side = order.BuySell.FromTransaq(), OriginalTransactionId = stockSharpTransactionId, PortfolioName = order.Client, ExpiryDate = order.ExpDate == null ? (DateTimeOffset?)null : order.ExpDate.Value.ApplyTimeZone(TimeHelper.Moscow), ExecutionType = ExecutionTypes.Order, }; var usualOrder = order as TransaqOrder; if (usualOrder != null) { execMsg.OrderId = usualOrder.OrderNo; execMsg.Balance = usualOrder.Balance; execMsg.ServerTime = usualOrder.WithdrawTime ?? usualOrder.Time ?? usualOrder.AcceptTime ?? DateTimeOffset.MinValue; execMsg.Comment = usualOrder.BrokerRef; execMsg.SystemComment = usualOrder.Result; execMsg.Price = usualOrder.Price; execMsg.Volume = usualOrder.Quantity; execMsg.OrderType = usualOrder.Price == 0 ? OrderTypes.Market : OrderTypes.Limit; execMsg.Commission = usualOrder.MaxCommission; if (usualOrder.ConditionType != TransaqAlgoOrderConditionTypes.None) { execMsg.OrderType = OrderTypes.Conditional; execMsg.Condition = new TransaqOrderCondition { AlgoType = usualOrder.ConditionType, AlgoValue = usualOrder.ConditionValue.To <decimal>(), AlgoValidAfter = usualOrder.ValidAfter, AlgoValidBefore = usualOrder.ValidBefore, }; } } else { var stopOrder = (TransaqStopOrder)order; execMsg.OrderId = stopOrder.ActiveOrderNo; execMsg.OrderType = OrderTypes.Conditional; execMsg.ServerTime = stopOrder.AcceptTime == null ? DateTimeOffset.MinValue : stopOrder.AcceptTime.Value.ApplyTimeZone(TimeHelper.Moscow); var stopCond = new TransaqOrderCondition { Type = stopOrder.StopLoss != null && stopOrder.TakeProfit != null ? TransaqOrderConditionTypes.TakeProfitStopLoss : (stopOrder.StopLoss != null ? TransaqOrderConditionTypes.StopLoss : TransaqOrderConditionTypes.TakeProfit), ValidFor = stopOrder.ValidBefore, LinkedOrderId = stopOrder.LinkedOrderNo, }; if (stopOrder.StopLoss != null) { stopCond.StopLossActivationPrice = stopOrder.StopLoss.ActivationPrice; stopCond.StopLossOrderPrice = stopOrder.StopLoss.OrderPrice; stopCond.StopLossByMarket = stopOrder.StopLoss.OrderPrice == null; stopCond.StopLossVolume = stopOrder.StopLoss.Quantity; //stopCond.StopLossUseCredit = stopOrder.StopLoss.UseCredit.To<bool>(); if (stopOrder.StopLoss.GuardTime != null) { stopCond.StopLossProtectionTime = (int)stopOrder.StopLoss.GuardTime.Value.TimeOfDay.TotalMinutes; } stopCond.StopLossComment = stopOrder.StopLoss.BrokerRef; } if (stopOrder.TakeProfit != null) { stopCond.TakeProfitActivationPrice = stopOrder.TakeProfit.ActivationPrice; stopCond.TakeProfitByMarket = stopOrder.TakeProfit.GuardSpread == null; stopCond.TakeProfitVolume = stopOrder.TakeProfit.Quantity; //stopCond.TakeProfitUseCredit = stopOrder.TakeProfit.UseCredit.To<bool>(); if (stopOrder.TakeProfit.GuardTime != null) { stopCond.TakeProfitProtectionTime = (int)stopOrder.TakeProfit.GuardTime.Value.TimeOfDay.TotalMinutes; } stopCond.TakeProfitComment = stopOrder.TakeProfit.BrokerRef; stopCond.TakeProfitCorrection = stopOrder.TakeProfit.Correction; stopCond.TakeProfitProtectionSpread = stopOrder.TakeProfit.GuardSpread; } } execMsg.OrderState = order.Status.ToStockSharpState(); //execMsg.OrderStatus = order2.Status.ToStockSharpStatus(); if (order.Status != TransaqOrderStatus.cancelled) { if (execMsg.OrderState == OrderStates.Failed && usualOrder != null) { execMsg.Error = new InvalidOperationException(usualOrder.Result); } } SendOutMessage(execMsg); //if (order.Condition != null && order.DerivedOrder == null && order2.ConditionType != TransaqAlgoOrderConditionTypes.None && order2.OrderNo != 0) // AddDerivedOrder(security, order2.OrderNo, order, (stopOrder, limitOrder) => stopOrder.DerivedOrder = limitOrder); } }
internal static void SetOrderRef(this ExecutionMessage trade, string orderRef) { trade.AddValue(_orderRef, orderRef); }
public Tuple <Order, bool, bool> ProcessOrderMessage(Security security, ExecutionMessage message) { if (security == null) { throw new ArgumentNullException("security"); } if (message == null) { throw new ArgumentNullException("message"); } if (message.Error != null) { throw new ArgumentException(LocalizedStrings.Str714Params.PutEx(message)); } bool isNew; var transactionId = message.TransactionId; if (transactionId == 0) { // ExecMsg.OriginalTransactionId == OrderStatMsg.TransactionId when orders info requested by OrderStatMsg transactionId = _orderStatusTransactions.Contains(message.OriginalTransactionId) ? 0 : message.OriginalTransactionId; } var securityData = _cache.GetData(security); var orderInfo = GetOrderInfo(securityData, message.OrderType, transactionId, message.OrderId, message.OrderStringId, trId => { var o = EntityFactory.CreateOrder(security, message.OrderType, trId); o.Time = message.ServerTime; o.Price = message.Price; o.Volume = message.Volume ?? 0; o.Direction = message.Side; o.Comment = message.Comment; o.ExpiryDate = message.ExpiryDate; o.Condition = message.Condition; o.UserOrderId = message.UserOrderId; o.Portfolio = message.PortfolioName.IsEmpty() ? _portfolios.FirstOrDefault().Value : ProcessPortfolio(message.PortfolioName).Item1; return(o); }, out isNew, true); var order = orderInfo.Item1; var isCancelled = orderInfo.Item2; //var isReReregisterCancelled = orderInfo.Item3; var raiseNewOrder = orderInfo.Item3; var isPending = order.State == OrderStates.Pending; //var isPrevIdSet = (order.Id != null || !order.StringId.IsEmpty()); bool isChanged; if (order.State == OrderStates.Done) { // данные о заявке могут приходить из маркет-дата и транзакционного адаптеров isChanged = false; //throw new InvalidOperationException("Изменение заявки в состоянии Done невозможно."); } else { if (message.OrderId != null) { order.Id = message.OrderId.Value; } if (!message.OrderStringId.IsEmpty()) { order.StringId = message.OrderStringId; } if (!message.OrderBoardId.IsEmpty()) { order.BoardId = message.OrderBoardId; } //// некоторые коннекторы не транслируют при отмене отмененный объем //// esper. при перерегистрации заявок необходимо обновлять баланс //if (message.Balance > 0 || !isCancelled || isReReregisterCancelled) //{ // // BTCE коннектор не транслирует баланс заявки // if (!(message.OrderState == OrderStates.Active && message.Balance == 0)) // order.Balance = message.Balance; //} if (message.Balance != null) { order.Balance = message.Balance.Value; } // IB коннектор не транслирует состояние заявки в одном из своих сообщений if (message.OrderState != null) { order.State = message.OrderState.Value; } if (order.Time == DateTimeOffset.MinValue) { order.Time = message.ServerTime; } // для новых заявок используем серверное время, // т.к. заявка получена первый раз и не менялась // ServerTime для заявки - это время регистрации order.LastChangeTime = isNew ? message.ServerTime : message.LocalTime; order.LocalTime = message.LocalTime; //нулевой объем может быть при перерегистрации if (order.Volume == 0 && message.Volume != null) { order.Volume = message.Volume.Value; } if (message.Commission != null) { order.Commission = message.Commission; } if (message.TimeInForce != null) { order.TimeInForce = message.TimeInForce.Value; } if (isPending) { if (order.State != OrderStates.Pending && message.Latency != null) { order.LatencyRegistration = message.Latency.Value; } } else if (isCancelled && order.State == OrderStates.Done) { if (message.Latency != null) { order.LatencyCancellation = message.Latency.Value; } } isChanged = true; } //if (isNew || (!isPrevIdSet && (order.Id != null || !order.StringId.IsEmpty()))) //{ // так как биржевые идентифиаторы могут повторяться, то переписываем старые заявки новыми как наиболее актуальными if (order.Id != null) { securityData.OrdersById[order.Id.Value] = order; _cache.AllOrdersById[order.Id.Value] = order; } if (!order.StringId.IsEmpty()) { securityData.OrdersByStringId[order.StringId] = order; _cache.AllOrdersByStringId[order.StringId] = order; } //} //if (message.OrderType == OrderTypes.Conditional && (message.DerivedOrderId != null || !message.DerivedOrderStringId.IsEmpty())) //{ // var derivedOrder = GetOrder(security, 0L, message.DerivedOrderId ?? 0, message.DerivedOrderStringId); // if (order == null) // _orderStopOrderAssociations.Add(Tuple.Create(message.DerivedOrderId ?? 0, message.DerivedOrderStringId), new RefPair<Order, Action<Order, Order>>(order, (s, o) => s.DerivedOrder = o)); // else // order.DerivedOrder = derivedOrder; //} message.CopyExtensionInfo(order); return(Tuple.Create(order, raiseNewOrder, isChanged)); }
internal static void SetEvRule(this ExecutionMessage trade, string rule) { trade.AddValue(_evRule, rule); }
public Tuple <MyTrade, bool> ProcessMyTradeMessage(Security security, ExecutionMessage message) { if (security == null) { throw new ArgumentNullException("security"); } if (message == null) { throw new ArgumentNullException("message"); } var originalTransactionId = _orderStatusTransactions.Contains(message.OriginalTransactionId) ? 0 : message.OriginalTransactionId; if (originalTransactionId == 0 && message.OrderId == null && message.OrderStringId.IsEmpty()) { throw new ArgumentOutOfRangeException("message", originalTransactionId, LocalizedStrings.Str715); } var securityData = _cache.GetData(security); var myTrade = securityData.MyTrades.TryGetValue(Tuple.Create(originalTransactionId, message.TradeId ?? 0)); if (myTrade != null) { return(Tuple.Create(myTrade, false)); } var order = GetOrder(security, originalTransactionId, message.OrderId, message.OrderStringId); if (order == null) { return(null); } var trade = message.ToTrade(EntityFactory.CreateTrade(security, message.TradeId, message.TradeStringId)); var isNew = false; myTrade = securityData.MyTrades.SafeAdd(Tuple.Create(order.TransactionId, trade.Id), key => { isNew = true; var t = EntityFactory.CreateMyTrade(order, trade); if (t.ExtensionInfo == null) { t.ExtensionInfo = new Dictionary <object, object>(); } if (message.Commission != null) { t.Commission = message.Commission; } if (message.Slippage != null) { t.Slippage = message.Slippage; } message.CopyExtensionInfo(t); //trades.Add(t); _cache.MyTrades.Add(t); return(t); }); return(Tuple.Create(myTrade, isNew)); // mika // http://stocksharp.com/forum/yaf_postst1072_Probliemy-so-sdielkami--pozitsiiami.aspx // из-за того, что сделки по заявке иногда приходит быстрее события NewOrders, неправильно расчитывается поза по стратегиям //var raiseOrderChanged = false; //trades.SyncDo(d => //{ // var newBalance = order.Volume - d.Sum(t => t.Trade.Volume); // if (order.Balance > newBalance) // { // raiseOrderChanged = true; // order.Balance = newBalance; // if (order.Balance == 0) // order.State = OrderStates.Done; // } //}); //if (raiseOrderChanged) // RaiseOrderChanged(order); }
internal static void SetEvMultiplier(this ExecutionMessage trade, decimal multiplier) { trade.AddValue(_evMultiplier, multiplier); }
private void ProcessExecutionMessage(ExecutionMessage message) { if (message.ExecutionType == null) throw new ArgumentException(LocalizedStrings.Str688Params.Put(message)); switch (message.ExecutionType) { case ExecutionTypes.Transaction: { if (_entityCache.IsMassCancelation(message.OriginalTransactionId)) { if (message.Error == null) RaiseMassOrderCanceled(message.OriginalTransactionId); else RaiseMassOrderCancelFailed(message.OriginalTransactionId, message.Error); break; } long transactionId; var order = _entityCache.GetOrder(message, out transactionId); if (order == null) { var security = LookupSecurity(message.SecurityId); ProcessTransactionMessage(null, security, message, transactionId); } else { ProcessTransactionMessage(order, order.Security, message, transactionId); } break; } case ExecutionTypes.Tick: case ExecutionTypes.OrderLog: //case null: { var security = LookupSecurity(message.SecurityId); switch (message.ExecutionType) { case ExecutionTypes.Tick: ProcessTradeMessage(security, message); break; case ExecutionTypes.OrderLog: ProcessOrderLogMessage(security, message); break; } if (CreateAssociatedSecurity && !IsAssociated(message.SecurityId.BoardCode)) { var clone = (ExecutionMessage)message.Clone(); clone.SecurityId = CreateAssociatedId(clone.SecurityId); ProcessExecutionMessage(clone); } break; } default: throw new ArgumentOutOfRangeException(LocalizedStrings.Str1695Params.Put(message.ExecutionType)); } }
internal static void SetLastTradePrice(this ExecutionMessage order, decimal price) { order.AddValue(_lastTradePrice, price); }
void IDisposable.Dispose() { Current = null; _itemsEnumerator.Dispose(); }
internal static void SetWhyHeld(this ExecutionMessage order, string whyHeld) { order.AddValue(_whyHeld, whyHeld); }