diff --git a/QuantConnect.BybitBrokerage.Tests/BybitBrokerageTests.cs b/QuantConnect.BybitBrokerage.Tests/BybitBrokerageTests.cs index 6bf5e59..0a5942e 100644 --- a/QuantConnect.BybitBrokerage.Tests/BybitBrokerageTests.cs +++ b/QuantConnect.BybitBrokerage.Tests/BybitBrokerageTests.cs @@ -22,6 +22,7 @@ using QuantConnect.BybitBrokerage.Api; using QuantConnect.BybitBrokerage.Models.Enums; using QuantConnect.Configuration; +using QuantConnect.Data; using QuantConnect.Interfaces; using QuantConnect.Lean.Engine.DataFeeds; using QuantConnect.Logging; @@ -63,8 +64,16 @@ protected override IBrokerage CreateBrokerage(IOrderProvider orderProvider, ISec var websocketUrl = Config.Get("bybit-websocket-url", "wss://stream-testnet.bybit.com"); _client = CreateRestApiClient(apiKey, apiSecret, apiUrl); - return new BybitBrokerage(apiKey, apiSecret, apiUrl, websocketUrl, algorithm.Object, orderProvider, - securityProvider, new AggregationManager(), null); + + return CreateBrokerage(apiKey, apiSecret, apiUrl, websocketUrl, algorithm.Object, orderProvider, securityProvider, new AggregationManager()); + } + + protected virtual IBrokerage CreateBrokerage(string apiKey, string apiSecret, string apiUrl, + string websocketUrl, IAlgorithm algorithm, IOrderProvider orderProvider, ISecurityProvider securityProvider, + IDataAggregator aggregator) + { + return new BybitBrokerage(apiKey, apiSecret, apiUrl, websocketUrl, algorithm, orderProvider, securityProvider, new AggregationManager(), null); + } protected virtual decimal TakerFee => BybitFeeModel.TakerNonVIPFee; @@ -199,7 +208,7 @@ public override void GetAccountHoldings() var afterQuantity = afterHoldings == null ? 0 : afterHoldings.Amount; var fee = order.Quantity * TakerFee; - + Assert.AreEqual(GetDefaultQuantity(), afterQuantity - beforeQuantity + fee); } diff --git a/QuantConnect.BybitBrokerage.Tests/BybitInverseFuturesBrokerageAdditionalTests.cs b/QuantConnect.BybitBrokerage.Tests/BybitInverseFuturesBrokerageAdditionalTests.cs new file mode 100644 index 0000000..dda904c --- /dev/null +++ b/QuantConnect.BybitBrokerage.Tests/BybitInverseFuturesBrokerageAdditionalTests.cs @@ -0,0 +1,36 @@ +/* + * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. + * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +using NUnit.Framework; +using QuantConnect.Brokerages; +using QuantConnect.Interfaces; +using QuantConnect.Lean.Engine.DataFeeds; + +namespace QuantConnect.BybitBrokerage.Tests +{ + [TestFixture, Explicit("Requires valid credentials to be setup and run outside USA")] + public class BybitInverseFuturesBrokerageAdditionalTests : BybitBrokerageAdditionalTests + { + protected override string BrokerageName => nameof(BybitInverseFuturesBrokerage); + + + protected override Brokerage CreateBrokerage(IAlgorithm algorithm, string apiKey, string apiSecret, + string apiUrl, string websocketUrl) + { + return new BybitInverseFuturesBrokerage(apiKey, apiSecret, apiUrl, websocketUrl, algorithm, new AggregationManager(), + null); + } + } +} \ No newline at end of file diff --git a/QuantConnect.BybitBrokerage.Tests/BybitInverseFuturesBrokerageHistoryProviderTests.cs b/QuantConnect.BybitBrokerage.Tests/BybitInverseFuturesBrokerageHistoryProviderTests.cs new file mode 100644 index 0000000..31f8523 --- /dev/null +++ b/QuantConnect.BybitBrokerage.Tests/BybitInverseFuturesBrokerageHistoryProviderTests.cs @@ -0,0 +1,54 @@ +/* + * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. + * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +using System; +using NUnit.Framework; + +namespace QuantConnect.BybitBrokerage.Tests +{ + [TestFixture, Explicit("Requires valid credentials to be setup and run outside USA")] + public class BybitInverseFuturesBrokerageHistoryProviderTests : BybitBrokerageHistoryProviderTests + { + private static readonly Symbol ETHUSD = Symbol.Create("ETHUSDT", SecurityType.CryptoFuture, Market.Bybit); + + private static TestCaseData[] ValidHistory + { + get + { + return new[] + { + // valid + new TestCaseData(ETHUSD, Resolution.Tick, Time.OneMinute, TickType.Trade), + new TestCaseData(ETHUSD, Resolution.Minute, Time.OneHour, TickType.Trade), + new TestCaseData(ETHUSD, Resolution.Hour, Time.OneDay, TickType.Trade), + new TestCaseData(ETHUSD, Resolution.Daily, TimeSpan.FromDays(15), TickType.Trade), + new TestCaseData(ETHUSD, Resolution.Hour, Time.OneDay, TickType.OpenInterest) + }; + } + } + + [Test, TestCaseSource(nameof(ValidHistory))] + public override void GetsHistory(Symbol symbol, Resolution resolution, TimeSpan period, TickType tickType) + { + base.GetsHistory(symbol, resolution, period, tickType); + } + + [Ignore("The brokerage is shared between different product categories, therefore this test is only required in the base class")] + public override void GetEmptyHistory(Symbol symbol, Resolution resolution, TimeSpan period, TickType tickType) + { + base.GetEmptyHistory(symbol, resolution, period, tickType); + } + } +} \ No newline at end of file diff --git a/QuantConnect.BybitBrokerage.Tests/BybitInverseFuturesBrokerageTests.Stream.cs b/QuantConnect.BybitBrokerage.Tests/BybitInverseFuturesBrokerageTests.Stream.cs new file mode 100644 index 0000000..0bdf798 --- /dev/null +++ b/QuantConnect.BybitBrokerage.Tests/BybitInverseFuturesBrokerageTests.Stream.cs @@ -0,0 +1,43 @@ +/* + * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. + * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +using NUnit.Framework; + +namespace QuantConnect.BybitBrokerage.Tests +{ + [TestFixture] + public partial class BybitInverseFuturesBrokerageTests + { + private static TestCaseData[] TestParameters + { + get + { + return new[] + { + // valid parameters, for example + new TestCaseData(BTCUSD, Resolution.Tick, false), + new TestCaseData(BTCUSD, Resolution.Minute, true), + new TestCaseData(BTCUSD, Resolution.Second, true), + }; + } + } + + [Test, TestCaseSource(nameof(TestParameters))] + public override void StreamsData(Symbol symbol, Resolution resolution, bool throwsException) + { + base.StreamsData(symbol, resolution, throwsException); + } + } +} \ No newline at end of file diff --git a/QuantConnect.BybitBrokerage.Tests/BybitInverseFuturesBrokerageTests.cs b/QuantConnect.BybitBrokerage.Tests/BybitInverseFuturesBrokerageTests.cs new file mode 100644 index 0000000..bd8f515 --- /dev/null +++ b/QuantConnect.BybitBrokerage.Tests/BybitInverseFuturesBrokerageTests.cs @@ -0,0 +1,138 @@ +/* + * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. + * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +using System; +using System.Linq; +using System.Threading; +using NUnit.Framework; +using QuantConnect.BybitBrokerage.Models.Enums; +using QuantConnect.Data; +using QuantConnect.Interfaces; +using QuantConnect.Lean.Engine.DataFeeds; +using QuantConnect.Logging; +using QuantConnect.Orders; +using QuantConnect.Securities; +using QuantConnect.Tests.Brokerages; +using QuantConnect.Util; + +namespace QuantConnect.BybitBrokerage.Tests; + +[TestFixture, Explicit("Requires valid credentials to be setup and run outside USA")] +public partial class BybitInverseFuturesBrokerageTests : BybitBrokerageTests +{ + private static Symbol BTCUSD = Symbol.Create("BTCUSD", SecurityType.CryptoFuture, "bybit"); + protected override Symbol Symbol { get; } = BTCUSD; + + protected override SecurityType SecurityType => SecurityType.Future; + protected override BybitProductCategory Category => BybitProductCategory.Inverse; + protected override decimal TakerFee => 0.0000015m; + + protected override decimal GetDefaultQuantity() => 10m; + + protected override IBrokerage CreateBrokerage(string apiKey, string apiSecret, string apiUrl, + string websocketUrl, IAlgorithm algorithm, IOrderProvider orderProvider, ISecurityProvider securityProvider, + IDataAggregator aggregator) + { + return new BybitInverseFuturesBrokerage(apiKey, apiSecret, apiUrl, websocketUrl, algorithm, orderProvider, securityProvider, new AggregationManager(), null); + + } + + /// + /// Provides the data required to test each order type in various cases + /// + private static TestCaseData[] OrderParameters() + { + return new[] + { + new TestCaseData(new MarketOrderTestParameters(BTCUSD)).SetName("MarketOrder"), + new TestCaseData(new LimitOrderTestParameters(BTCUSD, 50000m, 10000m)).SetName("LimitOrder"), + new TestCaseData(new StopMarketOrderTestParameters(BTCUSD, 50000m, 10000m)).SetName("StopMarketOrder"), + new TestCaseData(new StopLimitOrderTestParameters(BTCUSD, 50000m, 10000m)).SetName("StopLimitOrder"), + new TestCaseData(new LimitIfTouchedOrderTestParameters(BTCUSD, 50000m, 20000)).SetName( + "LimitIfTouchedOrder") + }; + } + + [Test, TestCaseSource(nameof(OrderParameters))] + public override void CancelOrders(OrderTestParameters parameters) + { + base.CancelOrders(parameters); + } + + [Test, TestCaseSource(nameof(OrderParameters))] + public override void LongFromZero(OrderTestParameters parameters) + { + base.LongFromZero(parameters); + } + + [Test, TestCaseSource(nameof(OrderParameters))] + public override void CloseFromLong(OrderTestParameters parameters) + { + base.CloseFromLong(parameters); + } + + [Test, TestCaseSource(nameof(OrderParameters))] + public override void ShortFromZero(OrderTestParameters parameters) + { + base.ShortFromZero(parameters); + } + + [Test, TestCaseSource(nameof(OrderParameters))] + public override void CloseFromShort(OrderTestParameters parameters) + { + base.CloseFromShort(parameters); + } + + [Test, TestCaseSource(nameof(OrderParameters))] + public override void ShortFromLong(OrderTestParameters parameters) + { + base.ShortFromLong(parameters); + } + + [Test, TestCaseSource(nameof(OrderParameters))] + public override void LongFromShort(OrderTestParameters parameters) + { + base.LongFromShort(parameters); + } + + + [Test] + public override void GetAccountHoldings() + { + Log.Trace(""); + Log.Trace("GET ACCOUNT HOLDINGS"); + Log.Trace(""); + var before = Brokerage.GetCashBalance(); + + var order = new MarketOrder(Symbol, GetDefaultQuantity(), DateTime.UtcNow); + PlaceOrderWaitForStatus(order); + + Thread.Sleep(3000); + + var after = Brokerage.GetCashBalance(); + + CurrencyPairUtil.DecomposeCurrencyPair(Symbol, out var baseCurrency, out _); + var beforeHoldings = before.FirstOrDefault(x => x.Currency == baseCurrency); + var afterHoldings = after.FirstOrDefault(x => x.Currency == baseCurrency); + + var beforeQuantity = beforeHoldings == null ? 0 : beforeHoldings.Amount; + var afterQuantity = afterHoldings == null ? 0 : afterHoldings.Amount; + + var fee = 0.00000015m; + + Assert.AreEqual(0, afterQuantity - beforeQuantity + fee); + } + +} \ No newline at end of file diff --git a/QuantConnect.BybitBrokerage/Api/BybitAccountApiEndpoint.cs b/QuantConnect.BybitBrokerage/Api/BybitAccountApiEndpoint.cs index f6f13aa..c0d2277 100644 --- a/QuantConnect.BybitBrokerage/Api/BybitAccountApiEndpoint.cs +++ b/QuantConnect.BybitBrokerage/Api/BybitAccountApiEndpoint.cs @@ -13,6 +13,7 @@ * limitations under the License. */ +using System; using System.Collections.Generic; using QuantConnect.Brokerages; using QuantConnect.BybitBrokerage.Models; @@ -42,13 +43,19 @@ public BybitAccountApiEndpoint(ISymbolMapper symbolMapper, string apiPrefix, ISe /// /// Obtain wallet balance, query asset information of each currency, and account risk rate information /// - /// The product category + /// The account type to fetch wallet balances for /// The wallet balances - public BybitBalance GetWalletBalances() + public BybitBalance GetWalletBalances(BybitAccountType accountType) { + if (accountType is not (BybitAccountType.Contract or BybitAccountType.Unified)) + { + throw new ArgumentOutOfRangeException(nameof(accountType), + "Wallet balances can only be fetched for 'UNIFIED' and 'CONTRACT'"); + } + var parameters = new KeyValuePair[] { - new("accountType", "UNIFIED") + new("accountType", accountType.ToStringInvariant().ToUpperInvariant()) }; var result = diff --git a/QuantConnect.BybitBrokerage/Api/BybitPositionApiEndpoint.cs b/QuantConnect.BybitBrokerage/Api/BybitPositionApiEndpoint.cs index 363d3f6..b75a823 100644 --- a/QuantConnect.BybitBrokerage/Api/BybitPositionApiEndpoint.cs +++ b/QuantConnect.BybitBrokerage/Api/BybitPositionApiEndpoint.cs @@ -49,10 +49,33 @@ public IEnumerable GetPositions(BybitProductCategory category { if (category == BybitProductCategory.Spot) return Array.Empty(); - var parameters = new KeyValuePair[] + var parameters = new List>(); + + if (category == BybitProductCategory.Linear) { - new("settleCoin", "USDT") - }; + parameters.Add(KeyValuePair.Create("settleCoin", "USDT")); + } + return FetchAll("/position/list", category, 200, parameters, true); } + + /// + /// It supports to switch the position mode for USDT perpetual and Inverse futures. + /// If you are in one-way Mode, you can only open one position on Buy or Sell side. If you are in hedge mode, you can open both Buy and Sell side positions simultaneously. + /// + /// The product category + /// The symbol for which the mode should be changed + /// The mode which should be set + public void SwitchPositionMode(BybitProductCategory category, Symbol symbol, PositionMode mode) + { + var ticker = SymbolMapper.GetBrokerageSymbol(symbol); + var requestBody = new + { + category, + mode = (int)mode, + symbol = ticker + }; + + ExecutePostRequest("/position/switch-mode", requestBody); + } } \ No newline at end of file diff --git a/QuantConnect.BybitBrokerage/BybitBrokerage.Brokerage.cs b/QuantConnect.BybitBrokerage/BybitBrokerage.Brokerage.cs index e315a52..3a23c32 100644 --- a/QuantConnect.BybitBrokerage/BybitBrokerage.Brokerage.cs +++ b/QuantConnect.BybitBrokerage/BybitBrokerage.Brokerage.cs @@ -104,7 +104,7 @@ public override List GetAccountHoldings() public override List GetCashBalance() { return ApiClient.Account - .GetWalletBalances().Assets + .GetWalletBalances(WalletAccountType).Assets .Select(x => new CashAmount(x.WalletBalance, x.Asset)).ToList(); } diff --git a/QuantConnect.BybitBrokerage/BybitBrokerage.Messaging.cs b/QuantConnect.BybitBrokerage/BybitBrokerage.Messaging.cs index c690af7..869d614 100644 --- a/QuantConnect.BybitBrokerage/BybitBrokerage.Messaging.cs +++ b/QuantConnect.BybitBrokerage/BybitBrokerage.Messaging.cs @@ -147,7 +147,7 @@ private void HandleOrderExecution(JToken message) var currency = tradeUpdate.Category switch { BybitProductCategory.Linear => "USDT", - BybitProductCategory.Inverse => GetBaseCurrency(symbol), + BybitProductCategory.Inverse => GetBaseCurrency(leanSymbol), BybitProductCategory.Spot => GetSpotFeeCurrency(leanSymbol, tradeUpdate), _ => throw new NotSupportedException($"category {tradeUpdate.Category} not implemented") }; @@ -178,7 +178,7 @@ static string GetSpotFeeCurrency(Symbol symbol, BybitTradeUpdate tradeUpdate) return tradeUpdate.Side == OrderSide.Buy ? quote : @base; } - static string GetBaseCurrency(string pair) + static string GetBaseCurrency(Symbol pair) { CurrencyPairUtil.DecomposeCurrencyPair(pair, out var baseCurrency, out _); return baseCurrency; diff --git a/QuantConnect.BybitBrokerage/BybitBrokerage.cs b/QuantConnect.BybitBrokerage/BybitBrokerage.cs index 2dacbb1..4c7d2cb 100644 --- a/QuantConnect.BybitBrokerage/BybitBrokerage.cs +++ b/QuantConnect.BybitBrokerage/BybitBrokerage.cs @@ -48,12 +48,6 @@ namespace QuantConnect.BybitBrokerage; [BrokerageFactory(typeof(BybitBrokerageFactory))] public partial class BybitBrokerage : BaseWebsocketsBrokerage, IDataQueueHandler { - private static readonly List SupportedBybitProductCategories = new() { BybitProductCategory.Spot, BybitProductCategory.Linear }; - - private static readonly List SuppotedSecurityTypes = new() { SecurityType.Crypto, SecurityType.CryptoFuture }; - - private static readonly string MarketName = Market.Bybit; - private readonly Dictionary _subscriptionManagers = new(); private IAlgorithm _algorithm; @@ -63,6 +57,12 @@ public partial class BybitBrokerage : BaseWebsocketsBrokerage, IDataQueueHandler private Lazy _apiClientLazy; private BrokerageConcurrentMessageHandler _messageHandler; + protected virtual string MarketName => Market.Bybit; + protected virtual BybitAccountType WalletAccountType => BybitAccountType.Unified; + protected virtual SecurityType[] SuppotedSecurityTypes { get; } = { SecurityType.Crypto, SecurityType.CryptoFuture }; + protected virtual BybitProductCategory[] SupportedBybitProductCategories { get; } = + { BybitProductCategory.Spot, BybitProductCategory.Linear }; + /// /// Order provider /// @@ -81,7 +81,7 @@ public partial class BybitBrokerage : BaseWebsocketsBrokerage, IDataQueueHandler /// /// Parameterless constructor for brokerage /// - public BybitBrokerage() : base(MarketName) + public BybitBrokerage() : base(Market.Bybit) { } @@ -120,7 +120,7 @@ public BybitBrokerage(string apiKey, string apiSecret, string restApiUrl, string public BybitBrokerage(string apiKey, string apiSecret, string restApiUrl, string webSocketBaseUrl, IAlgorithm algorithm, IOrderProvider orderProvider, ISecurityProvider securityProvider, IDataAggregator aggregator, LiveNodePacket job, BybitVIPLevel vipLevel = BybitVIPLevel.VIP0) - : base(MarketName) + : base(Market.Bybit) { Initialize( webSocketBaseUrl, @@ -307,8 +307,9 @@ protected virtual bool CanSubscribe(Symbol symbol) if (baseCanSubscribe && symbol.SecurityType == SecurityType.CryptoFuture) { - //Can only subscribe to non-inverse pairs - return CurrencyPairUtil.TryDecomposeCurrencyPair(symbol, out _, out var quoteCurrency) && quoteCurrency == "USDT"; + return CurrencyPairUtil.TryDecomposeCurrencyPair(symbol, out _, out var quoteCurrency) && + (quoteCurrency is "USDT" || SupportedBybitProductCategories.Contains(BybitProductCategory.Inverse) && + quoteCurrency is "USD"); } return baseCanSubscribe; @@ -457,7 +458,7 @@ private class ModulesReadLicenseRead : QuantConnect.Api.RestResponse /// Checks whether the specified symbol is supported by this brokerage by its security type /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static bool IsSupported(Symbol symbol) + protected bool IsSupported(Symbol symbol) { return SuppotedSecurityTypes.Contains(symbol.SecurityType); } @@ -483,13 +484,18 @@ private static BybitProductCategory GetBybitProductCategory(Symbol symbol) return BybitProductCategory.Spot; case SecurityType.CryptoFuture: - if (!CurrencyPairUtil.TryDecomposeCurrencyPair(symbol, out _, out var quoteCurrency) || - quoteCurrency != "USDT") + if (CurrencyPairUtil.TryDecomposeCurrencyPair(symbol, out _, out var quoteCurrency)) { - throw new ArgumentException($"Invalid symbol: {symbol}. Only linear futures are supported."); + if (quoteCurrency == "USDT") + { + return BybitProductCategory.Linear; + } + if (quoteCurrency == "USD") + { + return BybitProductCategory.Inverse; + } } - - return BybitProductCategory.Linear; + throw new ArgumentException($"Invalid symbol: {symbol}. Only linear futures are supported."); default: throw new ArgumentOutOfRangeException(nameof(symbol), symbol, "Not supported security type"); diff --git a/QuantConnect.BybitBrokerage/BybitBrokerageFactory.cs b/QuantConnect.BybitBrokerage/BybitBrokerageFactory.cs index 702a1aa..308572f 100644 --- a/QuantConnect.BybitBrokerage/BybitBrokerageFactory.cs +++ b/QuantConnect.BybitBrokerage/BybitBrokerageFactory.cs @@ -31,11 +31,6 @@ namespace QuantConnect.BybitBrokerage /// public class BybitBrokerageFactory : BrokerageFactory { - /// - /// The default order book depth for this brokerage - /// - protected virtual int DefaultOrderBookDepth => 50; - /// /// Gets the brokerage data required to run the brokerage from configuration/disk /// @@ -101,12 +96,30 @@ public override IBrokerage CreateBrokerage(LiveNodePacket job, IAlgorithm algori var aggregator = Composer.Instance.GetExportedValueByTypeName( Config.Get("data-aggregator", "QuantConnect.Lean.Engine.DataFeeds.AggregationManager"), forceTypeNameOnExisting: false); - var brokerage = new BybitBrokerage(apiKey, apiSecret, apiUrl, wsUrl, algorithm, aggregator, job, vipLevel); + var brokerage = CreateBrokerage(apiKey, apiSecret, apiUrl, wsUrl, algorithm, aggregator, job, vipLevel); Composer.Instance.AddPart(brokerage); return brokerage; } + /// + /// Creates a new BybitBrokerage instance + /// + /// The api key + /// The api secret + /// The rest api url + /// The web socket base url + /// The algorithm instance is required to retrieve account type + /// The aggregator for consolidating ticks + /// The live job packet + /// Bybit VIP level + /// New BybitBrokerage instance + protected virtual BybitBrokerage CreateBrokerage(string apiKey, string apiSecret, string apiUrl, string wsUrl, + IAlgorithm algorithm, IDataAggregator aggregator, LiveNodePacket job, BybitVIPLevel vipLevel) + { + return new BybitBrokerage(apiKey, apiSecret, apiUrl, wsUrl, algorithm, aggregator, job, vipLevel); + } + /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// diff --git a/QuantConnect.BybitBrokerage/BybitInverseFuturesBrokerage.cs b/QuantConnect.BybitBrokerage/BybitInverseFuturesBrokerage.cs new file mode 100644 index 0000000..edfbcb7 --- /dev/null +++ b/QuantConnect.BybitBrokerage/BybitInverseFuturesBrokerage.cs @@ -0,0 +1,81 @@ +/* + * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. + * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +using QuantConnect.Brokerages; +using QuantConnect.BybitBrokerage.Models.Enums; +using QuantConnect.Data; +using QuantConnect.Interfaces; +using QuantConnect.Packets; +using QuantConnect.Securities; + +namespace QuantConnect.BybitBrokerage; + +/// +/// Bybit inverse futures brokerage implementation +/// +[BrokerageFactory(typeof(BybitInverseFuturesBrokerageFactory))] +public class BybitInverseFuturesBrokerage : BybitBrokerage +{ + protected override SecurityType[] SuppotedSecurityTypes { get; } = { SecurityType.Crypto, SecurityType.CryptoFuture }; + protected override BybitProductCategory[] SupportedBybitProductCategories { get; } = { BybitProductCategory.Inverse }; + protected override BybitAccountType WalletAccountType => BybitAccountType.Contract; + + /// + /// Parameterless constructor for brokerage + /// + public BybitInverseFuturesBrokerage() + { + } + + /// + /// Constructor for brokerage + /// + /// api key + /// api secret + /// The rest api url + /// The web socket base url + /// the algorithm instance is required to retrieve account type + /// the aggregator for consolidating ticks + /// The live job packet + /// Bybit VIP level + public BybitInverseFuturesBrokerage(string apiKey, string apiSecret, string restApiUrl, string webSocketBaseUrl, + IAlgorithm algorithm, IDataAggregator aggregator, LiveNodePacket job, + BybitVIPLevel vipLevel = BybitVIPLevel.VIP0) + : base(apiKey, apiSecret, restApiUrl, webSocketBaseUrl, algorithm, algorithm?.Portfolio?.Transactions, + algorithm?.Portfolio, aggregator, job, vipLevel) + { + } + + /// + /// Constructor for brokerage + /// + /// The api key + /// The api secret + /// The rest api url + /// The web socket base url + /// The algorithm instance is required to retrieve account type + /// The order provider is required to retrieve orders + /// The security provider is required + /// The aggregator for consolidating ticks + /// The live job packet + /// Bybit VIP level + public BybitInverseFuturesBrokerage(string apiKey, string apiSecret, string restApiUrl, string webSocketBaseUrl, + IAlgorithm algorithm, IOrderProvider orderProvider, ISecurityProvider securityProvider, + IDataAggregator aggregator, LiveNodePacket job, BybitVIPLevel vipLevel = BybitVIPLevel.VIP0) + : base(apiKey, apiSecret, restApiUrl, webSocketBaseUrl, algorithm, orderProvider, + securityProvider, aggregator, job, vipLevel) + { + } +} \ No newline at end of file diff --git a/QuantConnect.BybitBrokerage/BybitInverseFuturesBrokerageFactory.cs b/QuantConnect.BybitBrokerage/BybitInverseFuturesBrokerageFactory.cs new file mode 100644 index 0000000..23df35d --- /dev/null +++ b/QuantConnect.BybitBrokerage/BybitInverseFuturesBrokerageFactory.cs @@ -0,0 +1,52 @@ +/* + * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. + * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +using QuantConnect.BybitBrokerage.Models.Enums; +using QuantConnect.Data; +using QuantConnect.Interfaces; +using QuantConnect.Packets; + +namespace QuantConnect.BybitBrokerage; + +/// +/// Factory method to create Bybit inverse brokerage +/// +public class BybitInverseFuturesBrokerageFactory : BybitBrokerageFactory +{ + /// + /// Initializes a new instance of the class + /// + public BybitInverseFuturesBrokerageFactory(): base(typeof(BybitInverseFuturesBrokerage)) + { + } + + /// + /// Creates a new BybitBrokerage instance + /// + /// The api key + /// The api secret + /// The rest api url + /// The web socket base url + /// The algorithm instance is required to retrieve account type + /// The aggregator for consolidating ticks + /// The live job packet + /// Bybit VIP level + /// New BybitBrokerage instance + protected override BybitBrokerage CreateBrokerage(string apiKey, string apiSecret, string apiUrl, string wsUrl, IAlgorithm algorithm, + IDataAggregator aggregator, LiveNodePacket job, BybitVIPLevel vipLevel) + { + return new BybitInverseFuturesBrokerage(apiKey, apiSecret, apiUrl, wsUrl, algorithm, aggregator, job, vipLevel); + } +} \ No newline at end of file diff --git a/QuantConnect.BybitBrokerage/Models/ByBitResponse.cs b/QuantConnect.BybitBrokerage/Models/ByBitResponse.cs index c8d0584..b26d1fb 100644 --- a/QuantConnect.BybitBrokerage/Models/ByBitResponse.cs +++ b/QuantConnect.BybitBrokerage/Models/ByBitResponse.cs @@ -22,8 +22,7 @@ namespace QuantConnect.BybitBrokerage.Models /// /// Bybits default http response message /// - /// - public class ByBitResponse + public class ByBitResponse { /// /// Success/Error code @@ -43,16 +42,25 @@ public class ByBitResponse /// [JsonProperty("retExtInfo")] public object ExtendedInfo { get; set; } - - /// - /// Business data result - /// - public T Result { get; set; } - + /// /// Current time /// [JsonConverter(typeof(BybitTimeConverter))] public DateTime Time { get; set; } } + + /// + /// Bybits default http data response message + /// + /// + public class ByBitResponse : ByBitResponse + { + /// + /// Business data result + /// + public T Result { get; set; } + + } + } \ No newline at end of file diff --git a/QuantConnect.BybitBrokerage/Models/Enums/PositionMode.cs b/QuantConnect.BybitBrokerage/Models/Enums/PositionMode.cs new file mode 100644 index 0000000..4cacb3d --- /dev/null +++ b/QuantConnect.BybitBrokerage/Models/Enums/PositionMode.cs @@ -0,0 +1,32 @@ +/* + * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. + * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +namespace QuantConnect.BybitBrokerage.Models.Enums; + +/// +/// Bybit position mode +/// +public enum PositionMode +{ + /// + /// One way mode + /// + MergedSingle = 0, + + /// + /// Hedge mode + /// + BothSides = 3, +} \ No newline at end of file