diff --git a/Common/Brokerages/BinanceBrokerageModel.cs b/Common/Brokerages/BinanceBrokerageModel.cs
index 488341025a0f..7c23bfb76244 100644
--- a/Common/Brokerages/BinanceBrokerageModel.cs
+++ b/Common/Brokerages/BinanceBrokerageModel.cs
@@ -31,6 +31,11 @@ public class BinanceBrokerageModel : DefaultBrokerageModel
private const decimal _defaultLeverage = 3;
private const decimal _defaultFutureLeverage = 25;
+ ///
+ /// The base Binance API endpoint URL.
+ ///
+ protected virtual string BaseApiEndpoint => "https://api.binance.com/api/v3";
+
///
/// Market name
///
@@ -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;
}
diff --git a/Common/Brokerages/BinanceUSBrokerageModel.cs b/Common/Brokerages/BinanceUSBrokerageModel.cs
index 1493f51d36dd..c68314e2187f 100644
--- a/Common/Brokerages/BinanceUSBrokerageModel.cs
+++ b/Common/Brokerages/BinanceUSBrokerageModel.cs
@@ -24,6 +24,11 @@ namespace QuantConnect.Brokerages
///
public class BinanceUSBrokerageModel : BinanceBrokerageModel
{
+ ///
+ /// The base Binance Futures API endpoint URL.
+ ///
+ protected override string BaseApiEndpoint => "https://api.binance.us/api/v3";
+
///
/// Market name
///
diff --git a/Common/Messages/Messages.Brokerages.cs b/Common/Messages/Messages.Brokerages.cs
index 95d0b39a3449..e045cb9bb516 100644
--- a/Common/Messages/Messages.Brokerages.cs
+++ b/Common/Messages/Messages.Brokerages.cs
@@ -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
///
[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.");
}
}
diff --git a/Tests/Common/Brokerages/BinanceBrokerageModelTests.cs b/Tests/Common/Brokerages/BinanceBrokerageModelTests.cs
index 478d9541cf0d..241bfc6e6500 100644
--- a/Tests/Common/Brokerages/BinanceBrokerageModelTests.cs
+++ b/Tests/Common/Brokerages/BinanceBrokerageModelTests.cs
@@ -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
{
@@ -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
{
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]