private void ProcessOrderRegisterMessage(OrderRegisterMessage message) { var condition = (OandaOrderCondition)message.Condition; string type; if (condition == null) type = message.Price == 0 ? "market" : "limit"; else type = condition.IsMarket ? _orderImit : "stop"; var response = _restClient.CreateOrder(GetAccountId(message.PortfolioName), message.SecurityId.ToOanda(), (int)message.Volume, message.Side.To<string>().ToLowerInvariant(), type, GetExpiryTime(message), message.Price, condition?.LowerBound, condition?.UpperBound, condition?.StopLossOffset, condition?.TakeProfitOffset, condition?.TrailingStopLossOffset); var execMsg = new ExecutionMessage { OriginalTransactionId = message.TransactionId, ServerTime = response.Time.FromOanda(), ExecutionType = ExecutionTypes.Transaction, PortfolioName = message.PortfolioName, HasOrderInfo = true, }; var tradeData = response.TradeOpened; if (tradeData != null) { execMsg.OrderState = OrderStates.Done; execMsg.OrderId = tradeData.Id; } else { execMsg.OrderState = OrderStates.Active; execMsg.OrderId = response.OrderOpened.Id; } SendOutMessage(execMsg); if (tradeData != null) { SendOutMessage(new ExecutionMessage { OriginalTransactionId = message.TransactionId, ExecutionType = ExecutionTypes.Transaction, TradePrice = (decimal)tradeData.Price, TradeVolume = tradeData.Units, ServerTime = tradeData.Time.FromOanda(), TradeId = tradeData.Id, HasTradeInfo = true, }); } }
/// <summary> /// Рассчитать комиссию. /// </summary> /// <param name="message">Сообщение, содержащее информацию по заявке или собственной сделке.</param> /// <returns>Комиссия. Если комиссию рассчитать невозможно, то будет возвращено <see langword="null"/>.</returns> public decimal? ProcessExecution(ExecutionMessage message) { var commission = OnProcessExecution(message); if (commission != null) Commission += commission.Value; return commission; }
/// <summary> /// Initializes a new instance of the <see cref="PnLInfo"/>. /// </summary> /// <param name="trade">Own trade.</param> /// <param name="closedVolume">The volume of position, which was closed by own trade.</param> /// <param name="pnL">The profit, realized by this trade.</param> public PnLInfo(ExecutionMessage trade, decimal closedVolume, decimal pnL) { if (trade == null) throw new ArgumentNullException(nameof(trade)); if (closedVolume < 0) throw new ArgumentOutOfRangeException(nameof(closedVolume), closedVolume, LocalizedStrings.Str946); Trade = trade; ClosedVolume = closedVolume; PnL = pnL; }
/// <summary> /// To calculate commission. /// </summary> /// <param name="message">The message containing the information about the order or own trade.</param> /// <returns>The commission. If the commission can not be calculated then <see langword="null" /> will be returned.</returns> public virtual decimal? ProcessExecution(ExecutionMessage message) { if (_rules.Count == 0) return null; var commission = _rules.Cache.Sum(rule => rule.ProcessExecution(message)); if (commission != null) Commission += commission.Value; return commission; }
/// <summary> /// Рассчитать прибыльность сделки. Если сделка уже ранее была обработана, то возвращается предыдущая информация. /// </summary> /// <param name="trade">Сделка.</param> /// <returns>Информация о новой сделке.</returns> public virtual PnLInfo ProcessMyTrade(ExecutionMessage trade) { if (trade == null) throw new ArgumentNullException("trade"); lock (_portfolioManagers.SyncRoot) { var manager = _portfolioManagers.SafeAdd(trade.PortfolioName, pf => new PortfolioPnLManager(pf)); PnLInfo info; if (manager.ProcessMyTrade(trade, out info)) _realizedPnL += info.PnL; return info; } }
/// <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; }
/// <summary> /// Callback of the order (re)registration. /// </summary> /// <param name="transId">Transaction ID.</param> /// <param name="data">(Re)registration result.</param> /// <param name="ex">(Re)registration error.</param> private void ClientOnOrderRegisterResult(long transId, PlaceEquityOrderResponse2 data, Exception ex) { if (ex != null) { this.AddWarningLog("RegisterOrder: {0}", ex); SendOutMessage(new ExecutionMessage { OriginalTransactionId = transId, OrderState = OrderStates.Failed, Error = new InvalidOperationException(LocalizedStrings.Str2258Params.Put(transId, ex)), OrderStatus = OrderStatus.RejectedBySystem, ExecutionType = ExecutionTypes.Transaction, HasOrderInfo = true, }); return; } var msg = new ExecutionMessage { SecurityId = new SecurityId { SecurityCode = data.symbol, BoardCode = AssociatedBoardCode }, PortfolioName = data.accountId.To<string>(), Side = data.orderAction.ETradeActionToSide(), OriginalTransactionId = transId, OrderState = OrderStates.Active, OrderId = data.orderNum, ExecutionType = ExecutionTypes.Transaction, ServerTime = ETradeUtil.ETradeTimestampToUTC(data.orderTime), HasOrderInfo = true, }; SaveOrder(transId, msg.OrderId ?? 0); if (data.messageList != null) { foreach (var m in data.messageList) this.AddDebugLog("ord #{0}: ({1}) {2}", data.orderNum, m.msgCode, m.msgDesc); } SendOutMessage(msg); }
public Tuple<Order, bool, bool> ProcessOrderMessage(Security security, ExecutionMessage message) { if (security == null) throw new ArgumentNullException(nameof(security)); if (message == null) throw new ArgumentNullException(nameof(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 = 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.OrderPrice; o.Volume = message.OrderVolume ?? 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; o.ClientCode = message.ClientCode; return o; }, out isNew, true); if (orderInfo == null) return null; 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.OrderVolume != null) order.Volume = message.OrderVolume.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; _allOrdersById[order.Id.Value] = order; } if (!order.StringId.IsEmpty()) { securityData.OrdersByStringId[order.StringId] = order; _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); }
private void ReadOrderStatus(IBSocket socket, ServerVersions version) { var id = socket.ReadInt(); var status = socket.ReadOrderStatus(); /* filled */ socket.ReadInt(); var balance = socket.ReadDecimal(); var avgPrice = socket.ReadDecimal(); var permId = version >= ServerVersions.V2 ? socket.ReadInt() : (int?)null; var parentId = version >= ServerVersions.V3 ? socket.ReadInt() : (int?)null; var lastTradePrice = version >= ServerVersions.V4 ? socket.ReadDecimal() : (decimal?)null; var clientId = version >= ServerVersions.V5 ? socket.ReadInt() : (int?)null; var whyHeld = version >= ServerVersions.V6 ? socket.ReadStr() : null; var execMsg = new ExecutionMessage { ExecutionType = ExecutionTypes.Transaction, OriginalTransactionId = id, Balance = balance, OrderStatus = status, OrderState = status.ToOrderState(), HasOrderInfo = true, }; execMsg.SetAveragePrice(avgPrice); if (permId != null) execMsg.SetPermId(permId.Value); if (parentId != null) execMsg.Condition = new IBOrderCondition { ParentId = parentId.Value }; if (lastTradePrice != null) execMsg.SetLastTradePrice(lastTradePrice.Value); if (clientId != null) execMsg.SetClientId(clientId.Value); if (whyHeld != null) execMsg.SetWhyHeld(whyHeld); SendOutMessage(execMsg); }
protected override void WriterFixOrderCondition(IFixWriter writer, ExecutionMessage message) { writer.WriteOrderCondition((QuikOrderCondition)message.Condition, TransactionSession.DateTimeFormat); }
private void SendOutErrorExecution(ExecutionMessage execMsg, Exception ex) { execMsg.ServerTime = CurrentTime; execMsg.Error = ex; execMsg.OrderState = OrderStates.Failed; SendOutMessage(execMsg); }
/// <summary> /// Process message. /// </summary> /// <param name="message">Message.</param> /// <returns>The result of processing. If <see langword="null" /> is returned, then generator has no sufficient data to generate new message.</returns> protected override Message OnProcess(Message message) { DateTimeOffset time; switch (message.Type) { case MessageTypes.Board: return null; case MessageTypes.Level1Change: { var l1Msg = (Level1ChangeMessage)message; var value = l1Msg.Changes.TryGetValue(Level1Fields.LastTradePrice); if (value != null) _lastTradePrice = (decimal)value; time = l1Msg.ServerTime; break; } case MessageTypes.Execution: { var execMsg = (ExecutionMessage)message; switch (execMsg.ExecutionType) { case ExecutionTypes.Tick: case ExecutionTypes.Trade: _lastTradePrice = execMsg.TradePrice.Value; break; case ExecutionTypes.OrderLog: if (execMsg.TradePrice != null) _lastTradePrice = execMsg.TradePrice.Value; 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; var trade = new ExecutionMessage { SecurityId = SecurityId, TradeId = IdGenerator.GetNextId(), ServerTime = time, LocalTime = time.LocalDateTime, OriginSide = GenerateDirection ? RandomGen.GetEnum<Sides>() : (Sides?)null, Volume = Volumes.Next(), ExecutionType = ExecutionTypes.Tick }; var priceStep = SecurityDefinition.PriceStep ?? 0.01m; _lastTradePrice += RandomGen.GetInt(-MaxPriceStepCount, MaxPriceStepCount) * priceStep; if (_lastTradePrice <= 0) _lastTradePrice = priceStep; trade.TradePrice = _lastTradePrice; LastGenerationTime = time; return trade; }
/// <summary> /// Create a copy of <see cref="ExecutionMessage"/>. /// </summary> /// <returns>Copy.</returns> public override Message Clone() { var clone = new ExecutionMessage { Balance = Balance, Comment = Comment, Condition = Condition.CloneNullable(), ClientCode = ClientCode, Currency = Currency, ServerTime = ServerTime, DepoName = DepoName, Error = Error, ExpiryDate = ExpiryDate, IsSystem = IsSystem, LocalTime = LocalTime, OpenInterest = OpenInterest, OrderId = OrderId, OrderStringId = OrderStringId, OrderBoardId = OrderBoardId, ExecutionType = ExecutionType, IsCancelled = IsCancelled, //Action = Action, OrderState = OrderState, OrderStatus = OrderStatus, OrderType = OrderType, OriginSide = OriginSide, PortfolioName = PortfolioName, Price = Price, SecurityId = SecurityId, Side = Side, SystemComment = SystemComment, TimeInForce = TimeInForce, TradeId = TradeId, TradeStringId = TradeStringId, TradePrice = TradePrice, TradeStatus = TradeStatus, TransactionId = TransactionId, OriginalTransactionId = OriginalTransactionId, Volume = Volume, //IsFinished = IsFinished, VisibleVolume = VisibleVolume, IsUpTick = IsUpTick, Commission = Commission, Latency = Latency, Slippage = Slippage, UserOrderId = UserOrderId, DerivedOrderId = DerivedOrderId, DerivedOrderStringId = DerivedOrderStringId, }; this.CopyExtensionInfo(clone); return clone; }
private void SessionOnStiQuoteSnap(ref structSTIQuoteSnap structQuoteSnap) { var l1CngMsg = new Level1ChangeMessage { SecurityId = new SecurityId { SecurityCode = structQuoteSnap.bstrSymbol, BoardCode = structQuoteSnap.bstrExch }, ServerTime = structQuoteSnap.bstrUpdateTime.StrToTime(), }; if (structQuoteSnap.bAskPrice != 0) l1CngMsg.TryAdd(Level1Fields.BestAskPrice, (decimal)structQuoteSnap.fAskPrice); if (structQuoteSnap.bBidPrice != 0) l1CngMsg.TryAdd(Level1Fields.BestBidPrice, (decimal)structQuoteSnap.fBidPrice); l1CngMsg.TryAdd(Level1Fields.BestAskVolume, (decimal)structQuoteSnap.nAskSize); l1CngMsg.TryAdd(Level1Fields.BestBidVolume, (decimal)structQuoteSnap.nBidSize); if (structQuoteSnap.bOpenPrice != 0) l1CngMsg.TryAdd(Level1Fields.OpenPrice, (decimal)structQuoteSnap.fOpenPrice); if (structQuoteSnap.bHighPrice != 0) l1CngMsg.TryAdd(Level1Fields.HighPrice, (decimal)structQuoteSnap.fHighPrice); if (structQuoteSnap.bLowPrice != 0) l1CngMsg.TryAdd(Level1Fields.LowPrice, (decimal)structQuoteSnap.fLowPrice); if (structQuoteSnap.bLastPrice != 0) l1CngMsg.TryAdd(Level1Fields.LastTradePrice, (decimal)structQuoteSnap.fLastPrice); l1CngMsg.TryAdd(Level1Fields.LastTradeVolume, (decimal)structQuoteSnap.nLastSize); l1CngMsg.TryAdd(Level1Fields.OpenInterest, (decimal)structQuoteSnap.nOpenInterest); l1CngMsg.TryAdd(Level1Fields.Volume, (decimal)structQuoteSnap.nCumVolume); l1CngMsg.TryAdd(Level1Fields.VWAP, (decimal)structQuoteSnap.fVwap); l1CngMsg.TryAdd(Level1Fields.ClosePrice, (decimal)structQuoteSnap.fClosePrice); // öåíà çàêðûòèÿ ïðîøëîãî äíÿ. SendOutMessage(l1CngMsg); if (_subscribedSecuritiesToTrade.Cache.Contains(structQuoteSnap.bstrSymbol) && structQuoteSnap.fLastPrice != 0) { var tickMsg= new ExecutionMessage { ExecutionType = ExecutionTypes.Tick, SecurityId = new SecurityId{SecurityCode = structQuoteSnap.bstrSymbol,BoardCode = structQuoteSnap.bstrExch}, //TradeId = structQuoteSnap., TradePrice = (decimal)structQuoteSnap.fLastPrice, TradeVolume = structQuoteSnap.nLastSize, //OriginSide = action.ToSide(), ServerTime = structQuoteSnap.bstrUpdateTime.StrToTime() }; SendOutMessage(tickMsg); } }
QuoteChangeMessage IOrderLogMarketDepthBuilder.Update(ExecutionMessage item) { if (item == null) { throw new ArgumentNullException(nameof(item)); } if (item.ExecutionType != ExecutionTypes.OrderLog) { throw new ArgumentException(nameof(item)); } if (item.OrderPrice == 0) { return(null); } _depth.ServerTime = item.ServerTime; _depth.LocalTime = item.LocalTime; QuoteChange?changedQuote = null; var quotes = item.Side == Sides.Buy ? _bids : _asks; if (item.IsOrderLogRegistered()) { if (item.OrderVolume != null) { QuoteChange ProcessRegister <T>(T id, Dictionary <T, decimal> orders) { var quote = quotes.SafeAdd(item.OrderPrice, key => new QuoteChange(key, 0)); var volume = item.OrderVolume.Value; if (orders.TryGetValue(id, out var prevVolume)) { quote.Volume += (volume - prevVolume); orders[id] = volume; } else { quote.Volume += volume; orders.Add(id, volume); } quotes[item.OrderPrice] = quote; return(quote); } if (item.OrderId != null) { changedQuote = ProcessRegister(item.OrderId.Value, _ordersByNum); } else if (!item.OrderStringId.IsEmpty()) { changedQuote = ProcessRegister(item.OrderStringId, _ordersByString); } } } else if (item.IsOrderLogMatched()) { var volume = item.TradeVolume ?? item.OrderVolume; if (volume != null) { QuoteChange?ProcessMatched <T>(T id, Dictionary <T, decimal> orders) { if (orders.TryGetValue(id, out var prevVolume)) { orders[id] = prevVolume - volume.Value; if (quotes.TryGetValue(item.OrderPrice, out var quote)) { quote.Volume -= volume.Value; if (quote.Volume <= 0) { quotes.Remove(item.OrderPrice); } quotes[item.OrderPrice] = quote; return(quote); } } return(null); } if (item.OrderId != null) { changedQuote = ProcessMatched(item.OrderId.Value, _ordersByNum); } else if (!item.OrderStringId.IsEmpty()) { changedQuote = ProcessMatched(item.OrderStringId, _ordersByString); } } } else if (item.IsOrderLogCanceled()) { QuoteChange?ProcessCanceled <T>(T id, Dictionary <T, decimal> orders) { if (orders.TryGetAndRemove(id, out var prevVolume)) { if (quotes.TryGetValue(item.OrderPrice, out var quote)) { quote.Volume -= prevVolume; if (quote.Volume <= 0) { quotes.Remove(item.OrderPrice); } quotes[item.OrderPrice] = quote; return(quote); } } return(null); } if (item.OrderId != null) { changedQuote = ProcessCanceled(item.OrderId.Value, _ordersByNum); } else if (!item.OrderStringId.IsEmpty()) { changedQuote = ProcessCanceled(item.OrderStringId, _ordersByString); } } if (changedQuote == null) { return(null); } var increment = new QuoteChangeMessage { ServerTime = item.ServerTime, LocalTime = item.LocalTime, SecurityId = _depth.SecurityId, State = QuoteChangeStates.Increment, }; var q = changedQuote.Value; if (item.Side == Sides.Buy) { increment.Bids = new[] { q } } ; else { increment.Asks = new[] { q } }; return(increment); } }
public Tuple<MyTrade, bool> ProcessMyTradeMessage(Security security, ExecutionMessage message) { if (security == null) throw new ArgumentNullException(nameof(security)); if (message == null) throw new ArgumentNullException(nameof(message)); var originalTransactionId = _orderStatusTransactions.Contains(message.OriginalTransactionId) ? 0 : message.OriginalTransactionId; if (originalTransactionId == 0 && message.OrderId == null && message.OrderStringId.IsEmpty()) throw new ArgumentOutOfRangeException(nameof(message), originalTransactionId, LocalizedStrings.Str715); var securityData = 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); _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); }
/// <summary> /// Create a copy of <see cref="ExecutionMessage"/>. /// </summary> /// <returns>Copy.</returns> public override Message Clone() { var clone = new ExecutionMessage { Balance = Balance, Comment = Comment, Condition = Condition?.Clone(), ClientCode = ClientCode, BrokerCode = BrokerCode, Currency = Currency, ServerTime = ServerTime, DepoName = DepoName, Error = Error, ExpiryDate = ExpiryDate, IsSystem = IsSystem, OpenInterest = OpenInterest, OrderId = OrderId, OrderStringId = OrderStringId, OrderBoardId = OrderBoardId, ExecutionType = ExecutionType, IsCancelled = IsCancelled, //Action = Action, OrderState = OrderState, OrderStatus = OrderStatus, OrderType = OrderType, OriginSide = OriginSide, PortfolioName = PortfolioName, OrderPrice = OrderPrice, SecurityId = SecurityId, Side = Side, SystemComment = SystemComment, TimeInForce = TimeInForce, TradeId = TradeId, TradeStringId = TradeStringId, TradePrice = TradePrice, TradeStatus = TradeStatus, TransactionId = TransactionId, OrderVolume = OrderVolume, TradeVolume = TradeVolume, //IsFinished = IsFinished, VisibleVolume = VisibleVolume, IsUpTick = IsUpTick, Commission = Commission, Latency = Latency, Slippage = Slippage, UserOrderId = UserOrderId, //DerivedOrderId = DerivedOrderId, //DerivedOrderStringId = DerivedOrderStringId, PnL = PnL, Position = Position, HasTradeInfo = HasTradeInfo, HasOrderInfo = HasOrderInfo, IsMarketMaker = IsMarketMaker, IsMargin = IsMargin, IsManual = IsManual, CommissionCurrency = CommissionCurrency, AveragePrice = AveragePrice, Yield = Yield, MinVolume = MinVolume, SubscriptionId = SubscriptionId, SubscriptionIds = SubscriptionIds?.ToArray() }; CopyTo(clone); return(clone); }
bool IOrderLogMarketDepthBuilder.Update(ExecutionMessage item) { if (item == null) { throw new ArgumentNullException(nameof(item)); } if (item.ExecutionType != ExecutionTypes.OrderLog) { throw new ArgumentException(nameof(item)); } if (item.OrderPrice == 0) { return(false); } var changed = false; var quotes = item.Side == Sides.Buy ? _bids : _asks; try { if (item.IsOrderLogRegistered()) { if (item.OrderId != null) { var quote = quotes.SafeAdd(item.OrderPrice, key => new QuoteChange(item.Side, key, 0)); var id = item.OrderId.Value; if (item.OrderVolume != null) { var volume = item.OrderVolume.Value; if (_orders.TryGetValue(id, out var prevVolume)) { quote.Volume += (volume - prevVolume); _orders[id] = volume; } else { quote.Volume += volume; _orders.Add(id, volume); } changed = true; } } } else if (item.IsOrderLogMatched()) { if (item.OrderId != null) { var id = item.OrderId.Value; var volume = item.TradeVolume ?? item.OrderVolume; if (volume != null) { if (_orders.TryGetValue(id, out var prevVolume)) { var quote = quotes.TryGetValue(item.OrderPrice); if (quote != null) { quote.Volume -= volume.Value; if (quote.Volume <= 0) { quotes.Remove(item.OrderPrice); } } _orders[id] = prevVolume - volume.Value; changed = true; } } } } else if (item.IsOrderLogCanceled()) { if (item.OrderId != null) { var id = item.OrderId.Value; if (_orders.TryGetValue(id, out var prevVolume)) { var quote = quotes.TryGetValue(item.OrderPrice); if (quote != null) { quote.Volume -= prevVolume; if (quote.Volume <= 0) { quotes.Remove(item.OrderPrice); } } _orders.Remove(id); changed = true; } } } } finally { if (changed) { _depth.ServerTime = item.ServerTime; _depth.LocalTime = item.LocalTime; _depth.Bids = _bids.Values.ToArray(); _depth.Asks = _asks.Values.ToArray(); } } return(changed); }
private void OnProcessOrders(string[] data) { var f = Wrapper.FieldsOrders; if (data.Length > 0) this.AddLog(LogLevels.Debug, () => "OnProcessOrders:\n" + data.Join("\n")); foreach (var str in data) { var cols = str.ToColumns(); // 83487901|41469-000|42550|M|B|8356|1|1|0:00:00||FORTS|0| // ... // 83487901|41469-000|42550|M|B|8356|1|0|12.12.2011 16:31:41|2198931532|FORTS|0| // NOTE: когда в первый раз приходит апдейт по заявке в нем нет ни времени, ни комментария. // 84352688|41469-000|12910|M|S|80.13|10|0|22.12.2011 17:16:58||MICEX_SHR|0|0| // 84352688|41469-000|12910|M|S|80.13|10|0|22.12.2011 17:16:58|2968835969|MICEX_SHR|0|80.408| // NOTE: на ММВБ заявка сперва приходит с пустым комментарием! var orderId = f.OrdNo.GetValue(cols); var transId = f.Comments.GetValue(cols); if (transId == 0) { var alfaTransactionId = _alfaIds.TryGetKey(orderId); transId = _localIds.TryGetKey(alfaTransactionId); if (transId == 0) { this.AddWarningLog("transaction id for order #{0} not found. creating new one.", orderId); transId = TransactionIdGenerator.GetNextId(); if (alfaTransactionId == 0) { alfaTransactionId = --_lastFakeAlfaTransactionId; _alfaIds.Add(alfaTransactionId, orderId); } _localIds.Add(transId, alfaTransactionId); } } var msg = new ExecutionMessage { SecurityId = new SecurityId { Native = f.PaperNo.GetValue(cols) }, PortfolioName = GetPortfolioName(f.AccCode.GetValue(cols), this.GetBoardCode(f.PlaceCode.GetValue(cols))), Side = f.BuySellStr.GetValue(cols), OrderPrice = f.Price.GetValue(cols), Volume = f.Qty.GetValue(cols), Balance = f.Rest.GetValue(cols), OriginalTransactionId = transId, OrderId = orderId, ExecutionType = ExecutionTypes.Order, }; var orderTime = f.TsTime.GetValue(cols); if (orderTime.TimeOfDay != TimeSpan.Zero) msg.ServerTime = orderTime.ApplyTimeZone(TimeHelper.Moscow); var stopPrice = f.StopPrice.GetValue(cols); var orderType = f.Blank.GetValue(cols); switch (orderType) { case "S": { var updateToPrice = f.UpdateNewPrice.GetValue(cols); if (updateToPrice != 0) // Stop + TargetProfit { var updGrowPrice = f.UpdateGrowPrice.GetValue(cols); var updDownPrice = f.UpdateDownPrice.GetValue(cols); msg.Condition = new AlfaOrderCondition { StopPrice = stopPrice, TargetPrice = msg.OrderPrice, Slippage = msg.Side == Sides.Buy ? updateToPrice - updGrowPrice : updDownPrice - updateToPrice }; } else // Stop { msg.Condition = new AlfaOrderCondition { StopPrice = stopPrice, Slippage = stopPrice == 0 ? 0 : msg.Side == Sides.Buy ? msg.OrderPrice - stopPrice : stopPrice - msg.OrderPrice }; } msg.OrderType = OrderTypes.Conditional; break; } case "T": { var level = f.TrailingLevel.GetValue(cols); var slippage = f.TrailingSlippage.GetValue(cols); msg.Condition = new AlfaOrderCondition { Level = level, Slippage = slippage, StopPrice = stopPrice }; msg.OrderType = OrderTypes.Conditional; break; } case "L": msg.OrderType = OrderTypes.Limit; break; default: this.AddWarningLog("Unknown order type '{0}' (id={1})", orderType, orderId); break; } var status = f.OrderStatus.GetValue(cols); switch (status) { case "O": // активная case "G": // с условием msg.OrderState = OrderStates.Active; break; case "M": // исполнена msg.OrderState = msg.Balance != 0 ? OrderStates.Active : OrderStates.Done; break; case "W": // удалена msg.OrderState = OrderStates.Done; break; case "N": // принята сервером АД, но пока не на бирже msg.OrderState = OrderStates.Pending; break; default: this.AddInfoLog("Order status {0} is not taken into account", status); break; } SendOutMessage(msg); } }
/// <summary> /// To calculate commission. /// </summary> /// <param name="message">The message containing the information about the order or own trade.</param> /// <returns>The commission. If the commission can not be calculated then <see langword="null" /> will be returned.</returns> protected override decimal? OnProcessExecution(ExecutionMessage message) { if (message.ExecutionType == ExecutionTypes.Order) return (decimal)Value; return null; }
/// <summary> /// Create a copy of <see cref="ExecutionMessage"/>. /// </summary> /// <returns>Copy.</returns> public override Message Clone() { var clone = new ExecutionMessage { Balance = Balance, Comment = Comment, Condition = Condition.CloneNullable(), ClientCode = ClientCode, BrokerCode = BrokerCode, Currency = Currency, ServerTime = ServerTime, DepoName = DepoName, Error = Error, ExpiryDate = ExpiryDate, IsSystem = IsSystem, LocalTime = LocalTime, OpenInterest = OpenInterest, OrderId = OrderId, OrderStringId = OrderStringId, OrderBoardId = OrderBoardId, ExecutionType = ExecutionType, IsCancelled = IsCancelled, //Action = Action, OrderState = OrderState, OrderStatus = OrderStatus, OrderType = OrderType, OriginSide = OriginSide, PortfolioName = PortfolioName, OrderPrice = OrderPrice, SecurityId = SecurityId, Side = Side, SystemComment = SystemComment, TimeInForce = TimeInForce, TradeId = TradeId, TradeStringId = TradeStringId, TradePrice = TradePrice, TradeStatus = TradeStatus, TransactionId = TransactionId, OriginalTransactionId = OriginalTransactionId, OrderVolume = OrderVolume, TradeVolume = TradeVolume, //IsFinished = IsFinished, VisibleVolume = VisibleVolume, IsUpTick = IsUpTick, Commission = Commission, Latency = Latency, Slippage = Slippage, UserOrderId = UserOrderId, DerivedOrderId = DerivedOrderId, DerivedOrderStringId = DerivedOrderStringId, PnL = PnL, Position = Position, HasTradeInfo = HasTradeInfo, HasOrderInfo = HasOrderInfo }; this.CopyExtensionInfo(clone); return(clone); }
/// <summary> /// To calculate commission. /// </summary> /// <param name="message">The message containing the information about the order or own trade.</param> /// <returns>The commission. If the commission can not be calculated then <see langword="null" /> will be returned.</returns> protected override decimal? OnProcessExecution(ExecutionMessage message) { if (message.ExecutionType != ExecutionTypes.Trade) return null; if (++_currentCount < Count) return null; _currentCount = 0; return (decimal)Value; }
protected override void WriterFixOrderCondition(IFixWriter writer, ExecutionMessage message) { writer.WriteOrderCondition((QuikOrderCondition)message.Condition); }
/// <summary> /// To calculate commission. /// </summary> /// <param name="message">The message containing the information about the order or own trade.</param> /// <returns>The commission. If the commission can not be calculated then <see langword="null" /> will be returned.</returns> protected override decimal? OnProcessExecution(ExecutionMessage message) { if (message.ExecutionType == ExecutionTypes.Trade) return (decimal)(message.TradePrice * message.Volume * Value); return null; }
/// <summary> /// Send message. /// </summary> /// <param name="message">Message.</param> protected override void OnSendInMessage(Message message) { switch (message.Type) { case MessageTypes.Reset: { if (_client != null) { DisposeClient(); } try { Connection.Close(); Connection.ClearCache(); } catch (Exception ex) { SendOutError(ex); } Connection.StatusChange -= ConnectionOnStatusChange; SendOutMessage(new ResetMessage()); break; } case MessageTypes.Connect: { if (_client != null) throw new InvalidOperationException(LocalizedStrings.Str3378); var doc = XDocument.Load("http://www.ddfplus.com/getusersettings.php?username={0}&password={1}".Put(Login, Password.To<string>())); var loginElem = doc.Element("usersettings").Elements("login").First(); if (loginElem.GetAttributeValue<string>("status") != "ok") throw new InvalidOperationException(LocalizedStrings.UnknownServerError); if (loginElem.GetAttributeValue<string>("credentials") != "ok") throw new InvalidOperationException(LocalizedStrings.Str3350); foreach (var elem in doc.Element("usersettings").Element("servers").Elements()) { switch (elem.GetAttributeValue<string>("type")) { case "stream": _streamAddress = elem.GetAttributeValue<string>("primary"); break; case "historicalv2": _historicalAddress = elem.GetAttributeValue<string>("primary"); break; case "extras": _extrasAddress = elem.GetAttributeValue<string>("primary"); break; case "news": _newsAddress = elem.GetAttributeValue<string>("primary"); break; } } SendOutMessage(new ConnectMessage()); Connection.StatusChange += ConnectionOnStatusChange; Connection.Properties["streamingversion"] = "3"; _client = new Client(); _client.Error += ClientOnError; _client.NewBookQuote += ClientOnNewBookQuote; _client.NewOHLCQuote += ClientOnNewOhlcQuote; _client.NewQuote += ClientOnNewQuote; Connection.Username = Login; Connection.Password = Password.To<string>(); Connection.Mode = ConnectionMode.TCPClient; break; } case MessageTypes.Disconnect: { if (_client == null) throw new InvalidOperationException(LocalizedStrings.Str1856); DisposeClient(); Connection.Close(); break; } case MessageTypes.SecurityLookup: { var lookupMsg = (SecurityLookupMessage)message; XDocument doc = null; if (!lookupMsg.SecurityId.SecurityCode.IsEmpty()) { doc = XDocument.Load("{0}/instruments/?lookup={1}".Put(_extrasAddress, lookupMsg.SecurityId.SecurityCode)); } else if (!lookupMsg.SecurityId.BoardCode.IsEmpty()) { doc = XDocument.Load("{0}/instruments/?exchange={1}".Put(_extrasAddress, lookupMsg.SecurityId.BoardCode)); } if (doc != null) { foreach (var element in doc.Element("instruments").Elements()) { SendOutMessage(new SecurityMessage { SecurityId = new SecurityId { SecurityCode = element.GetAttributeValue<string>("guid"), BoardCode = element.GetAttributeValue<string>("exchange"), }, Name = element.GetAttributeValue<string>("symbol_description"), OriginalTransactionId = lookupMsg.TransactionId, SecurityType = TraderHelper.FromIso10962(element.GetAttributeValue<string>("symbol_cfi")), PriceStep = element.GetAttributeValue<decimal?>("tick_increment"), Multiplier = element.GetAttributeValue<decimal?>("point_value"), Currency = element.GetAttributeValue<CurrencyTypes?>("currency") }); } } SendOutMessage(new SecurityLookupResultMessage { OriginalTransactionId = lookupMsg.TransactionId, }); break; } case MessageTypes.MarketData: { var mdMsg = (MarketDataMessage)message; switch (mdMsg.DataType) { case MarketDataTypes.Level1: break; case MarketDataTypes.MarketDepth: break; case MarketDataTypes.Trades: { if (mdMsg.Count != null || mdMsg.From != null || mdMsg.To != null) { var url = new Url("{0}/queryticks.ashx".Put(_historicalAddress)); url.QueryString .Append("username", Login) .Append("password", Password.To<string>()) .Append("symbol", mdMsg.SecurityId.SecurityCode) .Append("order", "asc"); if (mdMsg.Count != null) url.QueryString.Append("maxrecords", mdMsg.Count.Value); if (mdMsg.From != null) url.QueryString.Append("start", mdMsg.From.Value.FromDateTimeOffset(_defaultTimeFormatRequest)); if (mdMsg.To != null) url.QueryString.Append("end", mdMsg.To.Value.FromDateTimeOffset(_defaultTimeFormatRequest)); using (var client = new WebClient()) { var lines = client.DownloadString(url) .Split("\n") .Where(l => l != "\r") .ToArray(); var i = 0; foreach (var line in lines) { var columns = line.Split(','); try { var msg = new ExecutionMessage { SecurityId = mdMsg.SecurityId, OriginalTransactionId = mdMsg.TransactionId, ExecutionType = ExecutionTypes.Tick, ServerTime = columns[0].ToDateTime("yyyy-MM-dd HH:mm:ss.fff"), TradePrice = columns[3].To<decimal>(), Volume = columns[4].To<decimal>(), }; msg.AddValue("IsFinished", ++i == lines.Length); SendOutMessage(msg); } catch (Exception ex) { throw new InvalidOperationException(LocalizedStrings.Str2141Params.Put(line), ex); } } } } break; } case MarketDataTypes.News: break; case MarketDataTypes.CandleTimeFrame: { var tf = (TimeSpan)mdMsg.Arg; string serviceName; string timeFormatRequest = _defaultTimeFormatRequest; string timeFormatResponse = "yyyy-MM-dd"; if (tf == TimeSpan.FromMinutes(1)) { serviceName = "queryminutes"; timeFormatResponse = "yyyy-MM-dd HH:mm"; } else if (tf == TimeSpan.FromDays(1)) { serviceName = "queryeod"; timeFormatRequest = "yyyyMMdd"; } else throw new InvalidOperationException(LocalizedStrings.Str2102); var url = new Url("{0}/{1}.ashx".Put(_historicalAddress, serviceName)); url.QueryString .Append("username", Login) .Append("password", Password.To<string>()) .Append("symbol", mdMsg.SecurityId.SecurityCode) .Append("order", "asc"); if (mdMsg.Count != null) url.QueryString.Append("maxrecords", mdMsg.Count.Value); if (mdMsg.From != null) url.QueryString.Append("start", mdMsg.From.Value.FromDateTimeOffset(timeFormatRequest)); if (mdMsg.To != null) url.QueryString.Append("end", mdMsg.To.Value.FromDateTimeOffset(timeFormatRequest)); using (var client = new WebClient()) { var lines = client.DownloadString(url) .Split("\n") .Where(l => l != "\r") .ToArray(); var i = 0; foreach (var line in lines) { var columns = line.Split(','); try { SendOutMessage(new TimeFrameCandleMessage { SecurityId = mdMsg.SecurityId, OriginalTransactionId = mdMsg.TransactionId, OpenTime = columns[tf == TimeSpan.FromMinutes(1) ? 0 : 1].ToDateTime(timeFormatResponse).ApplyTimeZone(TimeHelper.Est), OpenPrice = columns[2].To<decimal>(), HighPrice = columns[3].To<decimal>(), LowPrice = columns[4].To<decimal>(), ClosePrice = columns[5].To<decimal>(), TotalVolume = columns[6].To<decimal>(), OpenInterest = columns.Length > 7 ? columns[7].To<decimal>() : (decimal?)null, IsFinished = ++i == lines.Length }); } catch (Exception ex) { throw new InvalidOperationException(LocalizedStrings.Str2141Params.Put(line), ex); } } } break; } default: { SendOutMarketDataNotSupported(mdMsg.TransactionId); return; } } SendOutMessage(new MarketDataMessage { OriginalTransactionId = mdMsg.TransactionId }); break; } } }
/// <summary> /// To calculate commission. /// </summary> /// <param name="message">The message containing the information about the order or own trade.</param> /// <returns>The commission. If the commission can not be calculated then <see langword="null" /> will be returned.</returns> protected override decimal? OnProcessExecution(ExecutionMessage message) { if (message.ExecutionType == ExecutionTypes.Trade && message.SecurityId.SecurityType == SecurityType) return (decimal)Value; return null; }
private void ReadMyTrade(IBSocket socket, ServerVersions version) { /* requestId */ if (version >= ServerVersions.V7) socket.ReadInt(); // http://www.interactivebrokers.com/en/software/api/apiguide/java/execution.htm var transactionId = socket.ReadInt(); //Handle the 2^31-1 == 0 bug if (transactionId == int.MaxValue) transactionId = 0; //Read Contract Fields var contractId = version >= ServerVersions.V5 ? socket.ReadInt() : -1; var secName = socket.ReadStr(); var type = socket.ReadSecurityType(); var expiryDate = socket.ReadExpiry(); var strike = socket.ReadDecimal(); var optionType = socket.ReadOptionType(); var multiplier = version >= ServerVersions.V9 ? socket.ReadMultiplier() : null; var boardCode = socket.ReadBoardCode(); var currency = socket.ReadCurrency(); var secCode = socket.ReadLocalCode(secName); var secClass = (version >= ServerVersions.V10) ? socket.ReadStr() : null; var tradeId = socket.ReadStr(); var time = socket.ReadDateTime("yyyyMMdd HH:mm:ss"); var portfolio = socket.ReadStr(); /* exchange */ socket.ReadStr(); var side = socket.ReadTradeSide(); var volume = socket.ReadDecimal(); var price = socket.ReadDecimal(); var permId = version >= ServerVersions.V2 ? socket.ReadInt() : (int?)null; var clientId = version >= ServerVersions.V3 ? socket.ReadInt() : (int?)null; var liquidation = version >= ServerVersions.V4 ? socket.ReadInt() : (int?)null; var cumulativeQuantity = version >= ServerVersions.V6 ? socket.ReadInt() : (int?)null; var averagePrice = version >= ServerVersions.V6 ? socket.ReadDecimal() : (decimal?)null; var orderRef = version >= ServerVersions.V8 ? socket.ReadStr() : null; var evRule = version >= ServerVersions.V9 ? socket.ReadStr() : null; var evMultiplier = version >= ServerVersions.V9 ? socket.ReadDecimal() : (decimal?)null; var secId = new SecurityId { SecurityCode = secCode, BoardCode = GetBoardCode(boardCode), InteractiveBrokers = contractId, }; SendOutMessage(new SecurityMessage { SecurityId = secId, Name = secName, SecurityType = type, ExpiryDate = expiryDate, Strike = strike, OptionType = optionType, Currency = currency, Multiplier = multiplier ?? 0, Class = secClass }); // заявка была создана руками if (transactionId == 0) return; _secIdByTradeIds[tradeId] = secId; var execMsg = new ExecutionMessage { ExecutionType = ExecutionTypes.Transaction, OriginalTransactionId = transactionId, TradeStringId = tradeId, OriginSide = side, TradePrice = price, TradeVolume = volume, PortfolioName = portfolio, ServerTime = time, SecurityId = secId, HasTradeInfo = true, }; if (permId != null) execMsg.SetPermId(permId.Value); if (clientId != null) execMsg.SetClientId(clientId.Value); if (liquidation != null) execMsg.SetLiquidation(liquidation.Value); if (cumulativeQuantity != null) execMsg.SetCumulativeQuantity(cumulativeQuantity.Value); if (averagePrice != null) execMsg.SetAveragePrice(averagePrice.Value); if (orderRef != null) execMsg.SetOrderRef(orderRef); if (evRule != null) execMsg.SetEvRule(evRule); if (evMultiplier != null) execMsg.SetEvMultiplier(evMultiplier.Value); SendOutMessage(execMsg); }
/// <summary> /// To calculate commission. /// </summary> /// <param name="message">The message containing the information about the order or own trade.</param> /// <returns>The commission. If the commission can not be calculated then <see langword="null" /> will be returned.</returns> protected override decimal? OnProcessExecution(ExecutionMessage message) { if (message.ExecutionType == ExecutionTypes.Trade && message.SecurityId.BoardCode.CompareIgnoreCase(BoardCode)) return (decimal)Value; return null; }
private void ReadOpenOrder(IBSocket socket, ServerVersions version) { var transactionId = socket.ReadInt(); var contractId = version >= ServerVersions.V17 ? socket.ReadInt() : -1; var secCode = socket.ReadStr(); var type = socket.ReadSecurityType(); var expiryDate = socket.ReadExpiry(); var strike = socket.ReadDecimal(); var optionType = socket.ReadOptionType(); var multiplier = version >= ServerVersions.V32 ? socket.ReadMultiplier() : null; var boardCode = socket.ReadBoardCode(); var currency = socket.ReadCurrency(); secCode = version >= ServerVersions.V2 ? socket.ReadLocalCode(secCode) : null; var secClass = (version >= ServerVersions.V32) ? socket.ReadStr() : null; var ibCon = new IBOrderCondition(); // read order fields var direction = socket.ReadOrderSide(); var volume = socket.ReadDecimal(); OrderTypes orderType; IBOrderCondition.ExtendedOrderTypes? extendedType; socket.ReadOrderType(out orderType, out extendedType); ibCon.ExtendedType = extendedType; var price = socket.ReadDecimal(); ibCon.StopPrice = socket.ReadDecimal(); var expiration = socket.ReadStr(); ibCon.Oca.Group = socket.ReadStr(); var portfolio = socket.ReadStr(); ibCon.IsOpenOrClose = socket.ReadStr() == "O"; ibCon.Origin = (IBOrderCondition.OrderOrigins)socket.ReadInt(); var comment = socket.ReadStr(); var clientId = version >= ServerVersions.V3 ? socket.ReadInt() : (int?)null; int? permId = null; if (version >= ServerVersions.V4) { permId = socket.ReadInt(); if (version < ServerVersions.V18) { // will never happen /* order.m_ignoreRth = */ socket.ReadBool(); } else ibCon.OutsideRth = socket.ReadBool(); ibCon.Hidden = socket.ReadBool(); ibCon.SmartRouting.DiscretionaryAmount = socket.ReadDecimal(); } if (version >= ServerVersions.V5) ibCon.GoodAfterTime = socket.ReadNullDateTime(IBSocketHelper.TimeFormat); if (version >= ServerVersions.V6) { // skip deprecated sharesAllocation field socket.ReadStr(); } if (version >= ServerVersions.V7) { ibCon.FinancialAdvisor.Group = socket.ReadStr(); ibCon.FinancialAdvisor.Allocation = socket.ReadFinancialAdvisor(); ibCon.FinancialAdvisor.Percentage = socket.ReadStr(); ibCon.FinancialAdvisor.Profile = socket.ReadStr(); } var orderExpiryDate = version >= ServerVersions.V8 ? socket.ReadNullDateTime(IBSocketHelper.TimeFormat) : null; var visibleVolume = volume; if (version >= ServerVersions.V9) { ibCon.Agent = socket.ReadAgent(); ibCon.PercentOffset = socket.ReadDecimal(); ibCon.Clearing.SettlingFirm = socket.ReadStr(); ibCon.ShortSale.Slot = (IBOrderCondition.ShortSaleSlots)socket.ReadInt(); ibCon.ShortSale.Location = socket.ReadStr(); if (socket.ServerVersion == ServerVersions.V51) socket.ReadInt(); //exempt code else if (version >= ServerVersions.V23) ibCon.ShortSale.ExemptCode = socket.ReadInt(); ibCon.AuctionStrategy = (IBOrderCondition.AuctionStrategies)socket.ReadInt(); ibCon.StartingPrice = socket.ReadDecimal(); ibCon.StockRefPrice = socket.ReadDecimal(); ibCon.Delta = socket.ReadDecimal(); ibCon.StockRangeLower = socket.ReadDecimal(); ibCon.StockRangeUpper = socket.ReadDecimal(); visibleVolume = socket.ReadInt(); if (version < ServerVersions.V18) { // will never happen /* order.m_rthOnly = */ socket.ReadBool(); } ibCon.BlockOrder = socket.ReadBool(); ibCon.SweepToFill = socket.ReadBool(); ibCon.AllOrNone = socket.ReadBool(); ibCon.MinVolume = socket.ReadInt(); ibCon.Oca.Type = (IBOrderCondition.OcaTypes)socket.ReadInt(); ibCon.SmartRouting.ETradeOnly = socket.ReadBool(); ibCon.SmartRouting.FirmQuoteOnly = socket.ReadBool(); ibCon.SmartRouting.NbboPriceCap = socket.ReadDecimal(); } if (version >= ServerVersions.V10) { ibCon.ParentId = socket.ReadInt(); ibCon.TriggerMethod = (IBOrderCondition.TriggerMethods)socket.ReadInt(); } if (version >= ServerVersions.V11) { ibCon.Volatility.Volatility = socket.ReadDecimal(); ibCon.Volatility.VolatilityTimeFrame = socket.ReadVolatilityType(); if (version == ServerVersions.V11) { if (!socket.ReadBool()) ibCon.Volatility.ExtendedOrderType = IBOrderCondition.ExtendedOrderTypes.Empty; else ibCon.Volatility.OrderType = OrderTypes.Market; } else { OrderTypes volOrdertype; IBOrderCondition.ExtendedOrderTypes? volExtendedType; socket.ReadOrderType(out volOrdertype, out volExtendedType); ibCon.Volatility.OrderType = volOrdertype; ibCon.Volatility.ExtendedOrderType = volExtendedType; ibCon.Volatility.StopPrice = socket.ReadDecimal(); if (volExtendedType != IBOrderCondition.ExtendedOrderTypes.Empty) { if (version >= ServerVersions.V27) { ibCon.Volatility.ConId = socket.ReadInt(); ibCon.Volatility.SettlingFirm = socket.ReadStr(); var portfolioName = socket.ReadStr(); if (!portfolioName.IsEmpty()) ibCon.Volatility.ClearingPortfolio = portfolioName; ibCon.Volatility.ClearingIntent = socket.ReadStr(); } if (version >= ServerVersions.V31) { var isOpenOrCloseStr = socket.ReadStr(); ibCon.Volatility.ShortSale.IsOpenOrClose = isOpenOrCloseStr == "?" ? (bool?)null : isOpenOrCloseStr.To<int>() == 1; ibCon.Volatility.IsShortSale = socket.ReadBool(); ibCon.Volatility.ShortSale.Slot = (IBOrderCondition.ShortSaleSlots)socket.ReadInt(); ibCon.Volatility.ShortSale.Location = socket.ReadStr(); } } } ibCon.Volatility.ContinuousUpdate = socket.ReadBool(); if (socket.ServerVersion == ServerVersions.V26) { ibCon.StockRangeLower = socket.ReadDecimal(); ibCon.StockRangeUpper = socket.ReadDecimal(); } ibCon.Volatility.IsAverageBestPrice = socket.ReadBool(); } if (version >= ServerVersions.V13) ibCon.TrailStopPrice = socket.ReadDecimal(); if (version >= ServerVersions.V30) ibCon.TrailStopVolumePercentage = socket.ReadNullDecimal(); if (version >= ServerVersions.V14) { ibCon.Combo.BasisPoints = socket.ReadDecimal(); ibCon.Combo.BasisPointsType = socket.ReadInt(); ibCon.Combo.LegsDescription = socket.ReadStr(); } if (version >= ServerVersions.V29) { var comboLegsCount = socket.ReadInt(); if (comboLegsCount > 0) { //contract.m_comboLegs = new Vector(comboLegsCount); for (var i = 0; i < comboLegsCount; ++i) { //int conId = socket.ReadInt(); //int ratio = socket.ReadInt(); //String action = socket.ReadStr(); //String exchange = socket.ReadStr(); //int openClose = socket.ReadInt(); //int shortSaleSlot = socket.ReadInt(); //String designatedLocation = socket.ReadStr(); //int exemptCode = socket.ReadInt(); //ComboLeg comboLeg = new ComboLeg(conId, ratio, action, exchange, openClose, // shortSaleSlot, designatedLocation, exemptCode); //contract.m_comboLegs.add(comboLeg); } } var orderComboLegsCount = socket.ReadInt(); if (orderComboLegsCount > 0) { //order.m_orderComboLegs = new Vector(orderComboLegsCount); for (var i = 0; i < orderComboLegsCount; ++i) { //var comboPrice = socket.ReadNullDecimal(); //OrderComboLeg orderComboLeg = new OrderComboLeg(comboPrice); //order.m_orderComboLegs.add(orderComboLeg); } } } if (version >= ServerVersions.V26) { var smartComboRoutingParamsCount = socket.ReadInt(); if (smartComboRoutingParamsCount > 0) { var @params = new List<Tuple<string, string>>(); for (var i = 0; i < smartComboRoutingParamsCount; ++i) @params.Add(Tuple.Create(socket.ReadStr(), socket.ReadStr())); ibCon.SmartRouting.ComboParams = @params; } } if (version >= ServerVersions.V15) { if (version >= ServerVersions.V20) { ibCon.Scale.InitLevelSize = socket.ReadNullInt(); ibCon.Scale.SubsLevelSize = socket.ReadNullInt(); } else { /* int notSuppScaleNumComponents = */ socket.ReadNullInt(); ibCon.Scale.InitLevelSize = socket.ReadNullInt(); } ibCon.Scale.PriceIncrement = socket.ReadNullDecimal(); } if (version >= ServerVersions.V28 && ibCon.Scale.PriceIncrement > 0) { ibCon.Scale.PriceAdjustValue = socket.ReadNullDecimal(); ibCon.Scale.PriceAdjustInterval = socket.ReadInt(); ibCon.Scale.ProfitOffset = socket.ReadNullDecimal(); ibCon.Scale.AutoReset = socket.ReadBool(); ibCon.Scale.InitPosition = socket.ReadNullInt(); ibCon.Scale.InitFillQty = socket.ReadNullInt(); ibCon.Scale.RandomPercent = socket.ReadBool(); } if (version >= ServerVersions.V24) socket.ReadHedge(ibCon); if (version >= ServerVersions.V25) ibCon.SmartRouting.OptOutSmartRouting = socket.ReadBool(); if (version >= ServerVersions.V19) { var portfolioName = socket.ReadStr(); if (!portfolioName.IsEmpty()) ibCon.Clearing.ClearingPortfolio = portfolioName; ibCon.Clearing.Intent = socket.ReadIntent(); } if (version >= ServerVersions.V22) ibCon.SmartRouting.NotHeld = socket.ReadBool(); if (version >= ServerVersions.V20) { if (socket.ReadBool()) { //UnderlyingComponent underComp = new UnderlyingComponent(); //underComp.ContractId = socket.ReadInt(); //underComp.Delta = socket.ReadDecimal(); //underComp.Price = socket.ReadDecimal(); //contract.UnderlyingComponent = underComp; } } if (version >= ServerVersions.V21) { ibCon.Algo.Strategy = socket.ReadStr(); if (!ibCon.Algo.Strategy.IsEmpty()) { var algoParamsCount = socket.ReadInt(); if (algoParamsCount > 0) { var algoParams = new List<Tuple<string, string>>(); for (var i = 0; i < algoParamsCount; i++) algoParams.Add(Tuple.Create(socket.ReadStr(), socket.ReadStr())); ibCon.Algo.Params = algoParams; } } } //OrderState orderState = new OrderState(); OrderStatus? status = null; if (version >= ServerVersions.V16) { socket.ReadStr(); //order.WhatIf = !(string.IsNullOrEmpty(rstr) || rstr == "0"); status = socket.ReadOrderStatus(); //orderState.InitMargin = socket.ReadStr(); //orderState.MaintMargin = socket.ReadStr(); //orderState.EquityWithLoan = socket.ReadStr(); //orderState.IbCommission = socket.ReadNullDecimal(); //orderState.MinCommission = socket.ReadNullDecimal(); //orderState.MaxCommission = socket.ReadNullDecimal(); //orderState.CommissionCurrency = socket.ReadStr(); //orderState.WarningText = socket.ReadStr(); } var secId = new SecurityId { SecurityCode = secCode, BoardCode = GetBoardCode(boardCode), InteractiveBrokers = contractId, }; SendOutMessage(new SecurityMessage { SecurityId = secId, ExpiryDate = expiryDate, Strike = strike, OptionType = optionType, Class = secClass, SecurityType = type, Currency = currency, Multiplier = multiplier ?? 0, }); var orderMsg = new ExecutionMessage { ExecutionType = ExecutionTypes.Transaction, SecurityId = secId, OriginalTransactionId = transactionId, OrderType = orderType, Side = direction, OrderVolume = volume, OrderPrice = price, Condition = ibCon, ExpiryDate = orderExpiryDate, VisibleVolume = visibleVolume, PortfolioName = portfolio, Comment = comment, OrderStatus = status, OrderState = status?.ToOrderState(), HasOrderInfo = true, }; if (orderMsg.OrderState == OrderStates.Active || orderMsg.OrderState == OrderStates.Done) orderMsg.OrderId = transactionId; switch (expiration) { case "DAY": orderMsg.TimeInForce = TimeInForce.PutInQueue; break; case "GTC": //orderMsg.ExpiryDate = DateTimeOffset.MaxValue; break; case "IOC": orderMsg.TimeInForce = TimeInForce.CancelBalance; break; case "FOK": orderMsg.TimeInForce = TimeInForce.MatchOrCancel; break; case "GTD": break; case "OPG": ibCon.IsMarketOnOpen = true; break; default: throw new InvalidOperationException(LocalizedStrings.Str2515Params.Put(expiration)); } if (clientId != null) orderMsg.SetClientId(clientId.Value); if (permId != null) orderMsg.SetPermId(permId.Value); SendOutMessage(orderMsg); }
/// <summary> /// To calculate commission. /// </summary> /// <param name="message">The message containing the information about the order or own trade.</param> /// <returns>The commission. If the commission can not be calculated then <see langword="null" /> will be returned.</returns> protected override decimal? OnProcessExecution(ExecutionMessage message) { if (message.ExecutionType != ExecutionTypes.Trade) return null; _currentTurnOver += message.GetTradePrice() * message.SafeGetVolume(); if (_currentTurnOver < TurnOver) return null; return (decimal)Value; }
public Tuple<OrderFail, bool> ProcessOrderFailMessage(Security security, ExecutionMessage message) { if (security == null) throw new ArgumentNullException(nameof(security)); if (message == null) throw new ArgumentNullException(nameof(message)); var data = 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(nameof(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); }
/// <summary> /// To calculate commission. /// </summary> /// <param name="message">The message containing the information about the order or own trade.</param> /// <returns>The commission. If the commission can not be calculated then <see langword="null" /> will be returned.</returns> protected abstract decimal? OnProcessExecution(ExecutionMessage message);
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; }
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) }; 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); }