Refactoring TradingBotBase.cs + clean architecture (#38)

* Refactoring TradingBotBase.cs + clean architecture

* Fix basic tests

* Fix tests

* Fix workers

* Fix open positions

* Fix closing position stucking the grain

* Fix comments

* Refactor candle handling to use IReadOnlyList for chronological order preservation across various components
This commit is contained in:
Oda
2025-12-01 19:32:06 +07:00
committed by GitHub
parent ab26260f6d
commit 9d536ea49e
74 changed files with 4525 additions and 2350 deletions

View File

@@ -57,4 +57,9 @@ public class PositionEntity
[ForeignKey("TakeProfit2TradeId")] public virtual TradeEntity? TakeProfit2Trade { get; set; }
[Column(TypeName = "decimal(18,8)")] public decimal NetPnL { get; set; }
/// <summary>
/// The trading type for this position (BacktestFutures or Futures)
/// </summary>
public TradingType TradingType { get; set; }
}

View File

@@ -331,6 +331,13 @@ public static class PostgreSqlMappers
{
if (backtest == null) return null;
// Configure JSON serializer to handle circular references
var jsonSettings = new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
PreserveReferencesHandling = PreserveReferencesHandling.None
};
return new BacktestEntity
{
Identifier = backtest.Id,
@@ -339,20 +346,20 @@ public static class PostgreSqlMappers
WinRate = backtest.WinRate,
GrowthPercentage = backtest.GrowthPercentage,
HodlPercentage = backtest.HodlPercentage,
ConfigJson = JsonConvert.SerializeObject(backtest.Config),
ConfigJson = JsonConvert.SerializeObject(backtest.Config, jsonSettings),
Name = backtest.Config?.Name ?? string.Empty,
Ticker = backtest.Config?.Ticker.ToString() ?? string.Empty,
Timeframe = (int)backtest.Config.Timeframe,
IndicatorsCsv = string.Join(',', backtest.Config.Scenario.Indicators.Select(i => i.Type.ToString())),
IndicatorsCount = backtest.Config.Scenario.Indicators.Count,
PositionsJson = JsonConvert.SerializeObject(backtest.Positions.Values.ToList()),
SignalsJson = JsonConvert.SerializeObject(backtest.Signals.Values.ToList()),
PositionsJson = JsonConvert.SerializeObject(backtest.Positions.Values.ToList(), jsonSettings),
SignalsJson = JsonConvert.SerializeObject(backtest.Signals.Values.ToList(), jsonSettings),
StartDate = backtest.StartDate,
EndDate = backtest.EndDate,
Duration = backtest.EndDate - backtest.StartDate,
MoneyManagementJson = JsonConvert.SerializeObject(backtest.Config?.MoneyManagement),
MoneyManagementJson = JsonConvert.SerializeObject(backtest.Config?.MoneyManagement, jsonSettings),
UserId = backtest.User?.Id ?? 0,
StatisticsJson = backtest.Statistics != null ? JsonConvert.SerializeObject(backtest.Statistics) : null,
StatisticsJson = backtest.Statistics != null ? JsonConvert.SerializeObject(backtest.Statistics, jsonSettings) : null,
SharpeRatio = backtest.Statistics?.SharpeRatio ?? 0m,
MaxDrawdown = backtest.Statistics?.MaxDrawdown ?? 0m,
MaxDrawdownRecoveryTime = backtest.Statistics?.MaxDrawdownRecoveryTime ?? TimeSpan.Zero,
@@ -615,7 +622,8 @@ public static class PostgreSqlMappers
{
Status = entity.Status,
SignalIdentifier = entity.SignalIdentifier,
InitiatorIdentifier = entity.InitiatorIdentifier
InitiatorIdentifier = entity.InitiatorIdentifier,
TradingType = entity.TradingType
};
// Set ProfitAndLoss with proper type
@@ -657,6 +665,7 @@ public static class PostgreSqlMappers
SignalIdentifier = position.SignalIdentifier,
UserId = position.User?.Id ?? 0,
InitiatorIdentifier = position.InitiatorIdentifier,
TradingType = position.TradingType,
MoneyManagementJson = position.MoneyManagement != null
? JsonConvert.SerializeObject(position.MoneyManagement)
: null,