public async Task GetOpenOrders(Prices prices) { var orders = await _bittrexApi.GetOpenOrders(); if (orders.Count > 0) { Console.WriteLine(orders .ToStringTable <OpenOrder>( new[] { "Market", "Bid/Ask", "Quantity", "Remaining", "Estimated Total", "Estimated EUR Value", "Estimated USD Value" }, x => x.Exchange, x => x.Limit.ToString("0.00000000"), x => x.Quantity, x => x.QuantityRemaining, x => ((x.Limit * x.Quantity) * 0.9975).ToString("0.00000000"), x => (((x.Limit * x.Quantity) * 0.9975) * (double)prices.Eur.Last).ToString("0.00 EUR"), x => (((x.Limit * x.Quantity) * 0.9975) * (double)prices.Usd.Last).ToString("0.00 USD"))); } else { Console.WriteLine("\tNo open orders found..."); } Console.WriteLine( $"\tTOTAL OPEN ORDERS: {(orders.Sum(x => x.Limit * x.Quantity) * (double)prices.Eur.Last):0.00} EUR / " + $"{(orders.Sum(x => x.Limit * x.Quantity) * (double)prices.Usd.Last):0.00} USD", ConsoleColor.Cyan); }
/// <summary> /// Queries the persistence layer for open trades and /// handles them, otherwise a new trade is created. /// </summary> /// <returns></returns> public async Task Process() { // Get our current trades. var tradeTable = await ConnectionManager.GetTableConnection(Constants.OrderTableName, Constants.IsDryRunning); var balanceTable = await ConnectionManager.GetTableConnection(Constants.BalanceTableName, Constants.IsDryRunning); var activeTrades = tradeTable.CreateQuery <Trade>().Where(x => x.IsOpen).ToList(); // Create two batches that we can use to update our tables. var batch = new TableBatchOperation(); var balanceBatch = new TableBatchOperation(); // Can't use FirstOrDefault directly because Linq for Table Storage doesn't support it. _totalBalance = balanceTable.CreateQuery <Balance>().Where(x => x.RowKey == "TOTAL").FirstOrDefault(); _dayBalance = balanceTable.CreateQuery <Balance>() .Where(x => x.RowKey == DateTime.UtcNow.ToString("yyyyMMdd")) .FirstOrDefault(); // Create both the balances if they don't exist yet. CreateBalancesIfNotExists(balanceBatch); // Handle our active trades. foreach (var trade in activeTrades) { var orders = await _api.GetOpenOrders(trade.Market); if (orders.Any(x => x.OrderUuid.ToString() == trade.OpenOrderId)) { // There's already an open order for this trade. // This means we're still buying it. _log($"Already an open order for trade {trade.OpenOrderId}"); } else { trade.OpenOrderId = null; // No open order with the order ID of the trade. // Check if this trade can be closed if (!await CloseTradeIfFulfilled(trade)) { // Check if we can sell our current pair await HandleTrade(trade); } batch.Add(TableOperation.Replace(trade)); } } // If we have less active trades than we can handle, find a new one. while (activeTrades.Count < Constants.MaxNumberOfConcurrentTrades) { var trade = await StartTrade(activeTrades, batch); if (trade != null) { // Add this to activeTrades so we don't trigger the same. activeTrades.Add(trade); batch.Add(TableOperation.Insert(trade)); } else { // No more trade to be found, kill it. break; } } _log($"Currently handling {activeTrades.Count} trades."); // If these actually changed make a roundtrip to the server to set them. if (_dayBalanceExists && _oldDayBalance != _dayBalance.Profit) { balanceBatch.Add(TableOperation.Replace(_dayBalance)); } if (_totalBalanceExists && _oldTotalBalance != _totalBalance.Profit) { balanceBatch.Add(TableOperation.Replace(_totalBalance)); } if (batch.Count > 0) { tradeTable.ExecuteBatch(batch); } if (balanceBatch.Count > 0) { balanceTable.ExecuteBatch(balanceBatch); } }