Files
quantconnect--lean/Common/Orders/Serialization/SerializedOrder.cs
Martin Molinero 24b6cc6d9a Refactor Order and OrderEvent json
- Adding new SerializedOrderEvent and SerializedOrder with new
  JsonConverters
- Specifying OrderEvent json converter when storing, streaming data
- Adding unit tests
2020-04-07 17:40:25 -03:00

256 lines
9.2 KiB
C#

/*
* 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.Collections.Generic;
using System.ComponentModel;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using QuantConnect.Orders.TimeInForces;
namespace QuantConnect.Orders.Serialization
{
/// <summary>
/// Data transfer object used for serializing an <see cref="Order"/> that was just generated by an algorithm
/// </summary>
public class SerializedOrder
{
/// <summary>
/// The unique order id
/// </summary>
[JsonProperty("id", Required = Required.Default)]
public string Id => $"{AlgorithmId}-{OrderId}";
/// <summary>
/// Algorithm Id, BacktestId or DeployId
/// </summary>
[JsonProperty("algorithm-id")]
public string AlgorithmId { get; set; }
/// <summary>
/// Order ID
/// </summary>
[JsonProperty("order-id")]
public int OrderId { get; set; }
/// <summary>
/// Order id to process before processing this order.
/// </summary>
[JsonProperty("contingent-id")]
public int ContingentId { get; set; }
/// <summary>
/// Brokerage Id for this order for when the brokerage splits orders into multiple pieces
/// </summary>
[JsonProperty("broker-id")]
public List<string> BrokerId { get; set; }
/// <summary>
/// Symbol of the Asset
/// </summary>
[JsonProperty("symbol")]
public string Symbol { get; set; }
/// <summary>
/// Price of the Order.
/// </summary>
[JsonProperty("price")]
public decimal Price { get; set; }
/// <summary>
/// Currency for the order price
/// </summary>
[JsonProperty("price-currency")]
public string PriceCurrency { get; set; }
/// <summary>
/// Gets the utc time this order was created. Alias for <see cref="Time"/>
/// </summary>
[JsonProperty("created-time")]
public double CreatedTime { get; set; }
/// <summary>
/// Gets the utc time the last fill was received, or null if no fills have been received
/// </summary>
[JsonProperty("last-fill-time", NullValueHandling = NullValueHandling.Ignore)]
public double? LastFillTime { get; set; }
/// <summary>
/// Gets the utc time this order was last updated, or null if the order has not been updated.
/// </summary>
[JsonProperty("last-update-time", NullValueHandling = NullValueHandling.Ignore)]
public double? LastUpdateTime { get; set; }
/// <summary>
/// Gets the utc time this order was canceled, or null if the order was not canceled.
/// </summary>
[JsonProperty("canceled-time", NullValueHandling = NullValueHandling.Ignore)]
public double? CanceledTime { get; set; }
/// <summary>
/// Number of shares to execute.
/// </summary>
[JsonProperty("quantity")]
public decimal Quantity { get; set; }
/// <summary>
/// Order Type
/// </summary>
[JsonProperty("type"), JsonConverter(typeof(StringEnumConverter), true)]
public OrderType Type { get; set; }
/// <summary>
/// Status of the Order
/// </summary>
[JsonProperty("status"), JsonConverter(typeof(StringEnumConverter), true)]
public OrderStatus Status { get; set; }
/// <summary>
/// Tag the order with some custom data
/// </summary>
[DefaultValue(""), JsonProperty("tag", DefaultValueHandling = DefaultValueHandling.Ignore)]
public string Tag { get; set; }
/// <summary>
/// Order Direction Property based off Quantity.
/// </summary>
[JsonProperty("direction"), JsonConverter(typeof(StringEnumConverter), true)]
public OrderDirection Direction { get; set; }
/// <summary>
/// The current price at order submission time
/// </summary>
[JsonProperty("submission-last-price", DefaultValueHandling = DefaultValueHandling.Ignore)]
public decimal SubmissionLastPrice { get; set; }
/// <summary>
/// The ask price at order submission time
/// </summary>
[JsonProperty("submission-ask-price", DefaultValueHandling = DefaultValueHandling.Ignore)]
public decimal SubmissionAskPrice { get; set; }
/// <summary>
/// The bid price at order submission time
/// </summary>
[JsonProperty("submission-bid-price", DefaultValueHandling = DefaultValueHandling.Ignore)]
public decimal SubmissionBidPrice { get; set; }
/// <summary>
/// The current stop price
/// </summary>
[JsonProperty("stop-price", DefaultValueHandling = DefaultValueHandling.Ignore)]
public decimal? StopPrice { get; set; }
/// <summary>
/// Signal showing the "StopLimitOrder" has been converted into a Limit Order
/// </summary>
[JsonProperty("stop-triggered", DefaultValueHandling = DefaultValueHandling.Ignore)]
public bool? StopTriggered { get; set; }
/// <summary>
/// The current limit price
/// </summary>
[JsonProperty("limit-price", DefaultValueHandling = DefaultValueHandling.Ignore)]
public decimal? LimitPrice { get; set; }
/// <summary>
/// The time in force type
/// </summary>
[JsonProperty("time-in-force-type")]
public string TimeInForceType { get; set; }
/// <summary>
/// The time in force expiration time if any
/// </summary>
[JsonProperty("time-in-force-expiry", DefaultValueHandling = DefaultValueHandling.Ignore)]
public double? TimeInForceExpiry { get; set; }
/// <summary>
/// Empty constructor required for JSON converter.
/// </summary>
private SerializedOrder()
{
}
/// <summary>
/// Creates a new serialized order instance based on the provided order
/// </summary>
public SerializedOrder(Order order, string algorithmId)
{
AlgorithmId = algorithmId;
OrderId = order.Id;
ContingentId = order.ContingentId;
BrokerId = order.BrokerId;
Symbol = order.Symbol.ID.ToString();
Price = order.Price;
PriceCurrency = order.PriceCurrency;
Quantity = order.Quantity;
Type = order.Type;
Status = order.Status;
Tag = order.Tag;
Direction = order.Direction;
CreatedTime = Time.DateTimeToUnixTimeStamp(order.CreatedTime);
if (order.LastFillTime.HasValue)
{
LastFillTime = Time.DateTimeToUnixTimeStamp(order.LastFillTime.Value);
}
if (order.LastUpdateTime.HasValue)
{
LastUpdateTime = Time.DateTimeToUnixTimeStamp(order.LastUpdateTime.Value);
}
if (order.CanceledTime.HasValue)
{
CanceledTime = Time.DateTimeToUnixTimeStamp(order.CanceledTime.Value);
}
if (order.OrderSubmissionData != null)
{
SubmissionAskPrice = order.OrderSubmissionData.AskPrice;
SubmissionBidPrice = order.OrderSubmissionData.BidPrice;
SubmissionLastPrice = order.OrderSubmissionData.LastPrice;
}
var timeInForceType = order.Properties.TimeInForce.GetType().Name;
// camelcase the type name, lowering the first char
TimeInForceType = char.ToLowerInvariant(timeInForceType[0]) + timeInForceType.Substring(1);
if (order.Properties.TimeInForce is GoodTilDateTimeInForce)
{
var expiry = (order.Properties.TimeInForce as GoodTilDateTimeInForce).Expiry;
TimeInForceExpiry = Time.DateTimeToUnixTimeStamp(expiry);
}
if (order.Type == OrderType.Limit)
{
var limit = order as LimitOrder;
LimitPrice = limit.LimitPrice;
}
else if (order.Type == OrderType.StopLimit)
{
var stopLimit = order as StopLimitOrder;
LimitPrice = stopLimit.LimitPrice;
StopPrice = stopLimit.StopPrice;
StopTriggered = stopLimit.StopTriggered;
}
else if (order.Type == OrderType.StopMarket)
{
var stopMarket = order as StopMarketOrder;
StopPrice = stopMarket.StopPrice;
}
}
}
}