/// <summary> /// Cancels any orders that have been buying for an entire cycle. /// </summary> /// <returns></returns> private async Task CancelUnboughtOrders() { // Only trigger if there are orders still buying. if (_activeTrades.Any(x => x.IsBuying)) { // Loop our current trades that are still looking to buy if there are any. foreach (var trade in _activeTrades.Where(x => x.IsBuying)) { var exchangeOrder = await _api.GetOrder(trade.BuyOrderId, trade.Market); // if this order is PartiallyFilled, don't cancel if (exchangeOrder?.Status == OrderStatus.PartiallyFilled) { continue; // not yet completed so wait } await _api.CancelOrder(trade.BuyOrderId, trade.Market); // Update the buy order in our data storage. trade.IsBuying = false; trade.OpenOrderId = null; trade.IsOpen = false; trade.SellType = SellType.Cancelled; trade.CloseDate = DateTime.UtcNow; // Update the order await _dataStore.SaveTradeAsync(trade); // Handle the trader that was dedicated to this order. var currentTrader = _currentTraders.FirstOrDefault(x => x.Identifier == trade.TraderId); // If there is a trader, update that as well... if (currentTrader != null) { currentTrader.IsBusy = false; currentTrader.LastUpdated = DateTime.UtcNow; // Update the trader to indicate that we're not busy anymore. await _dataStore.SaveTraderAsync(currentTrader); } await SendNotification($"Cancelled {trade.Market} buy order because it wasn't filled in time."); } } }
/// <summary> /// Cancels any orders that have been buying for an entire cycle. /// </summary> /// <returns></returns> private async Task CancelUnboughtOrders() { // Only trigger if there are orders still buying. if (_activeTrades.Any(x => x.IsBuying)) { // Loop our current buying trades if there are any. foreach (var trade in _activeTrades.Where(x => x.IsBuying)) { var exchangeOrder = await _api.GetOrder(trade.BuyOrderId, trade.Market); // if this order is PartiallyFilled, don't cancel if (exchangeOrder?.Status == OrderStatus.PartiallyFilled) { continue; // not yet completed so wait } // Cancel our open buy order. await _api.CancelOrder(trade.BuyOrderId, trade.Market); // Update the buy order. trade.IsBuying = false; trade.OpenOrderId = null; trade.IsOpen = false; trade.SellType = SellType.Cancelled; trade.CloseDate = DateTime.UtcNow; // Update the order in our batch. _orderBatch.Add(TableOperation.Replace(trade)); // Handle the trader that was dedicated to this order. var currentTrader = _currentTraders.FirstOrDefault(x => x.RowKey == trade.TraderId); if (currentTrader != null) { currentTrader.IsBusy = false; currentTrader.LastUpdated = DateTime.UtcNow; // Update the trader to indicate that we're not busy anymore. await _traderTable.ExecuteAsync(TableOperation.Replace(currentTrader)); } await SendNotification($"Cancelled {trade.Market} buy order."); } } }
/// <summary> /// Updates the buy orders by checking with the exchange what status they are currently. /// </summary> /// <returns></returns> private async Task UpdateOpenBuyOrders() { // There are trades that have an open order ID set & no sell order id set // that means its a buy trade that is waiting to get bought. See if we can update that first. _orderBatch = new TableBatchOperation(); foreach (var trade in _activeTrades.Where(x => x.OpenOrderId != null && x.SellOrderId == null)) { var exchangeOrder = await _api.GetOrder(trade.BuyOrderId, trade.Market); // if this order is filled, we can update our database. if (exchangeOrder?.Status == OrderStatus.Filled) { trade.OpenOrderId = null; trade.StakeAmount = exchangeOrder.OriginalQuantity * exchangeOrder.Price; trade.Quantity = exchangeOrder.OriginalQuantity; trade.OpenRate = exchangeOrder.Price; trade.OpenDate = exchangeOrder.Time; trade.IsBuying = false; // If this is enabled we place a sell order as soon as our buy order got filled. if (Constants.ImmediatelyPlaceSellOrder) { var sellPrice = Math.Round(trade.OpenRate * (1 + Constants.ImmediatelyPlaceSellOrderAtProfit), 8); var orderId = await _api.Sell(trade.Market, trade.Quantity, sellPrice); trade.CloseRate = sellPrice; trade.OpenOrderId = orderId; trade.SellOrderId = orderId; trade.IsSelling = true; trade.SellType = SellType.Immediate; } _orderBatch.Add(TableOperation.Replace(trade)); await SendNotification($"Buy order filled for {trade.Market} at {trade.OpenRate:0.00000000}."); } } if (_orderBatch.Count > 0) { await _orderTable.ExecuteBatchAsync(_orderBatch); } }