Technical Indicators
How indicators are configured, calculated and consumed by QuantJourney strategies.
Indicators are feature columns derived from market data before strategy hooks read them. Strategies should consume stored features rather than recomputing hidden state inside every hook.
Source
backtester/core.py + backtester/portfolio/instr_data.pyLayerFeature preparation
ModeWeights and orders
Inputprice fields and
indicators_configOutputfeature frames available through
get_feature(...)Primary API
indicators_config=[...]Main caveatWarmup periods create NaNs; strategy code must handle them explicitly.
Level 1: Configure Indicators
SMA 50 and 200 on close
python
strategy = MyStrategy(
...,
indicators_config=[
{
"function": "SMA",
"price_cols": ["close"],
"params": {"periods": [50, 200]},
},
],
)Level 2: Read Indicator Features
Consume indicators in signal code
python
def _compute_signals(self) -> pd.DataFrame:
sma_fast = self.instruments_data.get_feature("SMA_50_close")
sma_slow = self.instruments_data.get_feature("SMA_200_close")
valid = sma_fast.notna() & sma_slow.notna()
signal = (sma_fast > sma_slow).astype(float)
return signal.where(valid, 0.0).fillna(0.0)Level 3: Use Indicators In Order Mode
Read features inside _compute_orders
python
def _compute_orders(self, date, bars, current_positions, nav):
rsi = self.instruments_data.get_feature("RSI_14_close")
inst = "AAPL"
if date not in rsi.index or inst not in rsi.columns:
return
rsi_value = rsi.loc[date, inst]
if pd.isna(rsi_value):
return
if rsi_value < 30 and current_positions.get(inst, 0.0) == 0:
...Failure Modes
- Using an indicator before its warmup period is complete.
- Relying on implicit NaN behavior instead of masking and filling.
- Looking up the wrong generated feature name.
- Recomputing indicators inside every bar loop when the feature layer already prepared them.
- Mixing adjusted close with unadjusted OHLC without checking consistency.