Back to Posts
Listen to Thread

Brent and West Texas Intermediate (WTI) are the two most commonly cited crude oil benchmarks. Brent is the light, sweet crude found in the North Sea, while WTI is the light, sweet crude refined in the US Midwest and gulf coast.

This strategy uses that spread to trade USO and BNO, two exchange-traded funds linked to futures for the WTI and Brent respectively (United States Oil Fund and United States Brent Oil Fund). For years, Brent and WTI traded at very similar prices in a highly correlated fashion. In mid-2010 Brent started trading at a premium to WTI. Speculation abounds about not only what is driving the divergence, but also about when, if, and how this imbalance will unwind and of course, how to best profit from possible scenarios. In the meantime I wanted to see how a very simplistic strategy of buying BNO and selling USO based on the spread would have fared over the last few years.

I put this algorithm together by using Quantopian's Fetcher (https://www.quantopian.com/posts/new-feature-fetcher) to query the price data from Quandl. The handle_data evaluates the crude oil prices each day. If Brent is trading at premium to WTI, the algorithm buys 1,000 shares of BNO and sells 1,000 share of USO. If the premium is reversed, reverse the trades.

As just one of the many disclaimers I can already think of to mention here, BNO only started trading in June of 2010, so lots of the interesting prior history of this relationship is not open to backtesting with that instrument.

This example needs to be extended. I'd love to see other people press the clone button on this algorithm and improve it. From the comments below, I was thinking about:
1) a rolling condition like, buy BNO/sell USO when the spread is above trailing 30 day avg (lots of possible variations on that) and vice versa
2) market neutral implementation (this isn't constrained to be market neutral, it does the easiest first thing which is to buy / sell equal share amounts)
3) other ideas for tradeable instruments in Quantopian's data set that capture more history than BNO (which started trading in June 2010)

Clone Algorithm
340
Loading...
Backtest from to with initial capital ( data)
Cumulative performance:
Algorithm Benchmark
Custom data:
Week
Month
All
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Information Ratio
--
Benchmark Returns
--
Volatility
--
Max Drawdown
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Information Ratio 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
This backtest was created using an older version of the backtester. Please re-run this backtest to see results using the latest backtester. Learn more about the recent changes.
There was a runtime error.

You're not alone if you're wondering why there is a spread at all: http://www.zerohedge.com/news/2013-02-13/guest-post-explaining-wti-brent-spread-divergence

Perhaps unrelated, but the GLD vs. GDX trading pair relationship shifted recently, as well (see https://www.quantopian.com/posts/fixed-version-of-ernie-chans-gold-vs-gold-miners-stat-arb).

Reversion to mean pairs strategies are all good and well looking in from the outside. It's when you're in the trade and the two legs continue to diverge but not in the same proportion, and you're now legged to one side and the trade is now way out of your risk envelope - what do you do? Average in? Cut and run? No, a better way to trade this is to use a quad strategy. Blend USO / DX (dollar index) vs BNO / EC (Euro). Get four inter-related instruments blended into a more stable oscillation and you'll have a better "pairs" strategy.

@Anony - would you be willing to flesh out the intuition for the quad strategy a bit? Is the value-add purely a currency hedge? Curious if you're coming from a technical perspective or a fundamental one.

There are quite a number of modifications that could be made to this algorithm to make it more realistic - currently it doesn't address risk envelope at all, and frankly, its a bit of a buy and hold from mid/late 2010 on as implemented (because I just set a one-time threshold of the premium condition to (brent - WTI) > 0). So even worse than your point of unequal divergence, there is no attempt to capture fluctuations in the spread once its positive (which we've seen plenty of lately, including a switch from 'narrowing' to 'widening' storyline on Reuters in the last 24 hours: http://www.reuters.com/article/2013/04/09/markets-oil-idUSL3N0CW0RD20130409 )

Ideally I'd like to extend this to look at (or have anyone build on this to show):
(1) a rolling condition like, buy BNO/sell USO when the spread is above trailing 30 day avg (lots of possible variations on that) and vice versa

(2) market neutral implementation (this isn't constrained to be market neutral, it does the easiest first thing which is to buy / sell equal share amounts)

(3) other ideas for tradeable instruments in Quantopian's data set that capture more history than BNO (which started trading in June 2010)

We can all agree with the assumption that the perfect trading strategy would be one where we traded a sine wave. Where the range was well defined and the timeseries oscillated in a generally rhythmic manner. That's the basic theory behind pairs trading. But such a system exists only in our dreams. However, it may be possible to approximate such a sine wave timeseries by blending more than two instruments into halves of a basket pairs trading system. Such is the quad strat I mentioned above. So the trick is to identify blends of instruments that when placed in opposing baskets - generates (or nearly so) our utopian sine wave.

Here's just such a composite for you to ponder. I've paper traded this for a year and back tested it for 5 and it behaves remarkably well.

Build a pairs oscillation from the following two baskets:
1) AUDJPY, CHFJPY, GBPJPY
2) CADJPY, EURJPY, NZDJPY

Weight each fx pair according to its ratio to GBPJPY.
For instance if you buy 1.0 GBPJPY you would sell 1.4 EURJPY (or whatever GBPJPY/EURJPY equals).

When the synthetic weighted index (SWI) oscillates up buy #1 and sell #2...

Hi, I'm new to algorithmic trading and to Quantopian, and after cloning your algorithm and inspecting the code, there's one part of it that I'm a little confused about and was wondering if you could help me out.

In your handle_data method, you have a for loop that calculates the price and notional for each of your two stocks. However, since you're using the same variable names for both of them, won't the price and notational for BNO just overwrite the ones for USO, making the former useless? There must be something I've missed here, I look forward to hearing you reply!

Hi Sean:

Welcome to Quantopian!

In the following excerpt:

    # Initializing the position as zero at the start of each frame  
    notional=0  
    # This runs through each stock.  It computes  
    # our position at the start of each frame.  
    for stock in context.stocks:  
        price = data[stock].price  
        notional = notional + context.portfolio.positions[stock].amount * price  

the for loop is going through the list of two stocks, and accumulating each position value in the "notional" variable. (notional = notional + [new stuff]) Thus, at the end of the for loop, notional is the sum of all the position values. Hope that helps.

thanks,
Jean

Hi Jean,

Thanks a lot for you reply, I see what is going on now. I didn't pay attention to the fact that the notional value was cumulative. That's cleared up for me now.

is Fetcher opensource? part of zipline?

Hi,

Fetcher is not part of zipline, it is a datasource we built, similar to the trade history datasource. At the moment, the datasources are pretty dependent on quantopian infrastructure, so we don't have a plan to opensource them.

thanks,
fawce

Jessica, evidence for my case.

Here is a simple chart of a blend of soybean oil + Brazilian Real VS heating oil + Canadian Dollar.
1300 periods - the last 5 years.

https://dl.dropboxusercontent.com/u/29771494/Finance/DualBasket_BOHO.png

By tuning the weights up front and letting these four instruments oscillate as an opposing duopoly, we get a fairly regular pattern.

@Anony - very cool - thanks for sharing.
How did you set the weights? Tuning on prior historical data?

One needs to perform a ballpark rationalization between disparate prices for each basket first. BO's contract is in the $50 range while BRL is around $0.50 so you have to at least get those balanced (and deal with lot size and margins, etc....). Then to build the syndex (synthetic index) the two baskets are compared with their initial prices and then those weights are used throughout the test.

And because soybean oil is generally correlated with the Real, and heating oil with the CAD, that if you swap the currencies you then get an even flatter oscillator. (BO + CADUSD) / (HO + BRLUSD). I set the weights initially to something like this:

{ { "BO", .1 }, { "BRLUSD", 10.0 }, { "HO", 1.0 }, { "CADUSD", 3.0 } }

It kind of sucks, but here's an example of a dynamic linear model(beta is a random walk) that regresses the brent trade-able stock on the data.

@Anony Mole: spectral analysis isn't part of the basic theory of pairs trading.

edit: I screwed this up. I'll fix it and make it a new thread. Sorry about the threadjack.

Clone Algorithm
6
Loading...
Backtest from to with initial capital ( data)
Cumulative performance:
Algorithm Benchmark
Custom data:
Week
Month
All
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Information Ratio
--
Benchmark Returns
--
Volatility
--
Max Drawdown
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Information Ratio 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
This backtest was created using an older version of the backtester. Please re-run this backtest to see results using the latest backtester. Learn more about the recent changes.
There was a runtime error.

The performance graph of the original algorithm is extremely misleading since the algorithm basically stops taking on positions around May 2011. Basically it just becomes a buy and hold strategy after that. So the performance is basically just coming from a speculative buy in oil (especially since the ratios are not 1:1 between USO and BNO).

@Taylor - please do post, would like to take a look at your edited algo!

@Gunnar - yup, I should have called this out more clearly in the original post, but I did point out that it devolves into a buy and hold in the thread further down. I had hoped to (just haven't gotten to it yet) extend this to a more meaningful pairs trade that tracks the spread vs just trades on the dumb threshold. Initially I just wanted to throw this out as an example of how to use the new Fetcher feature.

And since we're updating, the spread is still narrowing, and of course still getting press: http://seekingalpha.com/article/1382511-wti-brent-spread-dips-below-9-50-for-first-time-in-24-months-headed-even-lower

Found a cool site to blend symbols:
https://www.tradingview.com/e
Enter the following as the symbol:
(BO1!*0.1+USDCAD*3)/(HO1!+BR1!*10)

Log in to reply to this thread.
Not a member? Sign up!