Tuesday, April 25, 2017

Exploring Asset Relationships

This post and notebook were originally posted on Quantopian forum. You can access it via this link.


Developing 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.


Quantopian 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')  

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 Futures

Let'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'),  

 spy = get_pricing('SPY',  
          fields = 'price',  

 es.name = es.name.root_symbol  
 spy.name = spy.name.symbol  
 res = es.to_frame().join(spy.to_frame())  

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  


Let'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[0], res.columns[1]);  

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. 

Commercial Announcement

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.

No comments:

Post a Comment

About Me

My photo
Data Science, algorithmic trading and Python enthusiast and researcher. Regularly conduct workshops for Quantopian, a Boston-based crowd-source hedge fund. Look out for my courses on Udemy as well. My motto? Being right is over-rated. This is especially true in trading. I rather keep exploring and learn continuously. All strategies suffer decay. Keep learning and growing. On that note, if you notice whatever I shared is wrong. Let me know. Rather than rejecting correction, I welcome them.