Fix status and filtered positions for metrics
This commit is contained in:
@@ -277,7 +277,7 @@ public class TradingBotBase : ITradingBot
|
||||
private async Task ManagePositions()
|
||||
{
|
||||
// First, process all existing positions that are not finished
|
||||
foreach (var position in Positions.Values.Where(p => p.IsOpen()))
|
||||
foreach (var position in Positions.Values.Where(p => !p.IsFinished()))
|
||||
{
|
||||
var signalForPosition = Signals[position.SignalIdentifier];
|
||||
if (signalForPosition == null)
|
||||
@@ -307,15 +307,17 @@ public class TradingBotBase : ITradingBot
|
||||
}
|
||||
|
||||
// Second, process all finished positions to ensure they are updated in the database
|
||||
// This should be removed in the future, when we have a better way to handle positions
|
||||
// TODO : This should be removed in the future, when we have a better way to handle positions
|
||||
foreach (var position in Positions.Values.Where(p => p.IsFinished()))
|
||||
{
|
||||
try
|
||||
{
|
||||
var positionInDatabase = await ServiceScopeHelpers.WithScopedService<ITradingService, Position>(_scopeFactory, async tradingService =>
|
||||
{
|
||||
return await tradingService.GetPositionByIdentifierAsync(position.Identifier);
|
||||
});
|
||||
var positionInDatabase = await ServiceScopeHelpers.WithScopedService<ITradingService, Position>(
|
||||
_scopeFactory,
|
||||
async tradingService =>
|
||||
{
|
||||
return await tradingService.GetPositionByIdentifierAsync(position.Identifier);
|
||||
});
|
||||
|
||||
if (positionInDatabase != null && positionInDatabase.Status != position.Status)
|
||||
{
|
||||
@@ -323,7 +325,6 @@ public class TradingBotBase : ITradingBot
|
||||
await LogInformation(
|
||||
$"💾 Database Update\nPosition: `{position.Identifier}`\nStatus: `{position.Status}`\nUpdated in database");
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -425,11 +426,11 @@ public class TradingBotBase : ITradingBot
|
||||
{
|
||||
var previousPositionStatus = internalPosition.Status;
|
||||
// Position found on the broker, means the position is filled
|
||||
var brokerNetPnL = brokerPosition.GetNetPnL();
|
||||
UpdatePositionPnl(positionForSignal.Identifier, brokerNetPnL);
|
||||
var brokerPnlBeforeFees = brokerPosition.GetPnLBeforeFees();
|
||||
UpdatePositionPnl(positionForSignal.Identifier, brokerPnlBeforeFees);
|
||||
var totalFees = internalPosition.GasFees + internalPosition.UiFees;
|
||||
var netPnl = brokerNetPnL - totalFees;
|
||||
internalPosition.ProfitAndLoss = new ProfitAndLoss { Realized = brokerNetPnL, Net = netPnl };
|
||||
var netPnl = brokerPnlBeforeFees - totalFees;
|
||||
internalPosition.ProfitAndLoss = new ProfitAndLoss { Realized = brokerPnlBeforeFees, Net = netPnl };
|
||||
internalPosition.Status = PositionStatus.Filled;
|
||||
await SetPositionStatus(internalPosition.SignalIdentifier, PositionStatus.Filled);
|
||||
|
||||
@@ -561,7 +562,7 @@ public class TradingBotBase : ITradingBot
|
||||
$"✅ Position Found on Broker\nPosition is already open on broker\nUpdating position status to Filled");
|
||||
|
||||
// Calculate net PnL after fees for broker position
|
||||
var brokerNetPnL = brokerPosition.GetNetPnL();
|
||||
var brokerNetPnL = brokerPosition.GetPnLBeforeFees();
|
||||
UpdatePositionPnl(positionForSignal.Identifier, brokerNetPnL);
|
||||
|
||||
// Update Open trade status when position is found on broker with 2 orders
|
||||
@@ -603,7 +604,7 @@ public class TradingBotBase : ITradingBot
|
||||
else
|
||||
{
|
||||
await LogWarning(
|
||||
$"❌ Position Never Filled\nNo position on exchange and no orders\nSignal: `{signal.Identifier}`\nPosition was never filled and will be marked as canceled.");
|
||||
$"❌ Position Never Filled\nNo position on exchange and no orders\nPosition was never filled and will be marked as canceled.");
|
||||
|
||||
// Position was never filled (still in New status), so just mark it as canceled
|
||||
// Don't call HandleClosedPosition as that would incorrectly add volume/PnL
|
||||
@@ -623,7 +624,8 @@ public class TradingBotBase : ITradingBot
|
||||
{
|
||||
lastCandle = Config.IsForBacktest
|
||||
? LastCandle
|
||||
: await exchangeService.GetCandle(Account, Config.Ticker, DateTime.UtcNow);
|
||||
: await exchangeService.GetCandle(Account, Config.Ticker,
|
||||
DateTime.UtcNow);
|
||||
});
|
||||
|
||||
var currentTime = Config.IsForBacktest ? lastCandle.Date : DateTime.UtcNow;
|
||||
@@ -1686,7 +1688,7 @@ public class TradingBotBase : ITradingBot
|
||||
$"📊 Position Status Change\nPosition: `{position.Ticker}`\nDirection: `{position.OriginDirection}`\nNew Status: `{positionStatus}`");
|
||||
|
||||
// Update Open trade status when position becomes Filled
|
||||
if (positionStatus == PositionStatus.Filled && position.Open != null)
|
||||
if (positionStatus == PositionStatus.Filled)
|
||||
{
|
||||
position.Open.SetStatus(TradeStatus.Filled);
|
||||
}
|
||||
@@ -1745,8 +1747,8 @@ public class TradingBotBase : ITradingBot
|
||||
public decimal GetProfitAndLoss()
|
||||
{
|
||||
// Calculate net PnL after deducting fees for each position
|
||||
var netPnl = Positions.Values.Where(p => p.ProfitAndLoss != null)
|
||||
.Sum(p => p.GetNetPnL());
|
||||
var netPnl = Positions.Values.Where(p => p.IsValidForMetrics() && p.ProfitAndLoss != null)
|
||||
.Sum(p => p.GetPnLBeforeFees());
|
||||
return netPnl;
|
||||
}
|
||||
|
||||
@@ -1760,7 +1762,7 @@ public class TradingBotBase : ITradingBot
|
||||
{
|
||||
decimal totalFees = 0;
|
||||
|
||||
foreach (var position in Positions.Values.Where(p => p.Open.Price > 0 && p.Open.Quantity > 0))
|
||||
foreach (var position in Positions.Values.Where(p => p.IsValidForMetrics()))
|
||||
{
|
||||
totalFees += TradingHelpers.CalculatePositionFees(position);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user