Lean  $LEAN_TAG$
EzeBrokerageModel.cs
1 /*
2 * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
3 * Lean Algorithmic Trading Engine v2.0. Copyright 2023 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 QuantConnect.Orders;
19 using System;
20 using System.Collections.Generic;
21 
23 {
24  /// <summary>
25  /// Provides Eze specific properties
26  /// </summary>
28  {
29  /// <summary>
30  /// Array's Eze supports security types
31  /// </summary>
32  private readonly HashSet<SecurityType> _supportSecurityTypes = new(
33  new[]
34  {
35  SecurityType.Equity,
36  SecurityType.Option,
37  SecurityType.Future,
38  SecurityType.FutureOption,
39  SecurityType.Index,
40  SecurityType.IndexOption
41  });
42 
43  /// <summary>
44  /// Array's Eze supports order types
45  /// </summary>
46  private readonly HashSet<OrderType> _supportOrderTypes = new(
47  new[]
48  {
49  OrderType.Market,
50  OrderType.Limit,
51  OrderType.StopMarket,
52  OrderType.StopLimit,
53  OrderType.MarketOnOpen,
54  OrderType.MarketOnClose,
55  });
56 
57  /// <summary>
58  /// Constructor for Eze brokerage model
59  /// </summary>
60  /// <param name="accountType">Cash or Margin</param>
61  public EzeBrokerageModel(AccountType accountType = AccountType.Margin) : base(accountType)
62  {
63  if (accountType == AccountType.Cash)
64  {
65  throw new NotSupportedException($"Eze brokerage can only be used with a {AccountType.Margin} account type");
66  }
67  }
68 
69  /// <summary>
70  /// Provides Eze fee model
71  /// </summary>
72  /// <param name="security">Security</param>
73  /// <returns>Eze Fee model</returns>
74  public override IFeeModel GetFeeModel(Security security)
75  {
76  return new EzeFeeModel();
77  }
78 
79  /// <summary>
80  /// Returns true if the brokerage could accept this order. This takes into account
81  /// order type, security type, and order size limits.
82  /// </summary>
83  /// <remarks>
84  /// For example, a brokerage may have no connectivity at certain times, or an order rate/size limit
85  /// </remarks>
86  /// <param name="security">The security of the order</param>
87  /// <param name="order">The order to be processed</param>
88  /// <param name="message">>If this function returns false, a brokerage message detailing why the order may not be submitted</param>
89  /// <returns>True if the brokerage could process the order, false otherwise</returns>
90  public override bool CanSubmitOrder(Security security, Order order, out BrokerageMessageEvent message)
91  {
92  var ezeOrderProperties = order.Properties as EzeOrderProperties;
93  if(ezeOrderProperties == null)
94  {
95  message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "InvalidOrderParam",
96  $"Order properties should be of type '{nameof(EzeOrderProperties)}'");
97  }
98 
99  if (string.IsNullOrEmpty(ezeOrderProperties.Account))
100  {
101  message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "InvalidOrderParam",
102  "Required order properties Account not set properly.");
103  return false;
104  }
105 
106  if (string.IsNullOrEmpty(ezeOrderProperties.Route))
107  {
108  message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "InvalidOrderParam",
109  "Required order properties Route not set properly.");
110  return false;
111  }
112 
113  if (!_supportSecurityTypes.Contains(security.Type))
114  {
115  message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
117 
118  return false;
119  }
120 
121  if (!_supportOrderTypes.Contains(order.Type))
122  {
123  message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
124  Messages.DefaultBrokerageModel.UnsupportedOrderType(this, order, _supportOrderTypes));
125 
126  return false;
127  }
128 
129  if (order.AbsoluteQuantity % 1 != 0)
130  {
131  message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
132  $"Order Quantity must be Integer, but provided {order.AbsoluteQuantity}.");
133 
134  return false;
135  }
136 
137  return base.CanSubmitOrder(security, order, out message);
138  }
139 
140  /// <summary>
141  /// Returns true if the brokerage could accept this order update. This takes into account
142  /// order type, security type, and order size limits.
143  /// </summary>
144  /// <param name="security">The security of the order</param>
145  /// <param name="order">The order to be updated</param>
146  /// <param name="request">The requested update to be made to the order</param>
147  /// <param name="message">If this function returns false, a brokerage message detailing why the order may not be updated</param>
148  /// <returns>True if the brokerage could update the order, false otherwise</returns>
149  /// <remarks>
150  /// The Eze supports update:
151  /// - quantity <see cref="Order.Quantity"/>
152  /// - LimitPrice <see cref="LimitOrder.LimitPrice"/>
153  /// - StopPrice <see cref="StopLimitOrder.StopPrice"/>
154  /// - OrderType <seealso cref="OrderType"/>
155  /// - Time In Force <see cref="Order.TimeInForce"/>
156  /// </remarks>
157  public override bool CanUpdateOrder(Security security, Order order, UpdateOrderRequest request, out BrokerageMessageEvent message)
158  {
159  message = null;
160  return true;
161  }
162  }
163 }