90 lines
2.6 KiB
Python
90 lines
2.6 KiB
Python
"""
|
|
Bollinger Bands 单元测试
|
|
|
|
Author: 张飞 翼德
|
|
Date: 2026-05-31
|
|
"""
|
|
|
|
import math
|
|
from bollinger import calc_bollinger
|
|
|
|
|
|
def test_basic():
|
|
"""基本功能测试"""
|
|
prices = [float(10 + i) for i in range(25)]
|
|
upper, middle, lower = calc_bollinger(prices, period=5)
|
|
assert len(upper) == 21 # 25 - 5 + 1
|
|
assert len(middle) == 21
|
|
assert len(lower) == 21
|
|
|
|
|
|
def test_sma_correctness():
|
|
"""验证 middle 等于 SMA"""
|
|
prices = [10.0, 11.0, 12.0, 13.0, 14.0]
|
|
upper, middle, lower = calc_bollinger(prices, period=3)
|
|
# SMA of [10,11,12] = 11.0
|
|
assert math.isclose(middle[0], 11.0)
|
|
# SMA of [11,12,13] = 12.0
|
|
assert math.isclose(middle[1], 12.0)
|
|
# SMA of [12,13,14] = 13.0
|
|
assert math.isclose(middle[2], 13.0)
|
|
|
|
|
|
def test_upper_lower_symmetry():
|
|
"""验证上下轨关于中轨对称"""
|
|
prices = [float(44 + i * 0.5 + (i % 3) * 0.2) for i in range(30)]
|
|
upper, middle, lower = calc_bollinger(prices, period=10)
|
|
for u, m, l in zip(upper, middle, lower):
|
|
assert math.isclose(u - m, m - l, rel_tol=1e-9)
|
|
|
|
|
|
def test_upper_gt_middle_gt_lower():
|
|
"""上轨 > 中轨 > 下轨"""
|
|
prices = [10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0]
|
|
upper, middle, lower = calc_bollinger(prices, period=5)
|
|
for u, m, l in zip(upper, middle, lower):
|
|
assert u > m > l
|
|
|
|
|
|
def test_num_std_zero():
|
|
"""num_std=0 → 三条线重合"""
|
|
prices = [10.0, 11.0, 12.0, 13.0, 14.0]
|
|
upper, middle, lower = calc_bollinger(prices, period=3, num_std=0.0)
|
|
for u, m, l in zip(upper, middle, lower):
|
|
assert math.isclose(u, m)
|
|
assert math.isclose(m, l)
|
|
|
|
|
|
def test_insufficient_data():
|
|
"""数据不足 → 空列表"""
|
|
prices = [10.0, 11.0, 12.0]
|
|
upper, middle, lower = calc_bollinger(prices, period=5)
|
|
assert upper == [] and middle == [] and lower == []
|
|
|
|
|
|
def test_period_invalid():
|
|
"""period <= 0"""
|
|
prices = [10.0, 11.0, 12.0]
|
|
upper, middle, lower = calc_bollinger(prices, period=0)
|
|
assert upper == [] and middle == [] and lower == []
|
|
upper, middle, lower = calc_bollinger(prices, period=-1)
|
|
assert upper == [] and middle == [] and lower == []
|
|
|
|
|
|
def test_empty_input():
|
|
"""空输入"""
|
|
upper, middle, lower = calc_bollinger([], period=5)
|
|
assert upper == [] and middle == [] and lower == []
|
|
|
|
|
|
if __name__ == "__main__":
|
|
test_basic()
|
|
test_sma_correctness()
|
|
test_upper_lower_symmetry()
|
|
test_upper_gt_middle_gt_lower()
|
|
test_num_std_zero()
|
|
test_insufficient_data()
|
|
test_period_invalid()
|
|
test_empty_input()
|
|
print("所有测试通过 ✅")
|