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:
@@ -5,6 +5,7 @@ using Managing.Domain.Bots;
|
||||
using Managing.Domain.Indicators;
|
||||
using Managing.Domain.Trades;
|
||||
using Managing.Domain.Users;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Domain.Backtests;
|
||||
|
||||
@@ -65,7 +66,7 @@ public class Backtest
|
||||
Timeframe = Config.Timeframe,
|
||||
IsForWatchingOnly = false, // Always start as active bot
|
||||
BotTradingBalance = initialTradingBalance,
|
||||
IsForBacktest = false, // Always false for live bots
|
||||
TradingType = TradingType.Futures, // Always Futures for live bots
|
||||
CooldownPeriod = Config.CooldownPeriod,
|
||||
MaxLossStreak = Config.MaxLossStreak,
|
||||
MaxPositionTimeHours = Config.MaxPositionTimeHours, // Properly copy nullable value
|
||||
@@ -99,7 +100,7 @@ public class Backtest
|
||||
Timeframe = Config.Timeframe,
|
||||
IsForWatchingOnly = Config.IsForWatchingOnly,
|
||||
BotTradingBalance = balance,
|
||||
IsForBacktest = true,
|
||||
TradingType = TradingType.BacktestFutures,
|
||||
CooldownPeriod = Config.CooldownPeriod,
|
||||
MaxLossStreak = Config.MaxLossStreak,
|
||||
MaxPositionTimeHours = Config.MaxPositionTimeHours,
|
||||
|
||||
@@ -21,7 +21,7 @@ public class TradingBotConfig
|
||||
|
||||
[Id(5)] [Required] public decimal BotTradingBalance { get; set; }
|
||||
|
||||
[Id(6)] [Required] public bool IsForBacktest { get; set; }
|
||||
[Id(6)] [Required] public TradingType TradingType { get; set; }
|
||||
|
||||
[Id(7)] [Required] public int CooldownPeriod { get; set; }
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ public abstract class BollingerBandsBase : IndicatorBase
|
||||
StDev = stdev;
|
||||
}
|
||||
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
if (candles.Count <= Period)
|
||||
{
|
||||
@@ -45,7 +45,7 @@ public abstract class BollingerBandsBase : IndicatorBase
|
||||
}
|
||||
}
|
||||
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
{
|
||||
if (candles.Count <= Period)
|
||||
{
|
||||
@@ -81,7 +81,7 @@ public abstract class BollingerBandsBase : IndicatorBase
|
||||
}
|
||||
}
|
||||
|
||||
public override IndicatorsResultBase GetIndicatorValues(HashSet<Candle> candles)
|
||||
public override IndicatorsResultBase GetIndicatorValues(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
return new IndicatorsResultBase()
|
||||
{
|
||||
@@ -93,7 +93,7 @@ public abstract class BollingerBandsBase : IndicatorBase
|
||||
/// <summary>
|
||||
/// Abstract method for processing Bollinger Bands signals - implemented by child classes
|
||||
/// </summary>
|
||||
protected abstract void ProcessBollingerBandsSignals(List<BollingerBandsResult> bbResults, HashSet<Candle> candles);
|
||||
protected abstract void ProcessBollingerBandsSignals(List<BollingerBandsResult> bbResults, IReadOnlyList<Candle> candles);
|
||||
|
||||
/// <summary>
|
||||
/// Maps Bollinger Bands results to candle objects with all BollingerBandsResult properties
|
||||
|
||||
@@ -20,7 +20,7 @@ public class BollingerBandsVolatilityProtection : BollingerBandsBase
|
||||
/// </summary>
|
||||
/// <param name="bbResults">List of Bollinger Bands calculation results</param>
|
||||
/// <param name="candles">Candles to process</param>
|
||||
protected override void ProcessBollingerBandsSignals(List<BollingerBandsResult> bbResults, HashSet<Candle> candles)
|
||||
protected override void ProcessBollingerBandsSignals(List<BollingerBandsResult> bbResults, IReadOnlyList<Candle> candles)
|
||||
{
|
||||
var bbCandles = MapBollingerBandsToCandle(bbResults, candles.TakeLast(Period.Value)).ToList();
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ public class StDevContext : IndicatorBase
|
||||
Period = period;
|
||||
}
|
||||
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
if (candles.Count <= Period)
|
||||
{
|
||||
@@ -44,7 +44,7 @@ public class StDevContext : IndicatorBase
|
||||
/// <summary>
|
||||
/// Runs the indicator using pre-calculated StdDev values for performance optimization.
|
||||
/// </summary>
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
{
|
||||
if (candles.Count <= Period)
|
||||
{
|
||||
@@ -85,7 +85,7 @@ public class StDevContext : IndicatorBase
|
||||
/// </summary>
|
||||
/// <param name="stDev">List of StdDev calculation results</param>
|
||||
/// <param name="candles">Candles to process</param>
|
||||
private void ProcessStDevSignals(List<StdDevResult> stDev, HashSet<Candle> candles)
|
||||
private void ProcessStDevSignals(List<StdDevResult> stDev, IReadOnlyList<Candle> candles)
|
||||
{
|
||||
var stDevCandles = MapStDev(stDev, candles.TakeLast(Period.Value));
|
||||
|
||||
@@ -126,7 +126,7 @@ public class StDevContext : IndicatorBase
|
||||
AddSignal(lastCandle, TradeDirection.None, confidence);
|
||||
}
|
||||
|
||||
public override IndicatorsResultBase GetIndicatorValues(HashSet<Candle> candles)
|
||||
public override IndicatorsResultBase GetIndicatorValues(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
var test = new IndicatorsResultBase()
|
||||
{
|
||||
|
||||
@@ -21,17 +21,17 @@ namespace Managing.Domain.Strategies
|
||||
double? KFactor { get; set; }
|
||||
double? DFactor { get; set; }
|
||||
|
||||
List<LightSignal> Run(HashSet<Candle> candles);
|
||||
List<LightSignal> Run(IReadOnlyList<Candle> candles);
|
||||
|
||||
/// <summary>
|
||||
/// Runs the indicator using pre-calculated indicator values for performance optimization.
|
||||
/// If pre-calculated values are not available or not applicable, falls back to regular Run().
|
||||
/// </summary>
|
||||
/// <param name="candles">The candles to process</param>
|
||||
/// <param name="candles">The candles to process (must be ordered chronologically)</param>
|
||||
/// <param name="preCalculatedValues">Pre-calculated indicator values (optional)</param>
|
||||
/// <returns>List of signals generated by the indicator</returns>
|
||||
List<LightSignal> Run(HashSet<Candle> candles, IndicatorsResultBase preCalculatedValues);
|
||||
List<LightSignal> Run(IReadOnlyList<Candle> candles, IndicatorsResultBase preCalculatedValues);
|
||||
|
||||
IndicatorsResultBase GetIndicatorValues(HashSet<Candle> candles);
|
||||
IndicatorsResultBase GetIndicatorValues(IReadOnlyList<Candle> candles);
|
||||
}
|
||||
}
|
||||
@@ -55,7 +55,7 @@ namespace Managing.Domain.Strategies
|
||||
|
||||
public User User { get; set; }
|
||||
|
||||
public virtual List<LightSignal> Run(HashSet<Candle> candles)
|
||||
public virtual List<LightSignal> Run(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
@@ -64,14 +64,16 @@ namespace Managing.Domain.Strategies
|
||||
/// Runs the indicator using pre-calculated values if available, otherwise falls back to regular Run().
|
||||
/// Default implementation falls back to regular Run() - override in derived classes to use pre-calculated values.
|
||||
/// </summary>
|
||||
public virtual List<LightSignal> Run(HashSet<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
/// <param name="candles">The candles to process (must be ordered chronologically)</param>
|
||||
/// <param name="preCalculatedValues">Pre-calculated indicator values (optional)</param>
|
||||
public virtual List<LightSignal> Run(IReadOnlyList<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
{
|
||||
// Default implementation: ignore pre-calculated values and use regular Run()
|
||||
// Derived classes should override this to use pre-calculated values for performance
|
||||
return Run(candles);
|
||||
}
|
||||
|
||||
public virtual IndicatorsResultBase GetIndicatorValues(HashSet<Candle> candles)
|
||||
public virtual IndicatorsResultBase GetIndicatorValues(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ public class BollingerBandsPercentBMomentumBreakout : BollingerBandsBase
|
||||
/// Long signals: %B crosses above 0.8 after being below (strong upward momentum)
|
||||
/// Short signals: %B crosses below 0.2 after being above (strong downward momentum)
|
||||
/// </summary>
|
||||
protected override void ProcessBollingerBandsSignals(List<BollingerBandsResult> bbResults, HashSet<Candle> candles)
|
||||
protected override void ProcessBollingerBandsSignals(List<BollingerBandsResult> bbResults, IReadOnlyList<Candle> candles)
|
||||
{
|
||||
var bbCandles = MapBollingerBandsToCandle(bbResults, candles.TakeLast(Period.Value)).ToList();
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ public class ChandelierExitIndicatorBase : IndicatorBase
|
||||
MinimumHistory = 1 + Period.Value;
|
||||
}
|
||||
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
if (candles.Count <= MinimumHistory)
|
||||
{
|
||||
@@ -43,7 +43,7 @@ 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)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
{
|
||||
if (candles.Count <= MinimumHistory)
|
||||
{
|
||||
@@ -88,7 +88,7 @@ public class ChandelierExitIndicatorBase : IndicatorBase
|
||||
/// 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)
|
||||
private void ProcessChandelierSignals(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
GetSignals(ChandelierType.Long, candles);
|
||||
GetSignals(ChandelierType.Short, candles);
|
||||
@@ -103,13 +103,13 @@ public class ChandelierExitIndicatorBase : IndicatorBase
|
||||
private void ProcessChandelierSignalsWithPreCalculated(
|
||||
List<ChandelierResult> chandelierLong,
|
||||
List<ChandelierResult> chandelierShort,
|
||||
HashSet<Candle> candles)
|
||||
IReadOnlyList<Candle> candles)
|
||||
{
|
||||
GetSignalsWithPreCalculated(ChandelierType.Long, chandelierLong, candles);
|
||||
GetSignalsWithPreCalculated(ChandelierType.Short, chandelierShort, candles);
|
||||
}
|
||||
|
||||
public override IndicatorsResultBase GetIndicatorValues(HashSet<Candle> candles)
|
||||
public override IndicatorsResultBase GetIndicatorValues(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
return new IndicatorsResultBase()
|
||||
{
|
||||
@@ -118,7 +118,7 @@ public class ChandelierExitIndicatorBase : IndicatorBase
|
||||
};
|
||||
}
|
||||
|
||||
private void GetSignals(ChandelierType chandelierType, HashSet<Candle> candles)
|
||||
private void GetSignals(ChandelierType chandelierType, IReadOnlyList<Candle> candles)
|
||||
{
|
||||
var chandelier = candles.GetChandelier(Period.Value, Multiplier.Value, chandelierType)
|
||||
.Where(s => s.ChandelierExit.HasValue).ToList();
|
||||
@@ -126,7 +126,7 @@ public class ChandelierExitIndicatorBase : IndicatorBase
|
||||
}
|
||||
|
||||
private void GetSignalsWithPreCalculated(ChandelierType chandelierType, List<ChandelierResult> chandelier,
|
||||
HashSet<Candle> candles)
|
||||
IReadOnlyList<Candle> candles)
|
||||
{
|
||||
ProcessChandelierSignalsForType(chandelier, chandelierType, candles);
|
||||
}
|
||||
@@ -139,7 +139,7 @@ public class ChandelierExitIndicatorBase : IndicatorBase
|
||||
/// <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)
|
||||
IReadOnlyList<Candle> candles)
|
||||
{
|
||||
var chandelierCandle = MapChandelierToCandle(chandelier, candles.TakeLast(MinimumHistory));
|
||||
if (chandelierCandle.Count == 0)
|
||||
|
||||
@@ -21,7 +21,7 @@ public class DualEmaCrossIndicatorBase : EmaBaseIndicatorBase
|
||||
MinimumHistory = Math.Max(fastPeriod, slowPeriod) * 2;
|
||||
}
|
||||
|
||||
public override IndicatorsResultBase GetIndicatorValues(HashSet<Candle> candles)
|
||||
public override IndicatorsResultBase GetIndicatorValues(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
return new IndicatorsResultBase()
|
||||
{
|
||||
@@ -30,7 +30,7 @@ public class DualEmaCrossIndicatorBase : EmaBaseIndicatorBase
|
||||
};
|
||||
}
|
||||
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
if (candles.Count <= MinimumHistory)
|
||||
{
|
||||
@@ -58,7 +58,7 @@ public class DualEmaCrossIndicatorBase : EmaBaseIndicatorBase
|
||||
/// <summary>
|
||||
/// Runs the indicator using pre-calculated EMA values for performance optimization.
|
||||
/// </summary>
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
{
|
||||
if (candles.Count <= MinimumHistory)
|
||||
{
|
||||
@@ -105,7 +105,7 @@ public class DualEmaCrossIndicatorBase : EmaBaseIndicatorBase
|
||||
/// <param name="fastEma">List of Fast EMA calculation results</param>
|
||||
/// <param name="slowEma">List of Slow EMA calculation results</param>
|
||||
/// <param name="candles">Candles to process</param>
|
||||
private void ProcessDualEmaCrossSignals(List<EmaResult> fastEma, List<EmaResult> slowEma, HashSet<Candle> candles)
|
||||
private void ProcessDualEmaCrossSignals(List<EmaResult> fastEma, List<EmaResult> slowEma, IReadOnlyList<Candle> candles)
|
||||
{
|
||||
var dualEmaCandles = MapDualEmaToCandle(fastEma, slowEma, candles.TakeLast(MinimumHistory));
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ public class EmaCrossIndicator : EmaBaseIndicatorBase
|
||||
Period = period;
|
||||
}
|
||||
|
||||
public override IndicatorsResultBase GetIndicatorValues(HashSet<Candle> candles)
|
||||
public override IndicatorsResultBase GetIndicatorValues(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
return new IndicatorsResultBase()
|
||||
{
|
||||
@@ -26,7 +26,7 @@ public class EmaCrossIndicator : EmaBaseIndicatorBase
|
||||
};
|
||||
}
|
||||
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
if (candles.Count <= Period)
|
||||
{
|
||||
@@ -52,7 +52,7 @@ public class EmaCrossIndicator : EmaBaseIndicatorBase
|
||||
/// <summary>
|
||||
/// Runs the indicator using pre-calculated EMA values for performance optimization.
|
||||
/// </summary>
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
{
|
||||
if (candles.Count <= Period)
|
||||
{
|
||||
@@ -93,7 +93,7 @@ public class EmaCrossIndicator : EmaBaseIndicatorBase
|
||||
/// </summary>
|
||||
/// <param name="ema">List of EMA calculation results</param>
|
||||
/// <param name="candles">Candles to process</param>
|
||||
private void ProcessEmaCrossSignals(List<EmaResult> ema, HashSet<Candle> candles)
|
||||
private void ProcessEmaCrossSignals(List<EmaResult> ema, IReadOnlyList<Candle> candles)
|
||||
{
|
||||
var emaCandles = MapEmaToCandle(ema, candles.TakeLast(Period.Value));
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ public class EmaCrossIndicatorBase : EmaBaseIndicatorBase
|
||||
Period = period;
|
||||
}
|
||||
|
||||
public override IndicatorsResultBase GetIndicatorValues(HashSet<Candle> candles)
|
||||
public override IndicatorsResultBase GetIndicatorValues(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
return new IndicatorsResultBase()
|
||||
{
|
||||
@@ -26,7 +26,7 @@ public class EmaCrossIndicatorBase : EmaBaseIndicatorBase
|
||||
};
|
||||
}
|
||||
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
if (candles.Count <= Period)
|
||||
{
|
||||
@@ -52,7 +52,7 @@ public class EmaCrossIndicatorBase : EmaBaseIndicatorBase
|
||||
/// <summary>
|
||||
/// Runs the indicator using pre-calculated EMA values for performance optimization.
|
||||
/// </summary>
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
{
|
||||
if (candles.Count <= Period)
|
||||
{
|
||||
@@ -93,7 +93,7 @@ public class EmaCrossIndicatorBase : EmaBaseIndicatorBase
|
||||
/// </summary>
|
||||
/// <param name="ema">List of EMA calculation results</param>
|
||||
/// <param name="candles">Candles to process</param>
|
||||
private void ProcessEmaCrossSignals(List<EmaResult> ema, HashSet<Candle> candles)
|
||||
private void ProcessEmaCrossSignals(List<EmaResult> ema, IReadOnlyList<Candle> candles)
|
||||
{
|
||||
var emaCandles = MapEmaToCandle(ema, candles.TakeLast(Period.Value).ToHashSet());
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ public class LaggingSTC : IndicatorBase
|
||||
CyclePeriods = cyclePeriods;
|
||||
}
|
||||
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
if (candles.Count <= 2 * (SlowPeriods + CyclePeriods))
|
||||
{
|
||||
@@ -54,7 +54,7 @@ public class LaggingSTC : IndicatorBase
|
||||
/// <summary>
|
||||
/// Runs the indicator using pre-calculated STC values for performance optimization.
|
||||
/// </summary>
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
{
|
||||
if (candles.Count <= 2 * (SlowPeriods + CyclePeriods))
|
||||
{
|
||||
@@ -95,7 +95,7 @@ public class LaggingSTC : IndicatorBase
|
||||
/// </summary>
|
||||
/// <param name="stc">List of STC calculation results</param>
|
||||
/// <param name="candles">Candles to process</param>
|
||||
private void ProcessLaggingStcSignals(List<StcResult> stc, HashSet<Candle> candles)
|
||||
private void ProcessLaggingStcSignals(List<StcResult> stc, IReadOnlyList<Candle> candles)
|
||||
{
|
||||
var stcCandles = MapStcToCandle(stc, candles.TakeLast(CyclePeriods.Value * 3));
|
||||
|
||||
@@ -142,7 +142,7 @@ public class LaggingSTC : IndicatorBase
|
||||
}
|
||||
}
|
||||
|
||||
public override IndicatorsResultBase GetIndicatorValues(HashSet<Candle> candles)
|
||||
public override IndicatorsResultBase GetIndicatorValues(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
var stc = candles.GetStc(FastPeriods.Value, FastPeriods.Value, SlowPeriods.Value).ToList();
|
||||
return new IndicatorsResultBase
|
||||
|
||||
@@ -21,7 +21,7 @@ public class MacdCrossIndicatorBase : IndicatorBase
|
||||
SignalPeriods = signalPeriods;
|
||||
}
|
||||
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
if (candles.Count <= 2 * (SlowPeriods + SignalPeriods))
|
||||
{
|
||||
@@ -47,7 +47,7 @@ public class MacdCrossIndicatorBase : IndicatorBase
|
||||
/// <summary>
|
||||
/// Runs the indicator using pre-calculated MACD values for performance optimization.
|
||||
/// </summary>
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
{
|
||||
if (candles.Count <= 2 * (SlowPeriods + SignalPeriods))
|
||||
{
|
||||
@@ -88,7 +88,7 @@ public class MacdCrossIndicatorBase : IndicatorBase
|
||||
/// </summary>
|
||||
/// <param name="macd">List of MACD calculation results</param>
|
||||
/// <param name="candles">Candles to process</param>
|
||||
private void ProcessMacdSignals(List<MacdResult> macd, HashSet<Candle> candles)
|
||||
private void ProcessMacdSignals(List<MacdResult> macd, IReadOnlyList<Candle> candles)
|
||||
{
|
||||
var macdCandle = MapMacdToCandle(macd, candles.TakeLast(SignalPeriods.Value));
|
||||
|
||||
@@ -114,7 +114,7 @@ public class MacdCrossIndicatorBase : IndicatorBase
|
||||
}
|
||||
}
|
||||
|
||||
public override IndicatorsResultBase GetIndicatorValues(HashSet<Candle> candles)
|
||||
public override IndicatorsResultBase GetIndicatorValues(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
return new IndicatorsResultBase()
|
||||
{
|
||||
|
||||
@@ -22,7 +22,7 @@ public class RsiDivergenceConfirmIndicatorBase : IndicatorBase
|
||||
/// Get RSI signals
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
if (candles.Count <= Period)
|
||||
{
|
||||
@@ -48,7 +48,7 @@ public class RsiDivergenceConfirmIndicatorBase : IndicatorBase
|
||||
/// <summary>
|
||||
/// Runs the indicator using pre-calculated RSI values for performance optimization.
|
||||
/// </summary>
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
{
|
||||
if (candles.Count <= Period)
|
||||
{
|
||||
@@ -90,7 +90,7 @@ public class RsiDivergenceConfirmIndicatorBase : IndicatorBase
|
||||
/// </summary>
|
||||
/// <param name="rsiResult">List of RSI calculation results</param>
|
||||
/// <param name="candles">Candles to process</param>
|
||||
private void ProcessRsiDivergenceConfirmSignals(List<RsiResult> rsiResult, HashSet<Candle> candles)
|
||||
private void ProcessRsiDivergenceConfirmSignals(List<RsiResult> rsiResult, IReadOnlyList<Candle> candles)
|
||||
{
|
||||
var candlesRsi = MapRsiToCandle(rsiResult, candles.TakeLast(10 * Period.Value));
|
||||
|
||||
@@ -101,7 +101,7 @@ public class RsiDivergenceConfirmIndicatorBase : IndicatorBase
|
||||
GetShortSignals(candlesRsi, candles);
|
||||
}
|
||||
|
||||
public override IndicatorsResultBase GetIndicatorValues(HashSet<Candle> candles)
|
||||
public override IndicatorsResultBase GetIndicatorValues(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
return new IndicatorsResultBase()
|
||||
{
|
||||
@@ -109,7 +109,7 @@ public class RsiDivergenceConfirmIndicatorBase : IndicatorBase
|
||||
};
|
||||
}
|
||||
|
||||
private void GetLongSignals(List<CandleRsi> candlesRsi, HashSet<Candle> candles)
|
||||
private void GetLongSignals(List<CandleRsi> candlesRsi, IReadOnlyList<Candle> candles)
|
||||
{
|
||||
// Set the low and high for first candle
|
||||
var firstCandleRsi = candlesRsi.First(c => c.Rsi > 0);
|
||||
@@ -182,7 +182,7 @@ public class RsiDivergenceConfirmIndicatorBase : IndicatorBase
|
||||
}
|
||||
}
|
||||
|
||||
private void GetShortSignals(List<CandleRsi> candlesRsi, HashSet<Candle> candles)
|
||||
private void GetShortSignals(List<CandleRsi> candlesRsi, IReadOnlyList<Candle> candles)
|
||||
{
|
||||
// Set the low and high for first candle
|
||||
var firstCandleRsi = candlesRsi.First(c => c.Rsi > 0);
|
||||
@@ -256,7 +256,7 @@ public class RsiDivergenceConfirmIndicatorBase : IndicatorBase
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckIfConfimation(CandleRsi currentCandle, TradeDirection direction, HashSet<Candle> candles)
|
||||
private void CheckIfConfimation(CandleRsi currentCandle, TradeDirection direction, IReadOnlyList<Candle> candles)
|
||||
{
|
||||
var lastCandleOnPeriod = candles.TakeLast(Period.Value).ToList();
|
||||
var signalsOnPeriod = Signals.Where(s => s.Date >= lastCandleOnPeriod[0].Date
|
||||
|
||||
@@ -25,7 +25,7 @@ public class RsiDivergenceIndicatorBase : IndicatorBase
|
||||
/// Get RSI signals
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
if (!Period.HasValue || candles.Count <= Period)
|
||||
{
|
||||
@@ -51,7 +51,7 @@ public class RsiDivergenceIndicatorBase : IndicatorBase
|
||||
/// <summary>
|
||||
/// Runs the indicator using pre-calculated RSI values for performance optimization.
|
||||
/// </summary>
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
{
|
||||
if (!Period.HasValue || candles.Count <= Period)
|
||||
{
|
||||
@@ -93,7 +93,7 @@ public class RsiDivergenceIndicatorBase : IndicatorBase
|
||||
/// </summary>
|
||||
/// <param name="rsiResult">List of RSI calculation results</param>
|
||||
/// <param name="candles">Candles to process</param>
|
||||
private void ProcessRsiDivergenceSignals(List<RsiResult> rsiResult, HashSet<Candle> candles)
|
||||
private void ProcessRsiDivergenceSignals(List<RsiResult> rsiResult, IReadOnlyList<Candle> candles)
|
||||
{
|
||||
var candlesRsi = MapRsiToCandle(rsiResult, candles.TakeLast(10 * Period.Value));
|
||||
|
||||
@@ -104,7 +104,7 @@ public class RsiDivergenceIndicatorBase : IndicatorBase
|
||||
GetShortSignals(candlesRsi, candles);
|
||||
}
|
||||
|
||||
public override IndicatorsResultBase GetIndicatorValues(HashSet<Candle> candles)
|
||||
public override IndicatorsResultBase GetIndicatorValues(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
return new IndicatorsResultBase()
|
||||
{
|
||||
@@ -112,7 +112,7 @@ public class RsiDivergenceIndicatorBase : IndicatorBase
|
||||
};
|
||||
}
|
||||
|
||||
private void GetLongSignals(List<CandleRsi> candlesRsi, HashSet<Candle> candles)
|
||||
private void GetLongSignals(List<CandleRsi> candlesRsi, IReadOnlyList<Candle> candles)
|
||||
{
|
||||
// Set the low and high for first candle
|
||||
var firstCandleRsi = candlesRsi.First(c => c.Rsi > 0);
|
||||
@@ -183,7 +183,7 @@ public class RsiDivergenceIndicatorBase : IndicatorBase
|
||||
}
|
||||
}
|
||||
|
||||
private void GetShortSignals(List<CandleRsi> candlesRsi, HashSet<Candle> candles)
|
||||
private void GetShortSignals(List<CandleRsi> candlesRsi, IReadOnlyList<Candle> candles)
|
||||
{
|
||||
// Set the low and high for first candle
|
||||
var firstCandleRsi = candlesRsi.First(c => c.Rsi > 0);
|
||||
@@ -255,7 +255,7 @@ public class RsiDivergenceIndicatorBase : IndicatorBase
|
||||
}
|
||||
}
|
||||
|
||||
private void AddSignal(CandleRsi candleSignal, TradeDirection direction, HashSet<Candle> candles)
|
||||
private void AddSignal(CandleRsi candleSignal, TradeDirection direction, IReadOnlyList<Candle> candles)
|
||||
{
|
||||
var signal = new LightSignal(candleSignal.Ticker, direction, Confidence.Low,
|
||||
candleSignal, candleSignal.Date, candleSignal.Exchange, Type, SignalType, Name);
|
||||
|
||||
@@ -21,7 +21,7 @@ public class StcIndicatorBase : IndicatorBase
|
||||
CyclePeriods = cyclePeriods;
|
||||
}
|
||||
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
if (candles.Count <= 2 * (SlowPeriods + CyclePeriods))
|
||||
{
|
||||
@@ -50,7 +50,7 @@ public class StcIndicatorBase : IndicatorBase
|
||||
/// <summary>
|
||||
/// Runs the indicator using pre-calculated STC values for performance optimization.
|
||||
/// </summary>
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
{
|
||||
if (candles.Count <= 2 * (SlowPeriods + CyclePeriods))
|
||||
{
|
||||
@@ -85,7 +85,7 @@ public class StcIndicatorBase : IndicatorBase
|
||||
}
|
||||
}
|
||||
|
||||
public override IndicatorsResultBase GetIndicatorValues(HashSet<Candle> candles)
|
||||
public override IndicatorsResultBase GetIndicatorValues(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
if (FastPeriods != null && SlowPeriods != null)
|
||||
{
|
||||
@@ -105,7 +105,7 @@ public class StcIndicatorBase : IndicatorBase
|
||||
/// </summary>
|
||||
/// <param name="stc">List of STC calculation results</param>
|
||||
/// <param name="candles">Candles to process</param>
|
||||
private void ProcessStcSignals(List<StcResult> stc, HashSet<Candle> candles)
|
||||
private void ProcessStcSignals(List<StcResult> stc, IReadOnlyList<Candle> candles)
|
||||
{
|
||||
if (CyclePeriods == null)
|
||||
return;
|
||||
|
||||
@@ -28,7 +28,7 @@ public class StochasticCrossIndicator : IndicatorBase
|
||||
DFactor = dFactor;
|
||||
}
|
||||
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
if (candles.Count <= 10 * StochPeriods.Value + 50)
|
||||
{
|
||||
@@ -55,7 +55,7 @@ public class StochasticCrossIndicator : IndicatorBase
|
||||
}
|
||||
}
|
||||
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
{
|
||||
if (candles.Count <= 10 * StochPeriods.Value + 50)
|
||||
{
|
||||
@@ -95,7 +95,7 @@ public class StochasticCrossIndicator : IndicatorBase
|
||||
/// Long signals: %K crosses above %D when both lines are below 20 (oversold)
|
||||
/// Short signals: %K crosses below %D when both lines are above 80 (overbought)
|
||||
/// </summary>
|
||||
private void ProcessStochasticSignals(List<StochResult> stochResults, HashSet<Candle> candles)
|
||||
private void ProcessStochasticSignals(List<StochResult> stochResults, IReadOnlyList<Candle> candles)
|
||||
{
|
||||
var stochCandles = MapStochToCandle(stochResults, candles.TakeLast(StochPeriods.Value));
|
||||
|
||||
@@ -132,7 +132,7 @@ public class StochasticCrossIndicator : IndicatorBase
|
||||
}
|
||||
}
|
||||
|
||||
public override IndicatorsResultBase GetIndicatorValues(HashSet<Candle> candles)
|
||||
public override IndicatorsResultBase GetIndicatorValues(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
return new IndicatorsResultBase()
|
||||
{
|
||||
|
||||
@@ -20,7 +20,7 @@ public class SuperTrendCrossEma : IndicatorBase
|
||||
MinimumHistory = 100 + Period.Value;
|
||||
}
|
||||
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
// Validate sufficient historical data for all indicators
|
||||
const int emaPeriod = 50;
|
||||
@@ -89,7 +89,7 @@ public class SuperTrendCrossEma : IndicatorBase
|
||||
/// Runs the indicator using pre-calculated SuperTrend values for performance optimization.
|
||||
/// Note: EMA50 and ADX are still calculated on-the-fly as they're not part of the standard indicator values.
|
||||
/// </summary>
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
{
|
||||
// Validate sufficient historical data for all indicators
|
||||
const int emaPeriod = 50;
|
||||
@@ -157,7 +157,7 @@ public class SuperTrendCrossEma : IndicatorBase
|
||||
List<SuperTrendResult> superTrend,
|
||||
List<EmaResult> ema50,
|
||||
List<AdxResult> adxResults,
|
||||
HashSet<Candle> candles,
|
||||
IReadOnlyList<Candle> candles,
|
||||
int minimumRequiredHistory,
|
||||
int adxThreshold)
|
||||
{
|
||||
@@ -237,7 +237,7 @@ public class SuperTrendCrossEma : IndicatorBase
|
||||
}
|
||||
}
|
||||
|
||||
public override IndicatorsResultBase GetIndicatorValues(HashSet<Candle> candles)
|
||||
public override IndicatorsResultBase GetIndicatorValues(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
return new IndicatorsResultBase()
|
||||
{
|
||||
|
||||
@@ -20,7 +20,7 @@ public class SuperTrendIndicatorBase : IndicatorBase
|
||||
MinimumHistory = 100 + Period.Value;
|
||||
}
|
||||
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
if (candles.Count <= MinimumHistory)
|
||||
{
|
||||
@@ -48,7 +48,7 @@ public class SuperTrendIndicatorBase : IndicatorBase
|
||||
/// <summary>
|
||||
/// Runs the indicator using pre-calculated SuperTrend values for performance optimization.
|
||||
/// </summary>
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
{
|
||||
if (candles.Count <= MinimumHistory)
|
||||
{
|
||||
@@ -89,7 +89,7 @@ public class SuperTrendIndicatorBase : IndicatorBase
|
||||
/// </summary>
|
||||
/// <param name="superTrend">List of SuperTrend calculation results</param>
|
||||
/// <param name="candles">Candles to process</param>
|
||||
private void ProcessSuperTrendSignals(List<SuperTrendResult> superTrend, HashSet<Candle> candles)
|
||||
private void ProcessSuperTrendSignals(List<SuperTrendResult> superTrend, IReadOnlyList<Candle> candles)
|
||||
{
|
||||
var superTrendCandle = MapSuperTrendToCandle(superTrend, candles.TakeLast(MinimumHistory));
|
||||
|
||||
@@ -112,7 +112,7 @@ public class SuperTrendIndicatorBase : IndicatorBase
|
||||
}
|
||||
}
|
||||
|
||||
public override IndicatorsResultBase GetIndicatorValues(HashSet<Candle> candles)
|
||||
public override IndicatorsResultBase GetIndicatorValues(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
return new IndicatorsResultBase()
|
||||
{
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Managing.Domain.Strategies.Signals
|
||||
|
||||
public TradeDirection Direction { get; }
|
||||
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
var signals = new List<LightSignal>();
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace Managing.Domain.Strategies.Signals
|
||||
/// Note: ThreeWhiteSoldiers is a pattern-based indicator that doesn't use traditional indicator calculations,
|
||||
/// so pre-calculated values are not applicable. This method falls back to regular Run().
|
||||
/// </summary>
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
{
|
||||
// ThreeWhiteSoldiers doesn't use traditional indicators, so pre-calculated values don't apply
|
||||
// Fall back to regular calculation
|
||||
@@ -55,7 +55,7 @@ namespace Managing.Domain.Strategies.Signals
|
||||
/// This method is shared between the regular Run() and optimized Run() methods.
|
||||
/// </summary>
|
||||
/// <param name="candles">Candles to process</param>
|
||||
private void ProcessThreeWhiteSoldiersSignals(HashSet<Candle> candles)
|
||||
private void ProcessThreeWhiteSoldiersSignals(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
var lastFourCandles = candles.TakeLast(4);
|
||||
Candle previousCandles = null;
|
||||
@@ -75,7 +75,7 @@ namespace Managing.Domain.Strategies.Signals
|
||||
}
|
||||
}
|
||||
|
||||
public override IndicatorsResultBase GetIndicatorValues(HashSet<Candle> candles)
|
||||
public override IndicatorsResultBase GetIndicatorValues(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ public class EmaTrendIndicatorBase : EmaBaseIndicatorBase
|
||||
Period = period;
|
||||
}
|
||||
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
if (candles.Count <= 2 * Period)
|
||||
{
|
||||
@@ -44,7 +44,7 @@ public class EmaTrendIndicatorBase : EmaBaseIndicatorBase
|
||||
/// <summary>
|
||||
/// Runs the indicator using pre-calculated EMA values for performance optimization.
|
||||
/// </summary>
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
{
|
||||
if (candles.Count <= 2 * Period)
|
||||
{
|
||||
@@ -85,7 +85,7 @@ public class EmaTrendIndicatorBase : EmaBaseIndicatorBase
|
||||
/// </summary>
|
||||
/// <param name="ema">List of EMA calculation results</param>
|
||||
/// <param name="candles">Candles to process</param>
|
||||
private void ProcessEmaTrendSignals(List<EmaResult> ema, HashSet<Candle> candles)
|
||||
private void ProcessEmaTrendSignals(List<EmaResult> ema, IReadOnlyList<Candle> candles)
|
||||
{
|
||||
var emaCandles = MapEmaToCandle(ema, candles.TakeLast(Period.Value));
|
||||
|
||||
@@ -108,7 +108,7 @@ public class EmaTrendIndicatorBase : EmaBaseIndicatorBase
|
||||
}
|
||||
}
|
||||
|
||||
public override IndicatorsResultBase GetIndicatorValues(HashSet<Candle> candles)
|
||||
public override IndicatorsResultBase GetIndicatorValues(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
return new IndicatorsResultBase()
|
||||
{
|
||||
|
||||
@@ -30,7 +30,7 @@ public class IchimokuKumoTrend : IndicatorBase
|
||||
ChikouOffset = chikouOffset; // Separate offset for Chikou span
|
||||
}
|
||||
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
// Need at least the greater of tenkanPeriods, kijunPeriods, senkouBPeriods, and all offset periods
|
||||
var maxOffset = Math.Max(Math.Max(OffsetPeriods.Value, SenkouOffset ?? OffsetPeriods.Value), ChikouOffset ?? OffsetPeriods.Value);
|
||||
@@ -56,7 +56,7 @@ public class IchimokuKumoTrend : IndicatorBase
|
||||
}
|
||||
}
|
||||
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
{
|
||||
// Need at least the greater of tenkanPeriods, kijunPeriods, senkouBPeriods, and all offset periods
|
||||
var maxOffset = Math.Max(Math.Max(OffsetPeriods.Value, SenkouOffset ?? OffsetPeriods.Value), ChikouOffset ?? OffsetPeriods.Value);
|
||||
@@ -160,7 +160,7 @@ public class IchimokuKumoTrend : IndicatorBase
|
||||
return candleIchimokuResults;
|
||||
}
|
||||
|
||||
private void ProcessKumoTrendSignals(List<CandleIchimoku> ichimokuResults, HashSet<Candle> candles)
|
||||
private void ProcessKumoTrendSignals(List<CandleIchimoku> ichimokuResults, IReadOnlyList<Candle> candles)
|
||||
{
|
||||
var mappedData = ichimokuResults;
|
||||
|
||||
@@ -193,7 +193,7 @@ public class IchimokuKumoTrend : IndicatorBase
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessKumoTrendSignalsFromResults(List<IchimokuResult> ichimokuResults, HashSet<Candle> candles)
|
||||
private void ProcessKumoTrendSignalsFromResults(List<IchimokuResult> ichimokuResults, IReadOnlyList<Candle> candles)
|
||||
{
|
||||
if (ichimokuResults.Count == 0)
|
||||
return;
|
||||
@@ -229,7 +229,7 @@ public class IchimokuKumoTrend : IndicatorBase
|
||||
}
|
||||
}
|
||||
|
||||
public override IndicatorsResultBase GetIndicatorValues(HashSet<Candle> candles)
|
||||
public override IndicatorsResultBase GetIndicatorValues(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
IEnumerable<IchimokuResult> ichimokuResults;
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ public class StochRsiTrendIndicatorBase : IndicatorBase
|
||||
Period = period;
|
||||
}
|
||||
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
if (candles.Count <= 10 * Period + 50)
|
||||
{
|
||||
@@ -55,7 +55,7 @@ public class StochRsiTrendIndicatorBase : IndicatorBase
|
||||
/// <summary>
|
||||
/// Runs the indicator using pre-calculated StochRsi values for performance optimization.
|
||||
/// </summary>
|
||||
public override List<LightSignal> Run(HashSet<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
public override List<LightSignal> Run(IReadOnlyList<Candle> candles, IndicatorsResultBase preCalculatedValues)
|
||||
{
|
||||
if (candles.Count <= 10 * Period + 50)
|
||||
{
|
||||
@@ -96,7 +96,7 @@ public class StochRsiTrendIndicatorBase : IndicatorBase
|
||||
/// </summary>
|
||||
/// <param name="stochRsi">List of StochRsi calculation results</param>
|
||||
/// <param name="candles">Candles to process</param>
|
||||
private void ProcessStochRsiTrendSignals(List<StochRsiResult> stochRsi, HashSet<Candle> candles)
|
||||
private void ProcessStochRsiTrendSignals(List<StochRsiResult> stochRsi, IReadOnlyList<Candle> candles)
|
||||
{
|
||||
var stochRsiCandles = MapStochRsiToCandle(stochRsi, candles.TakeLast(Period.Value));
|
||||
|
||||
@@ -119,7 +119,7 @@ public class StochRsiTrendIndicatorBase : IndicatorBase
|
||||
}
|
||||
}
|
||||
|
||||
public override IndicatorsResultBase GetIndicatorValues(HashSet<Candle> candles)
|
||||
public override IndicatorsResultBase GetIndicatorValues(IReadOnlyList<Candle> candles)
|
||||
{
|
||||
return new IndicatorsResultBase()
|
||||
{
|
||||
|
||||
@@ -55,13 +55,13 @@ public static class TradingBox
|
||||
{
|
||||
private static readonly IndicatorComboConfig _defaultConfig = new();
|
||||
|
||||
public static LightSignal GetSignal(HashSet<Candle> newCandles, LightScenario scenario,
|
||||
public static LightSignal GetSignal(IReadOnlyList<Candle> newCandles, LightScenario scenario,
|
||||
Dictionary<string, LightSignal> previousSignal, int? loopbackPeriod = 1)
|
||||
{
|
||||
return GetSignal(newCandles, scenario, previousSignal, _defaultConfig, loopbackPeriod, null);
|
||||
}
|
||||
|
||||
public static LightSignal GetSignal(HashSet<Candle> newCandles, LightScenario scenario,
|
||||
public static LightSignal GetSignal(IReadOnlyList<Candle> newCandles, LightScenario scenario,
|
||||
Dictionary<string, LightSignal> previousSignal, int? loopbackPeriod,
|
||||
Dictionary<IndicatorType, IndicatorsResultBase> preCalculatedIndicatorValues)
|
||||
{
|
||||
@@ -69,13 +69,13 @@ public static class TradingBox
|
||||
preCalculatedIndicatorValues);
|
||||
}
|
||||
|
||||
public static LightSignal GetSignal(HashSet<Candle> newCandles, LightScenario lightScenario,
|
||||
public static LightSignal GetSignal(IReadOnlyList<Candle> newCandles, LightScenario lightScenario,
|
||||
Dictionary<string, LightSignal> previousSignal, IndicatorComboConfig config, int? loopbackPeriod = 1)
|
||||
{
|
||||
return GetSignal(newCandles, lightScenario, previousSignal, config, loopbackPeriod, null);
|
||||
}
|
||||
|
||||
public static LightSignal GetSignal(HashSet<Candle> newCandles, LightScenario lightScenario,
|
||||
public static LightSignal GetSignal(IReadOnlyList<Candle> newCandles, LightScenario lightScenario,
|
||||
Dictionary<string, LightSignal> previousSignal, IndicatorComboConfig config, int? loopbackPeriod,
|
||||
Dictionary<IndicatorType, IndicatorsResultBase> preCalculatedIndicatorValues)
|
||||
{
|
||||
@@ -127,12 +127,11 @@ public static class TradingBox
|
||||
continue;
|
||||
}
|
||||
|
||||
var limitedCandles = newCandles.ToList();
|
||||
// Optimized: limitedCandles is already ordered, no need to re-order
|
||||
// newCandles is already a List and ordered chronologically
|
||||
var loopback = loopbackPeriod.HasValue && loopbackPeriod > 1 ? loopbackPeriod.Value : 1;
|
||||
var candleLoopback = limitedCandles.Count > loopback
|
||||
? limitedCandles.Skip(limitedCandles.Count - loopback).ToList()
|
||||
: limitedCandles;
|
||||
var candleLoopback = newCandles.Count > loopback
|
||||
? newCandles.Skip(newCandles.Count - loopback).ToList()
|
||||
: newCandles.ToList();
|
||||
|
||||
if (!candleLoopback.Any())
|
||||
{
|
||||
@@ -920,7 +919,7 @@ public static class TradingBox
|
||||
/// <returns>A dictionary of indicator types to their calculated values.</returns>
|
||||
public static Dictionary<IndicatorType, IndicatorsResultBase> CalculateIndicatorsValues(
|
||||
Scenario scenario,
|
||||
HashSet<Candle> candles)
|
||||
IReadOnlyList<Candle> candles)
|
||||
{
|
||||
var indicatorsValues = new Dictionary<IndicatorType, IndicatorsResultBase>();
|
||||
|
||||
|
||||
@@ -84,6 +84,12 @@ namespace Managing.Domain.Trades
|
||||
[Id(18)]
|
||||
public bool RecoveryAttempted { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The trading type for this position (BacktestFutures or Futures)
|
||||
/// </summary>
|
||||
[Id(19)]
|
||||
public TradingType TradingType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Return true if position is finished even if the position was canceled or rejected
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user