BotDeepSeek/README.md
2026-08-12 01:46:19 -07:00

162 lines
8.9 KiB
Markdown
Raw Permalink 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.

# Interactive Brokers 自动交易系统
基于 Python + ib_insync 的 IB 自动化交易框架,支持多策略并行、持仓归属追踪、
自动止损、断线自动重连。
## 项目结构
```
BotDeepSeek/
├── config.py # 配置管理dataclass + .env 环境变量)
├── connection.py # TWS/IB Gateway 连接管理(含自动重连)
├── bars.py # 共享K线订阅管理keepUpToDate 增量推送)
├── orders.py # 下单执行(成交确认、超时撤单、防重复单)
├── state.py # 持仓归属追踪JSON 持久化 + 启动对账)
├── main.py # 主程序入口
├── strategies/
│ ├── __init__.py
│ ├── base.py # 策略基类
│ ├── ma_cross.py # SMA 20/50 金叉 + ADX 趋势过滤
│ ├── short_term.py # EMA 5/10 金叉 + VWAP 确认 + 最长持仓限制
│ ├── mean_reversion.py # RSI超卖/布林带下轨/急跌 抄底
│ └── forex.py # 外汇均线交叉(默认关闭)
├── bot_state.json # 运行时生成:持仓归属状态(勿手动编辑,除非迁移持仓)
├── requirements.txt
└── .env.example
```
## 策略说明
| 策略 | 入场 | 出场(每轮重检) |
|------|------|------------------|
| MAStockStrategy | 金叉 + 连续2根确认 且 ADX>25 | **交易所STP止损 -2%**;快线跌破慢线且盈利 ≥1.5% |
| ShortTermMAVWAP | EMA金叉 + 连续2根确认 且 价格>VWAP | **交易所STP止损 -2%**持仓≥5天死叉且盈利 ≥1.5% |
| MeanReversion | RSI<30 / 触及布林下轨均需连续2根/ 5根急跌1% | **交易所STP止损 -2%**RSI>70 / 回到布林中轨 / 反弹1.5%需盈利≥1.5% |
| ForexMAStrategy | 快线金叉慢线 | **软止损 -1%**;死叉 |
**交易规模**:每笔按 `trade_value_usd`(默认 $2000按信号价折算股数
(如 $600 的股买 3 股,$95 的股买 21 股),每策略每标的最多一笔。
**入场确认**:交叉类信号要求交叉后下一根 K 线仍同向,超卖类信号要求
连续 2 根 K 线满足条件,过滤单根毛刺、降低交易频率。
所有策略共用 2 只标的AMZN、AAPL但**各自独立管理自己的持仓**(见下文"持仓归属")。
## 风控机制
1. **交易所硬止损(主)+ 软止损(兜底)**:每笔买入成交后,立即在交易所挂
**GTC 止损卖单STP**`stop_loss_pct`,股票默认 -2%`outsideRth=True` 盘后/隔夜
同样有效——即使 bot 停止、断网、电脑关机止损仍由交易所执行。bot 每 60 秒同步
止损单状态:成交→更新持仓归属;被撤/丢失→自动补挂;重启→自动认领。策略正常卖出前
会先撤掉对应止损单。若止损单因故不存在(如挂单被拒),原"软止损"(每 60 秒检查
收盘价)自动兜底。
⚠️ STP 触发后变成市价单,快速行情中成交价可能略低于止损价(滑点)。
2. **持仓归属**`bot_state.json` 记录每笔持仓属于哪个策略。策略只卖自己的持仓,
不会互相平仓。启动/重连时自动与账户真实持仓对账:
- 状态中有、账户没有 → 清除(说明已被手动平仓或断线期间成交)
- 账户中有、状态没有 → 标记为 **UNMANAGED**bot 永不会卖,需手动处理或迁移)
3. **最低盈利限制解除阻塞**:死叉卖出被盈利条件阻止后,每轮都会重检,
盈利达标即卖;同时止损兜底,不会无限套牢。
3b. **全局持仓上限**`max_positions`(默认 12 批)限制所有策略的并发持仓总数,
控制最大敞口约 $24k12 × $2000。达上限后新买入被跳过日志记录 SKIPPED
已有持仓正常管理退出,不会被强制平仓。
3c. **每日亏损熔断**:当日已实现亏损达到 `max_daily_loss`(默认 $150
当天禁止开新仓(次日自动重置,已有持仓正常退出)。
3d. **止损冷却期**:同一策略同一标的被止损后 30 分钟内禁止重买,
避免下跌通道中"买入→止损→再买"的连续失血;下单被拒/超时同样进入冷却。
3e. **MeanRev 趋势过滤**:仅在收盘价高于 SMA50 时允许抄底,不接下跌中的飞刀。
4. **完整K线信号**信号只用已收盘的K线计算避免未收完K线导致的信号闪烁。
5. **休市禁交易**通过最新K线时间判断市场是否开盘收盘/周末/节假日自动暂停信号。
6. **订单确认**下单后等待成交默认30秒超时自动撤单同一策略同一标的
有未成交单时不会重复下单。每笔订单带 `orderRef`(如 `MAStockStrategy:META`)方便在 TWS 中识别来源。
7. **增量K线订阅**:每个标的只订阅一次 `keepUpToDate` 实时K线流三个策略共享
替代原来每分钟全量拉取(原来 5 小时约 845MB 流量)。
## 配置
复制 `.env.example``.env` 后编辑(程序自动加载 `.env`
| 变量 | 默认值 | 说明 |
|------|--------|------|
| `IB_HOST` | `127.0.0.1` | IB Gateway 地址 |
| `IB_PORT` | `4001` | **4001=Gateway实盘**, 4002=Gateway模拟, 7496=TWS实盘, 7497=TWS模拟 |
| `IB_CLIENT_ID` | `1` | 客户端唯一 ID |
| `IB_ACCOUNT` | `U4845070` | 指定下单账户 |
| `IB_PAPER` | `false` | 仅用于启动日志警示;真实模式由端口/Gateway登录类型决定 |
策略参数在 `config.py` 中调整:`symbols`、`fast_ma_period`、`slow_ma_period`、
`trade_quantity`、`stop_loss_pct`、`min_profit_pct` 等。
## 运行
```bash
# 1. 启动 IB Gateway脚本会自动准备 JDK注意 /tmp 重启后会被清空)
./start_gateway.sh
# 在 Gateway 中登录,并确认 API 设置Enable ActiveX and Socket Clients、
# 端口、Trusted IPs 加入 127.0.0.1
# 2. 启动 bot前台调试
.venv/bin/python main.py
# 或后台重启(会自动先杀掉旧进程)
./restart_bot.sh
tail -f trading_bot.log
# 3. 查看当天成交明细与盈亏(可指定日期)
./report.sh [YYYY-MM-DD]
# 4. 复盘:往返交易统计(胜率/期望值/盈亏比/保本胜率,按策略/标的/信号归因)
.venv/bin/python analytics.py
.venv/bin/python analytics.py --since 2026-08-01
# 5. 可视化看板(单文件 HTML含权益曲线、收益分布、完整历史表可交互筛选
./dashboard.sh
# 6. 离线测试(不连 IB、不下单改动策略后必跑
.venv/bin/python -m unittest test_offline -v
```
### 复盘工具说明
| 工具 | 用途 |
|------|------|
| `daily_report.py` / `report.sh` | **单日**成交明细与盈亏(原有工具,中文文本输出) |
| `analytics.py` | **全历史**往返交易分析FIFO 配对 → 胜率、期望值、盈亏比、profit factor、最大回撤、以及按策略/标的/入场信号/出场原因/时段的归因。`--json` 输出可供程序消费 |
| `dashboard.py` / `dashboard.sh` | 把上述分析渲染成自包含 HTML 看板(权益曲线+回撤带、每日盈亏、四张归因图、收益分布直方图、持仓时长散点、完整交易历史表)。支持策略/标的/时间范围交互筛选,深浅色自适应,无 CDN 依赖 |
`analytics.py` 输出中最关键的一列是 **保本胜率breakeven win rate**:按该策略自己实现的平均盈利/平均亏损计算,需要多高的胜率才能不亏。实际胜率低于它,说明这套参数的风险收益结构本身是负期望的,调信号过滤器不会解决问题。
启动时如为实盘模式,日志会有醒目的 `LIVE TRADING MODE` 警示。
## ⚠️ 从旧版本迁移(重要)
旧版本没有持仓归属记录。如果升级时账户里还有旧 bot 开的仓位,新 bot
会把它们标记为 **UNMANAGED 并永远不管**(不会止损、不会止盈)。两个选择:
1. **手动平掉旧仓位**后再启动新 bot推荐最干净
2. 或手动编辑 `bot_state.json` 把旧仓位归属到某个策略,例如:
```json
{
"MAStockStrategy": {
"NVDA": {"quantity": 1, "entry_price": 207.33, "entry_date": "2026-07-20"}
}
}
```
注意:归属后该仓位立即受止损/止盈规则约束,若浮亏已超过 `stop_loss_pct`
启动后第一轮检查就会被止损卖出。
### 一次性迁移任务2026-07-22 已排期)
`close_legacy_positions.py` + cron 实现无人值守迁移开盘后09:45 ET
自动卖出 5 笔旧仓位NVDA/META/AVGO/MSFT/PLTR 各 1 股),**成功后才自动
启动新 bot**;失败则不启动(避免遗留 UNMANAGED 仓位),日志见
`close_legacy_positions.log`。该 cron 任务执行后自动删除。
## 安全警告
- 当前配置为**实盘模式**4001 端口),下单即真实成交
- 策略有止损但软止损依赖程序持续运行请保证机器、网络、Gateway 稳定
- 建议定期查看 `trading_bot.log``bot_state.json`
- 三个策略对同一标的最多各持 1 份(共 3 份),请确认账户风险敞口可接受