diff --git a/README.md b/README.md index 75b656b..37595c6 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ easy-tdx 要做的事很简单:**把机构的数据锁砸开,扔到每个普 **32个技术指标**(MACD、KDJ、RSI、BOLL……连”捉妖大师”和”30日乖离率信号”都给你算好)开箱即用。 **缠论分析**(笔、中枢、买卖点、背驰)一键出结果——你不再需要手画分型、猜线段。 -**内置回测引擎**——写个策略文件,一行命令跑回测,9 个经典策略自带,批量对比哪个最赚钱一目了然。 +**内置回测引擎**——写个策略文件,一行命令跑回测,15 个经典策略自带,批量对比哪个最赚钱一目了然。 装上就能跑。**Python API + CLI 双通道**,输出 JSON 天然喂给 AI Agent:Claude Code、OpenClaw、Hermes 直接吃。 @@ -376,7 +376,7 @@ python -X utf8 run_all_strategies.py SH 600519 --count 2000 --cash 1000000 --adj #### 自带策略示例 -`strategies/` 目录下有 9 个开箱即用的策略文件,可直接用于 `--strategy-file`: +`strategies/` 目录下有 15 个开箱即用的策略文件,可直接用于 `--strategy-file`: | 文件 | 策略 | 类型 | 适合行情 | |------|------|------|----------| @@ -389,6 +389,12 @@ python -X utf8 run_all_strategies.py SH 600519 --count 2000 --cash 1000000 --adj | `turtle_breakout.py` | 海龟交易法(唐安奇通道) | 趋势突破 | 牛市启动 | | `bias_reversal.py` | 乖离率反转 | 反转 | 震荡回归 | | `volume_price.py` | 量价配合 | 综合判断 | 放量突破 | +| `zhuoyao_momentum.py` | 捉妖大师多周期共振 | 趋势跟踪 | 多周期共振强势股 | +| `dmi_trend.py` | DMI/ADX 趋势强度跟踪 | 趋势跟踪 | 单边趋势(过滤震荡) | +| `cci_breakout.py` | CCI ±100 区间突破 | 区间突破 | 震荡转趋势 | +| `mfi_volume.py` | MFI 量价反转 | 量价反转 | 震荡市(带量能确认) | +| `trix_cross.py` | TRIX 三重平滑趋势交叉 | 趋势跟踪 | 中长线(抗噪音) | +| `mtm_momentum.py` | MTM 动量零线穿越 | 动量 | 趋势拐点 | 编写自定义策略只需继承 `Strategy` 基类: @@ -1110,6 +1116,19 @@ ruff format --check src/ tests/ # format check ## Changelog +### 1.8.2 (2026-06-09) + +**策略扩充 + 可视化** — 新增 6 个策略(共 15 个)、`--show` 资金曲线图、茅台 demo 截图。 + +- 新增 `run_all_strategies.py --show` 参数:自动弹出最佳策略资金曲线 vs 股价归一化对比图(matplotlib 双轴图 + 买卖点标记) +- 新增 `zhuoyao_momentum` 策略:ZHUOYAO 多周期共振(SHORT/TREND/MID 三重过滤) +- 新增 `dmi_trend` 策略:DMI/ADX 趋势强度跟踪 +- 新增 `cci_breakout` 策略:CCI ±100 区间突破 +- 新增 `mfi_volume` 策略:MFI 量价反转(带成交量权重的 RSI) +- 新增 `trix_cross` 策略:TRIX 三重平滑趋势交叉 +- 新增 `mtm_momentum` 策略:MTM 动量零线穿越 +- 新增 SH600519 贵州茅台 demo 截图 + ### 1.8.1 (2026-06-09) **回测增强** — 批量策略对比脚本新增最佳策略完整交易明细输出;版本号统一为单一来源(`pyproject.toml`)。 diff --git a/pyproject.toml b/pyproject.toml index 3536417..0e73ce3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "easy-tdx" -version = "1.8.1" +version = "1.8.2" description = "通达信 TCP 协议行情数据客户端,支持在线行情、离线数据读取与写入同步" readme = "README.md" requires-python = ">=3.10" diff --git a/strategies/cci_breakout.py b/strategies/cci_breakout.py new file mode 100644 index 0000000..c5a61fb --- /dev/null +++ b/strategies/cci_breakout.py @@ -0,0 +1,37 @@ +"""CCI 区间突破策略。 + +CCI 上穿 +100 时买入(进入强势区间);下穿 -100 时卖出(进入弱势区间)。 +CCI 衡量价格偏离统计平均的程度:|CCI| > 100 代表偏离显著。 + +和 RSI 超买超卖不同,CCI 突破是顺势策略——突破 +100 追多,不是超买反转。 +适合从震荡转入趋势的启动阶段。 + +用法:: + + easy-tdx backtest SZ 000001 --strategy-file strategies/cci_breakout.py --count 2000 --table +""" + +from easy_tdx import MyTT +from easy_tdx.backtest import Strategy + + +class CCIBreakoutStrategy(Strategy): + """CCI 区间突破策略。""" + + def init(self) -> None: + self.cci = self.I( + MyTT.CCI, self.data.close, self.data.high, self.data.low, + ) + + def next(self) -> None: + val = float(self.cci[self._bar_index]) + + # 入场:CCI 进入强势区间 + if val > 100: + if self.position["size"] == 0: + self.buy(size=0) + + # 出场:CCI 跌入弱势区间 + elif val < -100: + if self.position["size"] > 0: + self.sell(size=0) diff --git a/strategies/dmi_trend.py b/strategies/dmi_trend.py new file mode 100644 index 0000000..390c9f0 --- /dev/null +++ b/strategies/dmi_trend.py @@ -0,0 +1,40 @@ +"""DMI 趋势跟踪策略。 + +PDI > MDI(多头方向力强)且 ADX > 25(趋势强度足够)时买入。 +PDI < MDI 或 ADX < 20 时卖出——方向反转或趋势消失即离场。 + +DMI 是唯一直接衡量趋势强度的指标:ADX 区分"有趋势可跟"和"震荡别碰"。 +适合单边趋势行情,震荡市自动过滤。 + +用法:: + + easy-tdx backtest SZ 000001 --strategy-file strategies/dmi_trend.py --count 2000 --table +""" + +from easy_tdx import MyTT +from easy_tdx.backtest import Strategy + + +class DMITrendStrategy(Strategy): + """DMI 趋势跟踪策略。""" + + def init(self) -> None: + # DMI 返回 4 个数组: PDI, MDI, ADX, ADXR + self.pdi, self.mdi, self.adx, _ = self.I( + MyTT.DMI, self.data.close, self.data.high, self.data.low, + ) + + def next(self) -> None: + pdi = float(self.pdi[self._bar_index]) + mdi = float(self.mdi[self._bar_index]) + adx = float(self.adx[self._bar_index]) + + # 入场:多头方向力强 + 趋势强度足够 + if pdi > mdi and adx > 25: + if self.position["size"] == 0: + self.buy(size=0) + + # 出场:方向反转 或 趋势消失 + elif pdi < mdi or adx < 20: + if self.position["size"] > 0: + self.sell(size=0) diff --git a/strategies/mfi_volume.py b/strategies/mfi_volume.py new file mode 100644 index 0000000..d379979 --- /dev/null +++ b/strategies/mfi_volume.py @@ -0,0 +1,37 @@ +"""MFI 量价反转策略。 + +MFI < 20(资金流量超卖)买入;MFI > 80(资金流量超买)卖出。 +MFI 是成交量的 RSI——把量价关系压缩成一个振荡器,比纯价格 RSI 多了量能维度。 + +超卖区代表资金大举流出后恐慌见底,超买区代表资金涌入后过热。 +适合震荡市中的波段操作。 + +用法:: + + easy-tdx backtest SZ 000001 --strategy-file strategies/mfi_volume.py --count 2000 --table +""" + +from easy_tdx import MyTT +from easy_tdx.backtest import Strategy + + +class MFIVolumeStrategy(Strategy): + """MFI 量价反转策略。""" + + def init(self) -> None: + self.mfi = self.I( + MyTT.MFI, self.data.close, self.data.high, self.data.low, self.data.vol, + ) + + def next(self) -> None: + val = float(self.mfi[self._bar_index]) + + # 超卖买入 + if val < 20: + if self.position["size"] == 0: + self.buy(size=0) + + # 超买卖出 + elif val > 80: + if self.position["size"] > 0: + self.sell(size=0) diff --git a/strategies/mtm_momentum.py b/strategies/mtm_momentum.py new file mode 100644 index 0000000..3c18548 --- /dev/null +++ b/strategies/mtm_momentum.py @@ -0,0 +1,33 @@ +"""MTM 动量策略。 + +MTM 上穿 0 买入(动量由负转正,下跌动能耗尽);MTM 下穿 0 卖出(动量由正转负)。 +MTM = 当前价 - N 日前价格,最纯粹的动量指标。 + +信号极其灵敏,适合捕捉趋势拐点。代价是震荡市假信号多—— +可以配合其他趋势过滤器使用,这里先展示最简版本。 + +用法:: + + easy-tdx backtest SZ 000001 --strategy-file strategies/mtm_momentum.py --count 2000 --table +""" + +from easy_tdx import MyTT +from easy_tdx.backtest import Strategy, crossover + + +class MTMMomentumStrategy(Strategy): + """MTM 动量策略。""" + + def init(self) -> None: + # MTM 返回 2 个数组: MTM, MTMMA + self.mtm, self.mtm_ma = self.I(MyTT.MTM, self.data.close) + # 用 MTM 上穿 0 线作为买入信号,下穿 0 线作为卖出信号 + zeros = [0.0] * len(self.data.close) + self.buy_signal = crossover(self.mtm, zeros) + self.sell_signal = crossover(zeros, self.mtm) + + def next(self) -> None: + if self.buy_signal[self._bar_index] and self.position["size"] == 0: + self.buy(size=0) + elif self.sell_signal[self._bar_index] and self.position["size"] > 0: + self.sell(size=0) diff --git a/strategies/trix_cross.py b/strategies/trix_cross.py new file mode 100644 index 0000000..b0d7bf2 --- /dev/null +++ b/strategies/trix_cross.py @@ -0,0 +1,31 @@ +"""TRIX 三重平滑趋势策略。 + +TRIX 上穿信号线(TRIX_MA)买入;下穿卖出。 +TRIX 对收盘价做三次 EMA 平滑再算变化率,比 MACD 多一层过滤, +能有效屏蔽短期噪音,减少震荡市的假信号。 + +适合中长线趋势跟踪,信号比 MACD 更少但更干净。 + +用法:: + + easy-tdx backtest SZ 000001 --strategy-file strategies/trix_cross.py --count 2000 --table +""" + +from easy_tdx import MyTT +from easy_tdx.backtest import Strategy, crossover + + +class TRIXCrossStrategy(Strategy): + """TRIX 三重平滑趋势策略。""" + + def init(self) -> None: + # TRIX 返回 2 个数组: TRIX, TRMA(信号线) + self.trix, self.trma = self.I(MyTT.TRIX, self.data.close) + self.golden = crossover(self.trix, self.trma) + self.death = crossover(self.trma, self.trix) + + def next(self) -> None: + if self.golden[self._bar_index] and self.position["size"] == 0: + self.buy(size=0) + elif self.death[self._bar_index] and self.position["size"] > 0: + self.sell(size=0)