Lean  $LEAN_TAG$
BybitFeeModel.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.Util;
18 
19 namespace QuantConnect.Orders.Fees;
20 
21 /// <summary>
22 /// Bybit fee model implementation
23 /// </summary>
24 public class BybitFeeModel : FeeModel
25 {
26  /// <summary>
27  /// Tier 1 maker fees
28  /// https://learn.bybit.com/bybit-guide/bybit-trading-fees/
29  /// </summary>
30  public const decimal MakerNonVIPFee = 0.001m;
31 
32  /// <summary>
33  /// Tier 1 taker fees
34  /// https://learn.bybit.com/bybit-guide/bybit-trading-fees/
35  /// </summary>
36  public const decimal TakerNonVIPFee = 0.001m;
37 
38  private readonly decimal _makerFee;
39  private readonly decimal _takerFee;
40 
41  /// <summary>
42  /// Creates Binance fee model setting fees values
43  /// </summary>
44  /// <param name="mFee">Maker fee value</param>
45  /// <param name="tFee">Taker fee value</param>
46  public BybitFeeModel(decimal mFee = MakerNonVIPFee, decimal tFee = TakerNonVIPFee)
47  {
48  _makerFee = mFee;
49  _takerFee = tFee;
50  }
51 
52  /// <summary>
53  /// Gets the order fee associated with the specified order.
54  /// </summary>
55  /// <param name="parameters">A <see cref="OrderFeeParameters"/> object
56  /// containing the security and order</param>
57  /// <returns>The cost of the order in a <see cref="CashAmount"/> instance</returns>
58  public override OrderFee GetOrderFee(OrderFeeParameters parameters)
59  {
60  var security = parameters.Security;
61  var order = parameters.Order;
62 
63  var fee = GetFee(order);
64 
65  if(security.Symbol.ID.SecurityType == SecurityType.CryptoFuture)
66  {
67  var positionValue = security.Holdings.GetQuantityValue(order.AbsoluteQuantity, security.Price);
68  return new OrderFee(new CashAmount(positionValue.Amount * fee, positionValue.Cash.Symbol));
69  }
70 
71  if (order.Direction == OrderDirection.Buy)
72  {
73  // fees taken in the received currency
74  CurrencyPairUtil.DecomposeCurrencyPair(order.Symbol, out var baseCurrency, out _);
75  return new OrderFee(new CashAmount(order.AbsoluteQuantity * fee, baseCurrency));
76  }
77 
78  // get order value in quote currency
79  var unitPrice = security.BidPrice;
80  if (order.Type == OrderType.Limit)
81  {
82  // limit order posted to the order book
83  unitPrice = ((LimitOrder)order).LimitPrice;
84  }
85 
86  unitPrice *= security.SymbolProperties.ContractMultiplier;
87 
88  return new OrderFee(new CashAmount(
89  unitPrice * order.AbsoluteQuantity * fee,
90  security.QuoteCurrency.Symbol));
91  }
92 
93  /// <summary>
94  /// Gets the fee factor for the given order
95  /// </summary>
96  /// <param name="order">The order to get the fee factor for</param>
97  /// <returns>The fee factor for the given order</returns>
98  protected virtual decimal GetFee(Order order)
99  {
100  return GetFee(order, _makerFee, _takerFee);
101  }
102 
103  private static decimal GetFee(Order order, decimal makerFee, decimal takerFee)
104  {
105  // apply fee factor, currently we do not model 30-day volume, so we use the first tier
106  var fee = takerFee;
107  var props = order.Properties as BybitOrderProperties;
108 
109  if (order.Type == OrderType.Limit && ((props != null && props.PostOnly) || !order.IsMarketable))
110  {
111  // limit order posted to the order book
112  fee = makerFee;
113  }
114 
115  return fee;
116  }
117 }