Files
easy_tdx_max/tests/unit/test_realtime_session.py
T
GitHub 4bd5b5d833 release: v1.29.0 — 借鉴社区 Fork 六项特性:ZIG 策略 + 交易时段感知刷新 + 120M K 线 + 逐 bar 衍生字段 + 159 龙头池 + 多 Provider LLM 直连
- ZIG 右侧突破回补策略:MyTT 新增 ZIG 之字转向(未来函数,含前视偏差警示);
  波谷启动建仓挂硬止损(OCO)→ 见顶清仓记前高 → 右侧突破回补;路径依赖不实现
  entry_exit_masks(向量化守护测试白名单);含寻优预设网格与 --strategy-file 独立文件
- 交易时段感知刷新:realtime/session.py(09:15~11:30:30 / 13:00~15:05)+
  GET /market/session;看板 30/60/120s 轮询休市自动暂停(三态状态栏 + 开关持久化
  + 手动刷新不受限);SSE/WS 既有会话语义不动
- 120 分钟 K 线:/bars?category=MIN_120(MAC 原生 Period.MINS×120 优先,
  2×60M 相邻聚合兜底,标准客户端上限 400 根);前端周期选择器同步
- 逐 bar 衍生字段:/bars 与 /bars/index 附带 pre_close/change/change_pct/
  amplitude_pct(pre_close≤0.01 兜底防除零)
- 159 只核心龙头池:数据资产取自 Fork(东财全行业龙头名单,四组分层);
  universe=core 接入 screen scan / SignalScanner / StrengthRanker / market strength;
  GET /market/core-leaders + WebUI「龙头池」页(搜索/个股详情)
- 多 Provider LLM 直连:easy_tdx.ai + /llm/*(DeepSeek/通义/智谱/Kimi/MiniMax/
  OpenAI/Claude/Ollama/自定义,openai 兼容 + anthropic 原生双协议);
  配置落盘 ~/.easy_tdx/llm.json(WebUI「AI 设置」页 ⇆ 手工编辑双向兼容,
  文件>环境变量>预设;key 脱敏回显/CLEAR 清除);「AI 解读」后台任务化
  (复用 task_runner,提交+轮询,不占 HTTP 连接);思考型模型空白正文防御
  (reasoning_content 耗尽 max_tokens → 可操作报错;默认 16000);
  AI 解读历史页(自动归档 Prompt/正文/策略上下文 + 去回测带参引导)
- WebUI 加固:SPA fallback 对未知 /api/* 返回 JSON 404(不再 200 HTML 伪装解析错);
  index.html 一律 Cache-Control: no-store(防缓存旧资源引用);路由兜底重定向;
  全局风险提示常驻底栏 + 龙头池/AI 解读针对性免责声明
- 测试:新增 9 个单测文件共 59 例;黄金基线仅新增 zig_breakout 条目(其余零漂移);
  全量 1448 例通过
2026-09-02 20:19:17 +08:00

59 lines
2.1 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.
"""交易时段判断单元测试(realtime/session.pyv1.29)。
覆盖:窗口边界(09:15/11:30:30/13:00/15:05)、午休、周末、
盘前盘后、session_info 响应结构。
"""
from __future__ import annotations
from datetime import datetime
from easy_tdx.realtime.session import SESSION_WINDOWS, is_trading_time, session_info
def _dt(s: str) -> datetime:
# 2026-09-02 是周三(盘中日)
return datetime.strptime(f"2026-09-02 {s}", "%Y-%m-%d %H:%M:%S")
class TestIsTradingTime:
def test_weekday_morning_session(self):
assert is_trading_time(_dt("09:15:00")) # 集合竞价起
assert is_trading_time(_dt("10:30:00"))
assert is_trading_time(_dt("11:30:30")) # 窗口含端
def test_lunch_break_excluded(self):
assert not is_trading_time(_dt("11:31:00"))
assert not is_trading_time(_dt("12:30:00"))
assert not is_trading_time(_dt("12:59:59"))
def test_afternoon_session(self):
assert is_trading_time(_dt("13:00:00"))
assert is_trading_time(_dt("14:30:00"))
assert is_trading_time(_dt("15:05:00")) # 收盘竞价缓冲端点
assert not is_trading_time(_dt("15:05:01"))
def test_pre_and_post_market(self):
assert not is_trading_time(_dt("09:14:59"))
assert not is_trading_time(_dt("08:00:00"))
assert not is_trading_time(_dt("22:00:00"))
def test_weekend_rejected(self):
# 2026-09-05 周六 / 2026-09-06 周日,取盘中时间也应为 False
assert not is_trading_time(datetime(2026, 9, 5, 10, 0))
assert not is_trading_time(datetime(2026, 9, 6, 14, 0))
class TestSessionInfo:
def test_shape(self):
info = session_info(_dt("10:00:00"))
assert info["is_trading_time"] is True
assert info["weekday"] == 2 # 周三
assert len(info["sessions"]) == len(SESSION_WINDOWS)
assert info["session_desc"] == "09:15~11:30, 13:00~15:05"
assert "T" in info["server_time"] # isoformat
def test_closed(self):
info = session_info(datetime(2026, 9, 5, 10, 0)) # 周六
assert info["is_trading_time"] is False