Esempio n. 1
0
        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());
            }
        }
Esempio n. 2
0
        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());
            }
        }