Lean  $LEAN_TAG$
Chart.cs
1 /*
2  * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
3  * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14 */
15 
16 using System;
17 using System.Collections.Generic;
18 using System.Data;
19 using System.Drawing;
20 using Newtonsoft.Json;
21 using QuantConnect.Logging;
22 
23 namespace QuantConnect
24 {
25  /// <summary>
26  /// Single Parent Chart Object for Custom Charting
27  /// </summary>
28  [JsonObject]
29  public class Chart
30  {
31  /// Name of the Chart:
32  public string Name = "";
33 
34  /// Type of the Chart, Overlayed or Stacked.
35  [Obsolete("ChartType is now obsolete. Please use Series indexes instead by setting index in the series constructor.")]
36  public ChartType ChartType = ChartType.Overlay;
37 
38  /// List of Series Objects for this Chart:
39  public Dictionary<string, BaseSeries> Series = new Dictionary<string, BaseSeries>();
40 
41  /// <summary>
42  /// Default constructor for chart:
43  /// </summary>
44  public Chart() { }
45 
46  /// <summary>
47  /// Chart Constructor:
48  /// </summary>
49  /// <param name="name">Name of the Chart</param>
50  /// <param name="type"> Type of the chart</param>
51  [Obsolete("ChartType is now obsolete and ignored in charting. Please use Series indexes instead by setting index in the series constructor.")]
52  public Chart(string name, ChartType type = ChartType.Overlay)
53  {
54  Name = name;
55  Series = new Dictionary<string, BaseSeries>();
56  ChartType = type;
57  }
58 
59  /// <summary>
60  /// Constructor for a chart
61  /// </summary>
62  /// <param name="name">String name of the chart</param>
63  public Chart(string name)
64  {
65  Name = name;
66  Series = new Dictionary<string, BaseSeries>();
67  }
68 
69  /// <summary>
70  /// Add a reference to this chart series:
71  /// </summary>
72  /// <param name="series">Chart series class object</param>
73  public void AddSeries(BaseSeries series)
74  {
75  //If we dont already have this series, add to the chrt:
76  if (!Series.ContainsKey(series.Name))
77  {
78  Series.Add(series.Name, series);
79  }
80  else
81  {
82  throw new DuplicateNameException($"Chart.AddSeries(): ${Messages.Chart.ChartSeriesAlreadyExists}");
83  }
84  }
85 
86  /// <summary>
87  /// Gets Series if already present in chart, else will add a new series and return it
88  /// </summary>
89  /// <param name="name">Name of the series</param>
90  /// <param name="type">Type of the series</param>
91  /// <param name="index">Index position on the chart of the series</param>
92  /// <param name="unit">Unit for the series axis</param>
93  /// <param name="color">Color of the series</param>
94  /// <param name="symbol">Symbol for the marker in a scatter plot series</param>
95  /// <param name="forceAddNew">True will always add a new Series instance, stepping on existing if any</param>
96  public Series TryAddAndGetSeries(string name, SeriesType type, int index, string unit,
97  Color color, ScatterMarkerSymbol symbol, bool forceAddNew = false)
98  {
99  BaseSeries series;
100  if (forceAddNew || !Series.TryGetValue(name, out series))
101  {
102  series = new Series(name, type, index, unit)
103  {
104  Color = color,
105  ScatterMarkerSymbol = symbol
106  };
107  Series[name] = series;
108  }
109 
110  return (Series)series;
111  }
112 
113  /// <summary>
114  /// Gets Series if already present in chart, else will add a new series and return it
115  /// </summary>
116  /// <param name="name">Name of the series</param>
117  /// <param name="templateSeries">Series to be used as a template. It will be clone without values if the series is added to the chart</param>
118  /// <param name="forceAddNew">True will always add a new Series instance, stepping on existing if any</param>
119  public BaseSeries TryAddAndGetSeries(string name, BaseSeries templateSeries, bool forceAddNew = false)
120  {
121  BaseSeries chartSeries;
122  if (forceAddNew || !Series.TryGetValue(name, out chartSeries))
123  {
124  Series[name] = chartSeries = templateSeries.Clone(empty: true);
125  }
126 
127  return chartSeries;
128  }
129 
130  /// <summary>
131  /// Fetch a chart with only the updates since the last request,
132  /// Underlying series will save the index position.
133  /// </summary>
134  /// <returns></returns>
135  public Chart GetUpdates()
136  {
137  var copy = new Chart(Name);
138  try
139  {
140  foreach (var series in Series.Values)
141  {
142  copy.AddSeries(series.GetUpdates());
143  }
144  }
145  catch (Exception err)
146  {
147  Log.Error(err);
148  }
149  return copy;
150  }
151 
152  /// <summary>
153  /// Return a new instance clone of this object
154  /// </summary>
155  /// <returns></returns>
156  public Chart Clone()
157  {
158  var chart = new Chart(Name);
159 
160  foreach (var kvp in Series)
161  {
162  chart.Series.Add(kvp.Key, kvp.Value.Clone());
163  }
164 
165  return chart;
166  }
167  }
168 
169  /// <summary>
170  /// Type of chart - should we draw the series as overlayed or stacked
171  /// </summary>
172  public enum ChartType
173  {
174  /// Overlayed stacked (0)
175  Overlay,
176  /// Stacked series on top of each other. (1)
177  Stacked
178  }
179 }