@@ -31,9 +31,10 @@ namespace QuantConnect.Optimizer
3131 public class OptimizationBacktestMetrics : BacktestSummary
3232 {
3333 /// <summary>
34- /// The backtest's portfolio statistics; null when absent from the backtest result.
34+ /// The backtest's total performance (wraps <see cref="QuantConnect.Statistics.TradeStatistics"/>,
35+ /// <see cref="QuantConnect.Statistics.PortfolioStatistics"/>, and <see cref="QuantConnect.Statistics.Trade"/> list); null when absent from the backtest result.
3536 /// </summary>
36- public PortfolioStatistics PortfolioStatistics { get ; set ; }
37+ public AlgorithmPerformance TotalPerformance { get ; set ; }
3738
3839 /// <summary>
3940 /// Number of orders the backtest produced.
@@ -64,34 +65,40 @@ public static OptimizationBacktestMetrics ExtractFrom(string backtestId, Paramet
6465 return null ;
6566 }
6667
67- ParsedBacktest parsed = null ;
68+ AlgorithmPerformance totalPerformance = null ;
69+ var totalOrders = 0 ;
70+ IReadOnlyList < string > analysisNames = System . Array . Empty < string > ( ) ;
71+
6872 if ( ! string . IsNullOrEmpty ( jsonBacktestResult ) )
6973 {
7074 try
7175 {
72- parsed = JsonConvert . DeserializeObject < ParsedBacktest > ( jsonBacktestResult ) ;
76+ var jo = JObject . Parse ( jsonBacktestResult ) ;
77+ // Use case-insensitive lookups: BacktestingResultHandler serializes with CamelCaseNamingStrategy.
78+ totalPerformance = jo . GetValue ( "TotalPerformance" , System . StringComparison . OrdinalIgnoreCase ) ? . ToObject < AlgorithmPerformance > ( ) ;
79+ totalOrders = ( jo . GetValue ( "Orders" , System . StringComparison . OrdinalIgnoreCase ) as JObject ) ? . Count ?? 0 ;
80+ var analyses = jo . GetValue ( "Analysis" , System . StringComparison . OrdinalIgnoreCase ) ? . ToObject < List < QuantConnect . Analysis > > ( ) ;
81+ if ( analyses != null )
82+ {
83+ analysisNames = analyses
84+ . Where ( a => ! string . IsNullOrEmpty ( a ? . Name ) )
85+ . Select ( a => a . Name )
86+ . ToList ( ) ;
87+ }
7388 }
7489 catch ( JsonException ex )
7590 {
7691 Log . Error ( ex , $ "OptimizationBacktestMetrics.ExtractFrom(): failed to parse backtest result for '{ backtestId } '") ;
7792 }
7893 }
7994
80- var portfolioStats = parsed ? . TotalPerformance ? . PortfolioStatistics ;
81- var analysisNames = parsed ? . Analysis == null
82- ? ( IReadOnlyList < string > ) System . Array . Empty < string > ( )
83- : parsed . Analysis
84- . Where ( a => ! string . IsNullOrEmpty ( a ? . Name ) )
85- . Select ( a => a . Name )
86- . ToList ( ) ;
87-
8895 return new OptimizationBacktestMetrics
8996 {
9097 BacktestId = backtestId ,
9198 Parameters = parameters ,
92- SharpeRatio = portfolioStats ? . SharpeRatio ?? 0m ,
93- PortfolioStatistics = portfolioStats ,
94- TotalOrders = parsed ? . Orders ? . Count ?? 0 ,
99+ SharpeRatio = totalPerformance ? . PortfolioStatistics ? . SharpeRatio ?? 0m ,
100+ TotalPerformance = totalPerformance ,
101+ TotalOrders = totalOrders ,
95102 AnalysisNames = analysisNames
96103 } ;
97104 }
@@ -109,24 +116,5 @@ private static Dictionary<string, decimal> ParseParameterSet(ParameterSet parame
109116 }
110117 return result ;
111118 }
112-
113- // Minimal-shape DTO that binds only the backtest-result fields the analyzer reads.
114- private sealed class ParsedBacktest
115- {
116- [ JsonProperty ( "TotalPerformance" ) ]
117- public ParsedTotalPerformance TotalPerformance { get ; set ; }
118-
119- [ JsonProperty ( "Orders" ) ]
120- public JObject Orders { get ; set ; }
121-
122- [ JsonProperty ( "Analysis" ) ]
123- public List < QuantConnect . Analysis > Analysis { get ; set ; }
124- }
125-
126- private sealed class ParsedTotalPerformance
127- {
128- [ JsonProperty ( "PortfolioStatistics" ) ]
129- public PortfolioStatistics PortfolioStatistics { get ; set ; }
130- }
131119 }
132120}
0 commit comments