Skip to content
All library documents

Building and Evaluating an EWMAC Forecast from Interactive Brokers FX Data

Notebook pysystemtrade

Summary

This example adapts a pysystemtrade introductory trading rule to use spot foreign exchange prices from Interactive Brokers rather than futures prices from CSV files. It connects through ib_insync, retrieves configured currency-pair histories, and illustrates EURUSD as the selected instrument. The forecast is an exponentially weighted moving average crossover: subtract a slower EWMA from a faster EWMA, defaulting the slow span to four times the fast span when it is not supplied. The raw difference is scaled by a robust estimate of price-change volatility.

The example plots the resulting forecast alongside price and passes the forecast and price series into an account function to calculate percentage performance statistics and a P&L curve. It does not show the orders that the forecast would trigger, a detailed risk or execution model, or a controlled comparison against another rule. The author also notes that IB requires account equity and a subscription for historical futures data, and that spot FX is used to make the demonstration accessible through paper accounts. IB spot FX fees are described as high, limiting the example’s suitability as a live trading recommendation.

Key ideas

  • The example obtains historical spot FX prices from Interactive Brokers through ib_insync.
  • An EWMAC forecast subtracts a slower exponential moving average from a faster one.
  • The forecast is normalized by a robust volatility estimate based on price changes.
  • The notebook plots the forecast and calculates account statistics and a P&L curve.
  • The example does not display triggered orders, and the author cautions about IB spot FX fees.

Tags

Full text
# Modified introduction using forex data


## Modified introduction using forex data

This is the trading rule example shown in [the introduction](https://github.com/pst-group/pysystemtrade/blob/master/docs/introduction.md) but modified to use Interactive Brokers instead of CSV files as data source.

IB requires a minimum equity and a monthly subscription to provide historical data on future contracts.  This example was modified to use FX prices instead futures to make it runnable with free unfunded paper trading accounts.  Note that Rob [does not recommend trading FX spot data with IB due to their high fees](https://github.com/pst-group/pysystemtrade/issues/517#issuecomment-1010770678).

First, import the required packages and initialize ib_insync.  

```python
from sysbrokers.IB.ib_connection import connectionIB
from sysbrokers.IB.ib_Fx_prices_data import ibFxPricesData

from ib_insync import util
util.startLoop() #only required when running inside a notebook
```

Connecting to Interactive Brokers gateway...

```python
conn = connectionIB(111)
conn
```

See what fx instruments we have configured.  These are configured in `sysbrokers/IB/ib_config_spot_FX.csv`

```python
ibfxpricedata = ibFxPricesData(conn)
ibfxpricedata.get_list_of_fxcodes()
```

Now we select one instrument (`EURUSD`) and try to fetch historical data for it.

```python
ibfxpricedata.get_fx_prices('EURUSD')
```

Data can also be indexed as a python dict:

```python
ibfxpricedata['JPYUSD']
```

Create the trading rule

```python
import pandas as pd
from sysquant.estimators.vol import robust_vol_calc


def calc_ewmac_forecast(price, Lfast, Lslow=None):
    """
    Calculate the ewmac trading rule forecast, given a price and EWMA speeds Lfast, Lslow and vol_lookback

    """
    if Lslow is None:
        Lslow = 4 * Lfast

    ## We don't need to calculate the decay parameter, just use the span directly
    fast_ewma = price.ewm(span=Lfast).mean()
    slow_ewma = price.ewm(span=Lslow).mean()
    raw_ewmac = fast_ewma - slow_ewma

    vol = robust_vol_calc(price.diff())

    return raw_ewmac / vol
```

Run a forecast with the previous rule

```python
price=ibfxpricedata['EURUSD']
ewmac=calc_ewmac_forecast(price, 32, 128)
ewmac.tail(5)
```

```python
import matplotlib.pyplot as plt

plt.figure(figsize=(12,5))

ax1 = price.plot(color='blue', grid=True, label='Price')
ax2 = ewmac.plot(color='red', grid=True, secondary_y=True, label='Forecast')

h1, l1 = ax1.get_legend_handles_labels()
h2, l2 = ax2.get_legend_handles_labels()


plt.legend(h1+h2, l1+l2, loc=2)
plt.show()
```

The original introduction jumps directly to "Did we make any money?".  
I would like to see here the orders that were triggered by this forecast, but instead we jump directly into P&L.  Still, these are the P&L numbers for this forecast and data:

```python
from systems.accounts.account_forecast import pandl_for_instrument_forecast
account = pandl_for_instrument_forecast(forecast = ewmac, price = price)
account.percent.stats()
```

```python
account.curve().plot()
plt.show()
```

```python
conn.close_connection()
```
![notebook output](figures/p1_1.png)
![notebook output](figures/p1_2.png)

Shown in full with attribution under the source's licence. Licence: GPL-3.0

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.