Skip to content
All library documents

Exporting EMA Crossover Portfolio Targets to Collective2

Article Strategy library · Author: QuantConnect

Summary

This example shows how to send portfolio targets from a QuantConnect algorithm to Collective2 when a fast and slow exponential moving average cross. It initializes a set of equity, forex, futures, and options targets, disables scheduled automatic exports, and registers the Collective2 signal provider. After warm-up, it sends an initial SPY target, then updates that target when the 10-period and 100-period EMA values cross defined thresholds. The example uses separate thresholds around the crossover to reduce repeated signals near the boundary.

The document is an integration demonstration rather than evidence of a profitable trading strategy. It gives no performance results or evaluation of the EMA rule. Its code includes a placeholder API key and system ID that must be supplied for use, and target conventions differ by security type. The example also does not describe handling API failures, execution quality, or portfolio-level risk. Readers should treat its crossover and target settings as illustrative configuration choices.

Key ideas

  • The algorithm exports a target portfolio to Collective2 through a registered signal provider.
  • It uses a fast and a slow SPY EMA to trigger target updates.
  • Separate crossover thresholds create a buffer around the signal boundary.
  • The sample includes targets for multiple asset types but demonstrates changes only to SPY.
  • No evidence is provided that the signal rule is profitable.

Tags

Full text
# Collective2SignalExportDemonstrationAlgorithm


# Collective2SignalExportDemonstrationAlgorithm









This algorithm sends a list of portfolio targets to Collective2 API every time the ema indicators crosses between themselves.

## Source (Apache-2.0)

```python
# 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>
### This algorithm sends a list of portfolio targets to Collective2 API every time the ema indicators crosses between themselves.
### </summary>
### <meta name="tag" content="using data" />
### <meta name="tag" content="using quantconnect" />
### <meta name="tag" content="securities and portfolio" />
class Collective2SignalExportDemonstrationAlgorithm(QCAlgorithm):

    def initialize(self):
        ''' Initialize the date and add all equity symbols present in list _symbols '''

        self.set_start_date(2013, 10, 7)   #Set Start Date
        self.set_end_date(2013, 10, 11)    #Set End Date
        self.set_cash(100000)             #Set Strategy Cash

        # Symbols accepted by Collective2. Collective2 accepts stock, future, forex and US stock option symbols
        self.add_equity("GOOG")
        self._symbols = [
            Symbol.create("SPY", SecurityType.EQUITY, Market.USA),
            Symbol.create("EURUSD", SecurityType.FOREX, Market.OANDA),
            Symbol.create_future("ES", Market.CME, datetime(2023, 12, 15)),
            Symbol.create_option("GOOG", Market.USA, OptionStyle.AMERICAN, OptionRight.CALL, 130, datetime(2023, 9, 1))
        ]
        self.targets = []

        # Create a new PortfolioTarget for each symbol, assign it an initial amount of 0.05 and save it in self.targets list
        for item in self._symbols:
            symbol = self.add_security(item).symbol
            if symbol.security_type == SecurityType.EQUITY or symbol.security_type == SecurityType.FOREX:
                self.targets.append(PortfolioTarget(symbol, 0.05))
            else:
                self.targets.append(PortfolioTarget(symbol, 1))

        self.fast = self.ema("SPY", 10)
        self.slow = self.ema("SPY", 100)

        # Initialize these flags, to check when the ema indicators crosses between themselves
        self.ema_fast_is_not_set = True
        self.ema_fast_was_above = False

        # Set Collective2 export provider
        # Collective2 APIv4 KEY: This value is provided by Collective2 in your account section (See https://collective2.com/account-info)
        # See API documentation at https://trade.collective2.com/c2-api
        self.collective2_apikey = "YOUR APIV4 KEY"

        # Collective2 System ID: This value is found beside the system's name (strategy's name) on the main system page
        self.collective2_system_id = 0

        # Disable automatic exports as we manually set them
        self.signal_export.automatic_export_time_span = None

        # If using the Collective2 white-label API, you can specify it in the constructor with the optional parameter `use_white_label_api`:
        # e.g. Collective2SignalExport(self.collective2_apikey, self.collective2_system_id, use_white_label_api=True)
        # The API url can also be overridden by setting the Destination property:
        # e.g. Collective2SignalExport(self.collective2_apikey, self.collective2_system_id) { Destination = new Uri("your url") }
        self.signal_export.add_signal_export_provider(Collective2SignalExport(self.collective2_apikey, self.collective2_system_id))

        self.first_call = True

        self.set_warm_up(100)

    def on_data(self, data):
        ''' Reduce the quantity of holdings for one security and increase the holdings to the another
        one when the EMA's indicators crosses between themselves, then send a signal to Collective2 API '''
        if self.is_warming_up: return

        # Place an order as soon as possible to send a signal.
        if self.first_call:
            self.set_holdings("SPY", 0.1)
            self.targets[0] = PortfolioTarget(self.portfolio["SPY"].symbol, 0.1)
            self.signal_export.set_target_portfolio(self.targets)
            self.first_call = False

        fast = self.fast.current.value
        slow = self.slow.current.value

        # Set the value of flag _ema_fast_was_above, to know when the ema indicators crosses between themselves
        if self.ema_fast_is_not_set == True:
            if fast > slow *1.001:
                self.ema_fast_was_above = True
            else:
                self.ema_fast_was_above = False
            self.ema_fast_is_not_set = False

        # Check whether ema fast and ema slow crosses. If they do, set holdings to SPY
        # or reduce its holdings, change its value in self.targets list and send signals
        #  to Collective2 API from self.targets
        if fast > slow * 1.001 and (not self.ema_fast_was_above):
            self.set_holdings("SPY", 0.1)
            self.targets[0] = PortfolioTarget(self.portfolio["SPY"].symbol, 0.1)
            self.signal_export.set_target_portfolio(self.targets)
        elif fast < slow * 0.999 and (self.ema_fast_was_above):
            self.set_holdings("SPY", 0.01)
            self.targets[0] = PortfolioTarget(self.portfolio["SPY"].symbol, 0.01)
            self.signal_export.set_target_portfolio(self.targets)

```

Shown in full with attribution under the source's licence. Licence: Apache-2.0

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.