Add netpnl and initialBalance to backtests
This commit is contained in:
@@ -301,7 +301,9 @@ public class BacktestController : BaseController
|
|||||||
Fees = b.Fees,
|
Fees = b.Fees,
|
||||||
SharpeRatio = b.SharpeRatio,
|
SharpeRatio = b.SharpeRatio,
|
||||||
Score = b.Score,
|
Score = b.Score,
|
||||||
ScoreMessage = b.ScoreMessage
|
ScoreMessage = b.ScoreMessage,
|
||||||
|
InitialBalance = b.InitialBalance,
|
||||||
|
NetPnl = b.NetPnl
|
||||||
}),
|
}),
|
||||||
TotalCount = totalCount,
|
TotalCount = totalCount,
|
||||||
CurrentPage = page,
|
CurrentPage = page,
|
||||||
@@ -435,7 +437,9 @@ public class BacktestController : BaseController
|
|||||||
Fees = b.Fees,
|
Fees = b.Fees,
|
||||||
SharpeRatio = b.SharpeRatio,
|
SharpeRatio = b.SharpeRatio,
|
||||||
Score = b.Score,
|
Score = b.Score,
|
||||||
ScoreMessage = b.ScoreMessage
|
ScoreMessage = b.ScoreMessage,
|
||||||
|
InitialBalance = b.InitialBalance,
|
||||||
|
NetPnl = b.NetPnl
|
||||||
}),
|
}),
|
||||||
TotalCount = totalCount,
|
TotalCount = totalCount,
|
||||||
CurrentPage = page,
|
CurrentPage = page,
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ public class LightBacktestResponse
|
|||||||
[Required] public double? SharpeRatio { get; set; }
|
[Required] public double? SharpeRatio { get; set; }
|
||||||
[Required] public double Score { get; set; }
|
[Required] public double Score { get; set; }
|
||||||
[Required] public string ScoreMessage { get; set; } = string.Empty;
|
[Required] public string ScoreMessage { get; set; } = string.Empty;
|
||||||
|
[Required] public decimal InitialBalance { get; set; }
|
||||||
|
[Required] public decimal NetPnl { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class LightBacktestResponseMapper
|
public static class LightBacktestResponseMapper
|
||||||
@@ -41,7 +43,9 @@ public static class LightBacktestResponseMapper
|
|||||||
Fees = b.Fees,
|
Fees = b.Fees,
|
||||||
SharpeRatio = (double?)b.Statistics?.SharpeRatio,
|
SharpeRatio = (double?)b.Statistics?.SharpeRatio,
|
||||||
Score = b.Score,
|
Score = b.Score,
|
||||||
ScoreMessage = b.ScoreMessage
|
ScoreMessage = b.ScoreMessage,
|
||||||
|
InitialBalance = b.InitialBalance,
|
||||||
|
NetPnl = b.NetPnl
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -166,6 +166,8 @@ public class BacktestTradingBotGrain : Grain, IBacktestTradingBotGrain
|
|||||||
Metadata = metadata,
|
Metadata = metadata,
|
||||||
StartDate = candles.FirstOrDefault()!.OpenTime,
|
StartDate = candles.FirstOrDefault()!.OpenTime,
|
||||||
EndDate = candles.LastOrDefault()!.OpenTime,
|
EndDate = candles.LastOrDefault()!.OpenTime,
|
||||||
|
InitialBalance = tradingBot.WalletBalances.FirstOrDefault().Value,
|
||||||
|
NetPnl = finalPnl - fees,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (save && user != null)
|
if (save && user != null)
|
||||||
@@ -201,7 +203,9 @@ public class BacktestTradingBotGrain : Grain, IBacktestTradingBotGrain
|
|||||||
Fees = backtest.Fees,
|
Fees = backtest.Fees,
|
||||||
SharpeRatio = (double?)backtest.Statistics?.SharpeRatio,
|
SharpeRatio = (double?)backtest.Statistics?.SharpeRatio,
|
||||||
Score = backtest.Score,
|
Score = backtest.Score,
|
||||||
ScoreMessage = backtest.ScoreMessage
|
ScoreMessage = backtest.ScoreMessage,
|
||||||
|
InitialBalance = backtest.InitialBalance,
|
||||||
|
NetPnl = backtest.NetPnl
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -172,7 +172,8 @@ public class LiveTradingBotGrain : Grain, ILiveTradingBotGrain, IRemindable
|
|||||||
// Fallback: Get the first account for the user
|
// Fallback: Get the first account for the user
|
||||||
if (_state.State.User == null)
|
if (_state.State.User == null)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"Bot '{config.Name}' (ID: {_state.State.Identifier}) has no user information. Cannot determine fallback account.");
|
throw new InvalidOperationException(
|
||||||
|
$"Bot '{config.Name}' (ID: {_state.State.Identifier}) has no user information. Cannot determine fallback account.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var firstAccount = await ServiceScopeHelpers.WithScopedService<IAccountService, Account>(
|
var firstAccount = await ServiceScopeHelpers.WithScopedService<IAccountService, Account>(
|
||||||
@@ -183,8 +184,10 @@ public class LiveTradingBotGrain : Grain, ILiveTradingBotGrain, IRemindable
|
|||||||
var account = userAccounts.FirstOrDefault();
|
var account = userAccounts.FirstOrDefault();
|
||||||
if (account == null)
|
if (account == null)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"User '{_state.State.User.Name}' has no accounts configured.");
|
throw new InvalidOperationException(
|
||||||
|
$"User '{_state.State.User.Name}' has no accounts configured.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return account;
|
return account;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -193,7 +196,8 @@ public class LiveTradingBotGrain : Grain, ILiveTradingBotGrain, IRemindable
|
|||||||
_state.State.Config = config;
|
_state.State.Config = config;
|
||||||
await _state.WriteStateAsync();
|
await _state.WriteStateAsync();
|
||||||
|
|
||||||
_logger.LogInformation("Bot '{BotName}' (ID: {BotId}) using fallback account '{AccountName}' for user '{UserName}'",
|
_logger.LogInformation(
|
||||||
|
"Bot '{BotName}' (ID: {BotId}) using fallback account '{AccountName}' for user '{UserName}'",
|
||||||
config.Name, _state.State.Identifier, firstAccount.Name, _state.State.User.Name);
|
config.Name, _state.State.Identifier, firstAccount.Name, _state.State.User.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -461,6 +465,7 @@ public class LiveTradingBotGrain : Grain, ILiveTradingBotGrain, IRemindable
|
|||||||
{
|
{
|
||||||
_logger.LogError(ex, "Error during coordinated balance check for bot {BotId}",
|
_logger.LogError(ex, "Error during coordinated balance check for bot {BotId}",
|
||||||
_state.State.Identifier);
|
_state.State.Identifier);
|
||||||
|
SentrySdk.CaptureException(ex);
|
||||||
// Continue execution to avoid stopping the bot due to coordination errors
|
// Continue execution to avoid stopping the bot due to coordination errors
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1046,7 +1051,8 @@ public class LiveTradingBotGrain : Grain, ILiveTradingBotGrain, IRemindable
|
|||||||
{
|
{
|
||||||
if (_state.State.User == null)
|
if (_state.State.User == null)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"Bot '{_state.State.Config?.Name}' (ID: {_state.State.Identifier}) has no user information.");
|
throw new InvalidOperationException(
|
||||||
|
$"Bot '{_state.State.Config?.Name}' (ID: {_state.State.Identifier}) has no user information.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return Task.FromResult(_state.State.User);
|
return Task.FromResult(_state.State.User);
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ public class Backtest
|
|||||||
public Guid RequestId { get; set; }
|
public Guid RequestId { get; set; }
|
||||||
public object? Metadata { get; set; }
|
public object? Metadata { get; set; }
|
||||||
public string ScoreMessage { get; set; } = string.Empty;
|
public string ScoreMessage { get; set; } = string.Empty;
|
||||||
|
[Required] public decimal InitialBalance { get; set; }
|
||||||
|
[Required] public decimal NetPnl { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new TradingBotConfig based on this backtest's configuration for starting a live bot.
|
/// Creates a new TradingBotConfig based on this backtest's configuration for starting a live bot.
|
||||||
|
|||||||
@@ -25,4 +25,6 @@ public class LightBacktest
|
|||||||
[Id(12)] public string ScoreMessage { get; set; } = string.Empty;
|
[Id(12)] public string ScoreMessage { get; set; } = string.Empty;
|
||||||
[Id(13)] public object Metadata { get; set; }
|
[Id(13)] public object Metadata { get; set; }
|
||||||
[Id(14)] public string Ticker { get; set; } = string.Empty;
|
[Id(14)] public string Ticker { get; set; } = string.Empty;
|
||||||
|
[Id(15)] public decimal InitialBalance { get; set; }
|
||||||
|
[Id(16)] public decimal NetPnl { get; set; }
|
||||||
}
|
}
|
||||||
@@ -189,6 +189,9 @@ namespace Managing.Infrastructure.Databases.Migrations
|
|||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<decimal>("InitialBalance")
|
||||||
|
.HasColumnType("decimal(18,8)");
|
||||||
|
|
||||||
b.Property<decimal>("MaxDrawdown")
|
b.Property<decimal>("MaxDrawdown")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("decimal(18,8)")
|
.HasColumnType("decimal(18,8)")
|
||||||
@@ -211,6 +214,9 @@ namespace Managing.Infrastructure.Databases.Migrations
|
|||||||
.HasMaxLength(255)
|
.HasMaxLength(255)
|
||||||
.HasColumnType("character varying(255)");
|
.HasColumnType("character varying(255)");
|
||||||
|
|
||||||
|
b.Property<decimal>("NetPnl")
|
||||||
|
.HasColumnType("decimal(18,8)");
|
||||||
|
|
||||||
b.Property<string>("PositionsJson")
|
b.Property<string>("PositionsJson")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("jsonb");
|
.HasColumnType("jsonb");
|
||||||
|
|||||||
@@ -120,4 +120,12 @@ public class BacktestEntity
|
|||||||
|
|
||||||
[Required]
|
[Required]
|
||||||
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
|
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
[Column(TypeName = "decimal(18,8)")]
|
||||||
|
public decimal InitialBalance { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
[Column(TypeName = "decimal(18,8)")]
|
||||||
|
public decimal NetPnl { get; set; }
|
||||||
}
|
}
|
||||||
@@ -313,7 +313,9 @@ public static class PostgreSqlMappers
|
|||||||
Score = entity.Score,
|
Score = entity.Score,
|
||||||
ScoreMessage = entity.ScoreMessage,
|
ScoreMessage = entity.ScoreMessage,
|
||||||
RequestId = entity.RequestId,
|
RequestId = entity.RequestId,
|
||||||
Metadata = entity.Metadata
|
Metadata = entity.Metadata,
|
||||||
|
InitialBalance = entity.InitialBalance,
|
||||||
|
NetPnl = entity.NetPnl
|
||||||
};
|
};
|
||||||
|
|
||||||
return backtest;
|
return backtest;
|
||||||
@@ -353,7 +355,9 @@ public static class PostgreSqlMappers
|
|||||||
ScoreMessage = backtest.ScoreMessage ?? string.Empty,
|
ScoreMessage = backtest.ScoreMessage ?? string.Empty,
|
||||||
Metadata = backtest.Metadata?.ToString(),
|
Metadata = backtest.Metadata?.ToString(),
|
||||||
CreatedAt = DateTime.UtcNow,
|
CreatedAt = DateTime.UtcNow,
|
||||||
UpdatedAt = DateTime.UtcNow
|
UpdatedAt = DateTime.UtcNow,
|
||||||
|
InitialBalance = backtest.InitialBalance,
|
||||||
|
NetPnl = backtest.NetPnl
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user