#!/usr/bin/env python3 # -*- coding: utf-8 -*- """regime_tracker.py — 温区平滑跟踪 + 周期记录(2026-08-13) 设计(老莫确认方向 + 数据选参): - 实时温区判定:滞回确认 K=5(连续5天同温区才确认,滞后约5天,宁慢勿错) 数据依据:K=5 → 112周期/平均20.7天/无1天噪音(vs 原始457周期/151个1天) - 温区周期记录:regime_cycles 表(start/end/regime/days),供策略评估归因 - 温度(rsi):不滞后,实时反映恐慌/亢奋(与温区互补:温区滞后、温度实时) 写表: regime_cycles(market, start_date, end_date, regime, days) # 2026-08-14 阶段3 加 market 维度 输出: market_regime_smoothed.json(当前平滑温区 + 温度;A股顶层键向后兼容 + markets 双市场详情) """ import sys import json import sqlite3 from pathlib import Path from datetime import datetime # ── 消息通道统一路由(broadcast/xmpp by delivery) ── try: from messenger import install_stdio_hook as _msh _msh() except Exception: pass _SCRIPT_DIR = Path(__file__).resolve().parent sys.path.insert(0, str(_SCRIPT_DIR)) sys.path.insert(0, "/home/hmo/MoFin") DB = "/home/hmo/MoFin/data/mofin.db" OUT = "/home/hmo/MoFin/data/market_regime_smoothed.json" # 滞回确认天数(数据选参:K=5 甜区) CONFIRM_DAYS = 5 def load_daily_regime(market='a'): """读取指定市场 market_regime 逐日数据(时间正序)""" conn = sqlite3.connect(DB, timeout=5) rows = conn.execute( "SELECT date, above_ma20, adx, regime FROM market_regime " "WHERE market=? ORDER BY date ASC", (market,) ).fetchall() conn.close() return rows def classify_day(above, adx): """单日温区(与 market_regime 同逻辑)""" if above == 1 and adx is not None and adx >= 20: return "trend_up" if adx is not None and adx < 20: return "choppy" return "trend_down" def smooth_states(rows, k=CONFIRM_DAYS): """滞回确认:连续 K 天同温区才确认切换。返回 (states, cycles)""" dates = [r[0] for r in rows] raw = [classify_day(r[1], r[2]) for r in rows] n = len(dates) # 状态机:current 确认态;每 K 天窗口看是否一致 states = [None] * n current = None for i in range(n): if i < k - 1: continue window = raw[i - k + 1:i + 1] if len(set(window)) == 1: # 连续 K 天同温区 → 确认(切换) current = window[0] states[i] = current if current is not None else raw[i] # 开头填补(前 K-1 天用原始值) for i in range(min(k - 1, n)): states[i] = raw[i] # 聚合周期 cycles = [] cur = None for i in range(n): s = states[i] if cur is None or s != cur["regime"]: if cur: cycles.append(cur) cur = {"regime": s, "start": dates[i], "end": dates[i], "days": 1} else: cur["end"] = dates[i] cur["days"] += 1 if cur: cycles.append(cur) return states, cycles, dates def save_cycles(cycles, market='a'): """写入 regime_cycles 表(按市场重建:A/港股各自独立周期,互不清除)""" conn = sqlite3.connect(DB, timeout=30) conn.execute("PRAGMA busy_timeout=30000") conn.execute(""" CREATE TABLE IF NOT EXISTS regime_cycles ( id INTEGER PRIMARY KEY AUTOINCREMENT, market TEXT NOT NULL DEFAULT 'a', regime TEXT, start_date TEXT, end_date TEXT, days INTEGER, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) """) # 只清本市场周期(保持与 market_regime 同步) conn.execute("DELETE FROM regime_cycles WHERE market=?", (market,)) for cy in cycles: conn.execute( "INSERT INTO regime_cycles (market, regime, start_date, end_date, days) VALUES (?,?,?,?,?)", (market, cy["regime"], cy["start"], cy["end"], cy["days"]) ) conn.commit() conn.close() return len(cycles) def get_temp(market='a'): """实时温度(rsi 档位,不滞后),按市场""" try: from temp_band import get_market_temp return get_market_temp(market=market) except Exception: return {"band": "unknown", "rsi": None} def get_smoothed_regime(market='a'): """计算指定市场当前平滑温区(K=5 滞回确认)。 返回 {current_regime, current_date, states, cycles, dates, total_cycles, recent_cycles}; 数据不足(