4. How a strategy declares and uses data
4.1. 1. 策略层在整体中的位置
The strategy layer is responsible for two things: declaring “what data is needed” (and the window length, whether to use the latest period), and in realize() “using the data to compute signals”. Data is not actively pulled by the strategy; instead, the runtime prepares it at each step according to the declarations and injects it, and the strategy only retrieves it by id via get_data(dtype_id). In this way, backtesting and live trading use exactly the same data view and calling pattern.
4.2. 2. 策略如何声明需要的数据
When initializing the strategy class (__init__), declare data requirements via the following attributes:
data_types: One or more DataType objects (or a list/dict). Each DataType corresponds to a kind of “referencable information” and maps to a unique dtype_id (e.g.,
close_E_d).window_length: The length of the historical data window (e.g., 20 means the most recent 20 cycles). Can be a scalar (applies to all declared data types) or specified separately by dtype.
use_latest_data_cycle: Whether to use only the data from the “latest single cycle” (e.g., using only the latest cross-section for stock selection). Can be set separately by dtype.
After declaration, the engine will know which dtype_id the strategy needs and what window length, so it can prepare the corresponding data windows before running and update/inject them at each step.
4.3. 3. 运行时数据如何到达策略
Preparation stage: based on the backtest period (or the current time in live trading), and the strategy’s data_types and window_length, the engine pulls the data for the corresponding period from the DataSource, and pre-slices (or slices on demand) the “data window” for each time step.
Before each step runs: for each strategy in the Group to be run at the current step, the engine calls update_running_data_window to write the data window for the current step into that strategy’s internal state (indexed by dtype_id).
Inside realize(): the strategy retrieves the injected window data (a numpy array) by id via get_data(dtype_id) to compute signals. No parameters are needed, and there’s no need to care which table the data comes from.
Therefore, the data flow is “declaration → engine injects step by step → get_data references it”. The strategy code contains no “table reading” or “pulling/fetching” logic at all.
4.4. 4. 数据窗口的含义
Time dimension: window_length means “how many periods to look back”. For example, at daily frequency, window_length=20 means data for the most recent 20 trading days; the array shape is typically (n_periods,) or (n_assets, n_periods), with the last dimension being time and the last column being the most recent period.
Shapes in multi-asset cases: different strategy base classes organize data slightly differently:
RuleIterator: typically iterates by asset; each realize() sees a single-asset time series or cross section.
FactorSorter: a multi-asset cross section (e.g., one factor value per stock), used for ranking and stock selection.
GeneralStg: multi-asset, multi-dtype windows, returning a signal array with the same length as the number of assets.
The exact shapes are subject to the API and strategy base-class documentation; this series emphasizes “windows are prepared by the engine according to declarations, and the strategy retrieves them by id via get_data”.
4.5. 5. 过程数据(proc.*)
In addition to the static historical data described above (“declaration → engine injection”), qteasy supports process data: state that depends on the backtest/live execution path (such as current positions, cash, historical trade records, etc.). Process data does not need to be declared in data_types; it is maintained and injected at runtime by the Backtester (backtesting) or Trader (live trading).
Access pattern: in
realize(), retrieve as needed via forms likeself.get_data('proc.own_cash'),self.get_data('proc.trade_records', lag=0), etc.; supportslag(steps or time such as'1d') andwindow(such as'5d') parameters.Constraint: a single call allows only one
proc.*field, and it must not be mixed with static data in the same call; any strategy that uses process data will automatically follow the dynamic backtesting path (generate signals step by step, execute trades step by step).
See Process Data (proc.*) and Dynamic Backtesting for details.
4.6. 6. 参考数据(若有)
Besides the data_types declared by the strategy, qteasy supports “reference data” (such as the closing price of an index, used to calculate market returns, etc.). The difference between reference data and primary data is that it usually does not have a one-to-one correspondence with the asset pool, and it can also be obtained in a strategy via the corresponding dtype_id or a dedicated interface. For specific configuration and referencing methods, see the documentation and API for the current version.
4.7. 7. 小结
“Declare → engine injects → get_data references” ensures that:
Backtesting and live trading use the same data view and access pattern;
The strategy cannot access undeclared or future data, preventing lookahead bias at the mechanism level;
A unified interface that is easy to maintain and extend.
“Declaration → engine injection → get_data reference” also applies to process data, except that process data does not need to be declared, is injected step by step by the runtime layer, and only triggers the dynamic backtesting path when it is used. For more usage, see the “User Guide” and the “API Reference”.