106 lines
3.5 KiB
Python
106 lines
3.5 KiB
Python
"""v1.7.6 新增特征检测和信号淘汰机制测试"""
|
|
import os
|
|
import sys
|
|
import pandas as pd
|
|
import numpy as np
|
|
|
|
PROJECT_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
|
if PROJECT_DIR not in sys.path:
|
|
sys.path.insert(0, PROJECT_DIR)
|
|
|
|
|
|
def make_df(highs, lows, closes, opens=None, volumes=None):
|
|
df = pd.DataFrame({
|
|
"high": highs,
|
|
"low": lows,
|
|
"close": closes,
|
|
"open": opens or closes,
|
|
"volume": volumes or [1000] * len(closes),
|
|
})
|
|
return df
|
|
|
|
|
|
def test_detect_higher_lows_finds_clear_pattern():
|
|
"""验证底部抬高检测能识别清晰的逐步抬高低点"""
|
|
from altcoin_screener import detect_higher_lows
|
|
|
|
lows, highs, closes, volumes = [], [], [], []
|
|
for seg in range(6):
|
|
for _ in range(4):
|
|
low = seg * 5 + np.random.uniform(-0.3, 0.3)
|
|
high = low + np.random.uniform(2, 4)
|
|
lows.append(low)
|
|
highs.append(high)
|
|
closes.append((low + high) / 2)
|
|
volumes.append(np.random.uniform(800, 1200))
|
|
|
|
df = make_df(highs, lows, closes, volumes=volumes)
|
|
result = detect_higher_lows(df)
|
|
|
|
assert result["found"] is True
|
|
assert result["hl_count"] >= 4
|
|
assert "底部抬高" in result["signal"]
|
|
|
|
|
|
def test_detect_higher_lows_rejects_declining_trend():
|
|
"""验证下降趋势不会被误判为底部抬高"""
|
|
from altcoin_screener import detect_higher_lows
|
|
|
|
lows, highs, closes, volumes = [], [], [], []
|
|
for seg in range(6):
|
|
for _ in range(4):
|
|
low = 100 - seg * 3 + np.random.uniform(-0.3, 0.3)
|
|
high = low + np.random.uniform(1, 3)
|
|
lows.append(low)
|
|
highs.append(high)
|
|
closes.append((low + high) / 2)
|
|
volumes.append(np.random.uniform(800, 1200))
|
|
|
|
df = make_df(highs, lows, closes, volumes=volumes)
|
|
result = detect_higher_lows(df)
|
|
|
|
assert result["found"] is False
|
|
|
|
|
|
def test_detect_compression_surge_detects_tight_then_volume():
|
|
"""验证压缩后放量模式能被检测"""
|
|
from altcoin_screener import detect_compression_surge
|
|
|
|
lows = [100 + np.random.uniform(-0.5, 0.5) for _ in range(24)]
|
|
highs = [l + np.random.uniform(1, 2.5) for l in lows]
|
|
closes = [(h + l) / 2 for h, l in zip(highs, lows)]
|
|
volumes = [np.random.uniform(500, 800) for _ in range(21)] + [np.random.uniform(3000, 5000) for _ in range(3)]
|
|
|
|
df = make_df(highs, lows, closes, volumes=volumes)
|
|
result = detect_compression_surge(df)
|
|
|
|
assert result["found"] is True
|
|
assert result["range_pct"] < 20
|
|
assert result["vol_ratio"] > 2.0
|
|
assert "压缩放量" in result["signal"]
|
|
|
|
|
|
def test_detect_compression_surge_rejects_wide_range():
|
|
"""验证宽幅震荡不触发压缩检测"""
|
|
from altcoin_screener import detect_compression_surge
|
|
|
|
lows = [np.random.uniform(80, 120) for _ in range(24)]
|
|
highs = [l + np.random.uniform(5, 15) for l in lows]
|
|
closes = [(h + l) / 2 for h, l in zip(highs, lows)]
|
|
volumes = [np.random.uniform(500, 800) for _ in range(21)] + [np.random.uniform(3000, 5000) for _ in range(3)]
|
|
|
|
df = make_df(highs, lows, closes, volumes=volumes)
|
|
result = detect_compression_surge(df)
|
|
|
|
assert result["found"] is False
|
|
|
|
|
|
def test_signal_deprecation_config_exists():
|
|
"""验证信号淘汰机制配置可正确读取"""
|
|
from config_loader import get_review_params
|
|
|
|
dep = get_review_params().get("signal_deprecation", {})
|
|
assert dep.get("enabled") is True
|
|
assert dep.get("min_samples", 0) >= 5
|
|
assert 0 < dep.get("hit_rate_deprecate_threshold", 0) < 1
|