Fetch closed position to get last pnl realized
This commit is contained in:
@@ -1196,6 +1196,122 @@ public class TradingBotBase : ITradingBot
|
||||
: await exchangeService.GetCandle(Account, Config.Ticker, DateTime.UtcNow);
|
||||
});
|
||||
|
||||
// For live trading on GMX, fetch the actual position history to get real PnL data
|
||||
if (!Config.IsForBacktest)
|
||||
{
|
||||
try
|
||||
{
|
||||
Logger.LogInformation(
|
||||
$"🔍 **Fetching Position History from GMX**\nPosition: `{position.Identifier}`\nTicker: `{Config.Ticker}`");
|
||||
|
||||
List<Position> positionHistory = null;
|
||||
await ServiceScopeHelpers.WithScopedService<IExchangeService>(_scopeFactory,
|
||||
async exchangeService =>
|
||||
{
|
||||
// Get position history from the last 24 hours
|
||||
var fromDate = DateTime.UtcNow.AddHours(-24);
|
||||
var toDate = DateTime.UtcNow;
|
||||
positionHistory =
|
||||
await exchangeService.GetPositionHistory(Account, Config.Ticker, fromDate, toDate);
|
||||
});
|
||||
|
||||
// Find the matching position in history based on the most recent closed position
|
||||
if (positionHistory != null && positionHistory.Any())
|
||||
{
|
||||
// Get the most recent closed position from GMX
|
||||
var gmxPosition = positionHistory.OrderByDescending(p => p.Open?.Date ?? DateTime.MinValue)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (gmxPosition != null && gmxPosition.ProfitAndLoss != null)
|
||||
{
|
||||
Logger.LogInformation(
|
||||
$"✅ **GMX Position History Found**\n" +
|
||||
$"Position: `{position.Identifier}`\n" +
|
||||
$"GMX Realized PnL (after fees): `${gmxPosition.ProfitAndLoss.Realized:F2}`\n" +
|
||||
$"Bot's UI Fees: `${position.UiFees:F2}`\n" +
|
||||
$"Bot's Gas Fees: `${position.GasFees:F2}`");
|
||||
|
||||
// Use the actual GMX PnL data (this is already net of fees from GMX)
|
||||
// We use this for reconciliation with the bot's own calculations
|
||||
var totalBotFees = position.GasFees + position.UiFees;
|
||||
var gmxNetPnl = gmxPosition.ProfitAndLoss.Realized; // This is already after GMX fees
|
||||
|
||||
position.ProfitAndLoss = new ProfitAndLoss
|
||||
{
|
||||
// GMX's realized PnL is already after their fees
|
||||
Realized = gmxNetPnl,
|
||||
// For net, we keep it the same since GMX PnL is already net of their fees
|
||||
Net = gmxNetPnl - totalBotFees
|
||||
};
|
||||
|
||||
// Update the closing trade price if available
|
||||
if (gmxPosition.Open != null)
|
||||
{
|
||||
var closingPrice = gmxPosition.Open.Price;
|
||||
|
||||
// Determine which trade was the closing trade based on profitability
|
||||
bool isProfitable = position.ProfitAndLoss.Realized > 0;
|
||||
|
||||
if (isProfitable)
|
||||
{
|
||||
if (position.TakeProfit1 != null)
|
||||
{
|
||||
position.TakeProfit1.SetPrice(closingPrice, 2);
|
||||
position.TakeProfit1.SetDate(gmxPosition.Open.Date);
|
||||
position.TakeProfit1.SetStatus(TradeStatus.Filled);
|
||||
}
|
||||
|
||||
// Cancel SL trade when TP is hit
|
||||
if (position.StopLoss != null)
|
||||
{
|
||||
position.StopLoss.SetStatus(TradeStatus.Cancelled);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (position.StopLoss != null)
|
||||
{
|
||||
position.StopLoss.SetPrice(closingPrice, 2);
|
||||
position.StopLoss.SetDate(gmxPosition.Open.Date);
|
||||
position.StopLoss.SetStatus(TradeStatus.Filled);
|
||||
}
|
||||
|
||||
// Cancel TP trades when SL is hit
|
||||
if (position.TakeProfit1 != null)
|
||||
{
|
||||
position.TakeProfit1.SetStatus(TradeStatus.Cancelled);
|
||||
}
|
||||
|
||||
if (position.TakeProfit2 != null)
|
||||
{
|
||||
position.TakeProfit2.SetStatus(TradeStatus.Cancelled);
|
||||
}
|
||||
}
|
||||
|
||||
Logger.LogInformation(
|
||||
$"📊 **Position Reconciliation Complete**\n" +
|
||||
$"Position: `{position.Identifier}`\n" +
|
||||
$"Closing Price: `${closingPrice:F2}`\n" +
|
||||
$"Used: `{(isProfitable ? "Take Profit" : "Stop Loss")}`\n" +
|
||||
$"PnL from GMX: `${position.ProfitAndLoss.Realized:F2}`");
|
||||
}
|
||||
|
||||
// Skip the candle-based PnL calculation since we have actual GMX data
|
||||
goto SkipCandleBasedCalculation;
|
||||
}
|
||||
}
|
||||
|
||||
Logger.LogWarning(
|
||||
$"⚠️ **No GMX Position History Found**\nPosition: `{position.Identifier}`\nFalling back to candle-based calculation");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex,
|
||||
"Error fetching position history from GMX for position {PositionId}. Falling back to candle-based calculation.",
|
||||
position.Identifier);
|
||||
}
|
||||
}
|
||||
|
||||
if (currentCandle != null)
|
||||
{
|
||||
List<Candle> recentCandles = null;
|
||||
@@ -1402,6 +1518,7 @@ public class TradingBotBase : ITradingBot
|
||||
// No need to subtract fees from PnL as they're tracked separately
|
||||
}
|
||||
|
||||
SkipCandleBasedCalculation:
|
||||
await SetPositionStatus(position.SignalIdentifier, PositionStatus.Finished);
|
||||
|
||||
// Update position in database with all trade changes
|
||||
|
||||
Reference in New Issue
Block a user