Lean  $LEAN_TAG$
Order.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.ComponentModel;
19 using System.Linq;
20 using System.Threading;
21 using Newtonsoft.Json;
25 
26 namespace QuantConnect.Orders
27 {
28  /// <summary>
29  /// Order struct for placing new trade
30  /// </summary>
31  public abstract class Order
32  {
33  private volatile int _incrementalId;
34  private decimal _quantity;
35  private decimal _price;
36 
37  /// <summary>
38  /// Order ID.
39  /// </summary>
40  [JsonProperty(PropertyName = "id")]
41  public int Id { get; internal set; }
42 
43  /// <summary>
44  /// Order id to process before processing this order.
45  /// </summary>
46  [JsonProperty(PropertyName = "contingentId")]
47  public int ContingentId { get; internal set; }
48 
49  /// <summary>
50  /// Brokerage Id for this order for when the brokerage splits orders into multiple pieces
51  /// </summary>
52  [JsonProperty(PropertyName = "brokerId")]
53  public List<string> BrokerId { get; internal set; }
54 
55  /// <summary>
56  /// Symbol of the Asset
57  /// </summary>
58  [JsonProperty(PropertyName = "symbol")]
59  public Symbol Symbol { get; internal set; }
60 
61  /// <summary>
62  /// Price of the Order.
63  /// </summary>
64  [JsonProperty(PropertyName = "price")]
65  public decimal Price
66  {
67  get { return _price; }
68  internal set { _price = value.Normalize(); }
69  }
70 
71  /// <summary>
72  /// Currency for the order price
73  /// </summary>
74  [JsonProperty(PropertyName = "priceCurrency")]
75  public string PriceCurrency { get; internal set; }
76 
77  /// <summary>
78  /// Gets the utc time the order was created.
79  /// </summary>
80  [JsonProperty(PropertyName = "time")]
81  public DateTime Time { get; internal set; }
82 
83  /// <summary>
84  /// Gets the utc time this order was created. Alias for <see cref="Time"/>
85  /// </summary>
86  [JsonProperty(PropertyName = "createdTime")]
87  public DateTime CreatedTime => Time;
88 
89  /// <summary>
90  /// Gets the utc time the last fill was received, or null if no fills have been received
91  /// </summary>
92  [JsonProperty(PropertyName = "lastFillTime", NullValueHandling = NullValueHandling.Ignore)]
93  public DateTime? LastFillTime { get; internal set; }
94 
95  /// <summary>
96  /// Gets the utc time this order was last updated, or null if the order has not been updated.
97  /// </summary>
98  [JsonProperty(PropertyName = "lastUpdateTime", NullValueHandling = NullValueHandling.Ignore)]
99  public DateTime? LastUpdateTime { get; internal set; }
100 
101  /// <summary>
102  /// Gets the utc time this order was canceled, or null if the order was not canceled.
103  /// </summary>
104  [JsonProperty(PropertyName = "canceledTime", NullValueHandling = NullValueHandling.Ignore)]
105  public DateTime? CanceledTime { get; internal set; }
106 
107  /// <summary>
108  /// Number of shares to execute.
109  /// </summary>
110  [JsonProperty(PropertyName = "quantity")]
111  public virtual decimal Quantity
112  {
113  get { return _quantity; }
114  internal set { _quantity = value.Normalize(); }
115  }
116 
117  /// <summary>
118  /// Order Type
119  /// </summary>
120  [JsonProperty(PropertyName = "type")]
121  public abstract OrderType Type { get; }
122 
123  /// <summary>
124  /// Status of the Order
125  /// </summary>
126  [JsonProperty(PropertyName = "status")]
127  public OrderStatus Status { get; set; }
128 
129  /// <summary>
130  /// Order Time In Force
131  /// </summary>
132  [JsonIgnore]
134 
135  /// <summary>
136  /// Tag the order with some custom data
137  /// </summary>
138  [JsonProperty(PropertyName = "tag" ,DefaultValueHandling = DefaultValueHandling.Ignore)]
139  public string Tag { get; internal set; }
140 
141  /// <summary>
142  /// Additional properties of the order
143  /// </summary>
144  [JsonProperty(PropertyName = "properties")]
145  public IOrderProperties Properties { get; private set; }
146 
147  /// <summary>
148  /// The symbol's security type
149  /// </summary>
150  [JsonProperty(PropertyName = "securityType")]
152 
153  /// <summary>
154  /// Order Direction Property based off Quantity.
155  /// </summary>
156  [JsonProperty(PropertyName = "direction")]
158  {
159  get
160  {
161  if (Quantity > 0)
162  {
163  return OrderDirection.Buy;
164  }
165  if (Quantity < 0)
166  {
167  return OrderDirection.Sell;
168  }
169  return OrderDirection.Hold;
170  }
171  }
172 
173  /// <summary>
174  /// Get the absolute quantity for this order
175  /// </summary>
176  [JsonIgnore]
177  public decimal AbsoluteQuantity => Math.Abs(Quantity);
178 
179  /// <summary>
180  /// Deprecated
181  /// </summary>
182  [JsonProperty(PropertyName = "value"), Obsolete("Please use Order.GetValue(security) or security.Holdings.HoldingsValue")]
183  public decimal Value => Quantity * Price;
184 
185  /// <summary>
186  /// Gets the price data at the time the order was submitted
187  /// </summary>
188  [JsonProperty(PropertyName = "orderSubmissionData")]
189  public OrderSubmissionData OrderSubmissionData { get; internal set; }
190 
191  /// <summary>
192  /// Returns true if the order is a marketable order.
193  /// </summary>
194  [JsonProperty(PropertyName = "isMarketable")]
195  public bool IsMarketable
196  {
197  get
198  {
199  if (Type == OrderType.Limit)
200  {
201  // check if marketable limit order using bid/ask prices
202  var limitOrder = (LimitOrder)this;
203  return OrderSubmissionData != null &&
204  (Direction == OrderDirection.Buy && limitOrder.LimitPrice >= OrderSubmissionData.AskPrice ||
205  Direction == OrderDirection.Sell && limitOrder.LimitPrice <= OrderSubmissionData.BidPrice);
206  }
207 
208  return Type == OrderType.Market || Type == OrderType.ComboMarket;
209  }
210  }
211 
212  /// <summary>
213  /// Manager for the orders in the group if this is a combo order
214  /// </summary>
215  [JsonProperty(PropertyName = "groupOrderManager", DefaultValueHandling = DefaultValueHandling.Ignore)]
217 
218  /// <summary>
219  /// The adjustment mode used on the order fill price
220  /// </summary>
221  [JsonProperty(PropertyName = "priceAdjustmentMode")]
223 
224  /// <summary>
225  /// Added a default constructor for JSON Deserialization:
226  /// </summary>
227  protected Order()
228  {
229  Time = new DateTime();
230  PriceCurrency = string.Empty;
231  Symbol = Symbol.Empty;
232  Status = OrderStatus.None;
233  Tag = string.Empty;
234  BrokerId = new List<string>();
235  Properties = new OrderProperties();
236  GroupOrderManager = null;
237  }
238 
239  /// <summary>
240  /// New order constructor
241  /// </summary>
242  /// <param name="symbol">Symbol asset we're seeking to trade</param>
243  /// <param name="quantity">Quantity of the asset we're seeking to trade</param>
244  /// <param name="time">Time the order was placed</param>
245  /// <param name="groupOrderManager">Manager for the orders in the group if this is a combo order</param>
246  /// <param name="tag">User defined data tag for this order</param>
247  /// <param name="properties">The order properties for this order</param>
248  protected Order(Symbol symbol, decimal quantity, DateTime time, GroupOrderManager groupOrderManager, string tag = "",
249  IOrderProperties properties = null)
250  {
251  Time = time;
252  PriceCurrency = string.Empty;
253  Quantity = quantity;
254  Symbol = symbol;
255  Status = OrderStatus.None;
256  Tag = tag;
257  BrokerId = new List<string>();
258  Properties = properties ?? new OrderProperties();
259  GroupOrderManager = groupOrderManager;
260  }
261 
262  /// <summary>
263  /// New order constructor
264  /// </summary>
265  /// <param name="symbol">Symbol asset we're seeking to trade</param>
266  /// <param name="quantity">Quantity of the asset we're seeking to trade</param>
267  /// <param name="time">Time the order was placed</param>
268  /// <param name="tag">User defined data tag for this order</param>
269  /// <param name="properties">The order properties for this order</param>
270  protected Order(Symbol symbol, decimal quantity, DateTime time, string tag = "", IOrderProperties properties = null)
271  : this(symbol, quantity, time, null, tag, properties)
272  {
273  }
274 
275  /// <summary>
276  /// Creates an enumerable containing each position resulting from executing this order.
277  /// </summary>
278  /// <remarks>
279  /// This is provided in anticipation of a new combo order type that will need to override this method,
280  /// returning a position for each 'leg' of the order.
281  /// </remarks>
282  /// <returns>An enumerable of positions matching the results of executing this order</returns>
283  public virtual IEnumerable<IPosition> CreatePositions(SecurityManager securities)
284  {
285  var security = securities[Symbol];
286  yield return new Position(security, Quantity);
287  }
288 
289  /// <summary>
290  /// Gets the value of this order at the given market price in units of the account currency
291  /// NOTE: Some order types derive value from other parameters, such as limit prices
292  /// </summary>
293  /// <param name="security">The security matching this order's symbol</param>
294  /// <returns>The value of this order given the current market price</returns>
295  /// <remarks>TODO: we should remove this. Only used in tests</remarks>
296  public decimal GetValue(Security security)
297  {
298  var value = GetValueImpl(security);
299  return value*security.QuoteCurrency.ConversionRate*security.SymbolProperties.ContractMultiplier;
300  }
301 
302  /// <summary>
303  /// Gets the order value in units of the security's quote currency for a single unit.
304  /// A single unit here is a single share of stock, or a single barrel of oil, or the
305  /// cost of a single share in an option contract.
306  /// </summary>
307  /// <param name="security">The security matching this order's symbol</param>
308  protected abstract decimal GetValueImpl(Security security);
309 
310  /// <summary>
311  /// Gets the default tag for this order
312  /// </summary>
313  /// <returns>The default tag</returns>
314  public virtual string GetDefaultTag()
315  {
316  return string.Empty;
317  }
318 
319  /// <summary>
320  /// Gets a new unique incremental id for this order
321  /// </summary>
322  /// <returns>Returns a new id for this order</returns>
323  internal int GetNewId()
324  {
325  return Interlocked.Increment(ref _incrementalId);
326  }
327 
328  /// <summary>
329  /// Modifies the state of this order to match the update request
330  /// </summary>
331  /// <param name="request">The request to update this order object</param>
332  public virtual void ApplyUpdateOrderRequest(UpdateOrderRequest request)
333  {
334  if (request.OrderId != Id)
335  {
336  throw new ArgumentException("Attempted to apply updates to the incorrect order!");
337  }
338  if (request.Quantity.HasValue)
339  {
340  Quantity = request.Quantity.Value;
341  }
342  if (request.Tag != null)
343  {
344  Tag = request.Tag;
345  }
346  }
347 
348  /// <summary>
349  /// Returns a string that represents the current object.
350  /// </summary>
351  /// <returns>
352  /// A string that represents the current object.
353  /// </returns>
354  /// <filterpriority>2</filterpriority>
355  public override string ToString()
356  {
357  return Messages.Order.ToString(this);
358  }
359 
360  /// <summary>
361  /// Creates a deep-copy clone of this order
362  /// </summary>
363  /// <returns>A copy of this order</returns>
364  public abstract Order Clone();
365 
366  /// <summary>
367  /// Copies base Order properties to the specified order
368  /// </summary>
369  /// <param name="order">The target of the copy</param>
370  protected void CopyTo(Order order)
371  {
372  order.Id = Id;
373  // The group order manager has to be set before the quantity,
374  // since combo orders might need it to calculate the quantity in the Quantity setter.
376  order.Time = Time;
377  order.LastFillTime = LastFillTime;
379  order.CanceledTime = CanceledTime;
380  order.BrokerId = BrokerId.ToList();
381  order.ContingentId = ContingentId;
382  order.Price = Price;
384  order.Quantity = Quantity;
385  order.Status = Status;
386  order.Symbol = Symbol;
387  order.Tag = Tag;
388  order.Properties = Properties.Clone();
391  }
392 
393  /// <summary>
394  /// Creates an <see cref="Order"/> to match the specified <paramref name="request"/>
395  /// </summary>
396  /// <param name="request">The <see cref="SubmitOrderRequest"/> to create an order for</param>
397  /// <returns>The <see cref="Order"/> that matches the request</returns>
398  public static Order CreateOrder(SubmitOrderRequest request)
399  {
400  return CreateOrder(request.OrderId, request.OrderType, request.Symbol, request.Quantity, request.Time,
401  request.Tag, request.OrderProperties, request.LimitPrice, request.StopPrice, request.TriggerPrice, request.TrailingAmount,
402  request.TrailingAsPercentage, request.GroupOrderManager);
403  }
404 
405  private static Order CreateOrder(int orderId, OrderType type, Symbol symbol, decimal quantity, DateTime time,
406  string tag, IOrderProperties properties, decimal limitPrice, decimal stopPrice, decimal triggerPrice, decimal trailingAmount,
407  bool trailingAsPercentage, GroupOrderManager groupOrderManager)
408  {
409  Order order;
410  switch (type)
411  {
412  case OrderType.Market:
413  order = new MarketOrder(symbol, quantity, time, tag, properties);
414  break;
415 
416  case OrderType.Limit:
417  order = new LimitOrder(symbol, quantity, limitPrice, time, tag, properties);
418  break;
419 
420  case OrderType.StopMarket:
421  order = new StopMarketOrder(symbol, quantity, stopPrice, time, tag, properties);
422  break;
423 
424  case OrderType.StopLimit:
425  order = new StopLimitOrder(symbol, quantity, stopPrice, limitPrice, time, tag, properties);
426  break;
427 
428  case OrderType.TrailingStop:
429  order = new TrailingStopOrder(symbol, quantity, stopPrice, trailingAmount, trailingAsPercentage, time, tag, properties);
430  break;
431 
432  case OrderType.LimitIfTouched:
433  order = new LimitIfTouchedOrder(symbol, quantity, triggerPrice, limitPrice, time, tag, properties);
434  break;
435 
436  case OrderType.MarketOnOpen:
437  order = new MarketOnOpenOrder(symbol, quantity, time, tag, properties);
438  break;
439 
440  case OrderType.MarketOnClose:
441  order = new MarketOnCloseOrder(symbol, quantity, time, tag, properties);
442  break;
443 
444  case OrderType.OptionExercise:
445  order = new OptionExerciseOrder(symbol, quantity, time, tag, properties);
446  break;
447 
448  case OrderType.ComboLimit:
449  order = new ComboLimitOrder(symbol, quantity, limitPrice, time, groupOrderManager, tag, properties);
450  break;
451 
452  case OrderType.ComboLegLimit:
453  order = new ComboLegLimitOrder(symbol, quantity, limitPrice, time, groupOrderManager, tag, properties);
454  break;
455 
456  case OrderType.ComboMarket:
457  order = new ComboMarketOrder(symbol, quantity, time, groupOrderManager, tag, properties);
458  break;
459 
460  default:
461  throw new ArgumentOutOfRangeException();
462  }
463  order.Status = OrderStatus.New;
464  order.Id = orderId;
465  if (groupOrderManager != null)
466  {
467  lock (groupOrderManager.OrderIds)
468  {
469  groupOrderManager.OrderIds.Add(orderId);
470  }
471  }
472  return order;
473  }
474  }
475 }