Improve perf for backtests
This commit is contained in:
@@ -30,8 +30,7 @@ public class ChandelierExitIndicatorBase : IndicatorBase
|
||||
|
||||
try
|
||||
{
|
||||
GetSignals(ChandelierType.Long, candles);
|
||||
GetSignals(ChandelierType.Short, candles);
|
||||
ProcessChandelierSignals(candles);
|
||||
|
||||
return Signals.Where(s => s.Confidence != Confidence.None).OrderBy(s => s.Date).ToList();
|
||||
}
|
||||
@@ -41,6 +40,77 @@ public class ChandelierExitIndicatorBase : IndicatorBase
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runs the indicator using pre-calculated Chandelier values for performance optimization.
|
||||
/// </summary>
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
{
|
||||
if (candles.Count <= MinimumHistory)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Use pre-calculated Chandelier values if available
|
||||
List<ChandelierResult> chandelierLong = null;
|
||||
List<ChandelierResult> chandelierShort = null;
|
||||
if (preCalculatedValues?.ChandelierLong != null && preCalculatedValues.ChandelierLong.Any() &&
|
||||
preCalculatedValues?.ChandelierShort != null && preCalculatedValues.ChandelierShort.Any())
|
||||
{
|
||||
// Filter pre-calculated Chandelier values to match the candles we're processing
|
||||
chandelierLong = preCalculatedValues.ChandelierLong
|
||||
.Where(c => c.ChandelierExit.HasValue && candles.Any(candle => candle.Date == c.Date))
|
||||
.OrderBy(c => c.Date)
|
||||
.ToList();
|
||||
chandelierShort = preCalculatedValues.ChandelierShort
|
||||
.Where(c => c.ChandelierExit.HasValue && candles.Any(candle => candle.Date == c.Date))
|
||||
.OrderBy(c => c.Date)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
// If no pre-calculated values or they don't match, fall back to regular calculation
|
||||
if (chandelierLong == null || !chandelierLong.Any() || chandelierShort == null || !chandelierShort.Any())
|
||||
{
|
||||
return Run(candles);
|
||||
}
|
||||
|
||||
ProcessChandelierSignalsWithPreCalculated(chandelierLong, chandelierShort, candles);
|
||||
|
||||
return Signals.Where(s => s.Confidence != Confidence.None).OrderBy(s => s.Date).ToList();
|
||||
}
|
||||
catch (RuleException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes Chandelier signals for both Long and Short types.
|
||||
/// This method is shared between the regular Run() and optimized Run() methods.
|
||||
/// </summary>
|
||||
/// <param name="candles">Candles to process</param>
|
||||
private void ProcessChandelierSignals(HashSet<Candle> candles)
|
||||
{
|
||||
GetSignals(ChandelierType.Long, candles);
|
||||
GetSignals(ChandelierType.Short, candles);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes Chandelier signals using pre-calculated values.
|
||||
/// </summary>
|
||||
/// <param name="chandelierLong">Pre-calculated Long Chandelier values</param>
|
||||
/// <param name="chandelierShort">Pre-calculated Short Chandelier values</param>
|
||||
/// <param name="candles">Candles to process</param>
|
||||
private void ProcessChandelierSignalsWithPreCalculated(
|
||||
List<ChandelierResult> chandelierLong,
|
||||
List<ChandelierResult> chandelierShort,
|
||||
HashSet<Candle> candles)
|
||||
{
|
||||
GetSignalsWithPreCalculated(ChandelierType.Long, chandelierLong, candles);
|
||||
GetSignalsWithPreCalculated(ChandelierType.Short, chandelierShort, candles);
|
||||
}
|
||||
|
||||
public override IndicatorsResultBase GetIndicatorValues(HashSet<Candle> candles)
|
||||
{
|
||||
return new IndicatorsResultBase()
|
||||
@@ -54,9 +124,28 @@ public class ChandelierExitIndicatorBase : IndicatorBase
|
||||
{
|
||||
var chandelier = candles.GetChandelier(Period.Value, Multiplier.Value, chandelierType)
|
||||
.Where(s => s.ChandelierExit.HasValue).ToList();
|
||||
var chandelierCandle = MapChandelierToCandle(chandelier, candles.TakeLast(MinimumHistory));
|
||||
var previousCandle = chandelierCandle[0];
|
||||
ProcessChandelierSignalsForType(chandelier, chandelierType, candles);
|
||||
}
|
||||
|
||||
private void GetSignalsWithPreCalculated(ChandelierType chandelierType, List<ChandelierResult> chandelier, HashSet<Candle> candles)
|
||||
{
|
||||
ProcessChandelierSignalsForType(chandelier, chandelierType, candles);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes Chandelier signals for a specific type (Long or Short).
|
||||
/// This method is shared between regular and optimized signal processing.
|
||||
/// </summary>
|
||||
/// <param name="chandelier">Chandelier calculation results</param>
|
||||
/// <param name="chandelierType">Type of Chandelier (Long or Short)</param>
|
||||
/// <param name="candles">Candles to process</param>
|
||||
private void ProcessChandelierSignalsForType(List<ChandelierResult> chandelier, ChandelierType chandelierType, HashSet<Candle> candles)
|
||||
{
|
||||
var chandelierCandle = MapChandelierToCandle(chandelier, candles.TakeLast(MinimumHistory));
|
||||
if (chandelierCandle.Count == 0)
|
||||
return;
|
||||
|
||||
var previousCandle = chandelierCandle[0];
|
||||
foreach (var currentCandle in chandelierCandle.Skip(1))
|
||||
{
|
||||
// Short
|
||||
|
||||
Reference in New Issue
Block a user