Fix status IsFinished/IsOpen/IsForMetrics + use redis for markets on gmx.tsx instead of inmemory cache

This commit is contained in:
2025-10-08 12:13:04 +07:00
parent 67065469a6
commit 86dd6849ea
9 changed files with 209 additions and 86 deletions

View File

@@ -193,7 +193,7 @@ public class TradingBotBase : ITradingBot
public async Task UpdateSignals(HashSet<Candle> candles = null)
{
// If position open and not flipped, do not update signals
if (!Config.FlipPosition && Positions.Any(p => !p.Value.IsFinished())) return;
if (!Config.FlipPosition && Positions.Any(p => p.Value.IsOpen())) return;
// Check if we're in cooldown period for any direction
if (await IsInCooldownPeriodAsync())
@@ -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.IsFinished()))
foreach (var position in Positions.Values.Where(p => p.IsOpen()))
{
var signalForPosition = Signals[position.SignalIdentifier];
if (signalForPosition == null)
@@ -306,6 +306,31 @@ public class TradingBotBase : ITradingBot
await UpdatePosition(signalForPosition, position);
}
// 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
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);
});
if (positionInDatabase != null && positionInDatabase.Status != position.Status)
{
await UpdatePositionDatabase(position);
await LogInformation(
$"💾 Database Update\nPosition: `{position.Identifier}`\nStatus: `{position.Status}`\nUpdated in database");
}
}
catch (Exception ex)
{
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
var signalsWaitingForPosition = Signals.Values.Where(s => s.Status == SignalStatus.WaitingForPosition);
@@ -830,7 +855,7 @@ public class TradingBotBase : ITradingBot
// Check for any existing open position (not finished) for this ticker
var openedPosition =
Positions.Values.FirstOrDefault(p => !p.IsFinished() && p.SignalIdentifier != signal.Identifier);
Positions.Values.FirstOrDefault(p => p.IsOpen() && p.SignalIdentifier != signal.Identifier);
decimal lastPrice = await ServiceScopeHelpers.WithScopedService<IExchangeService, decimal>(_scopeFactory,
async exchangeService =>
@@ -1708,8 +1733,8 @@ public class TradingBotBase : ITradingBot
public int GetWinRate()
{
var succeededPositions = Positions.Values.Where(p => p.IsFinished()).Count(p => p.ProfitAndLoss?.Realized > 0);
var total = Positions.Values.Where(p => p.IsFinished()).Count();
var succeededPositions = Positions.Values.Where(p => p.IsValidForMetrics()).Count(p => p.IsInProfit());
var total = Positions.Values.Where(p => p.IsValidForMetrics()).Count();
if (total == 0)
return 0;