18 using Newtonsoft.Json;
20 using System.Diagnostics;
24 using System.Collections.Generic;
34 static void Main(
string[] args)
45 var description =
Config.
Get(
"strategy-description");
46 var version =
Config.
Get(
"strategy-version");
47 var backtestDataFile =
Config.
Get(
"backtest-data-source-file");
48 var liveDataFile =
Config.
Get(
"live-data-source-file");
49 var destination =
Config.
Get(
"report-destination");
50 var reportFormat =
Config.
Get(
"report-format");
51 var cssOverrideFile =
Config.
Get(
"report-css-override-file",
"css/report_override.css");
52 var htmlCustomFile =
Config.
Get(
"report-html-custom-file",
"template.html");
55 Log.
Trace($
"QuantConnect.Report.Main(): Parsing source files...{backtestDataFile}, {liveDataFile}");
56 var backtestSettings =
new JsonSerializerSettings
59 FloatParseHandling = FloatParseHandling.Decimal
62 var backtest = JsonConvert.DeserializeObject<
BacktestResult>(
File.ReadAllText(backtestDataFile), backtestSettings);
65 if (!
string.IsNullOrEmpty(liveDataFile))
67 var settings =
new JsonSerializerSettings
69 NullValueHandling = NullValueHandling.Ignore,
73 live = JsonConvert.DeserializeObject<
LiveResult>(
File.ReadAllText(liveDataFile), settings);
76 string cssOverrideContent =
null;
77 if (!
string.IsNullOrEmpty(cssOverrideFile))
79 if (
File.Exists(cssOverrideFile))
81 cssOverrideContent =
File.ReadAllText(cssOverrideFile);
85 Log.
Trace($
"QuantConnect.Report.Main(): CSS override file {cssOverrideFile} was not found");
89 string htmlCustomContent =
null;
90 if (!
string.IsNullOrEmpty(htmlCustomFile))
92 if (
File.Exists(htmlCustomFile))
94 htmlCustomContent =
File.ReadAllText(htmlCustomFile);
98 Log.
Trace($
"QuantConnect.Report.Main(): HTML custom file {htmlCustomFile} was not found");
103 Log.
Trace(
"QuantConnect.Report.Main(): Instantiating report...");
104 var report =
new Report(name, description, version, backtest, live, cssOverride: cssOverrideContent, htmlCustom: htmlCustomContent);
107 Log.
Trace(
"QuantConnect.Report.Main(): Starting content compile...");
111 report.Compile(out html, out _);
114 if (!
string.IsNullOrEmpty(destination))
116 Log.
Trace($
"QuantConnect.Report.Main(): Writing content to file {destination}");
117 File.WriteAllText(destination, html);
119 if (!String.IsNullOrEmpty(reportFormat) && reportFormat.ToUpperInvariant() ==
"PDF")
123 Log.
Trace(
"QuantConnect.Report.Main(): Starting conversion to PDF");
125 var pdfDestination = destination.Replace(
".html",
".pdf");
126 Process process =
new();
127 process.StartInfo.FileName =
"xvfb-run";
128 process.StartInfo.Arguments = $
"--server-args=\"-screen 0, 1600x1200x24+32\" wkhtmltopdf {destination} {pdfDestination}";
129 process.StartInfo.UseShellExecute =
false;
130 process.StartInfo.RedirectStandardOutput =
true;
131 process.StartInfo.RedirectStandardError =
true;
132 process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
134 process.OutputDataReceived += (sender, e) =>
Log.
Trace($
"QuantConnect.Report.Main(): {e.Data}");
135 process.ErrorDataReceived += (sender, e) =>
Log.
Error($
"QuantConnect.Report.Main(): {e.Data}");
139 process.BeginOutputReadLine();
140 process.BeginErrorReadLine();
142 var processExited = process.WaitForExit(1*60*1000);
146 Log.
Trace(
"QuantConnect.Report.Main(): Convert to PDF process exited with code " + process.ExitCode);
150 Log.
Error(
"QuantConnect.Report.Main(): Process did not exit within the timeout period.");
156 Log.
Error($
"QuantConnect.Report.Main(): {ex.Message}");
165 Log.
Trace(
"QuantConnect.Report.Main(): Completed.");
167 if (!Console.IsInputRedirected && !
Config.
GetBool(
"close-automatically"))