Skip to content

03 Modules Signals Usage Examples

Łukasz Rafał Czarnacki edited this page Mar 9, 2026 · 2 revisions

Signals Usage Examples

Source package: src/trade_lab/signals

These examples show practical signal usage with real DataFrames.

Example 1: Basic OHLC signal

from trade_lab.backtesting import BacktestEngine
from trade_lab.signals import OHLC

engine = BacktestEngine(ticker="SPY", start="2024-01-01", end="2025-01-01")
df = engine.fetch_data()

sig = OHLC()
df = sig.compute(df)

print(sig.output_columns)
print(df[sig.output_columns].tail())

Example 2: Heikin-Ashi signal with lag

from trade_lab.signals import HeikinAshi

ha = HeikinAshi(lag=1)
df = ha.compute(df)

print(ha.output_columns)
# -> ['signal__ha_open_lag1', 'signal__ha_high_lag1', ...]

Example 3: Temporal cyclical features

from trade_lab.signals import CyclicalTemporalSignal

month_cycle = CyclicalTemporalSignal(component="month", period=12)
df = month_cycle.compute(df)

print(month_cycle.output_columns)
# -> ['signal__month_p12_sin', 'signal__month_p12_cos']

Example 4: Chaining signals

from trade_lab.signals import OHLC, HeikinAshi

base = OHLC()
ha = HeikinAshi(source=base)

df = ha.compute(df)

HeikinAshi.compute() runs OHLC.compute() first through the source chain.

Example 5: Quick plotting

sig = OHLC()
df = sig.compute(df)
sig.plot(df)
temporal = CyclicalTemporalSignal("day_of_week", 7)
df = temporal.compute(df)
temporal.plot(df)

Example 6: External feature for ML workflows

from trade_lab.signals import ExternalSignal

df["VIX_norm"] = (df["VIX"] - 20.0) / 20.0

vix_feature = ExternalSignal(column="VIX_norm", name="vix_norm", lag=1)
df = vix_feature.compute(df)

print(vix_feature.output_columns)
# -> ['indicator__vix_norm__lag_0_lag1']

Use ExternalSignal with MLStrategy or trade_lab.ml_optimization. It is not compatible with StandardStrategy.

Common mistakes

  • Calling _compute() directly instead of compute().
  • Passing non-datetime index to CyclicalTemporalSignal.
  • Forgetting that first rows may be NaN because of shifting and warm-up.
  • Reusing the same output names without lag/suffix planning.
  • Expecting ExternalSignal to behave like a normal signal chain. It reads pre-existing columns instead.

Clone this wiki locally