Update perf
This commit is contained in:
@@ -8,8 +8,6 @@ using Managing.Core;
|
||||
using Managing.Domain.Backtests;
|
||||
using Managing.Domain.Bots;
|
||||
using Managing.Domain.Candles;
|
||||
using Managing.Domain.Indicators;
|
||||
using Managing.Domain.Scenarios;
|
||||
using Managing.Domain.Shared.Helpers;
|
||||
using Managing.Domain.Strategies.Base;
|
||||
using Managing.Domain.Users;
|
||||
@@ -226,28 +224,8 @@ public class BacktestExecutor
|
||||
// Pre-allocate and populate candle structures for maximum performance
|
||||
var orderedCandles = candles.OrderBy(c => c.Date).ToList();
|
||||
|
||||
// Pre-calculate all signals for the entire backtest period
|
||||
Dictionary<DateTime, LightSignal> preCalculatedSignals = null;
|
||||
var signalPreCalcStart = Stopwatch.GetTimestamp();
|
||||
if (config.Scenario != null && preCalculatedIndicatorValues != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
preCalculatedSignals = PreCalculateAllSignals(orderedCandles, config.Scenario, preCalculatedIndicatorValues);
|
||||
var signalPreCalcTime = Stopwatch.GetElapsedTime(signalPreCalcStart);
|
||||
_logger.LogInformation(
|
||||
"✅ Successfully pre-calculated {SignalCount} signals in {Duration:F2}ms",
|
||||
preCalculatedSignals.Count, signalPreCalcTime.TotalMilliseconds);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var signalPreCalcTime = Stopwatch.GetElapsedTime(signalPreCalcStart);
|
||||
_logger.LogWarning(ex,
|
||||
"❌ Failed to pre-calculate signals in {Duration:F2}ms, will calculate on-the-fly. Error: {ErrorMessage}",
|
||||
signalPreCalcTime.TotalMilliseconds, ex.Message);
|
||||
preCalculatedSignals = null;
|
||||
}
|
||||
}
|
||||
// Skip pre-calculated signals - the approach was flawed and caused performance regression
|
||||
// The signal calculation depends on rolling window state and cannot be pre-calculated effectively
|
||||
|
||||
// Use optimized rolling window approach - TradingBox.GetSignal only needs last 600 candles
|
||||
const int rollingWindowSize = 600;
|
||||
@@ -301,23 +279,10 @@ public class BacktestExecutor
|
||||
|
||||
if (!shouldSkipSignalUpdate)
|
||||
{
|
||||
// Use pre-calculated signals for maximum performance
|
||||
// Smart signal caching - reduce signal update frequency for performance
|
||||
// RSI and similar indicators don't need updates every candle for 15-minute data
|
||||
var signalUpdateStart = Stopwatch.GetTimestamp();
|
||||
|
||||
if (preCalculatedSignals != null && preCalculatedSignals.TryGetValue(candle.Date, out var preCalculatedSignal))
|
||||
{
|
||||
// Fast path: use pre-calculated signal directly
|
||||
if (preCalculatedSignal != null)
|
||||
{
|
||||
await tradingBot.AddSignal(preCalculatedSignal);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback: calculate signal on-the-fly (shouldn't happen in optimized path)
|
||||
await tradingBot.UpdateSignals(fixedCandlesHashSet);
|
||||
}
|
||||
|
||||
await tradingBot.UpdateSignals(fixedCandlesHashSet);
|
||||
signalUpdateTotalTime += Stopwatch.GetElapsedTime(signalUpdateStart);
|
||||
telemetry.TotalSignalUpdates++;
|
||||
}
|
||||
@@ -589,46 +554,6 @@ public class BacktestExecutor
|
||||
/// Pre-calculates all signals for the entire backtest period
|
||||
/// This eliminates repeated GetSignal() calls during the backtest loop
|
||||
/// </summary>
|
||||
private Dictionary<DateTime, LightSignal> PreCalculateAllSignals(
|
||||
List<Candle> orderedCandles,
|
||||
LightScenario scenario,
|
||||
Dictionary<IndicatorType, IndicatorsResultBase> preCalculatedIndicatorValues)
|
||||
{
|
||||
var signals = new Dictionary<DateTime, LightSignal>();
|
||||
var previousSignals = new Dictionary<string, LightSignal>();
|
||||
const int rollingWindowSize = 600;
|
||||
|
||||
_logger.LogInformation("⚡ Pre-calculating signals for {CandleCount} candles with rolling window size {WindowSize}",
|
||||
orderedCandles.Count, rollingWindowSize);
|
||||
|
||||
for (int i = 0; i < orderedCandles.Count; i++)
|
||||
{
|
||||
var currentCandle = orderedCandles[i];
|
||||
|
||||
// Build rolling window: last 600 candles up to current candle
|
||||
var windowStart = Math.Max(0, i - rollingWindowSize + 1);
|
||||
var windowCandles = orderedCandles.Skip(windowStart).Take(i - windowStart + 1).ToHashSet();
|
||||
|
||||
// Calculate signal for this candle using the same logic as TradingBox.GetSignal
|
||||
var signal = TradingBox.GetSignal(
|
||||
windowCandles,
|
||||
scenario,
|
||||
previousSignals,
|
||||
scenario?.LoopbackPeriod ?? 1,
|
||||
preCalculatedIndicatorValues);
|
||||
|
||||
if (signal != null)
|
||||
{
|
||||
signals[currentCandle.Date] = signal;
|
||||
previousSignals[signal.Identifier] = signal;
|
||||
}
|
||||
}
|
||||
|
||||
_logger.LogInformation("✅ Pre-calculated {SignalCount} signals for {CandleCount} candles",
|
||||
signals.Count, orderedCandles.Count);
|
||||
|
||||
return signals;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Backtest to LightBacktest
|
||||
|
||||
@@ -2,3 +2,10 @@ DateTime,TestName,CandlesCount,ExecutionTimeSeconds,ProcessingRateCandlesPerSec,
|
||||
2025-11-11T06:53:40Z,ExecuteBacktest_With_Two_Scenarios_Should_Show_Performance_Telemetry,576037926 576037588,1.52 1.53,3792.6 3758,8,15.26,11.35,23.73,0.0,0,0.0,0.0,0.0,0.0,2018.27,4 000,00,2.02,1919,e810ab60,dev,development
|
||||
2025-11-11T06:58:31Z,ExecuteBacktest_With_Two_Scenarios_Should_Show_Performance_Telemetry,576038904 576038584,1.48 1.49,3890.4 3858,4,15.27,11.03,23.74,0.0,0,0.0,0.0,0.0,0.0,2018.27 (Expected: 2018.27),4 000,00 (Expected: 40,0%),2.02 (Expected: 2.02%),19181918,e810ab60,dev,development
|
||||
2025-11-11T07:03:00Z,ExecuteBacktest_With_Two_Scenarios_Should_Show_Performance_Telemetry,576033954 576033649,1.70 1.71,3395.4 3364,9,15.29,11.00,23.75,0.0,0,0.0,0.0,0.0,0.0,2018.27 (Expected: 2018.27),40 (Expected: 40%),2.02 (Expected: 2.02%),19191918,e810ab60,dev,development
|
||||
2025-11-11T07:07:23Z,ExecuteBacktest_With_Two_Scenarios_Should_Show_Performance_Telemetry,576028957 576028743,1.99 2.00,2895.7 2874,3,15.30,11.20,24.91,0.0,0,0.0,0.0,0.0,0.0,2018.27 (Expected: 2018.27),40 (Expected: 40%),2.02 (Expected: 2.02%),19181918,90341369,dev,development
|
||||
2025-11-11T07:08:48Z,ExecuteBacktest_With_Two_Scenarios_Should_Show_Performance_Telemetry,576020748 576020540,2.78 2.80,2074.8 2054,0,15.27,11.13,24.95,0.0,0,0.0,0.0,0.0,0.0,2018.27 (Expected: 2018.27),40 (Expected: 40%),2.02 (Expected: 2.02%),19181918,90341369,dev,development
|
||||
2025-11-11T07:09:35Z,ExecuteBacktest_With_Two_Scenarios_Should_Show_Performance_Telemetry,576019355 576019187,2.98 3.00,1935.5 1918,7,15.28,11.27,23.74,0.0,0,0.0,0.0,0.0,0.0,2018.27 (Expected: 2018.27),40 (Expected: 40%),2.02 (Expected: 2.02%),19181918,90341369,dev,development
|
||||
2025-11-11T07:10:15Z,ExecuteBacktest_With_Two_Scenarios_Should_Show_Performance_Telemetry,576031357 576031098,1.84 1.85,3135.7 3109,8,15.29,11.08,24.89,0.0,0,0.0,0.0,0.0,0.0,2018.27 (Expected: 2018.27),40 (Expected: 40%),2.02 (Expected: 2.02%),19181918,90341369,dev,development
|
||||
2025-11-11T07:10:55Z,ExecuteBacktest_With_Two_Scenarios_Should_Show_Performance_Telemetry,576034016 576033795,1.69 1.70,3401.6 3379,5,15.27,11.27,23.74,0.0,0,0.0,0.0,0.0,0.0,2018.27 (Expected: 2018.27),40 (Expected: 40%),2.02 (Expected: 2.02%),19181918,90341369,dev,development
|
||||
2025-11-11T07:14:07Z,ExecuteBacktest_With_Two_Scenarios_Should_Show_Performance_Telemetry,576029692 576029392,1.94 1.96,2969.2 2939,2,15.26,10.16,23.73,0.0,0,0.0,0.0,0.0,0.0,2018.27 (Expected: 2018.27),40 (Expected: 40%),2.02 (Expected: 2.02%),19191918,90341369,dev,development
|
||||
2025-11-11T07:15:11Z,ExecuteBacktest_With_Two_Scenarios_Should_Show_Performance_Telemetry,576018866 576018800,3.05 3.06,1886.6 1880,0,15.71,10.54,24.24,0.0,0,0.0,0.0,0.0,0.0,2018.27 (Expected: 2018.27),40 (Expected: 40%),2.02 (Expected: 2.02%),19181918,90341369,dev,development
|
||||
|
||||
|
@@ -44,3 +44,10 @@ DateTime,TestName,CandlesCount,ExecutionTimeSeconds,ProcessingRateCandlesPerSec,
|
||||
2025-11-11T06:53:40Z,ExecuteBacktest_With_Large_Dataset_Should_Show_Performance_Telemetry,5760,1.12,5112.2,15.26,11.35,23.73,927.80,3828,66.5,78.67,0.48,0.01,24560.79,38,24.56,6015,e810ab60,dev,development
|
||||
2025-11-11T06:58:31Z,ExecuteBacktest_With_Large_Dataset_Should_Show_Performance_Telemetry,5760,1.55,3699.6,15.27,11.03,23.74,1319.91,3828,66.5,117.22,0.68,0.02,24560.79,38,24.56,6015,e810ab60,dev,development
|
||||
2025-11-11T07:03:00Z,ExecuteBacktest_With_Large_Dataset_Should_Show_Performance_Telemetry,5760,2.11,2720.5,15.29,11.00,23.75,1780.10,3828,66.5,145.96,0.92,0.03,24560.79,38,24.56,6015,e810ab60,dev,development
|
||||
2025-11-11T07:07:23Z,ExecuteBacktest_With_Large_Dataset_Should_Show_Performance_Telemetry,5760,5.115,1123.6,15.30,11.20,24.91,4447.27,3828,66.5,326.88,2.30,0.06,24560.79,38,24.56,6015,90341369,dev,development
|
||||
2025-11-11T07:08:48Z,ExecuteBacktest_With_Large_Dataset_Should_Show_Performance_Telemetry,5760,1.5,3827.1,15.27,11.13,24.95,1241.94,3828,66.5,128.70,0.64,0.02,24560.79,38,24.56,6015,90341369,dev,development
|
||||
2025-11-11T07:09:35Z,ExecuteBacktest_With_Large_Dataset_Should_Show_Performance_Telemetry,5760,1.015,5645.1,15.28,11.27,23.74,882.37,3828,66.5,62.61,0.46,0.01,24560.79,38,24.56,6015,90341369,dev,development
|
||||
2025-11-11T07:10:15Z,ExecuteBacktest_With_Large_Dataset_Should_Show_Performance_Telemetry,5760,1.985,2883.0,15.29,11.08,24.89,1662.32,3828,66.5,166.71,0.86,0.03,24560.79,38,24.56,6015,90341369,dev,development
|
||||
2025-11-11T07:10:55Z,ExecuteBacktest_With_Large_Dataset_Should_Show_Performance_Telemetry,5760,1.45,3954.1,15.27,11.27,23.74,1256.06,3828,66.5,94.29,0.65,0.02,24560.79,38,24.56,6015,90341369,dev,development
|
||||
2025-11-11T07:14:07Z,ExecuteBacktest_With_Large_Dataset_Should_Show_Performance_Telemetry,5760,0.815,7020.8,15.26,10.16,23.73,697.23,3828,66.5,53.42,0.36,0.01,24560.79,38,24.56,6016,90341369,dev,development
|
||||
2025-11-11T07:15:11Z,ExecuteBacktest_With_Large_Dataset_Should_Show_Performance_Telemetry,5760,1.76,3256.6,15.71,10.54,24.24,1411.34,3828,66.5,208.73,0.73,0.04,24560.79,38,24.56,6015,90341369,dev,development
|
||||
|
||||
|
Reference in New Issue
Block a user