/* * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections.Generic; using System.Linq; using QuantConnect.Data; using QuantConnect.Indicators; namespace QuantConnect.Algorithm { public partial class QCAlgorithm { private Dictionary _charts = new Dictionary(); private Dictionary _runtimeStatistics = new Dictionary(); /// /// Access to the runtime statistics property. User provided statistics. /// /// RuntimeStatistics are displayed in the head banner in live trading public Dictionary RuntimeStatistics { get { return _runtimeStatistics; } } /// /// Add a Chart object to algorithm collection /// /// Chart object to add to collection. /// public void AddChart(Chart chart) { if (!_charts.ContainsKey(chart.Name)) { _charts.Add(chart.Name, chart); } } /// /// Plot a chart using string series name, with value. /// /// Name of the plot series /// Value to plot /// public void Plot(string series, decimal value) { //By default plot to the primary chart: Plot("Strategy Equity", series, value); } /// /// Plot a chart using string series name, with int value. Alias of Plot(); /// /// Record(string series, int value) /// public void Record(string series, int value) { Plot(series, value); } /// /// Plot a chart using string series name, with double value. Alias of Plot(); /// /// public void Record(string series, double value) { Plot(series, value); } /// /// Plot a chart using string series name, with decimal value. Alias of Plot(); /// /// /// /// public void Record(string series, decimal value) { //By default plot to the primary chart: Plot(series, value); } /// /// Plot a chart using string series name, with double value. /// /// public void Plot(string series, double value) { Plot(series, (decimal)value); } /// /// Plot a chart using string series name, with int value. /// /// public void Plot(string series, int value) { Plot(series, (decimal)value); } /// ///Plot a chart using string series name, with float value. /// /// public void Plot(string series, float value) { Plot(series, (decimal)value); } /// /// Plot a chart to string chart name, using string series name, with double value. /// /// public void Plot(string chart, string series, double value) { Plot(chart, series, (decimal)value); } /// /// Plot a chart to string chart name, using string series name, with int value /// /// public void Plot(string chart, string series, int value) { Plot(chart, series, (decimal)value); } /// /// Plot a chart to string chart name, using string series name, with float value /// /// public void Plot(string chart, string series, float value) { Plot(chart, series, (decimal)value); } /// /// Plot a value to a chart of string-chart name, with string series name, and decimal value. If chart does not exist, create it. /// /// Chart name /// Series name /// Value of the point public void Plot(string chart, string series, decimal value) { //Ignore the reserved chart names: if ((chart == "Strategy Equity" && series == "Equity") || (chart == "Daily Performance") || (chart == "Meta")) { throw new Exception("Algorithm.Plot(): 'Equity', 'Daily Performance' and 'Meta' are reserved chart names created for all charts."); } // If we don't have the chart, create it: if (!_charts.ContainsKey(chart)) { _charts.Add(chart, new Chart(chart)); } var thisChart = _charts[chart]; if (!thisChart.Series.ContainsKey(series)) { //Number of series in total. var seriesCount = (from x in _charts.Values select x.Series.Count).Sum(); if (seriesCount > 10) { Error("Exceeded maximum series count: Each backtest can have up to 10 series in total."); return; } //If we don't have the series, create it: thisChart.AddSeries(new Series(series)); } var thisSeries = thisChart.Series[series]; if (thisSeries.Values.Count < 4000 || _liveMode) { thisSeries.AddPoint(Time, value, _liveMode); } else { Debug("Exceeded maximum points per chart, data skipped."); } } /// /// Plots the value of each indicator on the chart /// /// The chart's name /// The indicatorsto plot /// public void Plot(string chart, params IndicatorBase[] indicators) where T : BaseData { foreach (var indicator in indicators) { Plot(chart, indicator.Name, indicator); } } /// /// Automatically plots each indicator when a new value is available /// public void PlotIndicator(string chart, params IndicatorBase[] indicators) where T : BaseData { foreach (var i in indicators) { // copy loop variable for usage in closure var ilocal = i; i.Updated += (sender, args) => { Plot(chart, ilocal); }; } } /// /// Automatically plots each indicator when a new value is available, optionally waiting for indicator.IsReady to return true /// public void PlotIndicator(string chart, bool waitForReady, params IndicatorBase[] indicators) where T : BaseData { foreach (var i in indicators) { // copy loop variable for usage in closure var ilocal = i; i.Updated += (sender, args) => { if (!waitForReady || ilocal.IsReady) { Plot(chart, ilocal); } }; } } /// /// Set a runtime statistic for the algorithm. Runtime statistics are shown in the top banner of a live algorithm GUI. /// /// Name of your runtime statistic /// String value of your runtime statistic /// public void SetRuntimeStatistic(string name, string value) { //If not set, add it to the dictionary: if (!_runtimeStatistics.ContainsKey(name)) { _runtimeStatistics.Add(name, value); } //Set _runtimeStatistics[name] = value; } /// /// Set a runtime statistic for the algorithm. Runtime statistics are shown in the top banner of a live algorithm GUI. /// /// Name of your runtime statistic /// Decimal value of your runtime statistic public void SetRuntimeStatistic(string name, decimal value) { SetRuntimeStatistic(name, value.ToString()); } /// /// Set a runtime statistic for the algorithm. Runtime statistics are shown in the top banner of a live algorithm GUI. /// /// Name of your runtime statistic /// Int value of your runtime statistic public void SetRuntimeStatistic(string name, int value) { SetRuntimeStatistic(name, value.ToString()); } /// /// Set a runtime statistic for the algorithm. Runtime statistics are shown in the top banner of a live algorithm GUI. /// /// Name of your runtime statistic /// Double value of your runtime statistic public void SetRuntimeStatistic(string name, double value) { SetRuntimeStatistic(name, value.ToString()); } /// /// Get the chart updates by fetch the recent points added and return for dynamic plotting. /// /// /// List of chart updates since the last request /// GetChartUpdates returns the latest updates since previous request. public List GetChartUpdates(bool clearChartData = false) { var updates = _charts.Values.Select(chart => chart.GetUpdates()).ToList(); if (clearChartData) { // we can clear this data out after getting updates to prevent unnecessary memory usage foreach (var chart in _charts) { foreach (var series in chart.Value.Series) { series.Value.Purge(); } } } return updates; } } // End Partial Algorithm Template - Plotting. } // End QC Namespace