private async void HandleNonFilledOrder(ExchangeOrderResult orderResult, Candle candle) { ExchangeOrderResult result = null; Ticker ticker; switch (orderResult.Result) { case ExchangeAPIOrderResult.FilledPartially: Log($"Partially filled order quantity filled {orderResult.AmountFilled} of {orderResult.Amount}"); /* * * PARTIALLY FILLED * * 1. Save the initial order and what was filled * 2. Check in thrity seconds for any more filling of it * 3. Add a new order against this position * 4. If not filled after two more queries, cancel it * */ // 1. Save SavePosition(SaveOrder(orderResult, GetTimeStamp(candle.Timestamp))); // 2. Check in 30 seconds twice int counter = 0; while (counter < 3) { Log("Waiting 30 seconds.."); Pause(30); ++counter; result = await CheckOrderStatus(orderResult.OrderId); if (result.Result == ExchangeAPIOrderResult.Filled) // if status now is now filled great { Log($"Remaining quanity of order filled"); SaveOrder(orderResult, GetTimeStamp(candle.Timestamp)); UpdatePositionQuantity(); return; } else { if (counter == 2) // this is the last time & it wasn't filled { Log($"Remaining quanity of order not filled after waiting 90 seconds, cancelling the order, exchange order id {orderResult.OrderId}, message: {orderResult.Message}"); _trader.CancelOrder(orderResult.OrderId); // TODO: Could look at putting in another order for the outstanding quantity // Get the minimum quantity for the currency // if the outstanding quantity is more than the minimum quantity // get the current price // create a new order for the remaining quantity // update the position with the new quantity received } } } break; case ExchangeAPIOrderResult.Canceled: /* * * CANCELLED by exchange * * 1. Wait 10 seconds * 3. Check price now * 4. Issue a new Buy * */ Log($"Order cancelled by exchange for orderId {orderResult.OrderId}, waiting 10 seconds and retrying, message: {orderResult.Message}"); Log("Waiting 10 seconds"); Pause(10); ticker = _trader.GetLatestTicker(_inMemoryBot.BaseCoin, _inMemoryBot.Coin); if (orderResult.IsBuy) { Buy(new Candle() { Timestamp = DateTime.Now, ClosePrice = ticker.Ask }); } else { Sell(new Candle() { Timestamp = DateTime.Now, ClosePrice = ticker.Bid }); } break; case ExchangeAPIOrderResult.Error: /* * * ERROR * * 1. Wait 10 seconds and check again * 2. If still error, cancel it * 3. Check price now * 4. Issue a new Buy * */ Log($"Error reported on exchange for orderId {orderResult.OrderId}, message: {orderResult.Message}"); Log("Waiting 10 seconds to check again"); Pause(10); result = await CheckOrderStatus(orderResult.OrderId); Log($"Result.. {result.Result}"); // 2. If not filled, cancel it if (result.Result != ExchangeAPIOrderResult.Filled) { Log($"Not filled, cancelling order {orderResult.OrderId}"); _trader.CancelOrder(orderResult.OrderId); // 3. Check the price now ticker = _trader.GetLatestTicker(_inMemoryBot.BaseCoin, _inMemoryBot.Coin); Log($"Going to order again, latest ticker {JsonConvert.SerializeObject(ticker)} "); if (orderResult.IsBuy) { Buy(new Candle() { Timestamp = DateTime.Now, ClosePrice = ticker.Ask }); } else { Sell(new Candle() { Timestamp = DateTime.Now, ClosePrice = ticker.Bid }); } } break; case ExchangeAPIOrderResult.Pending: /* * * PENDING * * 1. Wait 30 seconds and check again * 2. If still pending, cancel it * 3. Check price now * 4. Issue a new Buy * */ Log($"Pending reported on exchange for orderId {orderResult.OrderId}, message: {orderResult.Message}"); // 1. Wait thirty seconds & check Pause(30); result = await CheckOrderStatus(orderResult.OrderId); // 2. If not filled, cancel it if (result.Result == ExchangeAPIOrderResult.Pending) { _trader.CancelOrder(orderResult.OrderId); // 3. Check the price now ticker = _trader.GetLatestTicker(_inMemoryBot.BaseCoin, _inMemoryBot.Coin); Log($"Order still pending after 30 seconds for orderId {orderResult.OrderId}, cancelling and re-ordering at new price {ticker.Ask}"); if (orderResult.IsBuy) { Buy(new Candle() { Timestamp = DateTime.Now, ClosePrice = ticker.Ask }); } else { Sell(new Candle() { Timestamp = DateTime.Now, ClosePrice = ticker.Bid }); } } break; case ExchangeAPIOrderResult.Unknown: /* * * UNKNOWN * * 1. Wait thirty seconds and check again * 2. If still unknow, cancel it * 3. Check price now * 4. Issue a new Buy * */ Log($"UNKNOWN reported by exchange for orderId {orderResult.OrderId}, message: {orderResult.Message}. Waiting 30 seconds to try again"); // 1. Wait thirty seconds & check Pause(30); result = await CheckOrderStatus(orderResult.OrderId); // 2. If not filled, cancel it if (result.Result == ExchangeAPIOrderResult.Unknown) { _trader.CancelOrder(orderResult.OrderId); // 3. Check the price now ticker = _trader.GetLatestTicker(_inMemoryBot.BaseCoin, _inMemoryBot.Coin); Log($"Order still UNKNOWN after 30 seconds for orderId {orderResult.OrderId}, cancelling and re-ordering at new price {ticker.Ask}"); if (orderResult.IsBuy) { Buy(new Candle() { Timestamp = DateTime.Now, ClosePrice = ticker.Ask }); } else { Sell(new Candle() { Timestamp = DateTime.Now, ClosePrice = ticker.Bid }); } } break; } }