Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature:Binance: Futures models support StopMarket OrderType #8441

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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