Finding Mean Reversion in FX

I have been told that my previous Neanderthals versus DeepQ Robotraders blog still is not very realistic as it uses Constant Maturity yields of US treasuries, which have the drawback of not being intuitive for non-FI managers.

I use that example because technically it was very easy to get the public data (one simple call to Quandl), but it is not difficult to extend the work to other assets classes.

Here I try the Foreign Exchange (FX) world. The ECB gathers FX rates for many currencies in the world; all we need is to use the list of available currencies and download each one:

Currencies available at ECB website

All the currencies are defined as EURCCY, meaning that you need CCY units to purchase one EUR.

Now that we have the data, let me show you how to find Mean Reverting trades, keeping in mind that:

  • This is only an educational example; for real trading conditions you need to know the funding costs for each currency,

In fact, I want to emphasise the dangers of blind quantitative trading without domain knowledge, and I will raise the issues at each step.

If interest rates differentials are negligible, the Assets under Management (AUM) for a portfolio of currencies of an EUR investor is

AUM (in EUR)=MXNEUR∗MXNunits+USDEUR∗USDunits + etc

Think of it this way: if you have 1000 pesos and 50 dollars, today you will have the equivalent of 1000 * (1/22.21) + 50 * (1/1.16) = 88.13 euros. The EUR AUM equivalent will change every time the FX price changes.

If now we plug a matrix with all the timeseries of FX expressed as CCYEUR, Johansen (see my original blog “Finding Mean Reverting Signals (part 1)”) will return unit vectors that correspond to mean reverting signals.

Unfortunately, the python code I use only allows up to 12 timeseries. To get around this drawback, I added to the code the ability to test subsets of all the currencies.

  • for a semblance of reality, I run Johansen only until 1/1/2018. Still, you can change the code to define which time range you want to use.


Swiss Franc (CHF), Turkish Lira (TRY), Israeli Shekel (ILS)

And lo and behold, I find lots of mean reverting possible trades ! As an example, above I show that by holding 100 Euros of Israeli Shekels, versus shorting 57.58 Euros of Swiss Francs and 8.95 Euros of Turkish Lira (I express them in Euros as otherwise the units are not intuitive) we get a trade that looks quite mean reverting. The half life is 49 days (last number).

The full list of the 37 mean reverting signals I found is:

Party poopers:

  • I am guilty of P-hacking. the P-value of the Johansen test is 1%, and if you look at my code you will see that I run the test 696 times, therefore expecting about 7 false positives. I should have used the Bonferroni correction (dividing the P-value by the number of tests) — but the coded python test does not allow that.

On the bright side:

  • The ‘half_life’ for this signals is lower that the rates example in my previous blog, allowing us to use it as a cut-off time.

In my code (see the bottom) I include all the code used (you will need to supply your own Quandl API access code — the data is public but using Quandl requires you to be registered).

Comments welcome.

Co-Founder of Lamat, a company specialized in solving high-value problems in finance by applying cutting edge numerical methods.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store