Signal Exports
Key Concepts
Introduction
QuantConnect Signal Exports allows you to transmit the state of an algorithm's trading and portfolio positions to your fund or a third-party service. QuantConnect implements two signal services out of the box: Collective2 and Numerai. To send portfolio targets to your fund, you need to create a custom Signal Export implementation.
Add Providers
To export signals to a signal provider, during initialization, add a signal export provider.
self.signal_export.add_signal_export_provider(CustomSignalExport())
You can add multiple signal export providers to a single algorithm.
Send Portfolio Targets
The signal export manager automatically sends signals when your portfolio holdings change to your fund or a third-party service.
By default, it waits five seconds after an order is filled to aggregate all the state changes into a single post.
Set the automatic_export_time_span
property to change the waiting time.
self.signal_export.automatic_export_time_span = timedelta(seconds=1)
To send targets that aren't based on your portfolio holdings, see Manual Exports.
To disable automatic exports, set the automatic_export_time_span
property to None
.
self.signal_export.automatic_export_time_span = None
Provider Structure
Signal export providers must implement the ISignalExportTarget
interface. Extensions of the ISignalExportTarget
interface must define the send
and the dispose
methods.
The send
receives a SignalExportTargetParameters
object with a list of PortfolioTarget
objects you can use to create the API request payload.
The dispose
method is called when the algorithm is disposed. You can use this method to release unmanaged resources such as HTTP Clients.
class CustomSignalExportExampleAlgorithm(QCAlgorithm): def initialize(self) -> None: # In the Initialize method, set the custom signal export provider self.add_equity("SPY") self.signal_export.add_signal_export_providers(CustomSignalExport()) def on_data(self, slice: Slice) -> None: # Buy the SPY ETF when the algorithm is not invested if not self.portfolio.invested: self.set_holdings("SPY", 0.1) # Define the custom signal export provider from requests import post class CustomSignalExport: def send(self, parameters: SignalExportTargetParameters) -> bool: # Create the request payload using the PortfolioTarget objects in the parameters # You can use the PortfolioTarget.Percent to calculate the target quantity # from the target percentage targets = [PortfolioTarget.percent(parameters.algorithm, x.symbol, x.quantity) for x in parameters.targets] ; data = [ {'symbol' : x.symbol.value, 'quantity': x.quantity} for x in targets ] # Send the request to your custom endpoint request_uri = "https://your-custom-endpoint.com/api/signal-export" response = post(request_uri, json = data) result = response.json() # Log the result of the request for debugging purposes success = result.get('success', False) parameters.algorithm.log(f"Send #{len(parameters.targets)} targets. Success: {success}"); return success def dispose(self) -> None: pass
Manual Exports
In some cases, you may need to send signals to your fund or a third-party manually. For example, the signal export manager sends signals after a fill event and you need to submit signals when the market is closed or your signals aren't based on your portfolio holdings.
To do this, pass a PortfolioTarget
object or a list of PortfolioTarget
objects to the set_target_portfolio
method. The method returns a boolean that represents if the targets were successfully sent to its destination. In this situation, the number you pass to the PortfolioTarget
constructor represents the portfolio weight. Don't use the PortfolioTarget.percent
method.
target = PortfolioTarget(self._symbol, weight) success = self.signal_export.set_target_portfolio(target)
If you use a margin account, you can send your current portfolio holdings by calling the set_target_portfolio_from_portfolio
method.
success = self.signal_export.set_target_portfolio_from_portfolio()