forked from QuantConnect/Lean
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Handle/filter new brokerage-side orders (QuantConnect#7706)
* Handle/filter brokerage side orders * Add unit tests * Minor fix * Add unrequested security for new brokerage-side orders * Add unit test for algorithms overriding the brokerage message handler * Add unit test for python algorithm overriding the brokerage message handler * Minor change * Address peer review
- Loading branch information
1 parent
1c93df8
commit 3dab2e4
Showing
17 changed files
with
585 additions
and
107 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
93 changes: 93 additions & 0 deletions
93
Algorithm.CSharp/CustomBrokerageSideOrderHandlingRegressionAlgorithm.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
/* | ||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. | ||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
using System; | ||
using System.Globalization; | ||
using QuantConnect.Brokerages; | ||
using QuantConnect.Interfaces; | ||
|
||
namespace QuantConnect.Algorithm.CSharp | ||
{ | ||
/// <summary> | ||
/// Algorithm demonstrating the usage of custom brokerage message handler and the new brokerage-side order handling/filtering. | ||
/// This test is supposed to be ran by the CustomBrokerageMessageHandlerTests unit test fixture. | ||
/// | ||
/// All orders are sent from the brokerage, none of them will be placed by the algorithm. | ||
/// </summary> | ||
public class CustomBrokerageSideOrderHandlingRegressionAlgorithm : QCAlgorithm | ||
{ | ||
private Symbol _spy = QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA); | ||
|
||
public override void Initialize() | ||
{ | ||
SetStartDate(2013, 10, 07); | ||
SetEndDate(2013, 10, 11); | ||
SetCash(100000); | ||
|
||
SetBrokerageMessageHandler(new CustomBrokerageMessageHandler(this)); | ||
} | ||
|
||
public override void OnEndOfAlgorithm() | ||
{ | ||
// The security should have been added | ||
if (!Securities.ContainsKey(_spy)) | ||
{ | ||
throw new Exception("Expected security to have been added"); | ||
} | ||
|
||
if (Transactions.OrdersCount == 0) | ||
{ | ||
throw new Exception("Expected orders to be added from brokerage side"); | ||
} | ||
|
||
if (Portfolio.Positions.Groups.Count != 1) | ||
{ | ||
throw new Exception("Expected only one position"); | ||
} | ||
} | ||
|
||
public class CustomBrokerageMessageHandler : IBrokerageMessageHandler | ||
{ | ||
private readonly IAlgorithm _algorithm; | ||
public CustomBrokerageMessageHandler(IAlgorithm algo) { _algorithm = algo; } | ||
|
||
/// <summary> | ||
/// Process the brokerage message event. Trigger any actions in the algorithm or notifications system required. | ||
/// </summary> | ||
/// <param name="message">Message object</param> | ||
public void HandleMessage(BrokerageMessageEvent message) | ||
{ | ||
_algorithm.Debug($"{_algorithm.Time.ToStringInvariant("o")} Event: {message.Message}"); | ||
} | ||
|
||
/// <summary> | ||
/// Handles a new order placed manually in the brokerage side | ||
/// </summary> | ||
/// <param name="eventArgs">The new order event</param> | ||
/// <returns>Whether the order should be added to the transaction handler</returns> | ||
public bool HandleOrder(NewBrokerageOrderNotificationEventArgs eventArgs) | ||
{ | ||
var order = eventArgs.Order; | ||
if (string.IsNullOrEmpty(order.Tag) || !int.TryParse(order.Tag, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value)) | ||
{ | ||
throw new Exception("Expected all new brokerage-side orders to have a valid tag"); | ||
} | ||
|
||
// We will only process orders with even tags | ||
return value % 2 == 0; | ||
} | ||
} | ||
} | ||
} |
63 changes: 63 additions & 0 deletions
63
Algorithm.Python/CustomBrokerageSideOrderHandlingRegressionAlgorithm.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. | ||
# Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
from AlgorithmImports import * | ||
|
||
### <summary> | ||
### Algorithm demonstrating the usage of custom brokerage message handler and the new brokerage-side order handling/filtering. | ||
### This test is supposed to be ran by the CustomBrokerageMessageHandlerTests unit test fixture. | ||
### | ||
### All orders are sent from the brokerage, none of them will be placed by the algorithm. | ||
### </summary> | ||
class CustomBrokerageSideOrderHandlingRegressionAlgorithm(QCAlgorithm): | ||
'''Algorithm demonstrating the usage of custom brokerage message handler and the new brokerage-side order handling/filtering. | ||
This test is supposed to be ran by the CustomBrokerageMessageHandlerTests unit test fixture. | ||
All orders are sent from the brokerage, none of them will be placed by the algorithm.''' | ||
|
||
def Initialize(self): | ||
self.SetStartDate(2013, 10, 7) | ||
self.SetEndDate(2013, 10, 11) | ||
self.SetCash(100000) | ||
|
||
self.SetBrokerageMessageHandler(CustomBrokerageMessageHandler(self)) | ||
|
||
self._spy = Symbol.Create("SPY", SecurityType.Equity, Market.USA) | ||
|
||
def OnEndOfAlgorithm(self): | ||
# The security should have been added | ||
if not self.Securities.ContainsKey(self._spy): | ||
raise Exception("Expected security to have been added") | ||
|
||
if self.Transactions.OrdersCount == 0: | ||
raise Exception("Expected orders to be added from brokerage side") | ||
|
||
if len(list(self.Portfolio.Positions.Groups)) != 1: | ||
raise Exception("Expected only one position") | ||
|
||
class CustomBrokerageMessageHandler(IBrokerageMessageHandler): | ||
__namespace__ = "CustomBrokerageSideOrderHandlingRegressionAlgorithm" | ||
|
||
def __init__(self, algorithm): | ||
self._algorithm = algorithm | ||
|
||
def HandleMessage(self, message): | ||
self._algorithm.Debug(f"{self._algorithm.Time} Event: {message.Message}") | ||
|
||
def HandleOrder(self, eventArgs): | ||
order = eventArgs.Order | ||
if order.Tag is None or not order.Tag.isdigit(): | ||
raise Exception("Expected all new brokerage-side orders to have a valid tag") | ||
|
||
# We will only process orders with even tags | ||
return int(order.Tag) % 2 == 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.