6. How Strategy runs: timing, data, and parameters
6.1. 1. 策略运行时机
The strategy’s execution timing (when and how frequently it runs) is not stored inside the strategy class, but is determined by the Group it belongs to. The Group’s run_freq and run_timing are specified when adding the strategy to an Operator (e.g., add_strategy(stg, run_freq='d', run_timing='close')). Therefore, placing the same strategy instance into Groups with different run_freq/run_timing will cause it to be invoked at different times.
6.2. 2. 单步运行流程(细化)
For the current time step (step_index):
Check group_timing_table: take the row corresponding to this step to get the list of Groups to run at this step (columns with value 1).
For each running Group:
For each Strategy within this Group: based on its data_types, window_length, and the current step, slice out this step’s data window from the prepared data, and call update_running_data_window to inject it into that strategy instance (written by dtype_id).
Call generate() for each strategy in this Group in order (it will internally call the no-arg realize()), collect the signals returned by each strategy, and form a list.
Use this Group’s blender to blend the signals in the list into one merged signal for the group.
If multiple Groups run in this step: then merge the signals from each group into one according to group_merge_type (or output them separately, depending on the implementation).
Hand the step’s final signal to the upper layer: in backtesting, pass it to the Backtester to parse into buys/sells and update positions; in live trading, pass it to the Trader/Broker to generate orders.
6.3. 3. Strategy 内部:realize() 与 get_pars / get_data
realize(): Takes no arguments. Strategy logic is implemented only within this method; it does not receive data or time via parameters. Instead, use get_pars(name, …) to fetch tunable parameters and get_data(dtype_id) to fetch the data window injected for the current step.
Return value: A scalar or a 1D array, depending on the strategy base class (RuleIterator is often a scalar, FactorSorter returns a factor array, and GeneralStg returns one signal per asset). The same realize() code is reused in both backtesting and live trading to ensure consistent behavior.
6.4. 4. 可调参数(Parameter)
Definition: In the strategy class’s init, use pars (a Parameter list or dict) to define the names, types, value ranges, etc. of tunable parameters.
Pre-run setup: use set_parameter (e.g.,
op.set_parameter(stg_id, pars=(...))) to write in the parameter values to be used before running.Optimization: The Optimizer samples or searches over the parameter space (determined by Parameter settings such as par_range). For each parameter set, it sets the parameters to the Operator and runs one backtest, aggregates results according to the objective function (e.g., Sharpe ratio), and thus finds a better parameter combination.
6.5. 5. 三种策略基类的输入/输出差异
Base class |
Inputs (get_data, etc.) |
Outputs (return value of realize) |
Typical use cases |
|---|---|---|---|
RuleIterator |
Single-asset or multi-asset data window, retrieved by dtype_id |
Scalar (e.g., 1/-1/0); the same rule iteration applies to all assets |
Timing, single rule with multiple instruments |
FactorSorter |
Multi-asset cross section (e.g., factor values for each stock) |
A 1D factor array; the engine selects stocks according to ranking and filtering rules |
Factor-based stock selection |
GeneralStg |
Multi-asset, multi-dtype windows |
A 1D signal array (one target position or weight per asset) |
General-purpose multi-asset signals |
6.6. 6. 小结
The same “step → prepare data → inject → realize() → mix” workflow serves both backtesting and live trading: the strategy does not care whether it is currently backtesting or live; it only depends on get_pars/get_data and the timing of its Group. The runtime layer is responsible for providing the corresponding data in different modes and handling the output signals. For more implementation details, see the “User Guide” and the API reference.