private void HandleEvent(object sender, ProfitableUserTradedEventArgs e) { if (e.Report.CurrencySymbol != _config.TargetCurrencySymbol) { _logger.Information("Report was not targeting our currency symbol."); return; } var eventOwnerUser = _repo.GetUserById(e.UserId); if (eventOwnerUser.CurrentWallet.Symbol == CurrentWallet.Symbol) { _logger.Information($"Skipping report due to trader and our wallets currency equality."); } if (AttachedUser == null || AttachedUser.Identifier == e.UserId) { if (!_attempCalculator.IsSucceededAttemp()) { _logger.Information("Skipping trade due to low attemps count."); return; } if (AttachedUser == null) { _logger.Information($"Attaching to user with Id: {e.UserId}"); AttachedUsersHistory.Add(e.UserId); AttachedUserProfit = e.Report; AttachedUser = eventOwnerUser; } _logger.Information("Attached user traded. Repeating actions."); var trade = _repo.GetTradeById(e.TradeId); _lastTradeDate = trade.TradeTime; if (AttachedUser.CurrentWallet.Symbol == CurrentWallet.Symbol) { _logger.Information("Currently the trader holds the currency that we already have."); return; } _logger.Warning($"Wallet balance was {CurrentWallet.Amount}{CurrentWallet.Symbol}"); _logger.Warning($"Selling {CurrentWallet.Amount}{CurrentWallet.Symbol} and buying {AttachedUser.CurrentWallet.Symbol}"); var newWallet = CalculateWalletBalanceAfterTrade(CurrentWallet, trade.Price); Wallets.Add(newWallet); _logger.Warning($"After selling balance is {CurrentWallet.Amount}{CurrentWallet.Symbol}"); } else { var maxTimeToWaitForAttachedUser = TimeSpan.FromTicks(AttachedUserProfit.AverageTradeThreshold.Ticks * 2); if (DateTime.UtcNow - _lastTradeDate > maxTimeToWaitForAttachedUser || e.Report.AverageProfitPerHour > AttachedUserProfit.AverageProfitPerHour) { DetachAttachedUser(); HandleEvent(this, e); } } }
private void HandleEvent(object sender, ProfitableUserTradedEventArgs e) { if (_isTradingLocked) { UpdateLockedState(); if (_isTradingLocked) { _logger.Information($"Trading is locked. Skipping profitable user with Id: {e.UserId}"); return; } else { UpdateCurrentWallet(); } } if (e.Report.CurrencySymbol != _config.TargetCurrencySymbol) { _logger.Information("Report was not targeting our currency symbol."); return; } var traderUser = _repo.GetUserById(e.UserId); if (traderUser.CurrentWallet.Symbol == CurrentWallet.Symbol) { _logger.Information("Currently the trader holds the currency that we already have."); return; } if (e.Report.AverageProfitPerHour < _config.Limiters.MinimalTraderProfitPerHourPercentage || e.Report.AverageTradesPerHour > _config.Limiters.MaximalTraderTradesPerHour) { _logger.Information($"Skipping profitable user's trade due to limiters. Trader user Id was {e.UserId}"); if (AttachedUser?.Identifier == e.UserId) { DetachAttachedUser(); } return; } if (AttachedUser == null || AttachedUser?.Identifier == e.UserId) { if (!_attempCalculator.IsSucceededAttemp()) { _logger.Information("Skipping trade due to low attemps count."); return; } if (AttachedUser == null) { _logger.Information($"Attaching to user with Id: {e.UserId}"); AttachedUsersHistory.Add(e.UserId); AttachedUserProfit = e.Report; AttachedUser = traderUser; } _logger.Information("Attached user traded. Repeating actions."); using (var client = CreateBinanceClient()) { var trade = _repo.GetTradeById(e.TradeId); var orderSide = CurrentWallet.Symbol == _symbolPair.Symbol1 ? OrderSide.Sell : OrderSide.Buy; var priceResult = client.GetPrice(_symbolPair.ToString()); var price = priceResult.Data.Price; var quantity = CurrentWallet.Symbol == _symbolPair.Symbol1 ? CurrentWallet.Amount : CurrentWallet.Amount / price; quantity = RecorrectQuantity(quantity); _logger.Warning($"Wallet balance is {CurrentWallet.Amount}{CurrentWallet.Symbol}"); _logger.Warning($"Selling {CurrentWallet.Amount}{CurrentWallet.Symbol} and buying {AttachedUser.CurrentWallet.Symbol} with price of {price}."); var placeOrderResult = client.PlaceOrder( timeInForce: TimeInForce.GoodTillCancel, symbol: _symbolPair.ToString(), quantity: quantity, type: OrderType.Limit, side: orderSide, price: price); _repo.BlacklistOrder(placeOrderResult.Data.OrderId); _isTradingLocked = true; _lastTradeDate = trade.TradeTime; _lastLockTime = DateTime.UtcNow; _lockedDueToOrderId = placeOrderResult.Data.OrderId; } _logger.Warning($"Locked the trading until the order with Id {_lockedDueToOrderId} become filled/expired/rejected."); } else { var maxSecondsToWait = AttachedUserProfit.AverageTradeThreshold.TotalSeconds * Math.E; maxSecondsToWait = Math.Min(maxSecondsToWait, _config.Limiters.MaximalSecondsToWaitForTheTrader); if (DateTime.UtcNow - _lastTradeDate > TimeSpan.FromSeconds(maxSecondsToWait) || e.Report.AverageProfitPerHour > AttachedUserProfit.AverageProfitPerHour * Math.E && e.Report.AverageTradesPerHour < AttachedUserProfit.AverageTradesPerHour) { DetachAttachedUser(); HandleEvent(this, e); } } }