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
|