Lean  $LEAN_TAG$
GoodTilDateTimeInForce.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;
18 
20 {
21  /// <summary>
22  /// Good Til Date Time In Force - order expires and will be cancelled on a fixed date/time
23  /// </summary>
25  {
26  /// <summary>
27  /// The date/time on which the order will expire and will be cancelled
28  /// </summary>
29  /// <remarks>The private set is required for JSON deserialization</remarks>
30  public DateTime Expiry { get; private set; }
31 
32  /// <summary>
33  /// Initializes a new instance of the <see cref="GoodTilDateTimeInForce"/> class
34  /// </summary>
35  /// <remarks>This constructor is required for JSON deserialization</remarks>
36  private GoodTilDateTimeInForce()
37  {
38  }
39 
40  /// <summary>
41  /// Initializes a new instance of the <see cref="GoodTilDateTimeInForce"/> class
42  /// </summary>
43  public GoodTilDateTimeInForce(DateTime expiry)
44  {
45  Expiry = expiry;
46  }
47 
48  /// <summary>
49  /// Checks if an order is expired
50  /// </summary>
51  /// <param name="security">The security matching the order</param>
52  /// <param name="order">The order to be checked</param>
53  /// <returns>Returns true if the order has expired, false otherwise</returns>
54  public override bool IsOrderExpired(Security security, Order order)
55  {
56  var exchangeHours = security.Exchange.Hours;
57 
58  var time = security.LocalTime;
59 
60  bool expired;
61  switch (order.SecurityType)
62  {
63  case SecurityType.Forex:
64  case SecurityType.Cfd:
65  // With real brokerages (IB, Oanda, FXCM have been verified) FX orders expire at 5 PM NewYork time.
66  // For now we use this fixed cut-off time, in future we might get this value from brokerage models,
67  // to support custom brokerage implementations.
68  expired = time.ConvertToUtc(exchangeHours.TimeZone) >= GetForexOrderExpiryDateTime(order);
69  break;
70 
71  case SecurityType.Crypto:
72  case SecurityType.CryptoFuture:
73  // expires at midnight after expiry date
74  expired = time.Date > Expiry.Date;
75  break;
76 
77  case SecurityType.Equity:
78  case SecurityType.Option:
79  case SecurityType.Future:
80  case SecurityType.FutureOption:
81  case SecurityType.IndexOption:
82  default:
83  // expires at market close of expiry date
84  expired = time >= exchangeHours.GetNextMarketClose(Expiry.Date, false);
85  break;
86  }
87 
88  return expired;
89  }
90 
91  /// <summary>
92  /// Checks if an order fill is valid
93  /// </summary>
94  /// <param name="security">The security matching the order</param>
95  /// <param name="order">The order to be checked</param>
96  /// <param name="fill">The order fill to be checked</param>
97  /// <returns>Returns true if the order fill can be emitted, false otherwise</returns>
98  public override bool IsFillValid(Security security, Order order, OrderEvent fill)
99  {
100  return true;
101  }
102 
103  /// <summary>
104  /// Returns the expiry date and time (UTC) for a Forex order
105  /// </summary>
106  public DateTime GetForexOrderExpiryDateTime(Order order)
107  {
108  var cutOffTimeZone = TimeZones.NewYork;
109  var cutOffTimeSpan = TimeSpan.FromHours(17);
110 
111  var expiryTime = Expiry.Date.Add(cutOffTimeSpan);
112  if (order.Time.Date == Expiry.Date)
113  {
114  // expiry date same as order date
115  var orderTime = order.Time.ConvertFromUtc(cutOffTimeZone);
116  if (orderTime.TimeOfDay > cutOffTimeSpan)
117  {
118  // order submitted after 5 PM, expiry on next date
119  expiryTime = expiryTime.AddDays(1);
120  }
121  }
122 
123  return expiryTime.ConvertToUtc(cutOffTimeZone);
124  }
125  }
126 }