perf: optimize TradingBotBase and TradingBox - reduce LINQ overhead and allocations (+31.1%)

This commit is contained in:
2025-11-11 12:21:50 +07:00
parent 1792cd2371
commit 46966cc5d8
6 changed files with 86 additions and 21 deletions

View File

@@ -75,10 +75,19 @@ public static class TradingBox
Dictionary<IndicatorType, IndicatorsResultBase> preCalculatedIndicatorValues)
{
var signalOnCandles = new List<LightSignal>();
// Optimize list creation - avoid redundant allocations
var limitedCandles = newCandles.Count <= 600
? newCandles.OrderBy(c => c.Date).ToList()
: newCandles.OrderBy(c => c.Date).TakeLast(600).ToList();
// Optimize list creation - avoid redundant allocations and multiple ordering
List<Candle> limitedCandles;
if (newCandles.Count <= 600)
{
// For small sets, just order once
limitedCandles = newCandles.OrderBy(c => c.Date).ToList();
}
else
{
// For large sets, use more efficient approach: sort then take last
var sorted = newCandles.OrderBy(c => c.Date).ToList();
limitedCandles = sorted.Skip(sorted.Count - 600).ToList();
}
foreach (var indicator in lightScenario.Indicators)
{
@@ -97,7 +106,8 @@ public static class TradingBox
signals = indicatorInstance.Run(newCandles);
}
if (signals == null || signals.Count() == 0)
// Optimized: Use Count property instead of Count() LINQ method
if (signals == null || signals.Count == 0)
{
// For trend and context strategies, lack of signal might be meaningful
// Signal strategies are expected to be sparse, so we continue
@@ -112,10 +122,11 @@ public static class TradingBox
continue;
}
// Ensure limitedCandles is ordered chronologically
var orderedCandles = limitedCandles.OrderBy(c => c.Date).ToList();
// Optimized: limitedCandles is already ordered, no need to re-order
var loopback = loopbackPeriod.HasValue && loopbackPeriod > 1 ? loopbackPeriod.Value : 1;
var candleLoopback = orderedCandles.TakeLast(loopback).ToList();
var candleLoopback = limitedCandles.Count > loopback
? limitedCandles.Skip(limitedCandles.Count - loopback).ToList()
: limitedCandles;
if (!candleLoopback.Any())
{
@@ -174,7 +185,9 @@ public static class TradingBox
return signalOnCandles.Single();
}
signalOnCandles = signalOnCandles.OrderBy(s => s.Date).ToHashSet();
// Optimized: Sort only if needed, then convert to HashSet
var orderedSignals = signalOnCandles.OrderBy(s => s.Date).ToList();
signalOnCandles = new HashSet<LightSignal>(orderedSignals);
// Check if all strategies produced signals - this is required for composite signals
var strategyNames = scenario.Indicators.Select(s => s.Name).ToHashSet();