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 using QuantConnect.Util;
23 
24 namespace QuantConnect
25 {
26  /// <summary>
27  /// Single Parent Chart Object for Custom Charting
28  /// </summary>
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  [JsonConverter(typeof(ChartSeriesJsonConverter))]
40  public Dictionary<string, BaseSeries> Series = new Dictionary<string, BaseSeries>();
41 
42  /// <summary>
43  /// Associated symbol if any, making this an asset plot
44  /// </summary>
45  [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
46  public Symbol Symbol { get; set; }
47 
48  /// <summary>
49  /// True to hide this series legend from the chart
50  /// </summary>
51  [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
52  public bool LegendDisabled { get; set; }
53 
54  /// <summary>
55  /// Default constructor for chart:
56  /// </summary>
57  public Chart() { }
58 
59  /// <summary>
60  /// Chart Constructor:
61  /// </summary>
62  /// <param name="name">Name of the Chart</param>
63  /// <param name="type"> Type of the chart</param>
64  [Obsolete("ChartType is now obsolete and ignored in charting. Please use Series indexes instead by setting index in the series constructor.")]
65  public Chart(string name, ChartType type = ChartType.Overlay)
66  {
67  Name = name;
68  Series = new Dictionary<string, BaseSeries>();
69  ChartType = type;
70  }
71 
72  /// <summary>
73  /// Constructor for a chart
74  /// </summary>
75  /// <param name="name">String name of the chart</param>
76  public Chart(string name) : this(name, null)
77  {
78  }
79 
80  /// <summary>
81  /// Constructor for a chart
82  /// </summary>
83  /// <param name="name">String name of the chart</param>
84  /// <param name="symbol">Associated symbol if any</param>
85  public Chart(string name, Symbol symbol)
86  {
87  Name = name;
88  Symbol = symbol;
89  Series = new Dictionary<string, BaseSeries>();
90  }
91 
92  /// <summary>
93  /// Add a reference to this chart series:
94  /// </summary>
95  /// <param name="series">Chart series class object</param>
96  public void AddSeries(BaseSeries series)
97  {
98  //If we dont already have this series, add to the chrt:
99  if (!Series.ContainsKey(series.Name))
100  {
101  Series.Add(series.Name, series);
102  }
103  else
104  {
105  throw new DuplicateNameException($"Chart.AddSeries(): ${Messages.Chart.ChartSeriesAlreadyExists}");
106  }
107  }
108 
109  /// <summary>
110  /// Gets Series if already present in chart, else will add a new series and return it
111  /// </summary>
112  /// <param name="name">Name of the series</param>
113  /// <param name="type">Type of the series</param>
114  /// <param name="index">Index position on the chart of the series</param>
115  /// <param name="unit">Unit for the series axis</param>
116  /// <param name="color">Color of the series</param>
117  /// <param name="symbol">Symbol for the marker in a scatter plot series</param>
118  /// <param name="forceAddNew">True will always add a new Series instance, stepping on existing if any</param>
119  public Series TryAddAndGetSeries(string name, SeriesType type, int index, string unit,
120  Color color, ScatterMarkerSymbol symbol, bool forceAddNew = false)
121  {
122  BaseSeries series;
123  if (forceAddNew || !Series.TryGetValue(name, out series))
124  {
125  series = new Series(name, type, index, unit)
126  {
127  Color = color,
128  ScatterMarkerSymbol = symbol
129  };
130  Series[name] = series;
131  }
132 
133  return (Series)series;
134  }
135 
136  /// <summary>
137  /// Gets Series if already present in chart, else will add a new series and return it
138  /// </summary>
139  /// <param name="name">Name of the series</param>
140  /// <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>
141  /// <param name="forceAddNew">True will always add a new Series instance, stepping on existing if any</param>
142  public BaseSeries TryAddAndGetSeries(string name, BaseSeries templateSeries, bool forceAddNew = false)
143  {
144  BaseSeries chartSeries;
145  if (forceAddNew || !Series.TryGetValue(name, out chartSeries))
146  {
147  Series[name] = chartSeries = templateSeries.Clone(empty: true);
148  }
149 
150  return chartSeries;
151  }
152 
153  /// <summary>
154  /// Fetch a chart with only the updates since the last request,
155  /// Underlying series will save the index position.
156  /// </summary>
157  /// <returns></returns>
158  public Chart GetUpdates()
159  {
160  var copy = CloneEmpty();
161  try
162  {
163  foreach (var series in Series.Values)
164  {
165  copy.AddSeries(series.GetUpdates());
166  }
167  }
168  catch (Exception err)
169  {
170  Log.Error(err);
171  }
172  return copy;
173  }
174 
175  /// <summary>
176  /// Return a new instance clone of this object
177  /// </summary>
178  /// <returns></returns>
179  public virtual Chart Clone()
180  {
181  var chart = CloneEmpty();
182 
183  foreach (var kvp in Series)
184  {
185  chart.Series.Add(kvp.Key, kvp.Value.Clone());
186  }
187 
188  return chart;
189  }
190 
191  /// <summary>
192  /// Return a new empty instance clone of this object
193  /// </summary>
194  public virtual Chart CloneEmpty()
195  {
196  return new Chart(Name) { LegendDisabled = LegendDisabled, Symbol = Symbol };
197  }
198  }
199 
200  /// <summary>
201  /// Type of chart - should we draw the series as overlayed or stacked
202  /// </summary>
203  public enum ChartType
204  {
205  /// Overlayed stacked (0)
206  Overlay,
207  /// Stacked series on top of each other. (1)
208  Stacked
209  }
210 }