Remove warning for backtest when signal is expired
This commit is contained in:
@@ -329,9 +329,10 @@ public class TradingBotBase : ITradingBot
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await LogWarning($"Failed to update finished position {position.Identifier} in database: {ex.Message}");
|
||||
await LogWarning(
|
||||
$"Failed to update finished position {position.Identifier} in database: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Then, open positions for signals waiting for a position open
|
||||
// But first, check if we already have a position for any of these signals
|
||||
@@ -1294,7 +1295,7 @@ public class TradingBotBase : ITradingBot
|
||||
// Update the closing trade price if available
|
||||
if (gmxPosition.Open != null)
|
||||
{
|
||||
var closingPrice = gmxPosition.Open.Price;
|
||||
var gmxClosingPrice = gmxPosition.Open.Price;
|
||||
|
||||
// Determine which trade was the closing trade based on profitability
|
||||
bool isProfitable = position.ProfitAndLoss.Realized > 0;
|
||||
@@ -1303,7 +1304,7 @@ public class TradingBotBase : ITradingBot
|
||||
{
|
||||
if (position.TakeProfit1 != null)
|
||||
{
|
||||
position.TakeProfit1.SetPrice(closingPrice, 2);
|
||||
position.TakeProfit1.SetPrice(gmxClosingPrice, 2);
|
||||
position.TakeProfit1.SetDate(gmxPosition.Open.Date);
|
||||
position.TakeProfit1.SetStatus(TradeStatus.Filled);
|
||||
}
|
||||
@@ -1318,7 +1319,7 @@ public class TradingBotBase : ITradingBot
|
||||
{
|
||||
if (position.StopLoss != null)
|
||||
{
|
||||
position.StopLoss.SetPrice(closingPrice, 2);
|
||||
position.StopLoss.SetPrice(gmxClosingPrice, 2);
|
||||
position.StopLoss.SetDate(gmxPosition.Open.Date);
|
||||
position.StopLoss.SetStatus(TradeStatus.Filled);
|
||||
}
|
||||
@@ -1338,7 +1339,7 @@ public class TradingBotBase : ITradingBot
|
||||
Logger.LogInformation(
|
||||
$"📊 Position Reconciliation Complete\n" +
|
||||
$"Position: `{position.Identifier}`\n" +
|
||||
$"Closing Price: `${closingPrice:F2}`\n" +
|
||||
$"Closing Price: `${gmxClosingPrice:F2}`\n" +
|
||||
$"Used: `{(isProfitable ? "Take Profit" : "Stop Loss")}`\n" +
|
||||
$"PnL from GMX: `${position.ProfitAndLoss.Realized:F2}`");
|
||||
}
|
||||
@@ -1359,6 +1360,10 @@ public class TradingBotBase : ITradingBot
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate P&L for backtests even if currentCandle is null
|
||||
decimal closingPrice = 0;
|
||||
bool pnlCalculated = false;
|
||||
|
||||
if (currentCandle != null)
|
||||
{
|
||||
List<Candle> recentCandles = null;
|
||||
@@ -1428,8 +1433,6 @@ public class TradingBotBase : ITradingBot
|
||||
wasTakeProfitHit = minPriceRecent <= position.TakeProfit1.Price;
|
||||
}
|
||||
|
||||
decimal closingPrice;
|
||||
|
||||
if (wasStopLossHit)
|
||||
{
|
||||
// Use actual execution price based on direction
|
||||
@@ -1534,6 +1537,40 @@ public class TradingBotBase : ITradingBot
|
||||
$"Closing at market price: `${closingPrice:F2}`");
|
||||
}
|
||||
|
||||
pnlCalculated = true;
|
||||
}
|
||||
else if (Config.IsForBacktest)
|
||||
{
|
||||
// For backtests when currentCandle is null, use a fallback closing price
|
||||
// This ensures P&L calculation always happens for backtests
|
||||
Logger.LogWarning(
|
||||
$"⚠️ Backtest: No current candle available for position {position.Identifier}. Using fallback closing price calculation.");
|
||||
|
||||
// Use the position's stop loss or take profit price as closing price
|
||||
if (position.StopLoss != null && position.StopLoss.Price > 0)
|
||||
{
|
||||
closingPrice = position.StopLoss.Price;
|
||||
position.StopLoss.SetStatus(TradeStatus.Filled);
|
||||
}
|
||||
else if (position.TakeProfit1 != null && position.TakeProfit1.Price > 0)
|
||||
{
|
||||
closingPrice = position.TakeProfit1.Price;
|
||||
position.TakeProfit1.SetStatus(TradeStatus.Filled);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Last resort: use entry price (no profit/loss)
|
||||
closingPrice = position.Open.Price;
|
||||
Logger.LogWarning(
|
||||
$"⚠️ Backtest: Using entry price as closing price for position {position.Identifier}");
|
||||
}
|
||||
|
||||
pnlCalculated = true;
|
||||
}
|
||||
|
||||
// Calculate P&L if we have a closing price
|
||||
if (pnlCalculated && closingPrice > 0)
|
||||
{
|
||||
var entryPrice = position.Open.Price;
|
||||
var positionSize = position.Open.Quantity * position.Open.Leverage;
|
||||
|
||||
@@ -1553,7 +1590,7 @@ public class TradingBotBase : ITradingBot
|
||||
var netPnl = pnl - totalFees;
|
||||
position.ProfitAndLoss = new ProfitAndLoss { Realized = pnl, Net = netPnl };
|
||||
}
|
||||
else if (position.ProfitAndLoss.Realized == 0)
|
||||
else if (position.ProfitAndLoss.Realized == 0 || position.ProfitAndLoss.Net == 0)
|
||||
{
|
||||
var totalFees = position.GasFees + position.UiFees;
|
||||
var netPnl = pnl - totalFees;
|
||||
@@ -1561,6 +1598,12 @@ public class TradingBotBase : ITradingBot
|
||||
position.ProfitAndLoss.Net = netPnl;
|
||||
}
|
||||
|
||||
Logger.LogInformation(
|
||||
$"💰 P&L Calculated for Position {position.Identifier}\n" +
|
||||
$"Entry: `${entryPrice:F2}` | Exit: `${closingPrice:F2}`\n" +
|
||||
$"Realized P&L: `${pnl:F2}` | Net P&L (after fees): `${position.ProfitAndLoss.Net:F2}`\n" +
|
||||
$"Total Fees: `${position.GasFees + position.UiFees:F2}`");
|
||||
|
||||
// Fees are now tracked separately in UiFees and GasFees properties
|
||||
// No need to subtract fees from PnL as they're tracked separately
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user