Add ui fee into TradingBot.cs

This commit is contained in:
2025-06-19 16:20:16 +07:00
parent 0aa1f40f53
commit cc330e8cc3
3 changed files with 37 additions and 33 deletions

View File

@@ -205,6 +205,7 @@ namespace Managing.Application.Backtesting
var growthPercentage = TradingHelpers.GetGrowthFromInitalBalance(config.BotTradingBalance, finalPnl); var growthPercentage = TradingHelpers.GetGrowthFromInitalBalance(config.BotTradingBalance, finalPnl);
var hodlPercentage = TradingHelpers.GetHodlPercentage(candles[0], candles.Last()); var hodlPercentage = TradingHelpers.GetHodlPercentage(candles[0], candles.Last());
var fees = bot.GetTotalFees();
var scoringParams = new BacktestScoringParams( var scoringParams = new BacktestScoringParams(
sharpeRatio: (double)stats.SharpeRatio, sharpeRatio: (double)stats.SharpeRatio,
maxDrawdownPc: (double)stats.MaxDrawdownPc, maxDrawdownPc: (double)stats.MaxDrawdownPc,
@@ -212,7 +213,7 @@ namespace Managing.Application.Backtesting
hodlPercentage: (double)hodlPercentage, hodlPercentage: (double)hodlPercentage,
winRate: winRate, winRate: winRate,
totalPnL: (double)finalPnl, totalPnL: (double)finalPnl,
fees: (double)bot.GetTotalFees(), fees: (double)fees,
tradeCount: bot.Positions.Count, tradeCount: bot.Positions.Count,
maxDrawdownRecoveryTime: stats.MaxDrawdownRecoveryTime maxDrawdownRecoveryTime: stats.MaxDrawdownRecoveryTime
); );
@@ -225,7 +226,7 @@ namespace Managing.Application.Backtesting
WinRate = winRate, WinRate = winRate,
GrowthPercentage = growthPercentage, GrowthPercentage = growthPercentage,
HodlPercentage = hodlPercentage, HodlPercentage = hodlPercentage,
Fees = bot.GetTotalFees(), Fees = fees,
WalletBalances = bot.WalletBalances.ToList(), WalletBalances = bot.WalletBalances.ToList(),
Statistics = stats, Statistics = stats,
OptimizedMoneyManagement = optimizedMoneyManagement, OptimizedMoneyManagement = optimizedMoneyManagement,

View File

@@ -1031,9 +1031,6 @@ public class TradingBot : Bot, ITradingBot
// Add PnL (could be positive or negative) // Add PnL (could be positive or negative)
Config.BotTradingBalance += position.ProfitAndLoss.Realized; Config.BotTradingBalance += position.ProfitAndLoss.Realized;
// Subtract fees
Config.BotTradingBalance -= GetPositionFees(position);
Logger.LogInformation( Logger.LogInformation(
$"💰 **Balance Updated**\nNew bot trading balance: `${Config.BotTradingBalance:F2}`"); $"💰 **Balance Updated**\nNew bot trading balance: `${Config.BotTradingBalance:F2}`");
} }
@@ -1146,51 +1143,50 @@ public class TradingBot : Bot, ITradingBot
/// <summary> /// <summary>
/// Calculates the total fees paid by the trading bot for each position. /// 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.
/// </summary> /// </summary>
/// <returns>Returns the total fees paid as a decimal value.</returns> /// <returns>Returns the total fees paid as a decimal value.</returns>
public decimal GetTotalFees() public decimal GetTotalFees()
{ {
decimal fees = 0; decimal totalFees = 0;
foreach (var position in Positions.Where(p => p.Open.Fee > 0))
foreach (var position in Positions.Where(p => p.Open.Price > 0 && p.Open.Quantity > 0))
{ {
fees += position.Open.Fee; totalFees += CalculatePositionFees(position);
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;
} }
return fees; return totalFees;
} }
/// <summary> /// <summary>
/// Calculates the total fees for a specific position /// Calculates the total fees for a specific position based on GMX V2 fee structure
/// </summary> /// </summary>
/// <param name="position">The position to calculate fees for</param> /// <param name="position">The position to calculate fees for</param>
/// <returns>The total fees for the position</returns> /// <returns>The total fees for the position</returns>
private decimal GetPositionFees(Position position) private decimal CalculatePositionFees(Position position)
{ {
decimal fees = 0; decimal fees = 0;
fees += position.Open.Fee; // Calculate position size in USD (leverage is already included in quantity calculation)
fees += position.StopLoss.Status == TradeStatus.Filled ? position.StopLoss.Fee : 0; var positionSizeUsd = position.Open.Price * position.Open.Quantity;
fees += position.TakeProfit1.Status == TradeStatus.Filled ? position.TakeProfit1.Fee : 0;
if (position.IsFinished() && // UI Fee: 0.1% of position size paid BOTH on opening AND closing
position.StopLoss.Status != TradeStatus.Filled && position.TakeProfit1.Status != TradeStatus.Filled) var uiFeeRate = 0.001m; // 0.1%
fees += position.Open.Fee; 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;
if (position.TakeProfit2 != null) // Network Fee: $0.50 for opening position only
fees += position.TakeProfit2.Status == TradeStatus.Filled ? position.TakeProfit2.Fee : 0; // Closing is handled by oracle, so no network fee for closing
var networkFeeForOpening = 0.50m;
fees += networkFeeForOpening;
return fees; return fees;
} }
public async Task ToggleIsForWatchOnly() public async Task ToggleIsForWatchOnly()
{ {
Config.IsForWatchingOnly = !Config.IsForWatchingOnly; Config.IsForWatchingOnly = !Config.IsForWatchingOnly;

View File

@@ -332,6 +332,13 @@ const BacktestRowDetails: React.FC<IBacktestRowDetailsProps> = ({
maximumFractionDigits: 2 maximumFractionDigits: 2
})} })}
></CardText> ></CardText>
<CardText
title="Total Fees"
content={"$" + backtest.fees.toLocaleString('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 2
})}
></CardText>
<CardText <CardText
title="Recommended Cooldown" title="Recommended Cooldown"
content={cooldownRecommendations.percentile75 + " candles"} content={cooldownRecommendations.percentile75 + " candles"}