Ejemplo n.º 1
0
        /// <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);
            }
        }