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