FX Manufacturing PMI Momentum#

New user? The best way to learn SigTech is to follow the steps in our user guide.

Restricted data: You will only have access to the data used in this notebook if your organisation has specifically purchased it. To check your current data access, view Data. If you would like to access more data, please contact sales@sigtech.com.

Changes will not be saved: Edits made to SigTech’s example notebooks like this will only persist for the duration of your session. When you restart the research environment, this notebook will have been restored to its original state, and any changes you have made will have been lost. To make permanent changes, copy and paste the content to a new notebook in one of your workspaces.

Introduction#

This notebook showcases how a simple Manufacturing PMI strategy trading AUDUSD 3M IMM forwards can be constructed in the SigTech Platform. The strategy will go long/short when Australian PMI is greater/less than its 10 month moving average.

Environment#

This section imports the relevant internal and external libraries, and sets up the platform environment.

[ ]:
import sigtech.framework as sig
from sigtech.framework.default_strategy_objects.rolling_fx_forwards import usd_aud_3m_imm

import numpy as np
import pandas as pd
import seaborn as sns
import datetime as dtm

sns.set(rc={'figure.figsize': (18, 6)})

start_date = dtm.date(2019,10,1)

env = sig.init(env_date=dtm.date(2024, 2, 22))

Universe#

An AUDUSD 3M IMM Fx Forward is defined as the instrument to trade

[ ]:
fx_forward = usd_aud_3m_imm()

Strategy#

Australian Manufacturing PMI data is retrieved using the sig.obj.get method

[ ]:
te_series = sig.obj.get("ECO AUS MANU PMI").data_df()

The 10 month moving average is calculated

[ ]:
pmi_df = pd.DataFrame({'date': te_series.index,
                       'value': te_series['actual_clean']})
pmi_df.index = pd.to_datetime(pmi_df['date'])
[ ]:
pmi_df['ma'] = pmi_df['value'].rolling(window=10).mean()
pmi_df = pmi_df.dropna()

The signal is calculated as 1 or -1 based on whether or not current PMI is greater than its moving average

[ ]:
pmi_df['signal'] = np.select([pmi_df['value'] > pmi_df['ma']], [1], -1)
[ ]:
pmi_df.plot(x='date',y=['value','ma'])
pmi_df.plot(x='date',y='signal',figsize=(18,2));

The signal column is renamed to the instrument to trade and the dataframe is used to create a signal object using the sig.signal_library.from_ts method. Note that the dataframe must be indexed by date.

[ ]:
signal_df = pmi_df[['signal']].rename(columns={'signal': fx_forward.name})
signal_df.index = signal_df.index.date
signal_obj = sig.signal_library.from_ts(signal_df)

Portfolio#

To build our portoflio, the SignalStrategy building block is used. By default, the identity allocation function is used, which returns the unchanged allocations as given by the signal strategy output.

[ ]:
pmi_signal_strategy = sig.SignalStrategy(
    start_date=start_date,
    currency=fx_forward.currency,
    signal_name=signal_obj.name,
    use_signal_for_rebalance_dates=True,
    end_date=dtm.date(2021,9,1)
)
[ ]:
pmi_signal_strategy.history()
[ ]:
pmi_signal_strategy.history().plot(label='signal',legend=True);
fx_forward.history()[start_date:].plot(label='rollingforward',legend=True);

Performance#

Shows some of the statistics and relevant performance metrics available on the platform for the strategy.

[ ]:
sig.PerformanceReport(pd.concat({'Inverse Vol Scaled': pmi_signal_strategy.history()}, axis=1),
                  cash=sig.CashIndex.from_currency('USD')).report()