Files
quantconnect--lean/Common/API/LiveAlgorithmResultsJsonConverter.cs
Martin Molinero cfa08a11fb Address reviews
- Removing `using QCAlgorithmFramework = QuantConnect.Algorithm.QCAlgorithm`
- Removing `QCAlgorithmFrameworkBridge`
- Removing `IsFrameworkAlgorithm`
- Making `EmitInsightBasedOnFill` private. Adding new
`IOrderEventProvider` exposing an `event` to which `QCAlgorithm` will
subscribe.
- `AccountType.Cash` algorithms will be allowed to manually trade and
emight insights manually or with alpha model.
2019-04-03 21:55:44 -03:00

188 lines
7.0 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using QuantConnect.Orders;
using QuantConnect.Packets;
using QuantConnect.Securities;
namespace QuantConnect.API
{
/// <summary>
/// Custom JsonConverter for LiveResults data for live algorithms
/// </summary>
public class LiveAlgorithmResultsJsonConverter : JsonConverter
{
/// <summary>
/// Gets a value indicating whether this <see cref="T:Newtonsoft.Json.JsonConverter"/> can write JSON.
/// </summary>
/// <value>
/// <c>true</c> if this <see cref="T:Newtonsoft.Json.JsonConverter"/> can write JSON; otherwise, <c>false</c>.
/// </value>
public override bool CanWrite
{
get { return false; }
}
/// <summary>
/// Writes the JSON representation of the object.
/// </summary>
/// <param name="writer">The <see cref="T:Newtonsoft.Json.JsonWriter"/> to write to.</param><param name="value">The value.</param><param name="serializer">The calling serializer.</param>
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException("The LiveAlgorithmResultsJsonConverter does not implement a WriteJson method.");
}
/// <summary>
/// Determines whether this instance can convert the specified object type.
/// </summary>
/// <param name="objectType">Type of the object.</param>
/// <returns>
/// <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
/// </returns>
public override bool CanConvert(Type objectType)
{
return typeof(LiveAlgorithmResults).IsAssignableFrom(objectType);
}
/// <summary>
/// Reads the JSON representation of the object.
/// </summary>
/// <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> to read from.</param><param name="objectType">Type of the object.</param><param name="existingValue">The existing value of object being read.</param><param name="serializer">The calling serializer.</param>
/// <returns>
/// The object value.
/// </returns>
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var jObject = JObject.Load(reader);
var liveResults = CreateLiveResultsFromJObject(jObject);
return liveResults;
}
/// <summary>
/// Custom parsing of live results data
/// </summary>
/// <param name="jObject">Json representing LiveResults</param>
/// <returns></returns>
public static LiveAlgorithmResults CreateLiveResultsFromJObject(JObject jObject)
{
var liveAlgoResults = new LiveAlgorithmResults
{
Success = jObject["success"].Value<bool>()
};
var success = jObject["success"].Value<bool>();
if (!success)
{
// Either there was an error in the running algrithm or the algorithm hasn't started
liveAlgoResults.Errors = jObject.Last.Children().Select(error => error.ToString()).ToList();
return liveAlgoResults;
}
liveAlgoResults.Success = true;
liveAlgoResults.LiveResults = new LiveResultsData
{
Resolution = (Resolution)Enum.Parse(typeof(Resolution), jObject["LiveResults"]["resolution"].Value<string>(), true),
Version = jObject["LiveResults"]["version"].Value<int>()
};
// Results json
var results = jObject["LiveResults"]["results"];
// Deserialize charting data
var charts = results["Charts"];
var chartDictionary = new Dictionary<string, Chart>();
foreach (var chart in charts.Children())
{
var newChart = new Chart(((JProperty) chart).Name)
{
Series = GetChartSeries(chart.First()["Series"])
};
chartDictionary.Add(newChart.Name, newChart);
}
// Live Results - At this time only that charting data can be returned from the api (9/30/2016)
liveAlgoResults.LiveResults.Results = new LiveResult(chartDictionary,
new Dictionary<int, Order>(),
new Dictionary<DateTime, decimal>(),
new Dictionary<string, Holding>(),
new CashBook(),
new Dictionary<string, string>(),
new Dictionary<string, string>()
);
return liveAlgoResults;
}
/// <summary>
/// Get series data for a specific chart
/// </summary>
/// <param name="series">Series data and properties for a chart</param>
/// <returns>Dictionary with the name of the series as the key and the Series itself as the value</returns>
private static Dictionary<string, Series> GetChartSeries(JToken series)
{
var chartSeriesDict = new Dictionary<string, Series>();
foreach (var child in series.Children())
{
var s = child.First();
var newSeries = new Series(((JProperty) child).Name)
{
SeriesType = (SeriesType) s["SeriesType"].Value<int>(),
Values = GetSeriesValues(s["Values"])
};
chartSeriesDict.Add(newSeries.Name, newSeries);
}
return chartSeriesDict;
}
/// <summary>
/// Get x and y value pairs that represent series data
/// </summary>
/// <param name="values">json array of x, y value pairs</param>
/// <returns>List of ChartPoints</returns>
private static List<ChartPoint> GetSeriesValues(JToken values)
{
var chartPoints = new List<ChartPoint>();
// Special ChartPoint that only represents time (only has x component)
if (values.Children().Count() == 1)
{
var point = values.Children().First();
var x = point["x"];
chartPoints.Add(new ChartPoint((long)x, 0));
}
// Typical series of values that is used for charting
else
{
foreach (var point in values.Children())
{
var x = point["x"];
var y = point["y"];
// this piece of code is why this entire custom serializer is necessary
if (y != null && y.Type == JTokenType.Float)
{
chartPoints.Add(new ChartPoint((long)x, (decimal)y));
}
else
{
chartPoints.Add(null);
}
}
}
return chartPoints;
}
}
}