import sigtech.framework as sigfrom sigtech.framework.analytics.performance.metrics import sharpe_ratioimport datetime as dtmimport pandas as pdimport numpy as npimport seaborn as snsimport matplotlib.pyplot as pltsns.set(rc={'figure.figsize': (18, 6)})ifnot sig.config.is_initialised(): sig.config.init() sig.config.set(sig.config.HISTORY_SCHEDULE_BUILD_FROM_DATA, True)
Momentum: varying window length
A RollingFutureStrategy object of the NY Harbor Heating Oil contract is created:
Define a function to construct a momentum strategy with a custom window length:
@sig.remotedefmomentum_strategy_sharpe(underlying_obj_name:str,window_length:int):''' Constructs a SMA-based momentum strategy with a given window length.'''# Get return signal_ts = sig.obj.get(underlying_obj_name).history().diff(window_length)# Create df with column name equal to underlying object name signal_ts = pd.DataFrame({underlying_obj_name: signal_ts})# Get sign of returns signal_ts = np.sign(signal_ts).dropna()# Create signal object, can be passed around between researchers signal_obj = sig.signal_library.from_ts(signal_ts) signal_strategy = sig.SignalStrategy( start_date=dtm.date(2010, 1, 4), currency='USD', signal_name=signal_obj.name, rebalance_frequency='EOM', allocation_function=sig.signal_library.allocation.identity, leverage=1, )returnsharpe_ratio(signal_strategy.history())
Use this function to construct a number of strategies and plot their Sharpe ratios:
plt.style.use('ggplot')
# Generate window lengths as powers of 2
x = [2 ** i for i in range(3, 12)]
# Generate resulting Sharpe ratios
ho_rf_usd_strat.build()
y = sig.calc_remote([momentum_strategy_sharpe(ho_rf_usd_strat.name, w) for w in x])
# Plot results and annotate chart
fig, ax = plt.subplots()
ax.scatter(x, y)
ax.set_title('Sharpe versus Momentum Window Length')
ax.set_xlabel('Momentum Window Length')
ax.set_ylabel('Strategy Sharpe')
ax.axhline(y=0., linestyle='--');
Momentum and Mean Reversion: varying window lengths
A 2D surface from varying both Momentum and Mean Reversion windows is created in the following example.
First, define a function to calculate the Sharpe for a combined Momentum and Mean Reversion strategy:
@sig.remotedefmmr_strategy_sharpe(underlying_obj_name:str,momentum_window_length:int,meanrev_window_length:int):""" Constructs a combined Momentum and Mean Reversion strategy on a given underlying. """# Identical lengths of windows will cancel out, ignore themif momentum_window_length == meanrev_window_length:return0.# Get history of underlyer obj_history = sig.obj.get(underlying_obj_name).history()# Create momentum and mean reversion signals and combine them signal_momentum = obj_history.pct_change().rolling( window=momentum_window_length).mean() signal_meanrev =-obj_history.pct_change().rolling(window=meanrev_window_length).mean() signal_ts = signal_momentum + signal_meanrev# Create df with column name equal to underlying object name signal_ts = pd.DataFrame({underlying_obj_name: signal_ts})# Get sign of returns signal_ts = np.sign(signal_ts).dropna()# Create signal object, can be passed around between researchers signal_obj = sig.signal_library.from_ts(signal_ts) strategy = sig.SignalStrategy( start_date=dtm.date(2010, 1, 4), currency='USD', signal_name=signal_obj.name, rebalance_frequency='EOM', allocation_function=sig.signal_library.allocation.identity, leverage=1, )returnsharpe_ratio(strategy.history())
Then use this function to construct a number of strategies and plot their Sharpe ratios on a 2D plot:
# Generate window lengths in specific ranges
mom_ws = [2 ** i for i in range(3, 12)]
mr_ws = range(2, 21, 2)
# Generate resulting Sharpe ratios in a 2D array
sharpes = sig.calc_remote(
[
mmr_strategy_sharpe(
underlying_obj_name=ho_rf_usd_strat.name,
momentum_window_length=w1,
meanrev_window_length=w2
)
for w2 in mr_ws for w1 in mom_ws
]
)
z = np.matrix(np.array(sharpes).reshape(len(mr_ws), len(mom_ws)))
# Plot results and annotate chart
fig, ax = plt.subplots()
plot = ax.contourf(mom_ws, mr_ws, z)
ax.set_title('Sharpe versus Momentum and Mean Reversion Window Lengths')
ax.set_xlabel('Momentum Window Length')
ax.set_ylabel('Mean Reversion Window Length')
cbar = fig.colorbar(plot, ax=ax)
cbar.ax.set_ylabel('Sharpe Ratio');