IntroductionDeveloping profitable and robust algorithms required a deep and thorough understanding of product structure and economic driver(s) for asset movement.
In this post, we are going to investigate the relationship between E-mini S&P 500, a futures contract, and S&P 500 ETF, an ETF, to illustrate the process. Clearly, the underlying assets for both are the S&P500 stocks and by definition, there should be a strong relationship between the two assets. This approach narrows the scope of the investigation to relative movement between the two assets. This is just a simple illustration. It is not exhaustive by any means.
If you are not familiar with the recently released Quantopian Future API, you can read more about it here and for a short video presentation on the Quantopian Futures API and introduction to Futures contract, you can access this post.
ApplicationQuantopian has expressed interest in algo that is market neutral. One way to achieve this is by hedging. If the algo has positive beta exposure to S&P500, one can look at using the E-mini S&P500 as a hedging instrument. The benefits of using futures are:
- Lower cost (trading 1 futures instead of 502 stocks)
- Speed of execution
- Lower capital requirement (margin)
- Liquidity in the futures market
We need to first import the relevant libraries
import pandas as pd # Pandas is Python's work horse for data analysis import seaborn as sns # Seaborn for vizualisation import statsmodels.api as sm # Statsmodels for statistical analysis from quantopian.research.experimental import history from quantopian.research.experimental import continuous_future
The last two lines are both Quantopian Futures API for extracting historical pricing and Continuous Futures prices.
Futures Contract Specifications
esh16 = symbols('ESH16') esh16
The returned data includes symbol, underlying symbol, asset name, exchange, start and end date, notice date, expiration date, auto close date, tick size, multiplier and exchange name in full:
Future(1034201603, symbol=u'ESH16', root_symbol=u'ES', asset_name=u'S&P 500 E-Mini', exchange=u'CME', start_date=Timestamp('2015-01-06 00:00:00+0000', tz='UTC'), end_date=Timestamp('2016-03-18 00:00:00+0000', tz='UTC'), first_traded=None, notice_date=None, expiration_date=Timestamp('2016-03-18 00:00:00+0000', tz='UTC'), auto_close_date=Timestamp('2016-03-16 00:00:00+0000', tz='UTC'), tick_size=0.25, multiplier=50.0, exchange_full=u'CME')
From the returned data, we can see that the multiplier for ES is 50. That means if the price of the futures is 2000, then the nominal contract value is 2000 times 50, which is 100k.
Now to extract the historical price of ESH16 on May 5, 2015,
history(esh16, fields='price', frequency='daily', start_date='2015-05-05', end_date='2015-05-05')
We get the price of 2068 on May 5, 2015.
2015-05-05 00:00:00+00:00 2068.0 Freq: C, Name: Future(1034201603 [ESH16]), dtype: float64
Futures are highly levered product because of margining. With margin requirement of each futures contract at $5000 CME, it translates to a leverage of 20 times or margin of 5%.
Only $5k is needed to secure a futures contract with notional value worth approx. $100k.
Continuous FuturesLet's start with downloading E-mini S&P500 futures and SPY ETF data for analysis
es = history(continuous_future('ES', offset=0, roll='volume', adjustment='mul'), fields='price', frequency='daily', start_date='2015-01-01', end_date='2016-06-01')
spy = get_pricing('SPY', fields = 'price', start_date='2015-01-01', end_date='2016-06-01')
es.name = es.name.root_symbol spy.name = spy.name.symbol res = es.to_frame().join(spy.to_frame()) res.head()
The returned data:
ES SPY 2015-01-02 00:00:00+00:00 2002.883 200.215 2015-01-05 00:00:00+00:00 1975.232 196.706 2015-01-06 00:00:00+00:00 1952.964 194.786 2015-01-07 00:00:00+00:00 1977.434 197.223 2015-01-08 00:00:00+00:00 2010.469 200.712
VisualizationLet's do a scatter plot for the whole period. The reason that I used ES as the independent variable is because many publications find that futures often lead the cash market. The other reason is that you are more likely to use futures as a hedging tool.
res = res.pct_change().dropna() res.plot.scatter(res.columns, res.columns);
You can, of course, perform a linear regression to formalise the relationship as I did in the notebook. Sometimes, we want to use a rolling beta instead of a fixed relationship to better model the changing market nature. Again, I show this in the notebook. Below chart demonstrates the concept of rolling beta.
After all that hard work, what next and how do we apply this? You can look applying this in futures pairs trading, hedging and use this as a first cut screen before utilising more advanced technology like co-integration.
I will be launching a new course called Trading with Sentiment Analysis on Udemy soon. Do make sure you sign up to receive special promotional price for the course.