public async Task Start() { _logger.LogInformation( "Starting {@MarketMaker} strategy bot", Strategy.MarketMaker.ToString()); try { var symbol = _binanceSpotExchange.GetSymbol( _marketMakerConfig.Base, _marketMakerConfig.Quote); _logger.LogInformation( "Trading pair {@symbol}", symbol); _logger.LogInformation( "Trading settings: SpreadInQuoteCoin={@SpreadInQuoteCoin}{@Quote}, TradeAssetAllocationInPercentage={@TradeAssetAllocationPercentage}%", _marketMakerConfig.SpreadInQuoteCoin, _marketMakerConfig.Quote.ToString(), _marketMakerConfig.TradeAssetAllocationPercentage); var tickCounter = 0; while (true) { try { tickCounter++; if (tickCounter > _marketMakerConfig.StopAfterTicks) { _logger.LogInformation( "\n============================================================================================================\n"); _logger.LogInformation( "Tick stop limit reached.Exiting... StopAfterTick={@StopAfterTick}", _marketMakerConfig.StopAfterTicks); await HandlePendingOrders(symbol); _logger.LogInformation( "\n========================================================END====================================================\n"); break; } _logger.LogInformation( "\n============================================================================================================\n"); _logger.LogInformation( "Start of new tick. TickInterval={@TickIntervalInSeconds}, TickCount={@tickCounter}", _marketMakerConfig.TickIntervalInSeconds, tickCounter); //var symbolInfo = await _binanceSpotExchange.GetSymbolInfoAsync(symbol); await HandlePendingOrders(symbol); _logger.LogInformation("Preparing for new orders..."); var orderBook = await _binanceSpotExchange.GetOrderBookAsync( symbol, 5); var baseCurrencyBalance = await _binanceSpotExchange.GetBalanceAsync(_marketMakerConfig.Base); var quoteCurrencyBalance = await _binanceSpotExchange.GetBalanceAsync(_marketMakerConfig.Quote); var lastBid = Coin.Round( orderBook.Bids.First().Price, _marketMakerConfig.Quote); var lastAsk = Coin.Round( orderBook.Asks.First().Price, _marketMakerConfig.Quote); var realMarketPrice = Coin.Round( (await _binanceSpotExchange.Get24HourPriceAsync(symbol)).LastPrice, _marketMakerConfig.Quote); var marketPrice = Coin.Round( (lastAsk + lastBid) / 2, _marketMakerConfig.Quote); var buyPrice = marketPrice - _marketMakerConfig.SpreadInQuoteCoin; var sellPrice = marketPrice + _marketMakerConfig.SpreadInQuoteCoin; //var buyQuantity = Coin.Round( // Math.Max(12, quoteCurrencyBalance.CommonTotal * _marketMakerConfig.TradeAssetAllocationPercentage / 100) / // marketPrice, // _marketMakerConfig.Base); //var sellQuantity = buyQuantity; // same as buy quantity var buyQuantity = Coin.Round(_marketMakerConfig.TradeFixedSizeInQuote / marketPrice, _marketMakerConfig.Base); var sellQuantity = buyQuantity; _logger.LogInformation( "Order Params. BuyPrice={@buyPrice}, MarketPrice={@marketPrice}, SellPrice={@sellPrice}, RealMarketPrice={@realMarketPrice}, BuyQty={@buyQuantity}, SellQty={@sellQuantity}, Bid={@lastBid}, Ask={@lastAsk}", buyPrice, marketPrice, sellPrice, realMarketPrice, buyQuantity, sellQuantity, lastBid, lastAsk); var sellingCost = sellPrice * sellQuantity; var buyingCost = buyPrice * buyQuantity; var fees = (sellingCost + buyingCost) * 0.001m; var profit = (sellPrice * sellQuantity) - (buyQuantity * buyPrice) - fees; _logger.LogInformation("Is it profitable? sellingCost={@sellingCost}, buyingCost={@buyingCost}, fees={@fees}, profit={@profit}. All price in {@Quote}", sellingCost, buyingCost, fees, profit, _marketMakerConfig.Quote.ToString()); if (profit > 0.1m) { _logger.LogInformation( "Expected Profit: {@profit}{@Quote}", profit, _marketMakerConfig.Quote.ToString()); var hasEnoughToPlaceBuyOrder = buyPrice * buyQuantity < quoteCurrencyBalance.CommonAvailable; var hasEnoughToPlaceSellOrder = baseCurrencyBalance.CommonAvailable > sellQuantity; if (!hasEnoughToPlaceBuyOrder) { _logger.LogError( "Not enough {@Quote} to place buy order", _marketMakerConfig.Quote.ToString()); } if (!hasEnoughToPlaceSellOrder) { _logger.LogError( "Not enough {@Base} to place sell order", _marketMakerConfig.Base.ToString()); } if (hasEnoughToPlaceBuyOrder && hasEnoughToPlaceSellOrder) { // TODO: scenarios // 1. No pending orders - (new orders can be placed) // 2. Both pending // 3. Order partially completed - convert pending orders to market order (only some quantities are sold or bought) // 4. only one of two orders are completed - convert pending limit order to market order // TODO: re-balance trading pair var ordersResult = await Task.WhenAll( _binanceSpotExchange.PlaceLimitBuyOrderAsync( symbol, buyQuantity, buyPrice, _marketMakerConfig.Test), _binanceSpotExchange.PlaceLimitSellOrderAsync( symbol, sellQuantity, sellPrice, _marketMakerConfig.Test)); if (ordersResult[0] && ordersResult[1]) { _logger.LogInformation("Buy and Sell orders placed successfully."); } else { _logger.LogWarning("Buy and Sell orders NOT placed successfully."); await HandlePendingOrders(symbol); } } } else { _logger.LogWarning("Not enough profit to place the order. SKIPPING.... sellingCost={@sellingCost}, buyingCost={@buyingCost}, fees={@fees}, profit={@profit}. All price in {@Quote}", sellingCost, buyingCost, fees, profit, _marketMakerConfig.Quote.ToString()); } Thread.Sleep(_marketMakerConfig.TickIntervalInSeconds * 1000); } catch (Exception ex) { _logger.LogError(ex, "Unexpected error. Cancelling all open orders"); await HandlePendingOrders(symbol); } } } catch (Exception ex) { _logger.LogError(ex, "Unexpected error when running {@MarketMaker} strategy bot, exiting...", Strategy.MarketMaker.ToString()); } }
public async Task Start() { _logger.LogInformation("Starting {@PriceBurst} strategy bot", Strategy.PriceBurst.ToString()); try { var symbol = _binanceSpotExchange.GetSymbol(_priceBurstConfig.Base, _priceBurstConfig.Quote); _logger.LogInformation("Trading pair {@symbol}", symbol); _logger.LogInformation("Trading settings: SpreadInQuoteCoin={@SpreadInQuoteCoin}, TradeProfit={@TradeProfitPercentage}%, TradeQuantity={@TradeQuantity}", _priceBurstConfig.TradeDifference, _priceBurstConfig.TradeProfitPercentage, _priceBurstConfig.TradeQuantity); var orderId = default(long?); while (true) { _logger.LogInformation("Start of next tick"); var orderBook = await _binanceSpotExchange.GetOrderBookAsync(symbol, 5); var baseCurrencyPrice = (await _binanceSpotExchange.Get24HourPriceAsync(symbol)).LastPrice; var baseCurrencyBalance = _binanceSpotExchange.GetBalanceAsync(_priceBurstConfig.Base); var lastBid = orderBook.Bids.First().Price; var lastAsk = orderBook.Asks.First().Price; var buyPrice = lastBid + _priceBurstConfig.TradeDifference; var sellPrice = lastAsk - _priceBurstConfig.TradeDifference; var profitablePrice = buyPrice * (1 + Convert.ToDecimal(_priceBurstConfig.TradeProfitPercentage) / 100); var difference = lastAsk - profitablePrice; _logger.LogInformation("BuyPrice={@buyPrice}, SellPrice={@sellPrice}, Bid={@lastBid}, Ask={@lastAsk}, Price={@profitablePrice}, Diff={@difference}", buyPrice, sellPrice, lastBid, lastAsk, profitablePrice, difference); Thread.Sleep(5 * 1000); } //var btcBalance = await _binanceSpotExchange.GetBalanceAsync(Coin.BTC); //_logger.LogInformation("Balance: {@btcBalance}", btcBalance); //var usdtBalance = await _binanceSpotExchange.GetBalanceAsync(Coin.USDT); //_logger.LogInformation("Balance: {@usdtBalance}", usdtBalance); //var symbol = _binanceSpotExchange.GetSymbol( // Coin.BTC, // Coin.USDT); //var currentBtcUsdtPrice = await ((IExchangeClient)client).GetTickerAsync("BTCUSDT"); //_logger.LogInformation("Current Balance: BTC={btcBalance}, USDT={usdtBalance}", btcBalance, usdtBalance); //var filters = client.Spot.System.GetExchangeInfo().Data.Symbols.Single(s => s.Name == "BTCUSDT").Filters; //var orderBook = await _binanceSpotExchange.GetOrderBookAsync(symbol, 5); //_logger.LogDebug("{@orderBook}", orderBook); //var buyPrice = orderBook.Bids.FirstOrDefault()?.Price ?? orderBook.Asks.First().Price; //var sellPrice = orderBook.Asks.First().Price; //await _binanceSpotExchange.PlaceLimitBuyOrderAsync(symbol, 0.01m, buyPrice, false); //await _binanceSpotExchange.PlaceMarketBuyOrderAsync(symbol, 0.01m, false); //await _binanceSpotExchange.PlaceLimitSellOrderAsync(symbol, 0.01m, sellPrice, false); //await _binanceSpotExchange.PlaceMarketSellOrderAsync(symbol, 0.01m, false); //var allOrders = await _binanceSpotExchange.GetOpenOrdersAsync("BTCUSDT"); ////foreach (var binanceOrder in allOrders) //{ //await _binanceSpotExchange.CancelAllOpenOrdersAsync("BTCUSDT"); //} } catch (Exception ex) { _logger.LogError(ex, "Unexpected error when running {@PriceBurst} strategy bot, exiting...", Strategy.PriceBurst.ToString()); } }