Update precalculated indicators values
This commit is contained in:
@@ -4,7 +4,6 @@ using Managing.Application.Abstractions.Repositories;
|
||||
using Managing.Application.Abstractions.Services;
|
||||
using Managing.Application.Bots;
|
||||
using Managing.Common;
|
||||
using Managing.Core;
|
||||
using Managing.Domain.Backtests;
|
||||
using Managing.Domain.Bots;
|
||||
using Managing.Domain.Candles;
|
||||
@@ -186,21 +185,11 @@ public class BacktestExecutor
|
||||
_logger.LogInformation("⚡ Pre-calculating indicator values for {IndicatorCount} indicators",
|
||||
config.Scenario.Indicators?.Count ?? 0);
|
||||
|
||||
// Convert LightScenario to Scenario for CalculateIndicatorsValuesAsync
|
||||
// Convert LightScenario to Scenario for CalculateIndicatorsValues
|
||||
var scenario = config.Scenario.ToScenario();
|
||||
|
||||
// Calculate all indicator values once with all candles
|
||||
preCalculatedIndicatorValues = await ServiceScopeHelpers
|
||||
.WithScopedService<ITradingService, Dictionary<IndicatorType, IndicatorsResultBase>>(
|
||||
_scopeFactory,
|
||||
async tradingService =>
|
||||
{
|
||||
return await tradingService.CalculateIndicatorsValuesAsync(scenario, candles);
|
||||
});
|
||||
|
||||
// Store pre-calculated values in trading bot for use during signal generation
|
||||
tradingBot.PreCalculatedIndicatorValues = preCalculatedIndicatorValues;
|
||||
|
||||
preCalculatedIndicatorValues = TradingBox.CalculateIndicatorsValues(scenario, candles);
|
||||
telemetry.IndicatorPreCalculationTime = Stopwatch.GetElapsedTime(indicatorCalcStart);
|
||||
_logger.LogInformation(
|
||||
"✅ Successfully pre-calculated indicator values for {IndicatorCount} indicator types in {Duration:F2}ms",
|
||||
@@ -264,7 +253,7 @@ public class BacktestExecutor
|
||||
|
||||
// Run with optimized backtest path (minimize async calls)
|
||||
var backtestStepStart = Stopwatch.GetTimestamp();
|
||||
await tradingBot.UpdateSignals(fixedCandles);
|
||||
await tradingBot.UpdateSignals(fixedCandles, preCalculatedIndicatorValues);
|
||||
await tradingBot.Run();
|
||||
|
||||
backtestStepTotalTime += Stopwatch.GetElapsedTime(backtestStepStart);
|
||||
|
||||
@@ -45,13 +45,6 @@ public class TradingBotBase : ITradingBot
|
||||
public Candle LastCandle { get; set; }
|
||||
public DateTime? LastPositionClosingTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Pre-calculated indicator values for backtesting optimization.
|
||||
/// Key is IndicatorType, Value is the calculated indicator result.
|
||||
/// </summary>
|
||||
public Dictionary<IndicatorType, IndicatorsResultBase> PreCalculatedIndicatorValues { get; set; }
|
||||
|
||||
|
||||
public TradingBotBase(
|
||||
ILogger<TradingBotBase> logger,
|
||||
IServiceScopeFactory scopeFactory,
|
||||
@@ -65,7 +58,6 @@ public class TradingBotBase : ITradingBot
|
||||
Positions = new Dictionary<Guid, Position>();
|
||||
WalletBalances = new Dictionary<DateTime, decimal>();
|
||||
PreloadSince = CandleHelpers.GetBotPreloadSinceFromTimeframe(config.Timeframe);
|
||||
PreCalculatedIndicatorValues = new Dictionary<IndicatorType, IndicatorsResultBase>();
|
||||
}
|
||||
|
||||
public async Task Start(BotStatus previousStatus)
|
||||
@@ -264,7 +256,7 @@ public class TradingBotBase : ITradingBot
|
||||
}
|
||||
|
||||
public async Task UpdateSignals(HashSet<Candle> candles,
|
||||
Dictionary<DateTime, LightSignal> preCalculatedSignals = null)
|
||||
Dictionary<IndicatorType, IndicatorsResultBase> preCalculatedIndicatorValues = null)
|
||||
{
|
||||
// Skip indicator checking if flipping is disabled and there's an open position
|
||||
// This prevents unnecessary indicator calculations when we can't act on signals anyway
|
||||
@@ -285,7 +277,7 @@ public class TradingBotBase : ITradingBot
|
||||
if (Config.IsForBacktest)
|
||||
{
|
||||
var backtestSignal = TradingBox.GetSignal(candles, Config.Scenario, Signals, Config.Scenario.LoopbackPeriod,
|
||||
PreCalculatedIndicatorValues);
|
||||
preCalculatedIndicatorValues);
|
||||
if (backtestSignal == null) return;
|
||||
await AddSignal(backtestSignal);
|
||||
}
|
||||
|
||||
@@ -2,13 +2,11 @@
|
||||
using Managing.Application.Abstractions.Services;
|
||||
using Managing.Domain.Accounts;
|
||||
using Managing.Domain.Bots;
|
||||
using Managing.Domain.Candles;
|
||||
using Managing.Domain.Indicators;
|
||||
using Managing.Domain.Scenarios;
|
||||
using Managing.Domain.Shared.Helpers;
|
||||
using Managing.Domain.Statistics;
|
||||
using Managing.Domain.Strategies;
|
||||
using Managing.Domain.Strategies.Base;
|
||||
using Managing.Domain.Synth.Models;
|
||||
using Managing.Domain.Trades;
|
||||
using Managing.Domain.Users;
|
||||
@@ -429,44 +427,6 @@ public class TradingService : ITradingService
|
||||
positionIdentifier, botConfig);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates indicators values for a given scenario and candles.
|
||||
/// </summary>
|
||||
/// <param name="scenario">The scenario containing indicators.</param>
|
||||
/// <param name="candles">The candles to calculate indicators for.</param>
|
||||
/// <returns>A dictionary of indicator types to their calculated values.</returns>
|
||||
public async Task<Dictionary<IndicatorType, IndicatorsResultBase>> CalculateIndicatorsValuesAsync(
|
||||
Scenario scenario,
|
||||
HashSet<Candle> candles)
|
||||
{
|
||||
// Offload CPU-bound indicator calculations to thread pool
|
||||
return await Task.Run(() =>
|
||||
{
|
||||
var indicatorsValues = new Dictionary<IndicatorType, IndicatorsResultBase>();
|
||||
|
||||
if (scenario?.Indicators == null || scenario.Indicators.Count == 0)
|
||||
{
|
||||
return indicatorsValues;
|
||||
}
|
||||
|
||||
// Build indicators from scenario
|
||||
foreach (var indicator in scenario.Indicators)
|
||||
{
|
||||
try
|
||||
{
|
||||
var buildedIndicator = ScenarioHelpers.BuildIndicator(ScenarioHelpers.BaseToLight(indicator));
|
||||
indicatorsValues[indicator.Type] = buildedIndicator.GetIndicatorValues(candles);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error calculating indicator {IndicatorName}: {ErrorMessage}",
|
||||
indicator.Name, ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
return indicatorsValues;
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<IndicatorBase?> GetIndicatorByNameUserAsync(string name, User user)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user