alphax/tests/test_event_driven_screener.py
2026-05-13 22:49:47 +08:00

125 lines
4.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import json
import os
import sys
from datetime import datetime, timedelta
from unittest.mock import patch
import pandas as pd
sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
from app.services import event_driven_screener as ed
def test_symbol_extraction_filters_usdt_suffix_and_pollution():
title = "Binance Futures Will Launch ABCUSDT, XYZUSDT and USD1USDT USDⓈ-Margined Perpetual Contracts"
symbols = ed._symbol_from_title(title)
assert "ABC/USDT" in symbols
assert "XYZ/USDT" in symbols
assert "ABCUSDT/USDT" not in symbols
assert "USD1/USDT" not in symbols
def test_recent_time_window_rejects_old_news():
assert ed._is_recent(datetime.now() - timedelta(hours=2), 3) is True
assert ed._is_recent(datetime.now() - timedelta(hours=8), 3) is False
assert ed._is_recent(None, 3) is False
def test_classify_major_listing_as_s_level_and_negative_as_risk():
level, event_type = ed.classify_event("Binance Futures Will Launch ABCUSDT USDⓈ-Margined Perpetual Contracts")
assert level == "S"
assert event_type == "major_listing_or_contract"
level, event_type = ed.classify_event("Binance Will Delist ABC on 2026-05-07")
assert level == "RISK"
assert event_type == "risk_negative"
def test_store_events_deduplicates_by_hash(tmp_path):
# 使用真实DB表但同一事件重复插入只保留一次
event = {
"source": "binance_listing",
"symbol": "ABC/USDT",
"title": "Binance Futures Will Launch ABCUSDT USDⓈ-Margined Perpetual Contracts",
"url": "https://example.com",
"published_at": datetime.now(),
"importance": "S",
"event_type": "major_listing_or_contract",
"raw": {"id": 1},
}
first = ed.store_events([event])
second = ed.store_events([event])
assert len(first) in (0, 1) # 若本地DB已有同事件允许0
assert second == []
def test_quick_technical_check_rejects_old_overheated_gain():
event = {
"source": "binance_listing",
"symbol": "ABC/USDT",
"title": "Binance Futures Will Launch ABCUSDT USDⓈ-Margined Perpetual Contracts",
"importance": "S",
}
with patch.object(ed, "_ticker_info", return_value={"price": 1.0, "change_24h": 35.0, "volume_24h": 10000000}):
result = ed.quick_technical_check(event)
assert result["decision"] == "risk"
assert "不追高" in result["reason"]
def test_theme_expansion_spreads_ton_news_to_ecosystem_symbols():
event = {
"source": "coingecko_trending",
"symbol": "TON/USDT",
"title": "Telegram becomes the main driver of the TON ecosystem and cuts TON fees",
"url": "https://example.com/ton",
"published_at": datetime.now(),
"importance": "B",
"event_type": "market_heat",
"raw": {},
}
expanded = ed.expand_theme_events([event])
by_symbol = {e["symbol"]: e for e in expanded}
assert "TON/USDT" in by_symbol
assert "NOT/USDT" in by_symbol
assert "DOGS/USDT" in by_symbol
assert by_symbol["DOGS/USDT"]["importance"] == "A"
assert by_symbol["DOGS/USDT"]["event_type"] == "theme_expansion"
assert "主题扩散:ton_ecosystem" in by_symbol["DOGS/USDT"]["title"]
def _fake_ohlcv(rows=60):
return pd.DataFrame({
"timestamp": pd.date_range("2026-05-01", periods=rows, freq="h"),
"open": [1.0] * rows,
"high": [1.02] * rows,
"low": [0.98] * rows,
"close": [1.0] * rows,
"volume": [1000.0] * rows,
})
def test_theme_static_accumulation_bonus_can_upgrade_to_recommend():
event = {
"source": "coingecko_trending",
"symbol": "DOGS/USDT",
"title": "[主题扩散:ton_ecosystem] Telegram becomes the main driver of the TON ecosystem",
"importance": "A",
"event_type": "theme_expansion",
}
with patch.object(ed, "_ticker_info", return_value={"price": 0.001, "change_24h": 5.0, "volume_24h": 10000000}), \
patch.object(ed, "fetch_klines", return_value=_fake_ohlcv()), \
patch.object(ed, "detect_volume_price_fly", return_value=None), \
patch.object(ed, "detect_static_accumulation", return_value={"static_count": 23, "vol_ratio": 1.4}), \
patch.object(ed, "full_pa_analysis", return_value={"ignition_points": []}), \
patch.object(ed, "fetch_derivatives_context", return_value={"funding_rate": 0, "top_trader_long_pct": 56}), \
patch.object(ed, "calc_atr", return_value=0.00005):
result = ed.quick_technical_check(event)
assert result["score"] >= 6
assert result["decision"] == "recommend"
assert any("生态主题+强静K蓄力升权" in s for s in result["signals"])