/// <inheritdoc /> public override ResponseObject <OrderUpdate> PlaceLimitOrder(TradingPair pair, OrderSide side, decimal quantity, decimal price, long tradeId) { var client = _communications.Client; var realQuantity = pair.RoundToTradable(quantity); var realPrice = pair.RoundToPriceable(price); var query = client.PlaceOrder( symbol: pair.ToString(), side: BinanceUtilities.ToExternal(side), type: OrderType.Limit, quantity: realQuantity, newClientOrderId: null, price: realPrice, timeInForce: TimeInForce.GoodTillCancel, stopPrice: null, icebergQty: null, orderResponseType: null, receiveWindow: (int)_communications.ReceiveWindow); return(query.Success ? new ResponseObject <OrderUpdate>( ResponseCode.Success, new OrderUpdate( query.Data.OrderId, tradeId, OrderUpdate.OrderStatus.New, OrderUpdate.OrderTypes.Limit, DateTimeOffset.Now.ToUnixTimeMilliseconds(), realPrice, side, pair, realQuantity)) : ResponseObject.OrderPlacementFailed(BinanceUtilities.ToInternalError(query.Error.Code), query.Error.Message)); }
/// <inheritdoc /> public override ResponseObject <OrderUpdate> PlaceStoplossOrder(TradingPair pair, OrderSide side, decimal quantity, decimal price, long tradeId) { var client = _communications.Client; decimal limitPrice; if (side == OrderSide.Sell) { // Set the limit price extremely low -> sell immediately for the best price. // 5% is an arbitrary number that is probably more than the spread, but is not // rejected by Binance for deviating too much from the current price. limitPrice = price * 0.95M; } else { // Skew the quantity and the price -> buy immediately for the best price. // Quantity must scale inverse because (quantity * price) is the amount that needs to // be locked. You cannot lock more assets than you have. // 2% is hardcoded on purpose because it is unlikely to change. limitPrice = price * 1.02M; quantity /= 1.02M; } var realQuantity = pair.RoundToTradable(quantity); var realLimitPrice = pair.RoundToPriceable(limitPrice); var realStopPrice = pair.RoundToPriceable(price); lock (_orderCache) { var query = client.PlaceOrder( symbol: pair.ToString(), side: BinanceUtilities.ToExternal(side), type: OrderType.StopLossLimit, quantity: realQuantity, newClientOrderId: null, price: realLimitPrice, timeInForce: TimeInForce.GoodTillCancel, stopPrice: realStopPrice, icebergQty: null, orderResponseType: null, receiveWindow: (int)_communications.ReceiveWindow); if (query.Success) { var order = new OrderUpdate( query.Data.OrderId, tradeId, OrderUpdate.OrderStatus.New, OrderUpdate.OrderTypes.StopLoss, DateTimeOffset.Now.ToUnixTimeMilliseconds(), realLimitPrice, side, pair, realQuantity) { StopPrice = realStopPrice, }; // Enter middleware instance to make sure this order is // also converted to a stoploss order when the exchange reports updates. _transformMiddleWare.Add(order.OrderId, x => x.OrderType = OrderUpdate.OrderTypes.StopLoss); return(new ResponseObject <OrderUpdate>(order)); } return(ResponseObject.OrderPlacementFailed(BinanceUtilities.ToInternalError(query.Error.Code), query.Error.Message)); } }