Lean  $LEAN_TAG$
BitfinexBrokerageModel.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;
20 using QuantConnect.Orders;
23 using QuantConnect.Util;
24 
26 {
27  /// <summary>
28  /// Provides Bitfinex specific properties
29  /// </summary>
31  {
32  private const decimal _maxLeverage = 3.3m;
33 
34  /// <summary>
35  /// Gets a map of the default markets to be used for each security type
36  /// </summary>
37  public override IReadOnlyDictionary<SecurityType, string> DefaultMarkets { get; } = GetDefaultMarkets();
38 
39  /// <summary>
40  /// Initializes a new instance of the <see cref="BitfinexBrokerageModel"/> class
41  /// </summary>
42  /// <param name="accountType">The type of account to be modeled, defaults to <see cref="AccountType.Margin"/></param>
43  public BitfinexBrokerageModel(AccountType accountType = AccountType.Margin)
44  : base(accountType)
45  {
46  }
47 
48  /// <summary>
49  /// Bitfinex global leverage rule
50  /// </summary>
51  /// <param name="security"></param>
52  /// <returns></returns>
53  public override decimal GetLeverage(Security security)
54  {
55  if (AccountType == AccountType.Cash || security.IsInternalFeed() || security.Type == SecurityType.Base)
56  {
57  return 1m;
58  }
59 
60  if (security.Type == SecurityType.Crypto)
61  {
62  return _maxLeverage;
63  }
64 
65  throw new ArgumentException(Messages.DefaultBrokerageModel.InvalidSecurityTypeForLeverage(security), nameof(security));
66  }
67 
68  /// <summary>
69  /// Get the benchmark for this model
70  /// </summary>
71  /// <param name="securities">SecurityService to create the security with if needed</param>
72  /// <returns>The benchmark for this brokerage</returns>
73  public override IBenchmark GetBenchmark(SecurityManager securities)
74  {
75  var symbol = Symbol.Create("BTCUSD", SecurityType.Crypto, Market.Bitfinex);
76  return SecurityBenchmark.CreateInstance(securities, symbol);
77  }
78 
79  /// <summary>
80  /// Provides Bitfinex fee model
81  /// </summary>
82  /// <param name="security"></param>
83  /// <returns></returns>
84  public override IFeeModel GetFeeModel(Security security)
85  {
86  return new BitfinexFeeModel();
87  }
88 
89  /// <summary>
90  /// Checks whether an order can be updated or not in the Bitfinex brokerage model
91  /// </summary>
92  /// <param name="security">The security of the order</param>
93  /// <param name="order">The order to be updated</param>
94  /// <param name="request">The update request</param>
95  /// <param name="message">If this function returns false, a brokerage message detailing why the order may not be updated</param>
96  /// <returns>True if the update requested quantity is valid, false otherwise</returns>
97  public override bool CanUpdateOrder(Security security, Order order, UpdateOrderRequest request, out BrokerageMessageEvent message)
98  {
99  // If the requested quantity is null is going to be ignored by the moment ApplyUpdateOrderRequest() method is call
100  if (request.Quantity == null)
101  {
102  message = null;
103  return true;
104  }
105 
106  // Check if the requested quantity is valid
107  var requestedQuantity = (decimal) request.Quantity;
108  return IsValidOrderSize(security, requestedQuantity, out message);
109  }
110 
111  /// <summary>
112  /// Returns true if the brokerage could accept this order. This takes into account
113  /// order type, security type, and order size limits.
114  /// </summary>
115  /// <remarks>
116  /// For example, a brokerage may have no connectivity at certain times, or an order rate/size limit
117  /// </remarks>
118  /// <param name="security">The security of the order</param>
119  /// <param name="order">The order to be processed</param>
120  /// <param name="message">If this function returns false, a brokerage message detailing why the order may not be submitted</param>
121  /// <returns>True if the brokerage could process the order, false otherwise</returns>
122  public override bool CanSubmitOrder(Security security, Order order, out BrokerageMessageEvent message)
123  {
124  if (!IsValidOrderSize(security, order.Quantity, out message))
125  {
126  return false;
127  }
128 
129  message = null;
130  if (security.Type != SecurityType.Crypto)
131  {
132  message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
133  Messages.DefaultBrokerageModel.UnsupportedSecurityType(this, security));
134 
135  return false;
136  }
137  return base.CanSubmitOrder(security, order, out message);
138  }
139 
140  private static IReadOnlyDictionary<SecurityType, string> GetDefaultMarkets()
141  {
142  var map = DefaultMarketMap.ToDictionary();
143  map[SecurityType.Crypto] = Market.Bitfinex;
144  return map.ToReadOnlyDictionary();
145  }
146  }
147 }