Beispiel #1
0
        public async Task <Order> PlaceNewOrder(string oSide, string oProdName,
                                                string oSize, string oPrice, bool chaseBestPrice, string orderType = "limit")
        {
            OrderPlacer limitOrder = new OrderPlacer(_auth);

            JObject orderBodyObj = new JObject();

            //orderBodyObj.Add(new JProperty("client_oid", ""));

            orderBodyObj.Add(new JProperty("type", orderType));
            orderBodyObj.Add(new JProperty("product_id", oProdName));
            orderBodyObj.Add(new JProperty("side", oSide));
            orderBodyObj.Add(new JProperty("price", oPrice));
            orderBodyObj.Add(new JProperty("size", oSize));

            //if post only is set then use this
            if (AvoidExFees)
            {
                if (orderType != "market")
                {
                    orderBodyObj.Add(new JProperty("post_only", Boolean.TrueString));//"T"));
                }
            }

            if (OrderStartingPrice == 0) //not yet set
            {
                OrderStartingPrice = Convert.ToDecimal(oPrice);
            }


            Logger.WriteLog(string.Format("placing new {0} {1} order @{2}", orderType, oSide, oPrice));

            //changed from await to .Result: neworder should wait for the new order to finish formulating
            var newOrder = limitOrder.PlaceOrder(orderBodyObj).Result;

            if (newOrder != null)
            {
                var myCurOrder = new MyOrder
                {
                    OrderId        = newOrder.Id,
                    Productname    = newOrder.Product_id,
                    OrderType      = orderType,
                    Status         = "OPEN",
                    UsdPrice       = Convert.ToDecimal(newOrder.Price),
                    ProductSize    = Convert.ToDecimal(newOrder.Size),
                    Side           = newOrder.Side,
                    ChaseBestPrice = chaseBestPrice
                };


                if (newOrder.Status != "rejected")
                {
                    //if there are no orders in order list then set
                    //already tracking order variables to false
                    if (MyChaseOrderList.Count == 0)
                    {
                        if (fillsClient.BusyCheckingOrder)
                        {
                            fillsClient.BusyCheckingOrder = false;
                        }

                        if (FillsClient.IsBusy_TrackIngOrder)
                        {
                            FillsClient.IsBusy_TrackIngOrder = false;
                        }
                    }

                    AddToOrderList(myCurOrder);

                    //if (chaseBestPrice && MyChaseOrderList.Count == 1)
                    if (chaseBestPrice && MyChaseOrderList.Count > 0)
                    {
                        Logger.WriteLog("Order list contains 1 or more order, starting order tracker");
                        fillsClient.startTracker();
                    }
                }
                else
                {
                    //wait before placing a new order
                    //Task.Delay(200);
                    Thread.Sleep(200);

                    Logger.WriteLog("Last order rejected, retrying...");
                    decimal adjustedPrice = getAdjustedCurrentPrice(myCurOrder);

                    try
                    {
                        var orderAtNewPrice = PlaceNewOrder(
                            oSide: myCurOrder.Side,
                            oProdName: myCurOrder.Productname,
                            oSize: myCurOrder.ProductSize.ToString(),
                            oPrice: adjustedPrice.ToString(),
                            chaseBestPrice: true,
                            orderType: orderType
                            );
                    }
                    catch (Exception)
                    {
                        Logger.WriteLog("error with recursive new order after last order rejected. Throwing OrderRetryError error (should be cought by CancelAndReorder func)");
                        throw new Exception("OrderRetryError");
                    }
                }
            }

            return(newOrder);
        }
Beispiel #2
0
        private bool CancelAndReorder()
        {
            isBusyCancelAndReorder = true;

            //Logger.WriteLog("\t\t in cancel and reorder");

            //wait until fill status check is done
            if (fillsClient.BusyCheckingOrder)
            {
                Logger.WriteLog("waiting for fill status check to finish");
            }

            int chekingOrderWaitCount = 0;

            while (fillsClient.BusyCheckingOrder)
            {
                Thread.Sleep(50);
            }
            //chekingOrderWaitCount += 1;



            BusyWithWithCancelReorder = true;

            for (int i = 0; i < MyChaseOrderList.Count; i++)
            {
                if (MyChaseOrderList.Count == 0)
                {
                    break;
                }

                MyOrder myCurrentOrder = MyChaseOrderList.FirstOrDefault();


                //// skip to the next order if current order is market order, since market orders cant be cancelled
                //if (myCurrentOrder.OrderType == "market")
                //{
                //    Logger.WriteLog(String.Format("market {0} order ({1}) of {2} {3} detected, skipping cancel and reorder",
                //        myCurrentOrder.Side, myCurrentOrder.OrderId, myCurrentOrder.ProductSize, myCurrentOrder.Productname));
                //    continue;
                //}

                //if market order -> will error out when trying to cancel and will be notified filled


                //if order has been partially filled, move to next order in list
                if (myCurrentOrder.Status == "PARTIALLY_FILLED")
                {
                    //change the order size to the remaining of unfilled
                    var UnfilledAmount = myCurrentOrder.ProductSize - myCurrentOrder.FilledSize;
                    if (UnfilledAmount < 0.01m) //smallest size possible to trade
                    {
                        UnfilledAmount = 0.01m;
                    }
                    myCurrentOrder.ProductSize = UnfilledAmount; //myCurrentOrder.ProductSize - myCurrentOrder.FilledSize;
                    //myCurrentOrder.Status = "OPEN";
                    myCurrentOrder.FilledSize = 0;

                    OrderRetriedCount = 1; //reset the retried count
                    Logger.WriteLog(string.Format(
                                        "Modifying partially filled order, retrying to {0} unfilled size of {1} {2} ",
                                        myCurrentOrder.Side, UnfilledAmount, myCurrentOrder.Productname));
                }


                //cancell ALL the current orders
                List <string> cancelledOrder = new List <string>();

                try
                {
                    //pratially filled order already cancelled in FillCLients filled event
                    if (myCurrentOrder.Status == "PARTIALLY_FILLED")
                    {
                        myCurrentOrder.Status = "OPEN";
                        //remove the partially filled order id from watch list
                        //new id will be added to watch list when a new order is placed
                        RemoveFromOrderList(myCurrentOrder.OrderId);
                    }
                    else
                    {
                        cancelledOrder = CancelSingleOrder(myCurrentOrder.OrderId).Result;
                        //remove the order from the watch list if cancelled
                        //cancelledOrder only indicates if cancelled or not. does not contain any data
                        if (cancelledOrder.Count() > 0)
                        {
                            RemoveFromOrderList(myCurrentOrder.OrderId); //notice how myCurrentOrder.OrderId is used instead of cancelledOrder.first()
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.WriteLog(string.Format(
                                        "error cancelling order {0}, retrying...", myCurrentOrder.OrderId));

                    if (ex.InnerException.Message == "OrderNotFound")
                    {
                        Logger.WriteLog("Order not found, removing from watch list and continueing" + myCurrentOrder.OrderId);

                        RemoveFromOrderList(myCurrentOrder.OrderId);

                        NotifyOrderUpdateListener(new OrderUpdateEventArgs
                        {
                            side          = "UNKNOWN",
                            filledAtPrice = "0",
                            Message       = "ORDER_NOT_FOUND",
                            OrderId       = "UNKNOWN",
                            fillFee       = "0",
                            fillSize      = "0",
                            ProductName   = "UNKNOWN"
                        });
                    }

                    if (ex.InnerException.Message == "OrderAlreadyDone")
                    {
                        Logger.WriteLog("Order already done " + myCurrentOrder.OrderId);

                        //order already done so remove from watch list 2018-02-18
                        Logger.WriteLog("Order already done, removing from watch list " + myCurrentOrder.OrderId);
                        RemoveFromOrderList(myCurrentOrder.OrderId);
                        NotifyFilledOtherWise(myCurrentOrder.OrderId);
                    }

                    continue; //continue and try again to cancel and reorder
                    //throw;
                }


                Logger.WriteLog(string.Format("\tCancelled {0} order ({1}): {2} {3} @{4}",
                                              myCurrentOrder.Side, myCurrentOrder.OrderId, myCurrentOrder.ProductSize, myCurrentOrder.Productname,
                                              myCurrentOrder.UsdPrice));


                decimal adjustedPrice = 0;


                decimal curPriceDifference = 0;

                if (OrderStartingPrice > 0)
                {
                    curPriceDifference = Math.Abs(OrderStartingPrice - PriceTicker.CurrentPrice);
                }


                //if (myCurrentOrder == null)
                //    continue;
                //OrderStartingPrice = adjustedPrice;

                //var priceChangePercent = PriceTicker.CurrentPrice * 10.00m;//0.0025m; //for testing
                decimal priceChangePercent = 0.0m;
                if (AvoidExFees)
                {
                    priceChangePercent = PriceTicker.CurrentPrice * 0.0020m; // 0.0025m
                }
                else
                {
                    priceChangePercent = PriceTicker.CurrentPrice * 0.0010m; // 0.0025m
                }
                //test!!
                //priceChangePercent = 0.00001m;

                if (OrderRetriedCount <= 13 && curPriceDifference <= priceChangePercent) // retry a total of 15 times or while less than a "big jump"
                {
                    adjustedPrice = getAdjustedCurrentPrice(myCurrentOrder);

                    try
                    {
                        //place new order limit order
                        var orderAtNewPrice = PlaceNewOrder(
                            oSide: myCurrentOrder.Side,
                            oProdName: myCurrentOrder.Productname,
                            oSize: myCurrentOrder.ProductSize.ToString(),
                            oPrice: adjustedPrice.ToString(),
                            chaseBestPrice: true,
                            orderType: "limit"
                            );


                        orderAtNewPrice.Wait();
                    }
                    catch (Exception)
                    {
                        Logger.WriteLog("error in cancel and reorder occured while placing new limit order, retrying...");

                        //put the order back in the active order list if there are no
                        //orders since it was cancelled above. this prevents it from
                        //locking up in case the order was cancelled
                        //and an error was encountered while placing a new order

                        if (MyChaseOrderList.Count == 0)
                        {
                            AddToOrderList(myCurrentOrder);
                        }

                        continue;
                    }
                }
                else
                {
                    if (curPriceDifference > priceChangePercent)
                    {
                        Logger.WriteLog("Price changed more than " + curPriceDifference + " Forcing market order");
                    }
                    adjustedPrice = getAdjustedCurrentPrice(myCurrentOrder, "market");
                    //place new market order

                    try
                    {
                        var orderAtNewPrice = PlaceNewOrder(
                            oSide: myCurrentOrder.Side,
                            oProdName: myCurrentOrder.Productname,
                            oSize: myCurrentOrder.ProductSize.ToString(),
                            oPrice: adjustedPrice.ToString(),
                            chaseBestPrice: true,
                            orderType: "market"
                            );


                        orderAtNewPrice.Wait();
                    }
                    catch (Exception)
                    {
                        Logger.WriteLog("Error in cancel and reorder occured while placing new market order, retrying...");

                        if (MyChaseOrderList.Count == 0)
                        {
                            AddToOrderList(myCurrentOrder);
                        }

                        continue;
                    }
                }
            }
            BusyWithWithCancelReorder = false;

            OrderRetriedCount += 1;

            Logger.WriteLog("Order retried count: " + OrderRetriedCount);

            Logger.WriteLog("Orders in ActiveOrderList:");

            try
            {
                MyChaseOrderList.ForEach(x => Logger.WriteLog("\t" + x.OrderId));
            }
            catch (Exception)
            {
                Logger.WriteLog("Error enumerating order list, list changed");
            }

            isBusyCancelAndReorder = false;

            return(true);
        }