/// <summary> /// Creates a buy order on the exchange. /// </summary> /// <param name="freeTrader">The trader placing the order</param> /// <param name="pair">The pair we're buying</param> /// <returns></returns> private async Task <Trade> CreateBuyOrder(Trader freeTrader, string pair, Candle signalCandle) { // Take the amount to invest per trader OR the current balance for this trader. var btcToSpend = 0.0m; if (freeTrader.CurrentBalance < _settings.AmountToInvestPerTrader || _settings.ProfitStrategy == ProfitType.Reinvest) { btcToSpend = freeTrader.CurrentBalance; } else { btcToSpend = _settings.AmountToInvestPerTrader; } // The amount here is an indication and will probably not be precisely what you get. var ticker = await _api.GetTicker(pair); var openRate = GetTargetBid(ticker, signalCandle); var amount = btcToSpend / openRate; // Get the order ID, this is the most important because we need this to check // up on our trade. We update the data below later when the final data is present. var orderId = await _api.Buy(pair, amount, openRate); await SendNotification($"Buying #{pair} with limit {openRate:0.00000000} BTC ({amount:0.0000} units)."); var trade = new Trade() { TraderId = freeTrader.Identifier, Market = pair, StakeAmount = btcToSpend, OpenRate = openRate, OpenDate = DateTime.UtcNow, Quantity = amount, OpenOrderId = orderId, BuyOrderId = orderId, IsOpen = true, IsBuying = true, StrategyUsed = _strategy.Name, SellType = SellType.None, }; if (_settings.PlaceFirstStopAtSignalCandleLow) { trade.StopLossRate = signalCandle.Low; _logger.LogInformation("Automatic stop set at signal candle low {Low}", signalCandle.Low.ToString("0.00000000")); } return(trade); }
/// <summary> /// Creates a buy order on the exchange. /// </summary> /// <param name="freeTrader">The trader placing the order</param> /// <param name="pair">The pair we're buying</param> /// <returns></returns> private async Task <Trade> CreateBuyOrder(Trader freeTrader, string pair) { // Take the amount to invest per trader OR the current balance for this trader. var btcToSpend = freeTrader.CurrentBalance > Constants.AmountOfBtcToInvestPerTrader ? Constants.AmountOfBtcToInvestPerTrader : freeTrader.CurrentBalance; // The amount here is an indication and will probably not be precisely what you get. var ticker = await _api.GetTicker(pair); var openRate = GetTargetBid(ticker); var amount = btcToSpend / openRate; var amountYouGet = (btcToSpend * (1 - Constants.TransactionFeePercentage)) / openRate; // Get the order ID, this is the most important because we need this to check // up on our trade. We update the data below later when the final data is present. var orderId = await _api.Buy(pair, amount, openRate); await SendNotification($"Buying {pair} at {openRate:0.0000000 BTC} which was spotted at bid: {ticker.Bid:0.00000000}, " + $"ask: {ticker.Ask:0.00000000}, " + $"last: {ticker.Last:0.00000000}, " + $"({amountYouGet:0.0000} units)."); return(new Trade() { TraderId = freeTrader.RowKey, Market = pair, StakeAmount = btcToSpend, OpenRate = openRate, OpenDate = DateTime.UtcNow, Quantity = amountYouGet, OpenOrderId = orderId, BuyOrderId = orderId, IsOpen = true, IsBuying = true, StrategyUsed = _strategy.Name, PartitionKey = "TRADE", SellType = SellType.None, RowKey = $"MNT{(DateTime.MaxValue.Ticks - DateTime.UtcNow.Ticks):d19}" }); }
/// <summary> /// Checks the implemented trading indicator(s), /// if one pair triggers the buy signal a new trade record gets created. /// </summary> /// <param name="trades"></param> /// <param name="amountOfBtcToInvestPerTrader"></param> /// <returns></returns> private async Task <Trade> FindTrade(List <Trade> trades, double amountOfBtcToInvestPerTrader) { // Get our Bitcoin balance from the exchange var currentBtcBalance = await _api.GetBalance("BTC"); // Do we even have enough funds to invest? if (currentBtcBalance < Constants.AmountOfBtcToInvestPerTrader) { throw new Exception("Insufficient BTC funds to perform a trade."); } // Retrieve our current markets var markets = await _api.GetMarketSummaries(); // Check if there are markets matching our volume. markets = markets.Where(x => (x.BaseVolume > Constants.MinimumAmountOfVolume || Constants.AlwaysTradeList.Contains(x.MarketName)) && x.MarketName.StartsWith("BTC-")).ToList(); // Remove existing trades from the list to check. foreach (var trade in trades) { markets.RemoveAll(x => x.MarketName == trade.Market); } // Remove items that are on our blacklist. foreach (var market in Constants.MarketBlackList) { markets.RemoveAll(x => x.MarketName == market); } // Check the buy signal! string pair = null; // Prioritize markets with high volume. foreach (var market in markets.Distinct().OrderByDescending(x => x.BaseVolume).ToList()) { if (await GetBuySignal(market.MarketName)) { // A match was made, buy that please! pair = market.MarketName; break; } } // No pairs found. Return. if (pair == null) { return(null); } var openRate = GetTargetBid(await _api.GetTicker(pair)); var amount = amountOfBtcToInvestPerTrader / openRate; var amountYouGet = (amountOfBtcToInvestPerTrader * (1 - Constants.TransactionFeePercentage)) / openRate; var orderId = await _api.Buy(pair, openRate, amount); return(new Trade() { Market = pair, StakeAmount = Constants.AmountOfBtcToInvestPerTrader, OpenRate = openRate, OpenDate = DateTime.UtcNow, Quantity = amountYouGet, OpenOrderId = orderId, BuyOrderId = orderId, IsOpen = true, StrategyUsed = _strategy.Name, PartitionKey = "TRADE", SellType = SellType.None, RowKey = $"MNT{(DateTime.MaxValue.Ticks - DateTime.UtcNow.Ticks):d19}" }); }