From c02ad0a89f630194a966d5b952853ae3664014a6 Mon Sep 17 00:00:00 2001 From: Adalyat Nazirov Date: Sat, 6 Feb 2021 02:23:54 +0300 Subject: [PATCH] Brokerage models improvements (#5267) * fix Atreyu brokerage type full name * improve brokerage models -AtreyuBrokerageModel -TradingTechnologiesBrokerageModel * remove Limit price checks --- Common/Brokerages/AtreyuBrokerageModel.cs | 111 ++++++++++++++++++ .../TradingTechnologiesBrokerageModel.cs | 12 +- Launcher/config.json | 2 +- 3 files changed, 115 insertions(+), 10 deletions(-) diff --git a/Common/Brokerages/AtreyuBrokerageModel.cs b/Common/Brokerages/AtreyuBrokerageModel.cs index 35702fdabd1e..0b8dd9447610 100644 --- a/Common/Brokerages/AtreyuBrokerageModel.cs +++ b/Common/Brokerages/AtreyuBrokerageModel.cs @@ -13,10 +13,17 @@ * limitations under the License. */ +using System.Linq; +using System.Collections.Generic; +using QuantConnect.Benchmarks; using QuantConnect.Data.Shortable; using QuantConnect.Interfaces; +using QuantConnect.Orders; using QuantConnect.Orders.Fees; +using QuantConnect.Orders.TimeInForces; using QuantConnect.Securities; +using QuantConnect.Util; +using static QuantConnect.StringExtensions; namespace QuantConnect.Brokerages { @@ -26,6 +33,25 @@ namespace QuantConnect.Brokerages public class AtreyuBrokerageModel : DefaultBrokerageModel { private readonly IShortableProvider _shortableProvider; + private readonly System.Type[] _supportedTimeInForces = + { + typeof(DayTimeInForce) + }; + + private readonly OrderType[] _supportedOrderTypes = + { + OrderType.Limit, + OrderType.Market, + OrderType.MarketOnClose + }; + + /// + /// The default markets for Trading Technologies + /// + public new static readonly IReadOnlyDictionary DefaultMarketMap = new Dictionary + { + {SecurityType.Equity, Market.USA} + }.ToReadOnlyDictionary(); /// /// Creates a new instance @@ -35,6 +61,11 @@ public AtreyuBrokerageModel(AccountType accountType = AccountType.Margin) : base _shortableProvider = new AtreyuShortableProvider(SecurityType.Equity, Market.USA); } + /// + /// Gets a map of the default markets to be used for each security type + /// + public override IReadOnlyDictionary DefaultMarkets => DefaultMarketMap; + /// /// Provides Atreyu fee model /// @@ -53,5 +84,85 @@ public override IShortableProvider GetShortableProvider() { return _shortableProvider; } + + /// + /// Get the benchmark for this model + /// + /// SecurityService to create the security with if needed + /// The benchmark for this brokerage + public override IBenchmark GetBenchmark(SecurityManager securities) + { + // Equivalent to no benchmark + return new FuncBenchmark(x => 0); + } + + /// + /// Returns true if the brokerage could accept this order. + /// + /// The security being ordered + /// The order to be processed + /// If this function returns false, a brokerage message detailing why the order may not be submitted + /// True if the brokerage could process the order, false otherwise + public override bool CanSubmitOrder(Security security, Order order, out BrokerageMessageEvent message) + { + message = null; + + // validate security type + if (!DefaultMarketMap.ContainsKey(security.Type)) + { + message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported", + Invariant($"The {nameof(AtreyuBrokerageModel)} does not support {security.Type} security type.") + ); + + return false; + } + + // validate order type + if (!_supportedOrderTypes.Contains(order.Type)) + { + message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported", + Invariant($"The {nameof(AtreyuBrokerageModel)} does not support {order.Type} order type.") + ); + + return false; + } + + // validate time in force + if (!_supportedTimeInForces.Contains(order.TimeInForce.GetType())) + { + message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported", + Invariant($"The {nameof(AtreyuBrokerageModel)} does not support {order.TimeInForce.GetType().Name} time in force.") + ); + + return false; + } + + // validate orders quantity + if (order.AbsoluteQuantity % 1 != 0) + { + message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported", + Invariant($"Order Quantity must be Integer, but provided {order.Quantity}.") + ); + + return false; + } + + return true; + } + + /// + /// Returns true if the brokerage would allow updating the order as specified by the request + /// + /// The security of the order + /// The order to be updated + /// The requested update to be made to the order + /// If this function returns false, a brokerage message detailing why the order may not be updated + /// True if the brokerage would allow updating the order, false otherwise + public override bool CanUpdateOrder(Security security, Order order, UpdateOrderRequest request, out BrokerageMessageEvent message) + { + message = null; + + return true; + } } } diff --git a/Common/Brokerages/TradingTechnologiesBrokerageModel.cs b/Common/Brokerages/TradingTechnologiesBrokerageModel.cs index f7ec9f0d19d7..8ed2d3509159 100644 --- a/Common/Brokerages/TradingTechnologiesBrokerageModel.cs +++ b/Common/Brokerages/TradingTechnologiesBrokerageModel.cs @@ -100,7 +100,7 @@ public override bool CanSubmitOrder(Security security, Order order, out Brokerag if (security.Type != SecurityType.Future) { message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported", - Invariant($"The {nameof(InteractiveBrokersBrokerageModel)} does not support {security.Type} security type.") + Invariant($"The {nameof(TradingTechnologiesBrokerageModel)} does not support {security.Type} security type.") ); return false; @@ -120,19 +120,13 @@ public override bool CanSubmitOrder(Security security, Order order, out Brokerag if (!_supportedTimeInForces.Contains(order.TimeInForce.GetType())) { message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported", - Invariant($"The {nameof(InteractiveBrokersBrokerageModel)} does not support {order.TimeInForce.GetType().Name} time in force.") + Invariant($"The {nameof(TradingTechnologiesBrokerageModel)} does not support {order.TimeInForce.GetType().Name} time in force.") ); return false; } - // validate stop/limit orders prices - var limit = order as LimitOrder; - if (limit != null) - { - return IsValidOrderPrices(security, OrderType.Limit, limit.Direction, security.Price, limit.LimitPrice, ref message); - } - + // validate stop orders prices var stopMarket = order as StopMarketOrder; if (stopMarket != null) { diff --git a/Launcher/config.json b/Launcher/config.json index f0181cf205dd..43efcbd5755a 100644 --- a/Launcher/config.json +++ b/Launcher/config.json @@ -328,7 +328,7 @@ "live-mode": true, // real brokerage implementations require the BrokerageTransactionHandler - "live-mode-brokerage": "QuantConnect.Brokerages.Atreyu.AtreyuBrokerage", + "live-mode-brokerage": "QuantConnect.Atreyu.AtreyuBrokerage", "data-queue-handler": "QuantConnect.Lean.Engine.DataFeeds.Queues.LiveDataQueue", "setup-handler": "QuantConnect.Lean.Engine.Setup.BrokerageSetupHandler", "result-handler": "QuantConnect.Lean.Engine.Results.LiveTradingResultHandler",