""" 波动率指标 — 布林带、ATR 所有函数返回与输入等长的 list[float],不足周期位置填 0.0。 """ import math def bollinger( data: list[float], period: int = 20, std: float = 2.0, ): """布林带 (Bollinger Bands) 使用流式计算方差,O(n) 复杂度。 Args: data: 价格序列(通常为收盘价) period: 中轨 SMA 周期 std: 标准差倍数 Returns: (upper, mid, lower) 三个等长序列 """ n = len(data) upper = [0.0] * n mid = [0.0] * n lower = [0.0] * n if n < period: return upper, mid, lower # 初始窗口的 sum 和 sum_sq window_sum = 0.0 window_sum_sq = 0.0 for i in range(period): v = data[i] window_sum += v window_sum_sq += v * v # 第一个点 mean = window_sum / period mid[period - 1] = mean variance = (window_sum_sq / period) - (mean * mean) stdev = math.sqrt(max(variance, 0.0)) upper[period - 1] = mean + std * stdev lower[period - 1] = mean - std * stdev # 滑动窗口计算后续点 for i in range(period, n): old_val = data[i - period] new_val = data[i] window_sum += new_val - old_val window_sum_sq += new_val * new_val - old_val * old_val mean = window_sum / period mid[i] = mean variance = (window_sum_sq / period) - (mean * mean) stdev = math.sqrt(max(variance, 0.0)) upper[i] = mean + std * stdev lower[i] = mean - std * stdev return upper, mid, lower def bollinger_upper(data: list[float], period: int = 20, std: float = 2.0) -> list[float]: """布林带上轨""" upper, _, _ = bollinger(data, period, std) return upper def bollinger_mid(data: list[float], period: int = 20) -> list[float]: """布林带中轨""" from .trend import sma as _sma return _sma(data, period) def bollinger_lower(data: list[float], period: int = 20, std: float = 2.0) -> list[float]: """布林带下轨""" _, _, lower = bollinger(data, period, std) return lower def atr( high: list[float], low: list[float], close: list[float], period: int = 14, ) -> list[float]: """平均真实波幅 (ATR) 使用 Wilder 平滑算法。 Args: high: 最高价序列 low: 最低价序列 close: 收盘价序列 period: 周期 Returns: 与输入等长的 ATR 序列,前 period 位置为 0 """ n = len(close) result = [0.0] * n if n < period + 1: return result # 计算 True Range tr = [0.0] * n tr[0] = high[0] - low[0] for i in range(1, n): tr[i] = max( high[i] - low[i], abs(high[i] - close[i - 1]), abs(low[i] - close[i - 1]), ) # 初始 ATR 为前 period 个 TR 的均值 result[period] = sum(tr[1:period + 1]) / period # Wilder 平滑 for i in range(period + 1, n): result[i] = (result[i - 1] * (period - 1) + tr[i]) / period return result