Skip to content

Commit 5941fc4

Browse files
committed
Extend daily stats series retention to two years
1 parent 6349d5f commit 5941fc4

2 files changed

Lines changed: 67 additions & 9 deletions

File tree

Engine/Results/BaseResultsHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -986,7 +986,7 @@ protected Dictionary<string, string> GetAlgorithmState(DateTime? endTime = null)
986986
/// <summary>
987987
/// Will generate the statistics results and update the provided runtime statistics
988988
/// </summary>
989-
protected StatisticsResults GenerateStatisticsResults(Dictionary<string, Chart> charts,
989+
protected virtual StatisticsResults GenerateStatisticsResults(Dictionary<string, Chart> charts,
990990
SortedDictionary<DateTime, decimal> profitLoss = null, CapacityEstimate estimatedStrategyCapacity = null)
991991
{
992992
var statisticsResults = new StatisticsResults();

Engine/Results/LiveTradingResultHandler.cs

Lines changed: 66 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ public class LiveTradingResultHandler : BaseResultsHandler, IResultHandler
7979
private bool _userExchangeIsOpen;
8080
private DateTime _lastChartSampleLogicCheck;
8181
private readonly Dictionary<string, SecurityExchangeHours> _exchangeHours;
82+
protected readonly SortedDictionary<DateTime, decimal> _dailyEquityClose = new();
83+
protected readonly object _dailyEquityCloseLock = new();
8284

8385

8486
/// <summary>
@@ -371,22 +373,78 @@ protected virtual void SetNextStatusUpdate()
371373
/// <summary>
372374
/// Removes chart series points older than their retention window: 10 days for performance charts, 2 days for all others.
373375
/// </summary>
376+
public override void Sample(DateTime time)
377+
{
378+
base.Sample(time);
379+
if (!Algorithm.IsWarmingUp)
380+
{
381+
lock (_dailyEquityCloseLock)
382+
{
383+
_dailyEquityClose[time.Date] = GetPortfolioValue();
384+
}
385+
}
386+
}
387+
388+
protected override StatisticsResults GenerateStatisticsResults(Dictionary<string, Chart> charts,
389+
SortedDictionary<DateTime, decimal> profitLoss = null, CapacityEstimate estimatedStrategyCapacity = null)
390+
{
391+
List<KeyValuePair<DateTime, decimal>> historicalCloses;
392+
lock (_dailyEquityCloseLock)
393+
{
394+
historicalCloses = _dailyEquityClose.ToList();
395+
}
396+
397+
if (historicalCloses.Count > 0 &&
398+
charts.TryGetValue(StrategyEquityKey, out var strategyEquity) &&
399+
strategyEquity.Series.TryGetValue(EquityKey, out var equitySeries))
400+
{
401+
var existingDates = new HashSet<DateTime>(equitySeries.Values.Select(v => v.Time.Date));
402+
var toInject = historicalCloses
403+
.Where(kvp => !existingDates.Contains(kvp.Key))
404+
.Select(kvp => (ISeriesPoint)new Candlestick(kvp.Key, kvp.Value, kvp.Value, kvp.Value, kvp.Value))
405+
.ToList();
406+
407+
if (toInject.Count > 0)
408+
{
409+
var mergedEquity = (CandlestickSeries)equitySeries.Clone();
410+
mergedEquity.Values.InsertRange(0, toInject);
411+
412+
var mergedChart = new Chart(StrategyEquityKey);
413+
foreach (var kvp in strategyEquity.Series)
414+
{
415+
mergedChart.Series[kvp.Key] = kvp.Key == EquityKey ? mergedEquity : kvp.Value;
416+
}
417+
418+
charts = new Dictionary<string, Chart>(charts) { [StrategyEquityKey] = mergedChart };
419+
}
420+
}
421+
422+
return base.GenerateStatisticsResults(charts, profitLoss, estimatedStrategyCapacity);
423+
}
424+
425+
/// <summary>
426+
/// Removes chart series points older than their retention window: 2 years for daily statistics series
427+
/// (Return, Benchmark), 2 days for all others.
428+
/// </summary>
374429
protected virtual void TrimCharts(DateTime utcNow)
375430
{
431+
var defaultLimit = utcNow.AddDays(-2);
432+
var dailyStatsLimit = utcNow.AddDays(-730);
433+
376434
lock (ChartLock)
377435
{
378436
foreach (var chart in Charts)
379437
{
380-
var timeLimitUtc = AlgorithmPerformanceCharts.Contains(chart.Key)
381-
? utcNow.AddDays(-10)
382-
: utcNow.AddDays(-2);
383-
384438
foreach (var series in chart.Value.Series)
385439
{
386-
series.Value.Values =
387-
(from v in series.Value.Values
388-
where v.Time > timeLimitUtc
389-
select v).ToList();
440+
var isDailyStatsSeries =
441+
(chart.Key == StrategyEquityKey && series.Key == ReturnKey) ||
442+
(chart.Key == BenchmarkKey && series.Key == BenchmarkKey);
443+
444+
var timeLimitUtc = isDailyStatsSeries ? dailyStatsLimit : defaultLimit;
445+
series.Value.Values = series.Value.Values
446+
.Where(v => v.Time > timeLimitUtc)
447+
.ToList();
390448
}
391449
}
392450
}

0 commit comments

Comments
 (0)