Example #1
0
        /// <summary>
        ///     Выставить заявку
        /// </summary>
        /// <param name="transaction">
        ///     Транзакция
        /// </param>
        /// <param name="order">
        ///     IB-заявка
        /// </param>
        public async Task PlaceOrderAsync(NewOrderTransaction transaction, IBOrder order)
        {
            var instrument = transaction.Instrument;

            var contract = await connector.ContractContainer.GetContractAsync(instrument, null);

            if (contract == null)
            {
                throw new TransactionRejectedException($"Details of contract {instrument.Code} are not available");
            }

            using (orderInfoContainerLock.Lock())
            {
                var tickerId = NextTickerId();
                order.OrderId = tickerId;

                // Сохраняем заявку по ее тикеру
                var orderInfo = new OrderInfo(order, transaction.Instrument)
                {
                    State = OrderState.New,
                    NewOrderTransactionId = transaction.TransactionId
                };
                orderInfoContainer.StoreByTickerId(tickerId, orderInfo, true);

                Socket.placeOrder(tickerId, contract, order);
            }
        }
Example #2
0
        public void Visit(NewOrderTransaction transaction)
        {
            var symbol = adapter.ResolveSymbolAsync(transaction.Instrument).Result;

            if (symbol == null)
            {
                Logger.Error().Print($"Unable to resolve symbol for {transaction.Instrument}");
                return;
            }

            var newTransactionId = IncTransId();
            var qlTrans          = new QLTransaction
            {
                ACTION              = ACTION.NEW_ORDER,
                ACCOUNT             = transaction.Account,
                CLIENT_CODE         = transaction.Account + @"//" + transaction.Comment,
                COMMENT             = transaction.Comment,
                SECCODE             = symbol,
                CLASSCODE           = symbol.Length >= 5 ? "SPBOPT" : "SPBFUT",
                EXECUTION_CONDITION = EXECUTION_CONDITION.PUT_IN_QUEUE,
                OPERATION           = transaction.Operation == OrderOperation.Buy ? OPERATION.B : OPERATION.S,
                QUANTITY            = transaction.Quantity.ToString(),
                PRICE    = transaction.Price.ToString("0.######"),
                TRANS_ID = newTransactionId.ToString(),
                TYPE     = TYPE.L,
            };

            Logger.Debug().PrintFormat("Visit: {0}", qlTrans);
            adapter.SendMessage(qlTrans);

            container.PutTransaction(newTransactionId, transaction);
        }
Example #3
0
 /// <summary>
 /// Получить транзакцию на постоновку заявки по её идентификатору
 /// </summary>
 /// <param name="transId">Идентификатор транзакции</param>
 /// <returns></returns>
 public NewOrderTransaction GetNewOrderTransaction(long transId)
 {
     using (locker.ReadLock())
     {
         NewOrderTransaction rValue = null;
         mapQuikTransIdOnNewOrderTransaction.TryGetValue(transId, out rValue);
         return(rValue);
     }
 }
Example #4
0
 /// <summary>
 /// Сохранить транзакцию на постановку заявки по её идентификатору
 /// </summary>
 /// <param name="id"></param>
 /// <param name="newOrderTransaction"></param>
 public void PutTransaction(long id, NewOrderTransaction newOrderTransaction)
 {
     using (locker.WriteLock())
     {
         currentSeccionTransactionIds.Add(id);
         newOrderTransactionsWithoutReplies.Add(id);
         mapQuikTransIdOnNewOrderTransaction.Add(id, newOrderTransaction);
     }
 }
        public static OrderParams GetOrderParams(this NewOrderTransaction transaction)
        {
            switch (transaction.ExecutionCondition)
            {
            case OrderExecutionCondition.FillOrKill:
                return(OrderParams.FOK);

            case OrderExecutionCondition.KillBalance:
                return(OrderParams.IOC);

            default:
            case OrderExecutionCondition.PutInQueue:
                return(OrderParams.PIQ);
            }
        }
        /// <summary>
        ///     Обработать транзакцию <see cref="NewOrderTransaction"/>
        /// </summary>
        /// <param name="transaction">
        ///     Транзакция для обработки
        /// </param>
        async void ITransactionVisitor.Visit(NewOrderTransaction transaction)
        {
            try
            {
                var order = new IBOrder
                {
                    Account       = transaction.Account,
                    ClientId      = connector.ClientId,
                    Action        = transaction.Operation == OrderOperation.Buy ? "BUY" : "SELL",
                    TotalQuantity = (int)transaction.Quantity,
                    OrderRef      = !string.IsNullOrWhiteSpace(transaction.Comment)
                        ? connector.IBOrderRouter.SessionUidInternal + transaction.Comment
                        : connector.IBOrderRouter.SessionUidInternal,
                    Transmit = true
                };

                switch (transaction.Type)
                {
                case OrderType.Limit:
                    order.OrderType = "LMT";
                    order.LmtPrice  = (double)transaction.Price;
                    break;

                case OrderType.Market:
                    order.OrderType = "MKT";
                    break;

                default:
                    throw new ArgumentOutOfRangeException("transaction.Type");
                }

                switch (transaction.ExecutionCondition)
                {
                case OrderExecutionCondition.PutInQueue:
                    order.Tif = "GTC";     /* Good till cancelled */
                    break;

                case OrderExecutionCondition.FillOrKill:
                    order.Tif = "FOC";     /* Fill or cancel */
                    break;

                case OrderExecutionCondition.KillBalance:
                    order.Tif = "IOC";     /* Immediate or cancel */
                    break;

                default:
                    throw new ArgumentOutOfRangeException("transaction.ExecutionCondition");
                }

                await connector.Adapter.PlaceOrderAsync(transaction, order);
            }
            catch (TransactionRejectedException exception)
            {
                Reject(transaction, exception.Message);
            }
            catch (Exception exception)
            {
                _Log.Error()
                .Print(exception, "Unable to send transaction", LogFields.Transaction(transaction),
                       LogFields.Message(exception.Message));
                Reject(transaction, "Transaction execution failed: {0}", exception.Message);
            }
        }
Example #7
0
        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));
            }
        }
Example #8
0
        /// <summary>
        ///     Постановка заявки
        /// </summary>
        private async void SendTransactionInternal(NewOrderTransaction transaction)
        {
            using (LogManager.Scope())
            {
                try
                {
                    // Получаем счет для транзакции
                    int accountId;
                    var hasAccountId = true;
                    using (accountsLock.ReadLock())
                    {
                        if (!accountIdsByCode.TryGetValue(transaction.Account, out accountId))
                        {
                            hasAccountId = false;
                        }
                    }

                    if (!hasAccountId)
                    {
                        OnMessageReceived(TransactionReply.Rejected(
                                              transaction,
                                              $"Account \"{transaction.Account}\" is unknown"));
                        return;
                    }

                    // Получаем инструмент для транзации
                    uint contractId;
                    try
                    {
                        contractId = await instrumentResolver.GetContractIdAsync(transaction.Instrument);

                        if (contractId == uint.MaxValue)
                        {
                            return;
                        }
                    }
                    catch (OperationCanceledException)
                    {
                        OnMessageReceived(TransactionReply.Rejected(
                                              transaction,
                                              $"Instrument \"{transaction.Instrument.Code}\" is unknown"));
                        return;
                    }

                    // Пребразовываем цену
                    var price = instrumentResolver.ConvertPrice(contractId, transaction.Price);
                    if (price == null)
                    {
                        OnMessageReceived(TransactionReply.Rejected(transaction, "Unable to convert price"));
                        return;
                    }

                    // Формируем запрос
                    var msg = new OrderRequest
                    {
                        new_order = new NewOrder
                        {
                            order = new WebAPI.Order
                            {
                                cl_order_id = transaction.TransactionId.ToString("N"),
                                account_id  = accountId,
                                contract_id = contractId,
                                side        = (uint)ConvertionHelper.GetSide(transaction.Operation),
                                order_type  = (uint)ConvertionHelper.GetOrderType(transaction.Type),
                                duration    = (uint)ConvertionHelper.GetDuration(transaction.ExecutionCondition),
                                limit_price = price.Value,
                                qty         = transaction.Quantity,
                                is_manual   = transaction.IsManual,

                                user_attribute =
                                {
                                    new UserAttribute
                                    {
                                        name  = CommentAttributeName,
                                        value = transaction.Comment
                                    }
                                }
                            },
                            suspend = false
                        },
                        request_id = adapter.GetNextRequestId()
                    };

                    // Запоминаем заявку
                    using (ordersLock.Lock())
                    {
                        var order = new Order(transaction);
                        ordersByTransactionId.Add(transaction.TransactionId, order);
                    }

                    // Запоминаем транзакцию
                    StoreTransaction(msg.request_id, transaction);

                    Logger.Debug().PrintFormat("Sending {0}", transaction);
                    adapter.SendMessage(msg);
                }
                catch (Exception e)
                {
                    Logger.Error().Print(e, $"Failed to send {transaction}");
                    OnMessageReceived(TransactionReply.Rejected(transaction, "Unable to send order"));
                }
            }
        }
Example #9
0
 void ITransactionVisitor.Visit(NewOrderTransaction transaction)
 {
     router.SendTransactionInternal(transaction);
 }
Example #10
0
        /// <summary>
        ///     Обработать транзакцию <see cref="NewOrderTransaction"/>
        /// </summary>
        /// <param name="transaction">
        ///     Транзакция для обработки
        /// </param>
        async void ITransactionVisitor.Visit(NewOrderTransaction transaction)
        {
            InstrumentData instrumentData;

            try
            {
                instrumentData = await _settings.InstrumentConverter.ResolveInstrumentAsync(this, transaction.Instrument);
            }
            catch (Exception e)
            {
                _Log.Error().Print(e, $"Failed to resolve instrument {transaction.Instrument}");
                SendMessage(TransactionReply.Rejected(transaction, "Failed to resolve instrument"));
                return;
            }

            if (instrumentData == null)
            {
                _Log.Error().Print($"Instrument {transaction.Instrument} hasn't been resolved");
                SendMessage(TransactionReply.Rejected(transaction, "Instrument hasn't been resolved"));
                return;
            }

            var msg = new NewOrderSingle();

            msg.TransactTime = new TransactTime(DateTime.UtcNow);
            msg.OrdType      = new OrdType(OrdType.LIMIT);
            msg.Symbol       = new Symbol(instrumentData.Symbol);
            msg.Account      = new Account(transaction.Account);
            switch (transaction.ExecutionCondition)
            {
            case OrderExecutionCondition.PutInQueue:
                msg.TimeInForce = new TimeInForce(TimeInForce.DAY);
                break;

            case OrderExecutionCondition.FillOrKill:
                msg.TimeInForce = new TimeInForce(TimeInForce.FILL_OR_KILL);
                break;

            default:
                SendMessage(TransactionReply.Rejected(transaction, $"Unknown execution condition: {transaction.ExecutionCondition}"));
                return;
            }

            switch (transaction.Operation)
            {
            case OrderOperation.Buy:
                msg.Side = new Side(Side.BUY);
                break;

            case OrderOperation.Sell:
                msg.Side = new Side(Side.SELL);
                break;

            default:
                SendMessage(TransactionReply.Rejected(transaction, $"Unknown operation: {transaction.Operation}"));
                return;
            }

            switch (transaction.Type)
            {
            case OrderType.Limit:
                break;

            default:
                SendMessage(TransactionReply.Rejected(transaction, $"Unsupported order type: {transaction.Type}"));
                return;
            }

            msg.OrderQty = new OrderQty(transaction.Quantity);
            msg.Price    = new Price(transaction.Price);

            var clOrderId = _newOrderTransactions.Add(transaction);

            msg.ClOrdID = new ClOrdID(clOrderId);

            if (!string.IsNullOrEmpty(transaction.Comment))
            {
                var comment = transaction.Comment;
                comment = comment.Length > 20 ? comment.Substring(0, 20) : comment;
                msg.SecondaryClOrdID = new SecondaryClOrdID(comment);
            }

            _orders.SaveOrderParams(transaction.TransactionId, clOrderId, msg.Symbol.Obj, msg.OrderQty.Obj, msg.Side.Obj);
            SendFixMessage(msg);
        }
 public static BuySell GetOperation(this NewOrderTransaction transaction)
 => transaction.Operation == OrderOperation.Buy ? BuySell.BUY : BuySell.SELL;
 public static OrderType GetOrderType(this NewOrderTransaction transaction)
 => transaction.Type == Messages.OrderType.Market ? OrderType.MARKET : OrderType.LIMIT;