private void InfoClient_OnInfoTrade(InfoTrade trade) { if (trade.acc_id == 0 || !mapAccountIdToAccount.ContainsKey(trade.acc_id)) { return; } var code = trade.security + "|" + trade.board; var instrument = connector.ResolveSymbolAsync(code).Result; if (instrument == null) { Logger.Error().Print($"Unable to resolve instrument for {code}"); return; } var fill = new FillMessage { Account = mapAccountIdToAccount[trade.acc_id].code, Instrument = instrument, ExchangeId = trade.code, Operation = trade.buy_sell == BuySell.BUY ? OrderOperation.Buy : OrderOperation.Sell, Price = PriceHelper.ToPrice(trade.price), Quantity = trade.qty, DateTime = DateTime.FromFileTime((long)trade.trade_time), ExchangeOrderId = trade.order_id }; OnMessageReceived(fill); }
private void InfoClient_OnInfoHolding(InfoHolding holding) { if (!accounts.ContainsKey(holding.account)) { return; } var code = holding.security + "|BRD-NORMAL"; var instrument = connector.ResolveSymbolAsync(code).Result; if (instrument == null) { Logger.Error().Print($"Unable to resolve instrument for {code}"); return; } if (!mapAccountIdToAccount.ContainsKey(holding.acc_id)) { mapAccountIdToAccount.Add(holding.acc_id, accounts[holding.account]); } var position = new PositionMessage { Account = holding.account, Instrument = instrument, Quantity = (int)holding.trade_buy_qty - (int)holding.trade_sell_qty, Price = PriceHelper.ToPrice(holding.settle_price) }; OnMessageReceived(position); }
public bool ProcessOrder(InfoOrder order) { var code = order.code; var price = PriceHelper.ToPrice(order.price); var sorted = order.buy_sell == BuySell.BUY ? bids : asks; if (!mapOrders.TryGetValue(code, out var info)) { //if (string.IsNullOrEmpty(order.security)) //{ // //Logger.DebugFormat("Получено обновление заявки с пустым полем security. OrderId: {0}", order.code); // return false; //} if (order.qtyLeft == 0 || order.status == OrderStatus.CANCELED || order.status == OrderStatus.MATCHED) { // TODO Проверить частичное return(false); } info = new ShortOrderInfo(code, price, order.buy_sell); mapOrders[order.code] = info; List <ShortOrderInfo> list; if (!sorted.TryGetValue(price, out list)) { sorted[price] = list = new List <ShortOrderInfo>(); } list.Add(info); } info.Quantity = order.qtyLeft; // Очищаем лишние заявки (в статусах Matched и Cancelled) if (order.qtyLeft == 0 || order.status == OrderStatus.CANCELED || order.status == OrderStatus.MATCHED) // TODO Проверить частичное { mapOrders.Remove(order.code); if (sorted.TryGetValue(price, out var list)) { list.Remove(info); if (!list.Any()) { sorted.Remove(price); } } } return(true); }
private void InfoClient_OnInfoOrder(InfoOrder order) { if (!accounts.ContainsKey(order.account)) { return; } var activeQuantity = order.qtyLeft; OrderState state; switch (order.status) { case OrderStatus.CANCELED: state = !string.IsNullOrEmpty(order.res_code) && order.res_code != "ENF_CANC" // TODO Hardcode волшебной строки ? OrderState.Error : OrderState.Cancelled; activeQuantity = 0; break; case OrderStatus.MATCHED: state = OrderState.Filled; break; case OrderStatus.FREEZED: case OrderStatus.QUEUED: state = order.qty_executed > 0 ? OrderState.PartiallyFilled : OrderState.Active; break; case OrderStatus.WAIT_APPROVAL: default: return; } //long filledQty = order.ActiveQty - (long)infoOrder.qtyLeft; Guid.TryParseExact(order.trn, "N", out var trId); var oscm = new OrderStateChangeMessage { TransactionId = trId, OrderExchangeId = order.code, Quantity = order.qty, ActiveQuantity = activeQuantity, FilledQuantity = order.qty_executed, // TODO Price = PriceHelper.ToPrice(order.price), ChangeTime = DateTime.Now, // TODO State = state }; OnMessageReceived(oscm); }
private InstrumentParams CreateParams(InfoSecboard secboard) { var instrument = connector.ResolveSymbolAsync(secboard.code).Result; if (instrument == null) { return(null); } var security = securitiesMap[secboard.security]; return(new InstrumentParams { Instrument = instrument, //ExpirationDate = security.execution_day, PriceStep = PriceHelper.ToPrice(security.price_step), LotSize = security.lot_size }); }
private void InfoClient_OnInfoSecboard(InfoSecboard secboard) { using (allInstrumentLock.WriteLock()) { var code = secboard.code; InstrumentParams ip; if (!instrumentsParams.TryGetValue(code, out ip)) { allInstruments.Add(code); ip = CreateParams(secboard); if (ip == null) { return; } instrumentsParams[code] = ip; } ip.TopPriceLimit = PriceHelper.ToPrice(secboard.price_max); ip.BottomPriceLimit = PriceHelper.ToPrice(secboard.price_min); ip.Settlement = PriceHelper.ToPrice(secboard.market_price); ip.PreviousSettlement = PriceHelper.ToPrice(secboard.prev_market_price); ip.LastPrice = PriceHelper.ToPrice(secboard.last_trade_price); //ip.SessionEndTime = secboard.finish_trade_time; ip.BestBidPrice = PriceHelper.ToPrice(secboard.best_buy); ip.BestOfferPrice = PriceHelper.ToPrice(secboard.best_sell); if (subscribedInstruments.Contains(code)) { OnMessageReceived(ip); } } }
public async void Visit(NewOrderTransaction transaction) { try { //internal async Task<string> ResolveInstrumentAsync(Instrument instrument) //{ // var data = await instrumentConverter.ResolveInstrumentAsync(this, instrument); // return data?.Symbol; //} var data = await connector.ResolveInstrumentDataAsync(transaction.Instrument); if (data == null) { OnMessageReceived(TransactionReply.Rejected(transaction, $"Unable to get symbol of {transaction.Instrument}")); return; } if (!accounts.TryGetValue(transaction.Account, out var account)) { OnMessageReceived(TransactionReply.Rejected(transaction, $"Не найден счет {transaction.Account}")); return; } var order = new SpimexAdapter.FTE.Order { account = account.code, firm = account.firm, client = account.client, security = data.Symbol, board = data.Board, @type = transaction.GetOrderType(), @params = transaction.GetOrderParams(), buy_sell = transaction.GetOperation(), price = PriceHelper.FromPrice(transaction.Price), qty = transaction.Quantity, trn = transaction.TransactionId.ToString("N"), isMarketMaker = transaction.IsMarketMakerOrder, comment = transaction.Comment, }; var reply = await transClient.SendOrder(order); OnMessageReceived(TransactionReply.Accepted(transaction, reply.code)); OrderState?state = null; switch (reply.status) { case OrderStatus.CANCELED: state = OrderState.Cancelled; break; case OrderStatus.MATCHED: state = OrderState.Filled; break; case OrderStatus.FREEZED: case OrderStatus.QUEUED: state = reply.qty_executed > 0 ? OrderState.PartiallyFilled : OrderState.Active; break; } var oscm = new OrderStateChangeMessage { TransactionId = transaction.TransactionId, OrderExchangeId = reply.code, Quantity = order.qty, ActiveQuantity = reply.qtyLeft, FilledQuantity = reply.qty_executed, Price = PriceHelper.ToPrice(order.price), ChangeTime = DateTime.Now, State = state }; OnMessageReceived(oscm); } catch (FTEException e) { OnMessageReceived(TransactionReply.Rejected(transaction, e.Message)); } }