diff --git a/CHANGELOG.md b/CHANGELOG.md index f728a92..9ac7657 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -273,3 +273,46 @@ mo_data.read_watchlist() → 返回 watchlist.json 等价 dict - [ ] 验证 `[PROFIT_PROTECT]` 标记取代 `[NEAR_SL]` 误报 - [ ] cash_log 目前只是建表,需要在截图导入/手动改现金时调用 `write_cash_log` 记录变更 - [ ] 如果启用 AlphaSift:`ALPHASIFT_ENABLED=true python3 mo_alphasift_bridge.py` + +--- + +## 2026-07-02 — 筹码因子模块上线(知微) + +> 基于中信建投《筹码分布因子系统构建》研报 + +### 新增文件 + +| 文件 | 用途 | +|------|------| +| `scripts/chip_factors.py` | 筹码因子计算引擎 — 分钟K线+筹码分布+情景权重 | +| `data/chip_cache/*.json` | 33只持仓/自选股的每日筹码状态缓存 | + +### 修改文件 + +| 文件 | 变更 | +|------|------| +| `mo_provider.py` | 新增 `get_minute_kline()` — 东方财富push2分钟K线(1s限流,单次≤240条) | +| `strategy_lifecycle.py` | 新增 `calc_chip_sr()` — 筹码支撑/阻力计算 + `reassess_strategy` 集成共振检测 | + +### 筹码因子模块详情 + +**`scripts/chip_factors.py`** (262行): +- `_build_chip_distribution()` — 从60日日线OHLCV估算筹码分布,每日衰减0.97 +- `calc_all()` — 计算三大因子:筹码穿透率(PTR)、当日穿透率(ptr_today)、筹码乖离率(bias) +- `batch_calc()` — 批量计算全部持仓+自选(1.5s限流) +- `chip_cache/` — 缓存每日筹码状态,支持因子滚动计算 + +**`strategy_lifecycle.py` 集成**: +- `calc_chip_sr()` — 从筹码分布找出强支撑/阻力(2%区间聚合) +- `detect_scenario()` 情景判定 → 动态权重:震荡市0.9 > 轮动市0.6 > 上涨0.4 > 急跌0.2 +- 共振检测 ⚡:筹码支撑 vs 枢轴弱支撑差距<3%时标记共振 +- 权重<0.5时标记不可靠,止损/止盈仍以枢轴为主 + +### 首次运行结果 +- 33只股票完成筹码分布计算 +- 最高亏损筹码占比:万科99.5% / 神华98.6% / 比亚迪股份98.7% +- 最低亏损筹码占比:建滔4.0% / 药明康德2.1% + +### 注意 +- 代码在 master 已推送,mohe 侧无需额外操作 +- 下次开盘后 strategy_lifecycle 会自动加载筹码 S/R diff --git a/__pycache__/strategy_lifecycle.cpython-312.pyc b/__pycache__/strategy_lifecycle.cpython-312.pyc index 4bd6e82..f539ffc 100644 Binary files a/__pycache__/strategy_lifecycle.cpython-312.pyc and b/__pycache__/strategy_lifecycle.cpython-312.pyc differ diff --git a/mo_data.py b/mo_data.py index 03a3d38..6143c95 100644 --- a/mo_data.py +++ b/mo_data.py @@ -185,6 +185,38 @@ def read_watchlist_json(): return read_watchlist() +# ── cash_log 写入 ───────────────────────────────────────────────────── + +def write_cash_log(cash_before, cash_after, frozen_before, frozen_after, + source, note, verified=0): + """记录现金变更到 cash_log 表。 + + 参数: + cash_before/after — 变更前后可用现金 + frozen_before/after — 变更前后冻结资金 + source — 'screenshot'/'manual'/'trade'/'import_xls' + note — 备注(如"卖出法拉电子200股") + verified — 0=未验证 1=Dad已确认 + 返回: + log_id (int) + """ + change_amount = round(cash_after - cash_before, 2) if cash_after is not None and cash_before is not None else 0 + db = sqlite3.connect(DB_PATH) + try: + cur = db.execute( + """INSERT INTO cash_log + (timestamp, cash_before, cash_after, frozen_before, frozen_after, + change_amount, source, note, verified) + VALUES (datetime('now','localtime'), ?, ?, ?, ?, ?, ?, ?, ?)""", + (cash_before, cash_after, frozen_before, frozen_after, + change_amount, source, note, verified) + ) + db.commit() + return cur.lastrowid + finally: + db.close() + + # ── 自检 ──────────────────────────────────────────────────────────── if __name__ == "__main__": diff --git a/scripts/xmpp_agent_core.py b/scripts/xmpp_agent_core.py index 15b93fa..2507838 100644 --- a/scripts/xmpp_agent_core.py +++ b/scripts/xmpp_agent_core.py @@ -77,21 +77,7 @@ class SendHandler(BaseHTTPRequestHandler): text = data.get('body', '') msg_type = data.get('type', 'chat') if text: - if msg_type == 'groupchat': - from xml.sax.saxutils import escape - import subprocess as sp - safe = escape(text) - stanza = ( - f"" - f"{safe}" - ) - sp.run([ - "docker", "exec", "ejabberd", "ejabberdctl", - "send_stanza_c2s", AGENT_NICK, "yoin.fun", - _xmpp_resource, stanza - ], capture_output=True, timeout=10) - else: - _outbound_queue.append((target, text, msg_type)) + _outbound_queue.append((target, text, msg_type)) self.send_response(200) self.end_headers() self.wfile.write(b'{"ok":true}')