Skip to content
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
49 changes: 39 additions & 10 deletions QuantConnect.BitfinexBrokerage.Tests/BitfinexBrokerageTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
using QuantConnect.Brokerages;
using QuantConnect.Tests.Common.Securities;
using QuantConnect.Lean.Engine.DataFeeds;
using QuantConnect.Orders;

namespace QuantConnect.Tests.Brokerages.Bitfinex
{
Expand All @@ -37,9 +38,10 @@ public partial class BitfinexBrokerageTests : BrokerageTests
/// <returns></returns>
protected override IBrokerage CreateBrokerage(IOrderProvider orderProvider, ISecurityProvider securityProvider)
{
var security = securityProvider.GetSecurity(Symbol);
var securities = new SecurityManager(new TimeKeeper(DateTime.UtcNow, TimeZones.NewYork))
{
{Symbol, SecurityProvider.GetSecurity(Symbol)}
{Symbol, security}
};

var transactions = new SecurityTransactionManager(null, securities);
Expand All @@ -48,8 +50,9 @@ protected override IBrokerage CreateBrokerage(IOrderProvider orderProvider, ISec

var algorithm = new Mock<IAlgorithm>();
algorithm.Setup(a => a.Transactions).Returns(transactions);
algorithm.Setup(a => a.BrokerageModel).Returns(new BitfinexBrokerageModel());
algorithm.Setup(a => a.BrokerageModel).Returns(new BitfinexBrokerageModel(AccountType.Cash));
algorithm.Setup(a => a.Portfolio).Returns(new SecurityPortfolioManager(securities, transactions, algorithmSettings));
algorithm.Setup(a => a.Securities).Returns(securities);

return new BitfinexBrokerage(
Config.Get("bitfinex-api-key"),
Expand All @@ -64,13 +67,21 @@ protected override IBrokerage CreateBrokerage(IOrderProvider orderProvider, ISec
/// Gets the symbol to be traded, must be shortable
/// </summary>
protected override Symbol Symbol => StaticSymbol;
private static Symbol StaticSymbol => Symbol.Create("ETHUSD", SecurityType.Crypto, Market.Bitfinex);
private static Symbol StaticSymbol => Symbol.Create("TESTBTCTESTUSD", SecurityType.Crypto, Market.Bitfinex);

/// <summary>
/// Gets the security type associated with the <see cref="BrokerageTests.Symbol" />
/// </summary>
protected override SecurityType SecurityType => SecurityType.Crypto;

private static TestCaseData[] OrderParameters =>
[
new TestCaseData(new MarketOrderTestParameters(StaticSymbol)),
new TestCaseData(new LimitOrderTestParameters(StaticSymbol, 1000m, 100m)),
new TestCaseData(new StopMarketOrderTestParameters(StaticSymbol, 1000m, 100m)),
new TestCaseData(new StopLimitOrderTestParameters(StaticSymbol, 1000m, 100m)),
];

/// <summary>
/// Gets the current market price of the specified security
/// </summary>
Expand All @@ -95,43 +106,61 @@ protected override decimal GetAskPrice(Symbol symbol)
/// </summary>
protected override decimal GetDefaultQuantity() => 0.04m;

[Explicit("Ignore a test")]
[TestCaseSource(nameof(OrderParameters))]
public override void CancelOrders(OrderTestParameters parameters)
{
base.CancelOrders(parameters);
}

[Explicit("Ignore a test")]
[TestCaseSource(nameof(OrderParameters))]
public override void LongFromZero(OrderTestParameters parameters)
{
base.LongFromZero(parameters);

if (parameters is not MarketOrderTestParameters)
{
// We expect the orders to be open
var openOrders = Brokerage.GetOpenOrders();
Assert.AreEqual(1, openOrders.Count);

var expectedOrderType = parameters switch
{
LimitOrderTestParameters _ => typeof(LimitOrder),
StopMarketOrderTestParameters _ => typeof(StopMarketOrder),
StopLimitOrderTestParameters _ => typeof(StopLimitOrder),
_ => throw new ArgumentException("Unsupported order type for this test", nameof(parameters))
};

// Check that the order type matches the expected type
Assert.IsInstanceOf(expectedOrderType, openOrders[0]);
}
}

[Explicit("Ignore a test")]
[TestCaseSource(nameof(OrderParameters))]
public override void CloseFromLong(OrderTestParameters parameters)
{
base.CloseFromLong(parameters);
}

[Explicit("Ignore a test")]
[TestCaseSource(nameof(OrderParameters))]
public override void ShortFromZero(OrderTestParameters parameters)
{
base.ShortFromZero(parameters);
}

[Explicit("Ignore a test")]
[TestCaseSource(nameof(OrderParameters))]
public override void CloseFromShort(OrderTestParameters parameters)
{
base.CloseFromShort(parameters);
}

[Explicit("Ignore a test")]
[TestCaseSource(nameof(OrderParameters))]
public override void ShortFromLong(OrderTestParameters parameters)
{
base.ShortFromLong(parameters);
}

[Explicit("Ignore a test")]
[TestCaseSource(nameof(OrderParameters))]
public override void LongFromShort(OrderTestParameters parameters)
{
base.LongFromShort(parameters);
Expand Down
7 changes: 7 additions & 0 deletions QuantConnect.BitfinexBrokerage/BitfinexBrokerage.Utility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,10 @@ private static string ConvertOrderType(AccountType accountType, OrderType orderT
outputOrderType = "STOP";
break;

case OrderType.StopLimit:
outputOrderType = "STOP LIMIT";
break;

default:
throw new NotSupportedException($"BitfinexBrokerage.ConvertOrderType: Unsupported order type: {orderType}");
}
Expand Down Expand Up @@ -213,6 +217,9 @@ private static decimal GetOrderPrice(Order order)

case OrderType.StopMarket:
return ((StopMarketOrder)order).StopPrice;

case OrderType.StopLimit:
return ((StopLimitOrder)order).LimitPrice;
}

throw new NotSupportedException($"BitfinexBrokerage.ConvertOrderType: Unsupported order type: {order.Type}");
Expand Down
16 changes: 13 additions & 3 deletions QuantConnect.BitfinexBrokerage/BitfinexBrokerage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ public override bool PlaceOrder(Order order)
{ "price", GetOrderPrice(order).ToStringInvariant() }
};

if (order is StopLimitOrder stopLimitOrder)
{
parameters.Add("price_aux_limit", stopLimitOrder.StopPrice.ToStringInvariant());
}

var orderProperties = order.Properties as BitfinexOrderProperties;
if (orderProperties != null)
{
Expand Down Expand Up @@ -200,19 +205,24 @@ public override List<Order> GetOpenOrders()
var price = item.Price;
var symbol = _symbolMapper.GetLeanSymbol(item.Symbol, SecurityType.Crypto, Market.Bitfinex);
var time = Time.UnixMillisecondTimeStampToDateTime(item.MtsCreate);
var orderTypeStr = item.Type.Replace("EXCHANGE", "").Trim();

if (item.Type.Replace("EXCHANGE", "").Trim() == "MARKET")
if (orderTypeStr == "MARKET")
{
order = new MarketOrder(symbol, quantity, time, price);
}
else if (item.Type.Replace("EXCHANGE", "").Trim() == "LIMIT")
else if (orderTypeStr == "LIMIT")
{
order = new LimitOrder(symbol, quantity, price, time);
}
else if (item.Type.Replace("EXCHANGE", "").Trim() == "STOP")
else if (orderTypeStr == "STOP")
{
order = new StopMarketOrder(symbol, quantity, price, time);
}
else if (orderTypeStr == "STOP LIMIT")
{
order = new StopLimitOrder(symbol, quantity, price, item.PriceAuxLimit, time);
}
else
{
OnMessage(new BrokerageMessageEvent(BrokerageMessageType.Error, (int)response.StatusCode,
Expand Down