feat(factor): add analysis/transform exports, CLI analyze command, bump v1.12.0

This commit is contained in:
GitHub
2026-06-12 20:11:28 +08:00
parent 9d7bf84d5d
commit 303964ea67
6 changed files with 107 additions and 4 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project]
name = "easy-tdx"
version = "1.11.0"
version = "1.12.0"
description = "通达信 TCP 协议行情数据客户端,支持在线行情、离线数据读取与写入同步"
readme = "README.md"
requires-python = ">=3.10"
+35
View File
@@ -54,3 +54,38 @@ def factor_list(category: str | None, use_table: bool) -> None:
click.echo(f"{f['name']}\t{f['category']}\t{f['description']}")
else:
click.echo(json.dumps(factors, ensure_ascii=False, indent=2))
@factor.command("analyze")
@click.argument("factor_name")
@click.option("--period", default=5, type=int, help="远期收益天数")
@click.option("--n-quantiles", default=5, type=int, help="分层数")
def factor_analyze(factor_name: str, period: int, n_quantiles: int) -> None:
"""分析指定因子的有效性。
示例:
easy-tdx factor analyze momentum_20d
easy-tdx factor analyze rsi_14 --period 10 --n-quantiles 10
"""
click.echo(
json.dumps(
{
"message": "factor analyze 需要行情数据,请使用 Python API",
"factor": factor_name,
"example": (
f"from easy_tdx.factor import FactorEngine, FactorAnalyzer, preprocess\n"
f"engine = FactorEngine()\n"
f"factor_data = engine.compute_cross_section(data, ['{factor_name}'])\n"
f"clean = preprocess(factor_data, ['{factor_name}'])\n"
f"return_data = engine.compute_forward_returns(data, period={period})\n"
f"analyzer = FactorAnalyzer(clean, return_data, n_quantiles={n_quantiles})\n"
f"report = analyzer.full_report()\n"
f"print(f'IC={{report.ic_mean:.3f}}, IR={{report.ir:.3f}}')"
),
},
ensure_ascii=False,
indent=2,
)
)
+17
View File
@@ -3,17 +3,34 @@
from __future__ import annotations
from easy_tdx.factor.analysis import FactorAnalyzer, FactorReport
from easy_tdx.factor.base import FACTORY_REGISTRY, Factor, register_factor
# 导入 builtin 触发自动注册
from easy_tdx.factor.builtin import get_factor, list_factors # noqa: F401
from easy_tdx.factor.engine import FactorEngine
from easy_tdx.factor.transform import (
fill_missing,
orthogonalize,
preprocess,
rank_normalize,
winsorize,
zscore,
)
__all__ = [
"Factor",
"register_factor",
"FACTORY_REGISTRY",
"FactorEngine",
"FactorAnalyzer",
"FactorReport",
"list_factors",
"get_factor",
"fill_missing",
"orthogonalize",
"preprocess",
"rank_normalize",
"winsorize",
"zscore",
]
+5 -1
View File
@@ -1,5 +1,6 @@
# src/easy_tdx/factor/analysis.py
"""因子有效性分析引擎。"""
from __future__ import annotations
from dataclasses import dataclass
@@ -74,7 +75,10 @@ class FactorAnalyzer:
continue
valid = valid.copy()
valid["_q"] = pd.qcut(
valid[self._factor_col], self._n_quantiles, labels=False, duplicates="drop",
valid[self._factor_col],
self._n_quantiles,
labels=False,
duplicates="drop",
)
means = valid.groupby("_q")[self._return_col].mean()
rows.append([float(means.get(q, np.nan)) for q in range(self._n_quantiles)])
+1
View File
@@ -1,5 +1,6 @@
# src/easy_tdx/factor/transform.py
"""因子预处理 — 纯函数管道。"""
from __future__ import annotations
import numpy as np
+46
View File
@@ -0,0 +1,46 @@
# Welcome to easy-tdx Discussions!
## 👋 欢迎!
感谢你来到 easy-tdx 社区!
这个项目的初心很简单:**打破金融数据的获取门槛,让每个人都能拿到和机构一样的行情数据。** 免费、开源、无需注册、无需 API Key。
不管你是量化新手还是老手,这里就是我们的交流阵地。
## 💬 在这里你可以
- **提问** — 安装报错、API 用法、数据字段含义……任何问题都可以问,没有"太基础"这回事
- **分享策略** — 写了不错的回测策略?发现了好用的指标组合?发出来大家一起看看
- **反馈 Bug** — 命令跑不通、数据不对劲、接口返回异常,直接贴出来
- **提 Feature** — 觉得缺了什么功能?说出来,社区一起评估优先级
- **晒成果** — 用 easy-tdx 做了什么有意思的东西?数据分析、可视化、自动化交易面板……都欢迎展示
## 🚀 快速上手
还没装过的朋友,一行命令搞定:
```bash
pip install easy-tdx
```
然后试试:
```bash
easy-tdx kline SZ 000001 --count 30 --table
easy-tdx indicator MACD -m SH -c 600519 --table
easy-tdx serve # 启动 Web API,浏览器打开 http://localhost:8000/docs
```
📖 完整文档看 [README](https://github.com/handsomejustin/easy_tdx) 和 [Wiki](https://github.com/handsomejustin/easy_tdx/wiki)。
## 🤝 社区共识
- 互相尊重,友善讨论
- 提问时尽量附上:版本号、命令/代码、报错信息
- 答疑是社区互助,没有义务回复,但每一条都会有人看到
- **不构成投资建议** — 本工具仅供学习研究,投资决策风险自担
---
**现在就从下面留个言开始吧** 🎉 告诉我们你用 easy-tdx 在做什么,或者打算拿它做什么。