SPY EMA Signals for Selecting E-Mini Futures Contracts
Summary
This algorithm uses the relationship between two exponential moving averages on SPY to generate directional signals for trading S&P 500 E-mini futures. After a warm-up period, it treats the fast average being above the slow average by a small tolerance as an uptrend and opens a futures position when flat. A downtrend signal liquidates an invested portfolio. The example uses daily data, 20- and 60-period averages, and a fixed order size of one contract.
The algorithm filters the futures chain by expiry and inspects available contracts before sending an order. Although the comments describe selecting the front eligible contract, the implementation sorts eligible contracts in reverse expiry order, which selects the latest expiry rather than the nearest one. The example dates span part of 2016, but no performance statistics or risk analysis are supplied. It illustrates signal generation on an equity and contract selection for a futures trade; it does not establish that this configuration is profitable or account for costs, roll management, or broader portfolio risk.
Key ideas
- Daily SPY fast and slow EMAs provide the direction signal for E-mini futures trades.
- The example opens one contract when the fast EMA exceeds the slow EMA by a tolerance and exits on a downtrend signal.
- A futures expiry filter narrows the available contract chain before selection.
- The code selects the latest eligible expiry, despite comments referring to the front contract.
- The example offers no reported performance evidence or discussion of trading costs.
Tags
Full text
# FuturesMomentumAlgorithm
# FuturesMomentumAlgorithm
EMA cross with SP500 E-mini futures In this example, we demostrate how to trade futures contracts using a equity to generate the trading signals It also shows how you can prefilter contracts easily based on expirations. It also shows how you can inspect the futures chain to pick a specific contract to trade.
## 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>
### EMA cross with SP500 E-mini futures
### In this example, we demostrate how to trade futures contracts using
### a equity to generate the trading signals
### It also shows how you can prefilter contracts easily based on expirations.
### It also shows how you can inspect the futures chain to pick a specific contract to trade.
### </summary>
### <meta name="tag" content="using data" />
### <meta name="tag" content="futures" />
### <meta name="tag" content="indicators" />
### <meta name="tag" content="strategy example" />
class FuturesMomentumAlgorithm(QCAlgorithm):
def initialize(self):
self.set_start_date(2016, 1, 1)
self.set_end_date(2016, 8, 18)
self.set_cash(100000)
fast_period = 20
slow_period = 60
self._tolerance = 1 + 0.001
self.is_up_trend = False
self.is_down_trend = False
self.set_warm_up(max(fast_period, slow_period))
# Adds SPY to be used in our EMA indicators
equity = self.add_equity("SPY", Resolution.DAILY)
self._fast = self.ema(equity.symbol, fast_period, Resolution.DAILY)
self._slow = self.ema(equity.symbol, slow_period, Resolution.DAILY)
# Adds the future that will be traded and
# set our expiry filter for this futures chain
future = self.add_future(Futures.Indices.SP_500_E_MINI)
future.set_filter(timedelta(0), timedelta(182))
def on_data(self, slice):
if self._slow.is_ready and self._fast.is_ready:
self.is_up_trend = self._fast.current.value > self._slow.current.value * self._tolerance
self.is_down_trend = self._fast.current.value < self._slow.current.value * self._tolerance
if (not self.portfolio.invested) and self.is_up_trend:
for chain in slice.futures_chains:
# find the front contract expiring no earlier than in 90 days
contracts = list(filter(lambda x: x.expiry > self.time + timedelta(90), chain.value))
# if there is any contract, trade the front contract
if len(contracts) == 0: continue
contract = sorted(contracts, key = lambda x: x.expiry, reverse=True)[0]
self.market_order(contract.symbol , 1)
if self.portfolio.invested and self.is_down_trend:
self.liquidate()
def on_end_of_day(self, symbol):
if self.is_up_trend:
self.plot("Indicator Signal", "EOD",1)
elif self.is_down_trend:
self.plot("Indicator Signal", "EOD",-1)
elif self._slow.is_ready and self._fast.is_ready:
self.plot("Indicator Signal", "EOD",0)
def on_order_event(self, order_event):
self.log(str(order_event))
```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.