Skip to content

Commit

Permalink
feat: Binance future support StopMarket for CryptoFuture (#8441)
Browse files Browse the repository at this point in the history
test:feat: CanSubmit StopMarket Crypto or CryptoFuture in Binance Model
  • Loading branch information
Romazes authored Dec 4, 2024
1 parent a1d0b6c commit a2efee8
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 23 deletions.
29 changes: 20 additions & 9 deletions Common/Brokerages/BinanceBrokerageModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ public class BinanceBrokerageModel : DefaultBrokerageModel
private const decimal _defaultLeverage = 3;
private const decimal _defaultFutureLeverage = 25;

/// <summary>
/// The base Binance API endpoint URL.
/// </summary>
protected virtual string BaseApiEndpoint => "https://api.binance.com/api/v3";

/// <summary>
/// Market name
/// </summary>
Expand Down Expand Up @@ -154,18 +159,24 @@ public override bool CanSubmitOrder(Security security, Order order, out Brokerag
quantityIsValid &= IsOrderSizeLargeEnough(stopLimitOrder.StopPrice);
price = stopLimitOrder.StopPrice;
break;
case StopMarketOrder:
// despite Binance API allows you to post STOP_LOSS and TAKE_PROFIT order types
// they always fails with the content
// {"code":-1013,"msg":"Take profit orders are not supported for this symbol."}
// currently no symbols supporting TAKE_PROFIT or STOP_LOSS orders
case StopMarketOrder stopMarketOrder:
if (security.Symbol.SecurityType != SecurityType.CryptoFuture)
{
// despite Binance API allows you to post STOP_LOSS and TAKE_PROFIT order types
// they always fails with the content
// {"code":-1013,"msg":"Take profit orders are not supported for this symbol."}
// currently no symbols supporting TAKE_PROFIT or STOP_LOSS orders

message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
Messages.BinanceBrokerageModel.UnsupportedOrderTypeWithLinkToSupportedTypes(order, security));
return false;
message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
Messages.BinanceBrokerageModel.UnsupportedOrderTypeWithLinkToSupportedTypes(BaseApiEndpoint, order, security));
return false;
}
quantityIsValid &= IsOrderSizeLargeEnough(stopMarketOrder.StopPrice);
price = stopMarketOrder.StopPrice;
break;
default:
message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
Messages.DefaultBrokerageModel.UnsupportedOrderType(this, order, new [] { OrderType.StopMarket, OrderType.StopLimit, OrderType.Market, OrderType.Limit }));
Messages.DefaultBrokerageModel.UnsupportedOrderType(this, order, new[] { OrderType.StopMarket, OrderType.StopLimit, OrderType.Market, OrderType.Limit }));
return false;
}

Expand Down
5 changes: 5 additions & 0 deletions Common/Brokerages/BinanceUSBrokerageModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ namespace QuantConnect.Brokerages
/// </summary>
public class BinanceUSBrokerageModel : BinanceBrokerageModel
{
/// <summary>
/// The base Binance Futures API endpoint URL.
/// </summary>
protected override string BaseApiEndpoint => "https://api.binance.us/api/v3";

/// <summary>
/// Market name
/// </summary>
Expand Down
5 changes: 2 additions & 3 deletions Common/Messages/Messages.Brokerages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -195,10 +195,9 @@ public static string UnsupportedOrderTypeForSecurityType(Orders.Order order, Sec
/// security. The message also contains a link to the supported order types in Binance
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnsupportedOrderTypeWithLinkToSupportedTypes(Orders.Order order, Securities.Security security)
public static string UnsupportedOrderTypeWithLinkToSupportedTypes(string baseApiEndpoint, Orders.Order order, Securities.Security security)
{
return Invariant($@"{order.Type} orders are not supported for this symbol. Please check 'https://api.binance.com/api/v3/exchangeInfo?symbol={
security.SymbolProperties.MarketTicker}' to see supported order types.");
return Invariant($@"{order.Type} orders are not supported for this symbol. Please check '{baseApiEndpoint}/exchangeInfo?symbol={security.SymbolProperties.MarketTicker}' to see supported order types.");
}
}

Expand Down
44 changes: 33 additions & 11 deletions Tests/Common/Brokerages/BinanceBrokerageModelTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@
*/

using Moq;
using System;
using NUnit.Framework;
using QuantConnect.Orders;
using QuantConnect.Securities;
using QuantConnect.Brokerages;
using QuantConnect.Orders.Fees;
using QuantConnect.Data.Market;
using QuantConnect.Orders;
using QuantConnect.Tests.Brokerages;
using System;
using QuantConnect.Orders.Fees;
using QuantConnect.Securities;

namespace QuantConnect.Tests.Common.Brokerages
{
Expand Down Expand Up @@ -121,22 +121,44 @@ public void CannotSubmitMarketOrder_IfPriceNotInitialized()
Assert.NotNull(message);
}

[Test]
public void CannotSubmitStopMarketOrder_Always()
[TestCase(nameof(BinanceBrokerageModel), SecurityType.Crypto, false)]
[TestCase(nameof(BinanceUSBrokerageModel), SecurityType.Crypto, false)]
[TestCase(nameof(BinanceFuturesBrokerageModel), SecurityType.CryptoFuture, true)]
[TestCase(nameof(BinanceCoinFuturesBrokerageModel), SecurityType.CryptoFuture, true)]
public void CannotSubmitStopMarketOrder_Always(string binanceBrokerageMode, SecurityType securityType, bool isCanSubmit)
{
var binanceBrokerageModel = binanceBrokerageMode switch
{
"BinanceBrokerageModel" => new BinanceBrokerageModel(),
"BinanceUSBrokerageModel" => new BinanceUSBrokerageModel(),
"BinanceFuturesBrokerageModel" => new BinanceFuturesBrokerageModel(AccountType.Margin),
"BinanceCoinFuturesBrokerageModel" => new BinanceCoinFuturesBrokerageModel(AccountType.Margin),
_ => throw new ArgumentException($"Invalid binanceBrokerageModel value: '{binanceBrokerageMode}'.")
};

var order = new Mock<StopMarketOrder>
{
Object =
{
Quantity = 100000,
StopPrice = 100000
StopPrice = 3_000
}
};
order.Setup(mock => mock.Quantity).Returns(1);

var security = TestsHelpers.GetSecurity(symbol: _btceur.Value, market: _btceur.ID.Market, quoteCurrency: "EUR");

Assert.AreEqual(false, BinanceBrokerageModel.CanSubmitOrder(security, order.Object, out var message));
Assert.NotNull(message);
var ETHUSDT = Symbol.Create("ETHUSDT", securityType, Market.Binance);

var security = TestsHelpers.GetSecurity(securityType: ETHUSDT.SecurityType, symbol: ETHUSDT.Value, market: ETHUSDT.ID.Market, quoteCurrency: "USDT");

Assert.AreEqual(isCanSubmit, binanceBrokerageModel.CanSubmitOrder(security, order.Object, out var message));
if (isCanSubmit)
{
Assert.IsNull(message);
}
else
{
Assert.NotNull(message);
}
}

[Test]
Expand Down

0 comments on commit a2efee8

Please sign in to comment.