Lean  $LEAN_TAG$
ZerodhaBrokerageModel.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.Linq;
19 using QuantConnect.Orders;
23 using QuantConnect.Util;
24 
25 
27 {
28  /// <summary>
29  /// Brokerage Model implementation for Zerodha
30  /// </summary>
32  {
33  private readonly Type[] _supportedTimeInForces =
34  {
36  typeof(DayTimeInForce),
38  };
39 
40  private readonly HashSet<OrderType> _supportedOrderTypes = new HashSet<OrderType>
41  {
42  OrderType.Limit,
43  OrderType.Market,
44  OrderType.StopMarket,
45  OrderType.StopLimit
46  };
47 
48  private const decimal _maxLeverage = 5m;
49 
50  /// <summary>
51  /// Initializes a new instance of the <see cref="ZerodhaBrokerageModel"/> class
52  /// </summary>
53  /// <param name="accountType">The type of account to be modelled, defaults to
54  /// <see cref="AccountType.Margin"/></param>
55  public ZerodhaBrokerageModel(AccountType accountType = AccountType.Margin) : base(accountType)
56  {
57  }
58 
59  /// <summary>
60  /// Returns true if the brokerage would be able to execute this order at this time assuming
61  /// market prices are sufficient for the fill to take place. This is used to emulate the
62  /// brokerage fills in backtesting and paper trading. For example some brokerages may not perform
63  /// executions during extended market hours. This is not intended to be checking whether or not
64  /// the exchange is open, that is handled in the Security.Exchange property.
65  /// </summary>
66  /// <param name="security"></param>
67  /// <param name="order">The order to test for execution</param>
68  /// <returns>True if the brokerage would be able to perform the execution, false otherwise</returns>
69  public override bool CanExecuteOrder(Security security, Order order)
70  {
71 
72  // validate security type
73  if (security.Type != SecurityType.Equity)
74  {
75  return false;
76  }
77 
78 
79  // validate time in force
80  if (!_supportedTimeInForces.Contains(order.TimeInForce.GetType()))
81  {
82  return false;
83  }
84 
85  return true;
86  }
87 
88  /// <summary>
89  /// Returns true if the brokerage could accept this order. This takes into account
90  /// order type, security type, and order size limits.
91  /// </summary>
92  /// <remarks>
93  /// For example, a brokerage may have no connectivity at certain times, or an order rate/size limit
94  /// </remarks>
95  /// <param name="security">The security being ordered</param>
96  /// <param name="order">The order to be processed</param>
97  /// <param name="message">If this function returns false, a brokerage message detailing why the order may not be submitted</param>
98  /// <returns>True if the brokerage could process the order, false otherwise</returns>
99  public override bool CanSubmitOrder(Security security, Order order, out BrokerageMessageEvent message)
100  {
101  message = null;
102 
103  // validate security type
104  if (security.Type != SecurityType.Equity)
105  {
106  message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
107  Messages.DefaultBrokerageModel.UnsupportedSecurityType(this, security));
108 
109  return false;
110  }
111 
112 
113  // validate order type
114  if (!_supportedOrderTypes.Contains(order.Type))
115  {
116  message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
117  Messages.DefaultBrokerageModel.UnsupportedOrderType(this, order, _supportedOrderTypes));
118 
119  return false;
120  }
121 
122 
123  // validate time in force
124  if (!_supportedTimeInForces.Contains(order.TimeInForce.GetType()))
125  {
126  message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
127  Messages.DefaultBrokerageModel.UnsupportedTimeInForce(this, order));
128 
129  return false;
130  }
131 
132  return true;
133  }
134 
135  /// <summary>
136  /// Returns true if the brokerage would allow updating the order as specified by the request
137  /// </summary>
138  /// <param name="security">The security of the order</param>
139  /// <param name="order">The order to be updated</param>
140  /// <param name="request">The requested update to be made to the order</param>
141  /// <param name="message">If this function returns false, a brokerage message detailing why the order may not be updated</param>
142  /// <returns>True if the brokerage would allow updating the order, false otherwise</returns>
143  public override bool CanUpdateOrder(Security security, Order order, UpdateOrderRequest request, out BrokerageMessageEvent message)
144  {
145  message = null;
146  return true;
147  }
148 
149  /// <summary>
150  /// Gets a map of the default markets to be used for each security type
151  /// </summary>
152  public override IReadOnlyDictionary<SecurityType, string> DefaultMarkets { get; } = GetDefaultMarkets();
153 
154  /// <summary>
155  /// Zerodha global leverage rule
156  /// </summary>
157  /// <param name="security"></param>
158  /// <returns></returns>
159  public override decimal GetLeverage(Security security)
160  {
161  if (AccountType == AccountType.Cash || security.IsInternalFeed() || security.Type == SecurityType.Base)
162  {
163  return 1m;
164  }
165 
166  if (security.Type == SecurityType.Equity || security.Type == SecurityType.Future || security.Type == SecurityType.Option || security.Type == SecurityType.Index)
167  {
168  return _maxLeverage;
169  }
170 
171  throw new ArgumentException(Messages.DefaultBrokerageModel.InvalidSecurityTypeForLeverage(security), nameof(security));
172  }
173 
174  /// <summary>
175  /// Provides Zerodha fee model
176  /// </summary>
177  /// <param name="security"></param>
178  /// <returns></returns>
179  public override IFeeModel GetFeeModel(Security security)
180  {
181  return new ZerodhaFeeModel();
182  }
183 
184  private static IReadOnlyDictionary<SecurityType, string> GetDefaultMarkets()
185  {
186  var map = DefaultMarketMap.ToDictionary();
187  map[SecurityType.Equity] = Market.India;
188 
189  return map.ToReadOnlyDictionary();
190  }
191  }
192 }