Exemplo n.º 1
0
        private void runSellStrategy(IWebSocketClientConnection webSocketConnection, string symbol)
        {
            OrderBook.IOrder bestBid   = _tradeclient.GetOrderBook(symbol).BestBid;
            OrderBook.IOrder bestOffer = _tradeclient.GetOrderBook(symbol).BestOffer;

            if (_priceType == PriceType.MARKET_AS_MAKER)
            {
                ulong sellPrice = 0;
                if (bestBid != null)
                {
                    sellPrice = bestBid.Price + (ulong)(0.01 * 1e8);
                }
                else if (bestOffer != null)
                {
                    sellPrice = bestOffer.Price;
                }

                if (sellPrice > 0 || _sell_floor_price > 0)
                {
                    if (sellPrice >= _sell_floor_price)
                    {
                        replaceOrder(webSocketConnection, symbol, OrderSide.SELL, sellPrice);
                        return;
                    }

                    _sellTargetPrice = _sell_floor_price; // find the best position as maker for the sell floor price
                }
                else
                {
                    // empty book scenario without a user defined sell floor price
                    _tradeclient.CancelOrderByClOrdID(webSocketConnection, _strategySellOrderClorid);
                    return;
                }
            }

            // available funds with a target price should execute ASAP even as liquidity takers whenever possible
            if (_sellTargetPrice > 0 && bestBid != null && bestBid.Price >= _sellTargetPrice && bestBid.UserId != _tradeclient.UserId)
            {
                ulong availableQty = calculateOrderQty(symbol, OrderSide.SELL, bestBid.Price, ulong.MaxValue);
                if (availableQty > _minOrderSize)
                {
                    ulong sell_qty = Math.Min(availableQty, bestBid.Qty);
                    // execute the order as taker and emulate IOC instruction
                    sendOrder(webSocketConnection, symbol, OrderSide.SELL, sell_qty, bestBid.Price, OrdType.LIMIT, 0, ExecInst.DEFAULT, TimeInForce.IMMEDIATE_OR_CANCEL);
                    return;
                }
                else
                {
                    // cancel current order to free balance to be used as taker
                    MiniOMS.IOrder own_sell_order = _tradeclient.miniOMS.GetOrderByClOrdID(_strategySellOrderClorid);
                    if (own_sell_order != null && (own_sell_order.OrdStatus == OrdStatus.NEW || own_sell_order.OrdStatus == OrdStatus.PARTIALLY_FILLED))
                    {
                        if (own_sell_order.LeavesQty > _minOrderSize)
                        {
                            ulong sell_qty = Math.Min(own_sell_order.LeavesQty, bestBid.Qty);
                            _tradeclient.CancelOrderByClOrdID(webSocketConnection, own_sell_order.ClOrdID);
                            sendOrder(webSocketConnection, symbol, OrderSide.SELL, sell_qty, bestBid.Price, OrdType.LIMIT, 0, ExecInst.DEFAULT, TimeInForce.IMMEDIATE_OR_CANCEL);
                            return;
                        }
                    }
                }
            }

            // post the order in the order book
            if (bestOffer != null)
            {
                if (bestOffer.UserId != _tradeclient.UserId)
                {
                    // sell @ 1 cent bellow the best price (TODO: parameter for price increment)
                    ulong sellPrice = bestOffer.Price - (ulong)(0.01 * 1e8);
                    if (sellPrice >= _sellTargetPrice)
                    {
                        // TODO: Become a Taker when the spread is "small" (i.e for stop trailing converted to pegged or for any pegged)
                        if (sellPrice > bestBid.Price)
                        {
                            replaceOrder(webSocketConnection, symbol, OrderSide.SELL, sellPrice);
                        }
                        else
                        {
                            // avoid being a taker or receiving a reject when using ExecInst=6 but stay in the book with max price
                            ulong max_sell_price = bestBid.Price + (ulong)(0.01 * 1e8);
                            var   own_order      = _tradeclient.miniOMS.GetOrderByClOrdID(_strategySellOrderClorid);
                            ulong availableQty   = calculateOrderQty(symbol, OrderSide.SELL);
                            if (own_order == null || own_order.Price != max_sell_price || availableQty > own_order.OrderQty)
                            {
                                replaceOrder(webSocketConnection, symbol, OrderSide.SELL, max_sell_price);
                            }
                        }
                    }
                    else
                    {
                        // cannot fight for the first position thus try to find a visible position in the book
                        OrderBook orderBook             = _tradeclient.GetOrderBook(symbol);
                        List <OrderBook.Order> sellside = orderBook.GetOfferOrders();
                        int i = sellside.BinarySearch(
                            new OrderBook.Order(OrderBook.OrdSide.SELL, _sellTargetPrice + (ulong)(0.01 * 1e8)),
                            new OrderBook.OrderPriceComparer()
                            );
                        int position = (i < 0 ? ~i : i);
                        Debug.Assert(position > 0);

                        // verificar se a profundidade vale a pena: (TODO: parameters for max_pos_depth and max_amount_depth)
                        if (position > 15 + 1 && orderBook.DoesAmountExceedsLimit(
                                OrderBook.OrdSide.SELL,
                                position - 1, (ulong)(20 * 1e8)))
                        {
                            _tradeclient.CancelOrderByClOrdID(webSocketConnection, _strategySellOrderClorid);
                            return;
                        }

                        var pivotOrder = sellside[position];
                        if (pivotOrder.UserId == _tradeclient.UserId)
                        {
                            // make sure the order is the same or from another client instance
                            MiniOMS.IOrder own_sell_order = _tradeclient.miniOMS.GetOrderByClOrdID(_strategySellOrderClorid);
                            if (sellside[position].OrderId == own_sell_order.OrderID)
                            {
                                // ordem ja e minha : pega + recursos disponiveis e cola no preco do vizinho se já nao estiver
                                ulong price_delta  = sellside.Count > position + 1 ? sellside[position + 1].Price - pivotOrder.Price : 0;
                                ulong newSellPrice = (price_delta > (ulong)(0.01 * 1e8) ?
                                                      pivotOrder.Price + price_delta - (ulong)(0.01 * 1e8) :
                                                      pivotOrder.Price);
                                ulong availableQty = calculateOrderQty(symbol, OrderSide.SELL);
                                if (newSellPrice > pivotOrder.Price || availableQty > pivotOrder.Qty)
                                {
                                    replaceOrder(webSocketConnection, symbol, OrderSide.SELL, newSellPrice, availableQty);
                                }
                            }
                        }
                        else
                        {
                            // estabelece preco de venda 1 centavo menor do que nesta posicao
                            ulong newSellPrice = pivotOrder.Price - (ulong)(0.01 * 1e8);
                            replaceOrder(webSocketConnection, symbol, OrderSide.SELL, newSellPrice);
                        }
                    }
                }
                else
                {
                    // check and replace the order on the top to get closer to the order in the second position and gather more available funds
                    MiniOMS.IOrder         own_sell_order = _tradeclient.miniOMS.GetOrderByClOrdID(_strategySellOrderClorid);
                    List <OrderBook.Order> sellside       = _tradeclient.GetOrderBook(symbol).GetOfferOrders();
                    if (sellside[0].OrderId == own_sell_order.OrderID)
                    {
                        ulong price_delta  = sellside.Count > 1 ? sellside[1].Price - sellside[0].Price : 0;
                        ulong newSellPrice = (price_delta > (ulong)(0.01 * 1e8) ?
                                              bestOffer.Price + price_delta - (ulong)(0.01 * 1e8) :
                                              bestOffer.Price);
                        ulong availableQty = calculateOrderQty(symbol, OrderSide.SELL);
                        if (newSellPrice > bestOffer.Price || availableQty > bestOffer.Qty)
                        {
                            replaceOrder(webSocketConnection, symbol, OrderSide.SELL, newSellPrice, availableQty);
                        }
                    }
                }
            }
            else
            {
                // empty book scenario
                ulong availableQty = calculateOrderQty(symbol, OrderSide.SELL);
                Debug.Assert(_sellTargetPrice > 0);
                ulong sell_price = Math.Max(_sellTargetPrice, bestBid != null ? bestBid.Price + (ulong)(0.01 * 1e8) : 0);
                sendOrder(webSocketConnection, symbol, OrderSide.SELL, availableQty, sell_price);
            }
        }
Exemplo n.º 2
0
        private void runSellStrategy(IWebSocketClientConnection webSocketConnection, string symbol)
        {
            OrderBook.IOrder bestOffer = _tradeclient.GetOrderBook(symbol).BestOffer;
            if (bestOffer != null)
            {
                if (bestOffer.UserId != _tradeclient.UserId)
                {
                    // sell @ 1 cent bellow the best price (TODO: parameter for price increment)
                    ulong sellPrice = bestOffer.Price - (ulong)(0.01 * 1e8);
                    if (sellPrice >= _sellTargetPrice)
                    {
                        replaceOrder(webSocketConnection, symbol, OrderSide.SELL, sellPrice);
                    }
                    else
                    {
                        // cannot fight for the first position thus try to find a visible position in the book
                        OrderBook orderBook             = _tradeclient.GetOrderBook(symbol);
                        List <OrderBook.Order> sellside = orderBook.GetOfferOrders();
                        int i = sellside.BinarySearch(
                            new OrderBook.Order(OrderBook.OrdSide.SELL, _sellTargetPrice + (ulong)(0.01 * 1e8)),
                            new OrderBook.OrderPriceComparer()
                            );
                        int position = (i < 0 ? ~i : i);
                        Debug.Assert(position > 0);

                        // verificar se a profundidade vale a pena: (TODO: parameters for max_pos_depth and max_amount_depth)
                        if (position > 5 + 1 && orderBook.DoesAmountExceedsLimit(
                                OrderBook.OrdSide.SELL,
                                position - 1, (ulong)(10 * 1e8)))
                        {
                            _tradeclient.CancelOrderByClOrdID(webSocketConnection, _strategySellOrderClorid);
                            return;
                        }

                        var pivotOrder = sellside[position];
                        if (pivotOrder.UserId == _tradeclient.UserId)
                        {
                            // ordem ja e minha : pega + recursos disponiveis e cola no preco no vizinho se já nao estiver
                            ulong price_delta  = sellside[position + 1].Price - pivotOrder.Price;
                            ulong newSellPrice = (price_delta > (ulong)(0.01 * 1e8) ?
                                                  pivotOrder.Price + price_delta - (ulong)(0.01 * 1e8) :
                                                  pivotOrder.Price);
                            ulong availableQty = calculateOrderQty(symbol, OrderSide.SELL);
                            if (newSellPrice > pivotOrder.Price || availableQty > pivotOrder.Qty)
                            {
                                replaceOrder(webSocketConnection, symbol, OrderSide.SELL, newSellPrice, availableQty);
                            }
                        }
                        else
                        {
                            // estabelece preco de venda 1 centavo menor do que nesta posicao
                            ulong newSellPrice = pivotOrder.Price - (ulong)(0.01 * 1e8);
                            replaceOrder(webSocketConnection, symbol, OrderSide.SELL, newSellPrice);
                        }
                    }
                }
                else
                {
                    // check and replace the order to get closer to the order in the second position and gather more available funds
                    List <OrderBook.Order> sellside = _tradeclient.GetOrderBook(symbol).GetOfferOrders();
                    ulong price_delta  = sellside.Count > 1 ? sellside[1].Price - sellside[0].Price : 0;
                    ulong newSellPrice = (price_delta > (ulong)(0.01 * 1e8) ?
                                          bestOffer.Price + price_delta - (ulong)(0.01 * 1e8) :
                                          bestOffer.Price);
                    ulong availableQty = calculateOrderQty(symbol, OrderSide.SELL);
                    if (newSellPrice > bestOffer.Price || availableQty > bestOffer.Qty)
                    {
                        replaceOrder(webSocketConnection, symbol, OrderSide.SELL, newSellPrice, availableQty);
                    }
                }
            }
            else
            {
                // TODO: empty book scenario
            }
        }