Skip to content

Trend Strength Indicator

Intuição

O Trend Strength Indicator (TSI) combina múltiplos horizontes de momentum (time-series) e normaliza pelo risco (volatilidade) para produzir um score contínuo de força de tendência.

Definição

Para cada janela w em windows:

  • r_w = ln(P_t) - ln(P_{t-w})
  • σ_w = std(Δln(P), window=w) * sqrt(w)
  • signal_w = sign(r_w) * min(|r_w/σ_w|, 2)

O indicador final é a média dos signal_w.

Uso

from quantmaster.features.trend import trend_strength_indicator

df["tsi"] = trend_strength_indicator(df, windows=[21, 63, 126, 252])

API

Source code in src/quantmaster/features/trend.py
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
def trend_strength_indicator(
    data: pd.DataFrame | pd.Series,
    *,
    windows: list[int] = [21, 63, 126, 252],
    price_col: str = "close",
) -> pd.Series:
    if not isinstance(windows, list) or not windows:
        raise TypeError("windows must be a non-empty list[int]")
    if not all(isinstance(w, int) for w in windows):
        raise TypeError("windows must be a list[int]")
    if not all(w > 0 for w in windows):
        raise ValueError("windows must contain only positive integers")

    uniq = sorted(set(windows))

    price = get_price_series(data, price_col=price_col).astype(float)
    price = price.where(price > 0)
    log_p = np.log(price)

    daily = log_p.diff()
    signals: list[pd.Series] = []
    for w in uniq:
        w = validate_positive_int(w, name="window")
        r = log_p.diff(w)
        sigma = daily.rolling(w).std(ddof=1) * np.sqrt(float(w))
        scaled = r / sigma.where(sigma > 0)
        s = np.sign(r) * scaled.abs().clip(upper=2.0)
        signals.append(s)

    df = pd.concat(signals, axis=1)
    out = df.mean(axis=1)
    out.name = "trend_strength_indicator_" + "_".join(str(w) for w in uniq)
    return out