Files
easy_tdx_max/pyproject.toml
T
Justin Gu 38731114b6 feat(backtest): 回测 REST API + 策略注册表 + 组合回测引擎
后端回测系统完整实现:

策略注册表(backtest/strategies/):
- Param schema 声明机制,支持动态表单渲染
- 5 个内置策略:MA交叉/MACD/布林/RSI/KDJ
- 参数校验(含 NaN/Inf 拦截、范围检查、类型强制转换)

REST API(web/routers/backtest.py):
- GET  /backtest/strategies  策略枚举 + 参数 schema
- POST /backtest/run         同步回测(内联 OHLCV)
- POST /backtest/run/async   后台任务回测(含 symbol 取行情)
- POST /backtest/portfolio/run/async  组合回测(多标的)
- GET  /backtest/tasks/{id}  任务轮询

后台任务执行器(web/task_runner.py):
- ThreadPoolExecutor + 进程内 LRU 任务表
- status-aware 淘汰(不淘汰 running 任务)
- 线程安全单例 + lifespan shutdown 接入

组合回测引擎改造(portfolio_engine.py):
- 接受策略实例,参数透传到每个标的
- 新增组合净值曲线(按日期并集 forward-fill 对齐求和)

审计修复(/check 三轮):
- Param.validate 拦截 NaN/Inf/giant-int(防 DoS)
- ohlcv max_length=2000(防内存耗尽)
- LRU 淘汰跳过 running 任务(修复结果丢失竞态)
- get_runner double-checked locking(修复单例竞态)
- shutdown 接入 lifespan(修复资源泄漏)

测试:808 passed(含 39 回测路由 + 8 组合引擎 + 安全回归)
2026-07-03 03:34:34 +08:00

68 lines
1.9 KiB
TOML

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "easy-tdx"
version = "1.16.3"
description = "通达信 TCP 协议行情数据客户端,支持在线行情、离线数据读取与写入同步"
readme = "README.md"
requires-python = ">=3.10"
dependencies = ["pandas>=2.0,<3", "tzdata>=2024.1", "click>=8.0,<9"]
[project.scripts]
easy-tdx = "easy_tdx.cli:cli" # cli/__init__.py exposes the click group
[project.optional-dependencies]
dev = ["pytest>=8.0", "pytest-asyncio>=0.23", "pytest-cov", "mypy>=1.9", "ruff>=0.4", "scipy>=1.10,<1.16", "httpx>=0.27"]
science = ["scipy>=1.10,<1.16"]
web = ["fastapi>=0.110,<1", "uvicorn[standard]>=0.29"]
[tool.hatch.build.targets.wheel]
packages = ["src/easy_tdx"]
[tool.mypy]
strict = true
python_version = "3.12"
# 跳过未跟踪的本地脚本(依赖外部 unified_config/sqlalchemy/requests,不属于库)
exclude = ["src/easy_tdx/exchange_margin\\.py"]
[[tool.mypy.overrides]]
module = ["pandas", "tabulate", "matplotlib", "matplotlib.*"]
ignore_missing_imports = true
[[tool.mypy.overrides]]
module = "easy_tdx.MyTT"
# Type stubs provided via MyTT.pyi — keep strict checks enabled
[[tool.mypy.overrides]]
module = ["fastapi.*", "uvicorn.*", "pydantic.*"]
ignore_missing_imports = true
[[tool.mypy.overrides]]
module = ["scipy", "scipy.*"]
ignore_missing_imports = true
[tool.ruff]
target-version = "py310"
line-length = 100
extend-exclude = ["*.pyi", "src/easy_tdx/exchange_margin.py"]
[tool.ruff.lint]
select = ["E", "F", "I", "UP"]
[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "--tb=short"
asyncio_mode = "auto"
[tool.coverage.run]
source = ["easy_tdx"]
omit = ["tests/*"]
[tool.coverage.report]
# 覆盖率门槛。从 50 提升到 60(审计 #9):补充 reconnect/bitmap/config 测试后
# 实测约 61%。进一步提到 70 需补 web/ 路由与更多 client 镜像测试,留待后续。
fail_under = 60
show_missing = true