Lean  $LEAN_TAG$
SeriesJsonConverter.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.Linq;
18 using System.Drawing;
19 using Newtonsoft.Json;
20 using Newtonsoft.Json.Linq;
21 using System.Collections.Generic;
22 
23 namespace QuantConnect.Util
24 {
25  /// <summary>
26  /// Json Converter for Series which handles special Pie Series serialization case
27  /// </summary>
28  public class SeriesJsonConverter : JsonConverter
29  {
30  private ColorJsonConverter _colorJsonConverter = new ();
31 
32  /// <summary>
33  /// Write Series to Json
34  /// </summary>
35  /// <param name="writer">The Json Writer to use</param>
36  /// <param name="value">The value to written to Json</param>
37  /// <param name="serializer">The Json Serializer to use</param>
38  public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
39  {
40  var baseSeries = value as BaseSeries;
41  if (baseSeries == null)
42  {
43  return;
44  }
45 
46  writer.WriteStartObject();
47 
48  writer.WritePropertyName("name");
49  writer.WriteValue(baseSeries.Name);
50  writer.WritePropertyName("unit");
51  writer.WriteValue(baseSeries.Unit);
52  writer.WritePropertyName("index");
53  writer.WriteValue(baseSeries.Index);
54  writer.WritePropertyName("seriesType");
55  writer.WriteValue(baseSeries.SeriesType);
56 
57  if (baseSeries.ZIndex.HasValue)
58  {
59  writer.WritePropertyName("zIndex");
60  writer.WriteValue(baseSeries.ZIndex.Value);
61  }
62 
63  if (baseSeries.IndexName != null)
64  {
65  writer.WritePropertyName("indexName");
66  writer.WriteValue(baseSeries.IndexName);
67  }
68 
69  if (baseSeries.Tooltip != null)
70  {
71  writer.WritePropertyName("tooltip");
72  writer.WriteValue(baseSeries.Tooltip);
73  }
74 
75  switch (value)
76  {
77  case Series series:
78  var values = series.Values;
79  if (series.SeriesType == SeriesType.Pie)
80  {
81  values = new List<ISeriesPoint>();
82  var dataPoint = series.ConsolidateChartPoints();
83  if (dataPoint != null)
84  {
85  values.Add(dataPoint);
86  }
87  }
88 
89  // have to add the converter we want to use, else will use default
90  serializer.Converters.Add(_colorJsonConverter);
91 
92  writer.WritePropertyName("values");
93  serializer.Serialize(writer, values);
94  writer.WritePropertyName("color");
95  serializer.Serialize(writer, series.Color);
96  writer.WritePropertyName("scatterMarkerSymbol");
97  serializer.Serialize(writer, series.ScatterMarkerSymbol);
98  break;
99 
100  default:
101  writer.WritePropertyName("values");
102  serializer.Serialize(writer, (value as BaseSeries).Values);
103  break;
104  }
105 
106  writer.WriteEndObject();
107  }
108 
109  /// <summary>
110  /// Reads series from Json
111  /// </summary>
112  public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
113  {
114  var jObject = JObject.Load(reader);
115 
116  var name = (jObject["Name"] ?? jObject["name"]).Value<string>();
117  var unit = (jObject["Unit"] ?? jObject["unit"]).Value<string>();
118  var index = (jObject["Index"] ?? jObject["index"]).Value<int>();
119  var seriesType = (SeriesType)(jObject["SeriesType"] ?? jObject["seriesType"]).Value<int>();
120  var values = (JArray)(jObject["Values"] ?? jObject["values"]);
121 
122  var zindex = jObject.TryGetPropertyValue<int?>("ZIndex") ?? jObject.TryGetPropertyValue<int?>("zIndex");
123  var indexName = jObject.TryGetPropertyValue<string>("IndexName") ?? jObject.TryGetPropertyValue<string>("indexName");
124  var tooltip = jObject.TryGetPropertyValue<string>("Tooltip") ?? jObject.TryGetPropertyValue<string>("tooltip");
125 
126  if (seriesType == SeriesType.Candle)
127  {
128  return new CandlestickSeries()
129  {
130  Name = name,
131  Unit = unit,
132  Index = index,
133  ZIndex = zindex,
134  Tooltip = tooltip,
135  IndexName = indexName,
136  SeriesType = seriesType,
137  Values = values.ToObject<List<Candlestick>>(serializer).Where(x => x != null).Cast<ISeriesPoint>().ToList()
138  };
139  }
140 
141  var result = new Series()
142  {
143  Name = name,
144  Unit = unit,
145  Index = index,
146  ZIndex = zindex,
147  Tooltip = tooltip,
148  IndexName = indexName,
149  SeriesType = seriesType,
150  Color = (jObject["Color"] ?? jObject["color"])?.ToObject<Color>(serializer) ?? Color.Empty,
151  ScatterMarkerSymbol = (jObject["ScatterMarkerSymbol"] ?? jObject["scatterMarkerSymbol"])?.ToObject<ScatterMarkerSymbol>(serializer) ?? ScatterMarkerSymbol.None
152  };
153 
154  if (seriesType == SeriesType.Scatter)
155  {
156  result.Values = values.ToObject<List<ScatterChartPoint>>(serializer).Where(x => x != null).Cast<ISeriesPoint>().ToList();
157  }
158  else
159  {
160  result.Values = values.ToObject<List<ChartPoint>>(serializer).Where(x => x != null).Cast<ISeriesPoint>().ToList();
161  }
162  return result;
163  }
164 
165  /// <summary>
166  /// Determine if this Converter can convert this type
167  /// </summary>
168  /// <param name="objectType">Type that we would like to convert</param>
169  /// <returns>True if <see cref="Series"/></returns>
170  public override bool CanConvert(Type objectType)
171  {
172  return typeof(BaseSeries).IsAssignableFrom(objectType);
173  }
174  }
175 }