This page shows how to create intraday strategies on the SigTech platform—iteratively going through different intraday strategies, where each iteration will add more complexity as well as explain the functionality being used.
import sigtech.framework as sigfrom sigtech.framework.instruments.futures import Futurefrom sigtech.framework.infra.objects.dtypes import ( AnyType, IntType, StringType, DictType)from collections import defaultdictimport datetime as dtmimport pandas as pdimport pytzimport seaborn as snsimport numpy as npsns.set(rc={'figure.figsize': (18, 6)})ifnot sig.config.is_initialised(): env = sig.init() env[sig.config.CUSTOM_DATA_SOURCE_CONFIG]= [ ('[A-Z]{6} CURNCY','REFINITIV'), ]
Intraday strategies
Overview
Introduction
Empty strategy
Basic strategy
Intermediate strategy: FX
Intermediate strategy: Futures
This section covers the concept of creating intraday strategies on the SigTech platform. The SigTech backtesting engine operates as a timeline, where processes, such as trades and margin adjustments, are queued. Once all processes have been queued, the timeline gets run-through over the time period.
On each of the trading processes queued on the timeline, there are three key points in time:
Decision time: the point where the order is generated, and queued on the timeline to be executed at the execution time.
Sizing time: in relation to the decision point, this is a previous point in time used for sizing the trade that is to take place. for example, calculating the order size by using the price data at the sizing time.
Execution time: this is where the queued order gets executed and assumed filled.
These time points are essential to all trading actions taking place on the timeline.
In the following sub-sections, a number of intraday strategies are created. The idea is that the first strategy will be a strategy in its most basic form, while the subsequent strategies will become increasingly more complex.
Empty strategy
Strategy intro
The first strategy to be created is an empty strategy—a strategy that does nothing. Although there's no logic in terms of trading behaviour, there's still a few steps that need to be taken for it to operate properly on the timeline.
Strategy behaviour
The strategy does nothing apart from holding the initial cash specified when instantiating the strategy from the start_date to the end_date.
Key functionality
When creating a strategy, a strategy class needs to be defined. In this case it is named EmptyStrategy.
The created strategy class inherits from the Strategy class—all strategies created on the SigTech platform need to inherit from the Strategy class to make use of the functionality in the library framework.
The method strategy_initialization is inherited from the Strategy class, and needs to be overwritten to avoid throwing an exception—eventhough a pass statement is enough, as shown below.
In this next iteration of an intraday strategy we introduce the concept of processes. Processes are different actions that are scheduled on the timeline, which in turn are enacted as the timeline is replayed.
Strategy behaviour
The following strategy does the following actions every day:
Buys front future contract at 01:00
Sells front future contract at 11:00
Sweeps PnL at 18:59:59
Key functionality
See previous strategies for already introduced functionality.
add_method: allows for adding methods or functions to the timeline which manipulate the strategy in some way. In this case, the method trade to the timeline. The method takes a reference time as a parameter—the point in time the process will relate to. Additional keyword arguments can be provided to the add_method method.
size_dt_from_decision_dt: specifies when the position sizing is done relative to the decision date-time. This method usually simply subtracts a datetime.timedelta from the decision_dt argument.
execution_dt_from_datetime: similar to the above, this method is expected to modify the passed decision_dt to specify when the order is filled. Optionally, one can use the instrument argument to make the execution_dt instrument dependent.
add_position_target: no matter what the current position holdings are at a given time, the add_position_target method will change the position of an asset based on a weight fraction of the overall portfolio, if the argument unit_type are used with the value WEIGHT.
add_margin_cleanup: this method applies the variation margin based on the latest price movement, and cash gets added/removed to/from the cash account from/to the spot margin account.
classBasicStrategy(sig.Strategy): futures_group =StringType(default='NG COMDTY FUTURES GROUP') trade_timings =DictType(AnyType())def__init__(self):super().__init__() self.fut_grp = sig.obj.get(self.futures_group) self.calendar = sig.calendar.build_calendar( self.fut_grp.exchange().holidays) self.timezone = pytz.timezone(self.fut_grp.exchange().timezone)defstrategy_initialization(self,dt): for _d in self.calendar.range(self.start_date, self.end_date): d = _d.astype(dtm.datetime)# Gets active contract on date active_contract = self.fut_grp.active_contract(d, True)# Loops through the entry and exit timesfor trade_dir, trade_time in self.trade_timings.items():# Adds the process trade to the timeline self.add_method( self.timezone.localize(dtm.datetime.combine(d, trade_time)), self.trade, asset=active_contract.name, direction=trade_dir )# Runs a clean up margin process at end of day self.add_margin_cleanup(d, Future)deftrade(self,dt,asset,direction): self.add_position_target(dt, asset, direction, unit_type='WEIGHT')defsize_dt_from_decision_dt(self,decision_dt):return decision_dt - dtm.timedelta(minutes=1)defexecution_dt_from_datetime(self,instrument,dt):return dt + dtm.timedelta(minutes=1)
In this iteration of intraday strategies, the concept of signals gets included where the signal is momentum-based and applied to the spot FX market.
Strategy behaviour
This strategy calculates a simple momentum signal on each minute on each business day. The calculated momentum signal will be used as a weight representation of the portfolio, i.e. the higher the value of the momentum signal, the larger the position in the relevant asset. The rebalance process creates a trade based on the difference between the target and the current weight in relevant asset.
Key functionality
Tip: see previous strategies for already introduced functionality.
add_fx_spot_trade: this method allows for performing FX spot trades.
This strategy operates the same as the previously defined strategy, but with Futures instead of FX Spot.
Strategy behaviour
This strategy calculates a simple momentum signal on each minute, on each business date. The calculated momentum signal is used as a weight representation of the portfolio—the higher the value of the momentum signal, the larger the position in the relevant asset. The rebalance process creates a trade based on the difference between the target and the current weight in the relevant asset.