QuantJourney Backtester

QuantJourney Backtester

Share product feedback

✓

Thank you.

Your note is now in the QuantJourney inbox.

docs/engine/technical-indicators.mdx

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.

Sourcebacktester/core.py + backtester/portfolio/instr_data.py
LayerFeature preparation
ModeWeights and orders
Inputprice fields and indicators_config
Outputfeature frames available through get_feature(...)
Primary APIindicators_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.