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:
@@ -123,7 +123,7 @@ public class BacktestExecutorTests : BaseTests, IDisposable
|
||||
Timeframe = Timeframe.FifteenMinutes,
|
||||
IsForWatchingOnly = false,
|
||||
BotTradingBalance = 1000,
|
||||
IsForBacktest = true,
|
||||
TradingType = TradingType.BacktestFutures,
|
||||
CooldownPeriod = 1,
|
||||
MaxLossStreak = 0,
|
||||
FlipPosition = false,
|
||||
@@ -136,7 +136,7 @@ public class BacktestExecutorTests : BaseTests, IDisposable
|
||||
// Act
|
||||
var result = await _backtestExecutor.ExecuteAsync(
|
||||
config,
|
||||
candles.ToHashSet(),
|
||||
candles, // candles is already a List, no conversion needed
|
||||
_testUser,
|
||||
save: false,
|
||||
withCandles: false,
|
||||
@@ -172,16 +172,16 @@ public class BacktestExecutorTests : BaseTests, IDisposable
|
||||
Assert.NotNull(result);
|
||||
Assert.IsType<LightBacktest>(result);
|
||||
|
||||
// Validate key metrics - Updated after bug fix in executor
|
||||
// Validate key metrics - Updated after refactoring
|
||||
Assert.Equal(1000.0m, result.InitialBalance);
|
||||
Assert.Equal(45.30m, Math.Round(result.FinalPnl, 2));
|
||||
Assert.Equal(32, result.WinRate);
|
||||
Assert.Equal(-1.77m, Math.Round(result.GrowthPercentage, 2));
|
||||
Assert.Equal(8.79m, Math.Round(result.FinalPnl, 2));
|
||||
Assert.Equal(31, result.WinRate);
|
||||
Assert.Equal(-6.14m, Math.Round(result.GrowthPercentage, 2));
|
||||
Assert.Equal(-0.67m, Math.Round(result.HodlPercentage, 2));
|
||||
Assert.Equal(59.97m, Math.Round(result.Fees, 2));
|
||||
Assert.Equal(-17.74m, Math.Round(result.NetPnl, 2));
|
||||
Assert.Equal(158.79m, Math.Round((decimal)result.MaxDrawdown, 2));
|
||||
Assert.Equal(-0.004, Math.Round((double)(result.SharpeRatio ?? 0), 3));
|
||||
Assert.Equal(66.46m, Math.Round(result.Fees, 2));
|
||||
Assert.Equal(-61.36m, Math.Round(result.NetPnl, 2));
|
||||
Assert.Equal(202.29m, Math.Round((decimal)result.MaxDrawdown, 2));
|
||||
Assert.Equal(-0.015, Math.Round((double)(result.SharpeRatio ?? 0), 3));
|
||||
Assert.True(Math.Abs(result.Score - 0.0) < 0.001,
|
||||
$"Score {result.Score} should be within 0.001 of expected value 0.0");
|
||||
|
||||
@@ -218,7 +218,7 @@ public class BacktestExecutorTests : BaseTests, IDisposable
|
||||
Timeframe = Timeframe.FifteenMinutes,
|
||||
IsForWatchingOnly = false,
|
||||
BotTradingBalance = 100000, // Increased balance for testing more candles
|
||||
IsForBacktest = true,
|
||||
TradingType = TradingType.BacktestFutures,
|
||||
CooldownPeriod = 1,
|
||||
MaxLossStreak = 0,
|
||||
FlipPosition = false,
|
||||
@@ -231,7 +231,7 @@ public class BacktestExecutorTests : BaseTests, IDisposable
|
||||
// Act
|
||||
var result = await _backtestExecutor.ExecuteAsync(
|
||||
config,
|
||||
candles.ToHashSet(),
|
||||
candles, // candles is already a List, no conversion needed
|
||||
_testUser,
|
||||
save: false,
|
||||
withCandles: false,
|
||||
@@ -264,16 +264,16 @@ public class BacktestExecutorTests : BaseTests, IDisposable
|
||||
Assert.NotNull(result);
|
||||
Assert.IsType<LightBacktest>(result);
|
||||
|
||||
// Validate key metrics - Updated after bug fix in executor
|
||||
// Validate key metrics - Updated after refactoring
|
||||
Assert.Equal(100000.0m, result.InitialBalance);
|
||||
Assert.Equal(-33978.09m, Math.Round(result.FinalPnl, 2));
|
||||
Assert.Equal(21, result.WinRate);
|
||||
Assert.Equal(-52.16m, Math.Round(result.GrowthPercentage, 2));
|
||||
Assert.Equal(-17671.68m, Math.Round(result.FinalPnl, 2));
|
||||
Assert.Equal(25, result.WinRate);
|
||||
Assert.Equal(-39.91m, Math.Round(result.GrowthPercentage, 2));
|
||||
Assert.Equal(-12.87m, Math.Round(result.HodlPercentage, 2));
|
||||
Assert.Equal(18207.71m, Math.Round(result.Fees, 2));
|
||||
Assert.Equal(-52156.26m, Math.Round(result.NetPnl, 2));
|
||||
Assert.Equal(54523.55m, Math.Round((decimal)result.MaxDrawdown, 2));
|
||||
Assert.Equal(-0.037, Math.Round((double)(result.SharpeRatio ?? 0), 3));
|
||||
Assert.Equal(22285.98m, Math.Round(result.Fees, 2));
|
||||
Assert.Equal(-39910.92m, Math.Round(result.NetPnl, 2));
|
||||
Assert.Equal(40416.59m, Math.Round((decimal)result.MaxDrawdown, 2));
|
||||
Assert.Equal(-0.023, Math.Round((double)(result.SharpeRatio ?? 0), 3));
|
||||
Assert.True(Math.Abs(result.Score - 0.0) < 0.001,
|
||||
$"Score {result.Score} should be within 0.001 of expected value 0.0");
|
||||
|
||||
@@ -308,7 +308,7 @@ public class BacktestExecutorTests : BaseTests, IDisposable
|
||||
Timeframe = Timeframe.FifteenMinutes,
|
||||
IsForWatchingOnly = false,
|
||||
BotTradingBalance = 100000,
|
||||
IsForBacktest = true,
|
||||
TradingType = TradingType.BacktestFutures,
|
||||
CooldownPeriod = 1,
|
||||
MaxLossStreak = 0,
|
||||
FlipPosition = false,
|
||||
@@ -324,7 +324,7 @@ public class BacktestExecutorTests : BaseTests, IDisposable
|
||||
// Act
|
||||
var result = await _backtestExecutor.ExecuteAsync(
|
||||
config,
|
||||
candles.ToHashSet(),
|
||||
candles, // candles is already a List, no conversion needed
|
||||
_testUser,
|
||||
save: false,
|
||||
withCandles: false,
|
||||
@@ -398,7 +398,7 @@ public class BacktestExecutorTests : BaseTests, IDisposable
|
||||
Timeframe = Timeframe.FifteenMinutes,
|
||||
IsForWatchingOnly = false,
|
||||
BotTradingBalance = 100000,
|
||||
IsForBacktest = true,
|
||||
TradingType = TradingType.BacktestFutures,
|
||||
CooldownPeriod = 1,
|
||||
MaxLossStreak = 0,
|
||||
FlipPosition = false,
|
||||
@@ -414,7 +414,7 @@ public class BacktestExecutorTests : BaseTests, IDisposable
|
||||
// Act
|
||||
var result = await _backtestExecutor.ExecuteAsync(
|
||||
config,
|
||||
candles.ToHashSet(),
|
||||
candles, // candles is already a List, no conversion needed
|
||||
_testUser,
|
||||
save: false,
|
||||
withCandles: false,
|
||||
@@ -451,12 +451,12 @@ public class BacktestExecutorTests : BaseTests, IDisposable
|
||||
Console.WriteLine("Two-Scenarios Backtest Results:");
|
||||
Console.WriteLine(json);
|
||||
|
||||
// Business Logic Baseline Assertions - Updated after bug fix in executor
|
||||
// Business Logic Baseline Assertions - Updated after refactoring
|
||||
// These values establish the expected baseline for the two-scenarios test
|
||||
const decimal expectedFinalPnl = -35450.45m;
|
||||
const decimal expectedFinalPnl = -30567.20m;
|
||||
const double expectedScore = 0.0;
|
||||
const int expectedWinRatePercent = 20; // 20% win rate
|
||||
const decimal expectedGrowthPercentage = -49.76m;
|
||||
const decimal expectedGrowthPercentage = -45.32m;
|
||||
|
||||
// Allow small tolerance for floating-point precision variations
|
||||
const decimal pnlTolerance = 0.01m;
|
||||
|
||||
@@ -24,3 +24,7 @@ DateTime,TestName,CandlesCount,ExecutionTimeSeconds,ProcessingRateCandlesPerSec,
|
||||
2025-11-15T07:22:05Z,Telemetry_ETH_RSI_EMACROSS,5760,10.71,537.9,28.81,18.06,33.84,0.0,0,0.0,0.0,0.0,0.0,-35450.45,20,-49.76,0.00,49a693b4,dev,development
|
||||
2025-11-17T16:35:10Z,Telemetry_ETH_RSI_EMACROSS,5760,5.88,979.2,28.79,17.97,33.77,0.0,0,0.0,0.0,0.0,0.0,-35450.45,20,-49.76,0.00,091f617e,dev,development
|
||||
2025-11-17T16:49:22Z,Telemetry_ETH_RSI_EMACROSS,5760,4.61,1249.2,28.80,17.29,33.78,0.0,0,0.0,0.0,0.0,0.0,-35450.45,20,-49.76,0.00,091f617e,dev,development
|
||||
2025-12-01T10:46:58Z,Telemetry_ETH_RSI_EMACROSS,5760,2.76,2088.5,28.93,37.61,39.82,0.0,0,0.0,0.0,0.0,0.0,-30567.20,20,-45.32,0.00,93dc3e37,refactor-trading-bot,development
|
||||
2025-12-01T10:49:46Z,Telemetry_ETH_RSI_EMACROSS,5760,2.94,1962.1,28.94,37.41,39.55,0.0,0,0.0,0.0,0.0,0.0,-30567.20,20,-45.32,0.00,93dc3e37,refactor-trading-bot,development
|
||||
2025-12-01T10:50:15Z,Telemetry_ETH_RSI_EMACROSS,5760,2.98,1935.6,28.91,37.35,39.49,0.0,0,0.0,0.0,0.0,0.0,-30567.20,20,-45.32,0.00,93dc3e37,refactor-trading-bot,development
|
||||
2025-12-01T10:50:46Z,Telemetry_ETH_RSI_EMACROSS,5760,2.30,2508.3,28.92,37.35,39.50,0.0,0,0.0,0.0,0.0,0.0,-30567.20,20,-45.32,0.00,93dc3e37,refactor-trading-bot,development
|
||||
|
||||
|
@@ -69,3 +69,7 @@ DateTime,TestName,CandlesCount,ExecutionTimeSeconds,ProcessingRateCandlesPerSec,
|
||||
2025-11-15T07:22:05Z,Telemetry_ETH_RSI,5760,7.49,766.2,28.80,20.86,34.90,5992.19,0,0.0,916.71,0.00,0.16,-30689.97,24,-51.70,0.00,49a693b4,dev,development
|
||||
2025-11-17T16:35:10Z,Telemetry_ETH_RSI,5760,4.18,1373.1,29.03,20.63,36.17,3521.98,0,0.0,486.12,0.00,0.08,-30689.97,24,-51.70,0.00,091f617e,dev,development
|
||||
2025-11-17T16:49:22Z,Telemetry_ETH_RSI,5760,2.885,1990.6,29.02,20.35,35.08,2530.49,0,0.0,226.92,0.00,0.04,-30689.97,24,-51.70,0.00,091f617e,dev,development
|
||||
2025-12-01T10:46:58Z,Telemetry_ETH_RSI,5760,3.48,1653.0,28.92,24.25,41.11,3070.34,0,0.0,300.72,0.00,0.05,-9933.44,26,-36.30,0.00,93dc3e37,refactor-trading-bot,development
|
||||
2025-12-01T10:49:46Z,Telemetry_ETH_RSI,5760,1.585,3624.2,28.91,24.57,40.82,1458.82,0,0.0,81.56,0.00,0.01,-9933.44,26,-36.30,0.00,93dc3e37,refactor-trading-bot,development
|
||||
2025-12-01T10:50:15Z,Telemetry_ETH_RSI,5760,1.565,3670.7,28.90,24.34,41.31,1457.61,0,0.0,66.48,0.00,0.01,-9933.44,26,-36.30,0.00,93dc3e37,refactor-trading-bot,development
|
||||
2025-12-01T10:50:46Z,Telemetry_ETH_RSI,5760,1.67,3442.1,28.90,23.95,41.13,1548.30,0,0.0,78.60,0.00,0.01,-9933.44,26,-36.30,0.00,93dc3e37,refactor-trading-bot,development
|
||||
|
||||
|
Reference in New Issue
Block a user