Beta hedging#

This page shows the construction of a beta hedge for strategies built on the SigTech platform. A beta hedge serves to offset the volatility associated with trading a financial instrument or portfolio.

Environment#

Begin by setting up your environment:

import pandas as pd
import seaborn as sns
from uuid import uuid4

import sigtech.framework as sig

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

Learn more: Setting up your environment

Simple example#

Rolling beta#

The following example demonstrates how to use a rolling ES SP500 futures strategy as a beta hedge for a rolling NQ Nasdaq futures strategy.

Start by importing ES and NQ default rolling futures strategies, and then build them:

from sigtech.framework.default_strategy_objects.rolling_futures \
    import es_index_front, nq_index_front
nq_rfs = nq_index_front()
es_rfs = es_index_front()
nq_rfs.build()
es_rfs.build()

Use the rolling_beta method from the SigTech signal_library to compute the rolling beta of nq_rfs to es_rfs. The rolling window is set to 60 days:

window = 60
beta = sig.signal_library.core.rolling_beta(
    ts=nq_rfs.history(), market_ts=es_rfs.history(), window=window
).dropna()
beta.plot(title='Rolling Beta: NQ to ES');

As expected, the beta of NQ to ES is mostly above 1. This is due to the higher level of volatility generally associated with NQ.

Hedging with the signal strategy#

Once the rolling beta exposure is computed, create a signal that assigns 1.0 to the strategy to be hedged, nq_rfs, and beta to the hedging instrument, es_rfs.

signal = pd.DataFrame.from_dict({
    nq_rfs.name: 1.0,
    es_rfs.name: - beta
})

Combine this signal with the SignalStrategy building block to create a beta hedged version of a strategy:

def get_hedged_strategy(signal, freq):
    strategy = sig.SignalStrategy(
        signal_name=sig.signal_library.core.from_ts(signal).name,
        start_date=signal.first_valid_index(),
        currency='USD',
        rebalance_frequency=freq,
        ticker=f'BetaHedgedStrategy_{freq}_{str(uuid4())[:4]}'
    )
    strategy.build()
    return strategy

Impact of the beta estimation window#

To examine the impact of the rebalancing frequency on the hedged strategy:

frequencies = ['2BD', '1W', 'EOM', '60BD', '6M']
bh_strategies = {freq: get_hedged_strategy(signal, freq) for freq in frequencies}
strategy_histories = pd.concat(
    {f: s.history() for f, s in bh_strategies.items()}, axis=1)
strategy_histories.plot();

Realised beta#

The following code block measures the impact of the realised beta on the hedged strategy. As expected, more frequent rebalancing tends to decrease the magnitude of the realised beta:

realised_betas = {}
for f, s in bh_strategies.items():
    realised_betas[f] = sig.signal_library.core.rolling_beta(
        ts=s.history(), market_ts=es_rfs.history(), window=window
    ).dropna()
pd.DataFrame(realised_betas).plot(title='Realised Rolling Betas');