""" 动量指标 — RSI、Stochastic 所有函数返回与输入等长的 list[float],不足周期位置填 0.0。 """ def rsi(data: list[float], period: int = 14) -> list[float]: """相对强弱指数 (RSI) 使用 Wilder 平滑算法,Wilder's RSI = 100 - [100 / (1 + avg_gain / avg_loss)] Args: data: 价格序列 period: 周期(默认 14) Returns: 与 data 等长的 RSI 序列 [0, 100],前 period 位置为 0 """ n = len(data) result = [0.0] * n if n < period + 1: return result # 计算价格变化 changes = [data[i] - data[i - 1] for i in range(1, n)] # 初始平均涨幅和跌幅(Simple average of first `period` changes) gains = [max(c, 0) for c in changes[:period]] losses = [abs(min(c, 0)) for c in changes[:period]] avg_gain = sum(gains) / period avg_loss = sum(losses) / period # 计算第一个 RSI if avg_loss == 0: result[period] = 100.0 else: rs = avg_gain / avg_loss result[period] = 100.0 - (100.0 / (1.0 + rs)) # Wilder 平滑后续值 for i in range(period, n - 1): change = changes[i] gain = max(change, 0.0) loss = abs(min(change, 0.0)) avg_gain = (avg_gain * (period - 1) + gain) / period avg_loss = (avg_loss * (period - 1) + loss) / period if avg_loss == 0: result[i + 1] = 100.0 else: rs = avg_gain / avg_loss result[i + 1] = 100.0 - (100.0 / (1.0 + rs)) return result def stoch( high: list[float], low: list[float], close: list[float], k_period: int = 14, k_smooth: int = 3, d_smooth: int = 3, ): """Stochastic 指标 (KDJ 中的 K/D) %K = 100 * (close - lowest_low) / (highest_high - lowest_low) %K_smoothed = SMA(%K, k_smooth) %D = SMA(%K_smoothed, d_smooth) Args: high: 最高价序列 low: 最低价序列 close: 收盘价序列 k_period: %K 窗口 k_smooth: %K 平滑周期 d_smooth: %D 平滑周期 Returns: (k_values, d_values) 两个等长序列,范围 [0, 100] """ n = len(close) k_raw = [0.0] * n k_values = [0.0] * n d_values = [0.0] * n if n < k_period: return k_values, d_values # 计算原始 %K for i in range(k_period - 1, n): highest = max(high[i - k_period + 1 : i + 1]) lowest = min(low[i - k_period + 1 : i + 1]) if highest != lowest: k_raw[i] = 100.0 * (close[i] - lowest) / (highest - lowest) else: k_raw[i] = 50.0 # 平滑 %K from .trend import sma as _sma k_smoothed = _sma(k_raw, k_smooth) d_smoothed = _sma(k_smoothed, d_smooth) return k_smoothed, d_smoothed def stoch_k( high: list[float], low: list[float], close: list[float], k_period: int = 14, k_smooth: int = 3, ) -> list[float]: """Stochastic %K""" k, _ = stoch(high, low, close, k_period, k_smooth) return k def stoch_d( high: list[float], low: list[float], close: list[float], k_period: int = 14, k_smooth: int = 3, d_smooth: int = 3, ) -> list[float]: """Stochastic %D""" _, d = stoch(high, low, close, k_period, k_smooth, d_smooth) return d