122 lines
5.0 KiB
Python
122 lines
5.0 KiB
Python
import os
|
||
import sys
|
||
from datetime import datetime, timedelta
|
||
|
||
import pytest
|
||
from fastapi.testclient import TestClient
|
||
|
||
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)
|
||
|
||
from app.db import altcoin_db
|
||
from app.web import web_server
|
||
|
||
|
||
@pytest.fixture
|
||
def temp_db(monkeypatch, tmp_path):
|
||
db_path = tmp_path / "altcoin_monitor.db"
|
||
monkeypatch.setattr(altcoin_db, "DB_PATH", str(db_path))
|
||
monkeypatch.setattr(web_server, "init_db", altcoin_db.init_db)
|
||
monkeypatch.setattr(web_server, "get_review_stats", altcoin_db.get_review_stats)
|
||
monkeypatch.setattr(web_server, "get_stats", altcoin_db.get_stats)
|
||
altcoin_db.init_db()
|
||
return db_path
|
||
|
||
|
||
def test_iteration_log_roundtrip_and_summary(temp_db):
|
||
altcoin_db.log_strategy_iteration(
|
||
run_date="2026-04-29",
|
||
trigger_source="daily_review",
|
||
title="缩小滞后指标权重",
|
||
summary="复盘发现 MACD/RSI 追涨假信号偏多,降低滞后指标基础权重。",
|
||
findings=[
|
||
"过去 5 次失败案例里,4 次同时出现滞后指标共振但没有前瞻量价确认",
|
||
"横盘样本集中在仅有 MACD/RSI 共振的票",
|
||
],
|
||
problems=[
|
||
"滞后指标在启动末端给出追涨确认,导致入场过晚",
|
||
],
|
||
actions=[
|
||
"category_base_weights.滞后: 0.5 → 0.3",
|
||
"kill_min_samples: 5 → 4",
|
||
],
|
||
changed_rules=[
|
||
{"field": "category_base_weights.滞后", "old": 0.5, "new": 0.3},
|
||
{"field": "kill_min_samples", "old": 5, "new": 4},
|
||
],
|
||
metrics={"reviews_done": 6, "fail_count": 4, "new_rules": 1},
|
||
related_symbols=["DOGE/USDT", "PEPE/USDT"],
|
||
pollution_summary={
|
||
"window_days": 7,
|
||
"effective_start": "2026-04-22T00:00:00",
|
||
"contaminated_symbol_count": 2,
|
||
"screening_hit_count": 3,
|
||
"recommendation_hit_count": 1,
|
||
"contaminated_symbols": ["EUR/USDT", "USD1/USDT"],
|
||
"layer_counts": {"coarse": 2, "fine": 1},
|
||
},
|
||
)
|
||
altcoin_db.log_strategy_iteration(
|
||
run_date="2026-04-29",
|
||
trigger_source="manual",
|
||
title="补充等待回踩过滤",
|
||
summary="将追高型候选延后到回踩确认。",
|
||
findings=["爆发前 1H 放量但偏离 5EMA 过远的票,回撤概率上升"],
|
||
problems=["原有即刻买入条件对急拉币容忍度过高"],
|
||
actions=["新增 wait_pullback 场景说明"],
|
||
changed_rules=[],
|
||
metrics={"affected_candidates": 3},
|
||
related_symbols=["FIL/USDT"],
|
||
)
|
||
|
||
logs = altcoin_db.get_strategy_iteration_logs(limit=10)
|
||
assert len(logs) == 2
|
||
assert logs[0]["title"] == "补充等待回踩过滤"
|
||
assert logs[1]["changed_rules"][0]["field"] == "category_base_weights.滞后"
|
||
assert logs[1]["metrics"]["reviews_done"] == 6
|
||
assert logs[1]["pollution_summary"]["contaminated_symbol_count"] == 2
|
||
assert logs[1]["pollution_summary"]["contaminated_symbols"] == ["EUR/USDT", "USD1/USDT"]
|
||
|
||
summary = altcoin_db.get_strategy_iteration_summary(days=30)
|
||
assert summary["total_logs"] == 2
|
||
assert summary["unique_run_days"] == 1
|
||
assert summary["trigger_counts"]["daily_review"] == 1
|
||
assert summary["trigger_counts"]["manual"] == 1
|
||
assert summary["change_rule_count"] == 2
|
||
assert summary["recent_titles"][0] == "补充等待回踩过滤"
|
||
|
||
|
||
def test_review_api_exposes_iteration_logs(temp_db):
|
||
altcoin_db.log_strategy_iteration(
|
||
run_date="2026-04-29",
|
||
trigger_source="daily_review",
|
||
title="新增失败案例日志化",
|
||
summary="把问题和动作拆开记录到网站。",
|
||
findings=["用户需要直接看到每天改了什么"],
|
||
problems=["之前只有复盘结果,没有策略修改过程记录"],
|
||
actions=["新增 strategy_iteration_log 表与 review 页面展示"],
|
||
changed_rules=[{"field": "ui.review.iteration_log", "old": False, "new": True}],
|
||
metrics={"items": 1},
|
||
related_symbols=["FIL/USDT"],
|
||
pollution_summary={
|
||
"window_days": 7,
|
||
"effective_start": "2026-04-22T00:00:00",
|
||
"contaminated_symbol_count": 1,
|
||
"screening_hit_count": 1,
|
||
"recommendation_hit_count": 0,
|
||
"contaminated_symbols": ["EUR/USDT"],
|
||
"layer_counts": {"coarse": 1},
|
||
},
|
||
)
|
||
|
||
client = TestClient(web_server.app)
|
||
resp = client.get("/api/review")
|
||
assert resp.status_code == 200
|
||
data = resp.json()
|
||
assert data["iteration_summary"]["total_logs"] == 1
|
||
assert data["iteration_logs"][0]["title"] == "新增失败案例日志化"
|
||
assert data["iteration_logs"][0]["changed_rules"][0]["field"] == "ui.review.iteration_log"
|
||
assert data["iteration_logs"][0]["pollution_summary"]["contaminated_symbol_count"] == 1
|
||
assert data["iteration_logs"][0]["pollution_summary"]["contaminated_symbols"] == ["EUR/USDT"]
|