From cc330e8cc3b44027ab017cb93e5d280195d394c1 Mon Sep 17 00:00:00 2001 From: cryptooda Date: Thu, 19 Jun 2025 16:20:16 +0700 Subject: [PATCH] Add ui fee into TradingBot.cs --- .../Backtesting/Backtester.cs | 5 +- src/Managing.Application/Bots/TradingBot.cs | 58 +++++++++---------- .../organism/Backtest/backtestRowDetails.tsx | 7 +++ 3 files changed, 37 insertions(+), 33 deletions(-) diff --git a/src/Managing.Application/Backtesting/Backtester.cs b/src/Managing.Application/Backtesting/Backtester.cs index e2d9ff1..dc6053c 100644 --- a/src/Managing.Application/Backtesting/Backtester.cs +++ b/src/Managing.Application/Backtesting/Backtester.cs @@ -205,6 +205,7 @@ namespace Managing.Application.Backtesting var growthPercentage = TradingHelpers.GetGrowthFromInitalBalance(config.BotTradingBalance, finalPnl); var hodlPercentage = TradingHelpers.GetHodlPercentage(candles[0], candles.Last()); + var fees = bot.GetTotalFees(); var scoringParams = new BacktestScoringParams( sharpeRatio: (double)stats.SharpeRatio, maxDrawdownPc: (double)stats.MaxDrawdownPc, @@ -212,7 +213,7 @@ namespace Managing.Application.Backtesting hodlPercentage: (double)hodlPercentage, winRate: winRate, totalPnL: (double)finalPnl, - fees: (double)bot.GetTotalFees(), + fees: (double)fees, tradeCount: bot.Positions.Count, maxDrawdownRecoveryTime: stats.MaxDrawdownRecoveryTime ); @@ -225,7 +226,7 @@ namespace Managing.Application.Backtesting WinRate = winRate, GrowthPercentage = growthPercentage, HodlPercentage = hodlPercentage, - Fees = bot.GetTotalFees(), + Fees = fees, WalletBalances = bot.WalletBalances.ToList(), Statistics = stats, OptimizedMoneyManagement = optimizedMoneyManagement, diff --git a/src/Managing.Application/Bots/TradingBot.cs b/src/Managing.Application/Bots/TradingBot.cs index 5d91d22..d856e43 100644 --- a/src/Managing.Application/Bots/TradingBot.cs +++ b/src/Managing.Application/Bots/TradingBot.cs @@ -1030,10 +1030,7 @@ public class TradingBot : Bot, ITradingBot { // Add PnL (could be positive or negative) Config.BotTradingBalance += position.ProfitAndLoss.Realized; - - // Subtract fees - Config.BotTradingBalance -= GetPositionFees(position); - + Logger.LogInformation( $"💰 **Balance Updated**\nNew bot trading balance: `${Config.BotTradingBalance:F2}`"); } @@ -1146,51 +1143,50 @@ public class TradingBot : Bot, ITradingBot /// /// Calculates the total fees paid by the trading bot for each position. + /// Includes UI fees (0.1% of position size) and network fees ($0.50 for opening). + /// Closing fees are handled by oracle, so no network fee for closing. /// /// Returns the total fees paid as a decimal value. public decimal GetTotalFees() { - decimal fees = 0; - foreach (var position in Positions.Where(p => p.Open.Fee > 0)) + decimal totalFees = 0; + + foreach (var position in Positions.Where(p => p.Open.Price > 0 && p.Open.Quantity > 0)) { - fees += position.Open.Fee; - fees += position.StopLoss.Status == TradeStatus.Filled ? position.StopLoss.Fee : 0; - fees += position.TakeProfit1.Status == TradeStatus.Filled ? position.TakeProfit1.Fee : 0; - - if (position.IsFinished() && - position.StopLoss.Status != TradeStatus.Filled && position.TakeProfit1.Status != TradeStatus.Filled) - fees += position.Open.Fee; - - if (position.TakeProfit2 != null) - fees += position.TakeProfit2.Fee; + totalFees += CalculatePositionFees(position); } - return fees; + return totalFees; } /// - /// Calculates the total fees for a specific position + /// Calculates the total fees for a specific position based on GMX V2 fee structure /// /// The position to calculate fees for /// The total fees for the position - private decimal GetPositionFees(Position position) + private decimal CalculatePositionFees(Position position) { decimal fees = 0; - - fees += position.Open.Fee; - fees += position.StopLoss.Status == TradeStatus.Filled ? position.StopLoss.Fee : 0; - fees += position.TakeProfit1.Status == TradeStatus.Filled ? position.TakeProfit1.Fee : 0; - - if (position.IsFinished() && - position.StopLoss.Status != TradeStatus.Filled && position.TakeProfit1.Status != TradeStatus.Filled) - fees += position.Open.Fee; - - if (position.TakeProfit2 != null) - fees += position.TakeProfit2.Status == TradeStatus.Filled ? position.TakeProfit2.Fee : 0; - + + // Calculate position size in USD (leverage is already included in quantity calculation) + var positionSizeUsd = position.Open.Price * position.Open.Quantity; + + // UI Fee: 0.1% of position size paid BOTH on opening AND closing + var uiFeeRate = 0.001m; // 0.1% + var uiFeeOpen = positionSizeUsd * uiFeeRate; // Fee paid on opening + var uiFeeClose = positionSizeUsd * uiFeeRate; // Fee paid on closing + var totalUiFees = uiFeeOpen + uiFeeClose; // Total: 0.2% of position size + fees += totalUiFees; + + // Network Fee: $0.50 for opening position only + // Closing is handled by oracle, so no network fee for closing + var networkFeeForOpening = 0.50m; + fees += networkFeeForOpening; + return fees; } + public async Task ToggleIsForWatchOnly() { Config.IsForWatchingOnly = !Config.IsForWatchingOnly; diff --git a/src/Managing.WebApp/src/components/organism/Backtest/backtestRowDetails.tsx b/src/Managing.WebApp/src/components/organism/Backtest/backtestRowDetails.tsx index a61a7ef..07bf275 100644 --- a/src/Managing.WebApp/src/components/organism/Backtest/backtestRowDetails.tsx +++ b/src/Managing.WebApp/src/components/organism/Backtest/backtestRowDetails.tsx @@ -332,6 +332,13 @@ const BacktestRowDetails: React.FC = ({ maximumFractionDigits: 2 })} > +