Search…
5. Single-instrument signal strategy
To build on your RollingFutureStrategy, add signals to take long or short positions during different time periods.

A simple signal strategy

1. Set up a single-instrument RollingFutureStrategy again

The first few code blocks are very close to what you already used in the previous two tutorials:

Set up environment

1
import sigtech.framework as sig
2
import datetime as dtm
3
4
sig.init();
Copied!

Define instrument, time period, and RollingFutureStrategy

1
my_instrument = sig.obj.get("KC COMDTY FUTURES GROUP")
2
3
my_start = dtm.date(2019, 1, 1)
4
my_end = dtm.date(2021, 12, 31)
5
6
my_rfs = sig.RollingFutureStrategy(
7
start_date=my_start,
8
end_date=my_end,
9
10
currency=my_instrument.currency,
11
contract_code=my_instrument.contract_code,
12
contract_sector=my_instrument.contract_sector,
13
14
rolling_rule="F_0"
15
)
Copied!

2. Create a DataFrame of signals

Every RollingFutureStrategy instance has a history, in the format of a simple table of dates and values:
1
# View your RollingFutureStrategy instance's history
2
my_rfs.history()
Copied!
Note: the table is a pandas Series. Run my_rfs.history? to see this confirmed in its docstring.

Duplicate the history Series and reset its values

1
# Make a copy of the history Series
2
signals = my_rfs.history().copy()
3
4
# Reset its values to 0
5
signals.values[:] = 0
6
7
# View it
8
signals
Copied!
The signals series you've just created has all the same dates as the history of your RollingFutureStrategy, but the values are now reset to 0. In the next step you will repopulate the values with signals—indicators of what position to take.

Add the signals

A signal of 1 indicates a 100% long position, while a signal of -1 indicates a 100% short position. Set a signal of -1 for the first four months of each year in the time period, and 1 for the final four months of each year, assuming there is a strategic rationale for this relating to seasonal market activity:
1
# short position for first 4 months of each year
2
signals.loc[signals.index.month <= 4] = -1
3
4
# long position for last 4 months of each year
5
signals.loc[signals.index.month >= 8] = 1
6
7
# view new values
8
signals
Copied!

Convert series to DataFrame and associate with RFS instance

For future steps to work, signals needs to be in DataFrame format and have the exact same name as your RollingFutureStrategy instance. This name-sharing allows the SignalStrategy instance to reference the relevant RollingFutureStrategy instance:
1
# Convert pandas Series to pandas Dataframe
2
# and give it the same name as your RollingFutureStrategy instance
3
signals = signals.to_frame(my_rfs.name)
4
5
# View the dataframe
6
signals
Copied!

3. Define SignalStrategy

1
seasonal_strategy = sig.SignalStrategy(
2
start_date=my_start,
3
end_date=my_end,
4
currency='USD',
5
6
# Reference the signals DataFrame
7
signal_name=sig.signal_library.from_ts(signals).name,
8
# This also tells the SignalStrategy which underyling strategy to use
9
# (the RollingFutureStrategy instance) as they have identical names
10
11
rebalance_frequency='SOM',
12
# Note that this means only the signals for the start of the month matter.
13
# All the other signal values are irrelevant.
14
15
# Set allocation function to normalize number of short and long positions
16
# (hold the same number of long and short positions at any given time).
17
allocation_function=sig.signal_library.allocation.normalize_weights,
18
19
# Use .? to view other possible arguments for the SignalStrategy building block.
20
)
Copied!

4. View performance

1
seasonal_strategy.plot.performance()
Copied!

👷
Your turn: customise the strategy

Try a different set of signals.