chore: deployed JSON retirement

This commit is contained in:
知微
2026-07-20 18:10:35 +08:00
parent 73520464b6
commit 4383c384be
9 changed files with 1954 additions and 42656 deletions
-40644
View File
File diff suppressed because it is too large Load Diff
-5
View File
@@ -65,11 +65,6 @@ class MoConfig:
warnings.warn("watchlist_path is deprecated — use mo_data.read_watchlist() for DB data", DeprecationWarning, stacklevel=2) warnings.warn("watchlist_path is deprecated — use mo_data.read_watchlist() for DB data", DeprecationWarning, stacklevel=2)
return Path() return Path()
@property
def price_events_path(self) -> Path:
"""⚠️ 已废弃!数据在 mofin.db price_events 表。"""
return self.data_dir / "price_events.json"
@property @property
def live_prices_path(self) -> Path: def live_prices_path(self) -> Path:
"""⚠️ DEPRECATED: 实时价格已迁移到 mofin_db.live_prices 表。""" """⚠️ DEPRECATED: 实时价格已迁移到 mofin_db.live_prices 表。"""
+1 -1
View File
@@ -21,7 +21,7 @@ from datetime import datetime
from pathlib import Path from pathlib import Path
from typing import Optional, Callable from typing import Optional, Callable
DATA_DIR = Path(__file__).parent / "data" DATA_DIR = Path("/home/hmo/MoFin/data") # 绝对路径:全系统唯一权威数据目录
DB_PATH = DATA_DIR / "mofin.db" DB_PATH = DATA_DIR / "mofin.db"
# ═══════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════
-23
View File
@@ -934,29 +934,6 @@ def build_report():
except Exception: except Exception:
pass pass
# price_events 特殊处理:活跃存储是 price_events.jsonprice_monitor 实时写入),
# DB 表是旧遗留。读 JSON 最后一条事件的时间。
try:
_pe_path = Path("/home/hmo/web-dashboard/data/price_events.json")
if _pe_path.exists():
_pe = json.loads(_pe_path.read_text(encoding="utf-8"))
_items = _pe if isinstance(_pe, list) else _pe.get("events", [])
if _items:
_last = _items[-1]
_ts = _last.get("timestamp") or _last.get("created_at") or ""
_dt = datetime.fromisoformat(str(_ts).replace("Z", ""))
_age = (now - _dt).total_seconds() / 3600
# 替换 db_freshness 里 price_events 那条(DB 旧数据)
db_freshness = [f for f in db_freshness if f["table"] != "price_events"]
db_freshness.append({
"table": "price_events.json", "label": "价格事件",
"last_record": _dt.strftime("%m-%d %H:%M"),
"age_hours": round(_age, 1),
"warn": _age > 24,
})
except Exception:
pass
# ── Tab 3: 流程/cron映射 ── # ── Tab 3: 流程/cron映射 ──
pipelines = [] pipelines = []
for j in sorted(cron_jobs, key=lambda x: x.get("name","")): for j in sorted(cron_jobs, key=lambda x: x.get("name","")):
+6 -36
View File
@@ -12,7 +12,6 @@ from mo_data import read_decisions
BREACH_PATH = "/home/hmo/.hermes/zone_breach.json" BREACH_PATH = "/home/hmo/.hermes/zone_breach.json"
STATE_PATH = "/home/hmo/.hermes/price_trigger_state.json" STATE_PATH = "/home/hmo/.hermes/price_trigger_state.json"
EVENTS_PATH = "/home/hmo/web-dashboard/data/price_events.json"
# DB 模块(同步实时价到 mofin.db) # DB 模块(同步实时价到 mofin.db)
sys.path.insert(0, "/home/hmo/MoFin") sys.path.insert(0, "/home/hmo/MoFin")
@@ -319,27 +318,14 @@ def save_breaches(data):
json.dump(data, f, ensure_ascii=False, indent=2) json.dump(data, f, ensure_ascii=False, indent=2)
def load_events():
try:
with open(EVENTS_PATH) as f:
return json.load(f)
except:
return {"events": []}
def save_events(events):
os.makedirs(os.path.dirname(EVENTS_PATH), exist_ok=True)
with open(EVENTS_PATH, 'w') as f:
json.dump(events, f, ensure_ascii=False, indent=2)
def record_event(code, name, event_type, price, trigger_value, event_label=""): def record_event(code, name, event_type, price, trigger_value, event_label=""):
"""记录一次价格触发事件 — 双写:DB price_events 表(权威)+ price_events.json(遗留读取方兼容)""" """记录一次价格触发事件 DB price_events 表(唯一权威存储,JSON 已退役)。
now = datetime.now().isoformat()
date_str = datetime.now().strftime("%Y-%m-%d") price_events.code 有 FK -> stocks(code),未注册的股票(新候选/港股)
先注册再写事件,否则 FK 失败事件丢失。
"""
now = datetime.now().isoformat()
# 1. 写 DB 表(权威存储)。price_events.code 有 FK -> stocks(code)
# 未注册的股票(新候选/港股)会先注册再写事件,否则 FK 失败事件丢失。
if HAS_DB: if HAS_DB:
try: try:
from mofin_db import get_conn, write_price_event from mofin_db import get_conn, write_price_event
@@ -355,22 +341,6 @@ def record_event(code, name, event_type, price, trigger_value, event_label=""):
except Exception as e: except Exception as e:
print(f"[price_events DB写入失败] {e}", file=sys.stderr) print(f"[price_events DB写入失败] {e}", file=sys.stderr)
# 2. 写 JSON(遗留读取方:mo_config/strategy_feedback/system_health_check 还在读)
events = load_events()
events["events"].append({
"code": code,
"name": name,
"event_type": event_type, # entry_zone, stop_loss, take_profit, exit_zone
"price": round(price, 2),
"trigger_value": trigger_value,
"event_label": event_label,
"timestamp": now,
"date": date_str,
})
# 保留最近10000条
events["events"] = events["events"][-10000:]
save_events(events)
def get_trigger_zones(trigger): def get_trigger_zones(trigger):
"""返回该trigger所有可监控的区间列表,跳过已执行的batch""" """返回该trigger所有可监控的区间列表,跳过已执行的batch"""
+4 -4
View File
@@ -18,7 +18,6 @@ from mo_data import read_decisions
DATA_DIR = Path(__file__).parent.parent / "data" DATA_DIR = Path(__file__).parent.parent / "data"
ACCURACY_PATH = DATA_DIR / "accuracy_stats.json" ACCURACY_PATH = DATA_DIR / "accuracy_stats.json"
EVENTS_PATH = DATA_DIR / "price_events.json"
FEEDBACK_PATH = DATA_DIR / "strategy_feedback.json" FEEDBACK_PATH = DATA_DIR / "strategy_feedback.json"
@@ -174,15 +173,16 @@ def generate_adjustment(decision, phase_check, accuracy_trend):
def run(): def run():
decisions = read_decisions() decisions = read_decisions()
# 优先从 SQLite 读取价格事件 # 价格事件:只从 DB price_events 表读(JSON 已退役)
try: try:
from mofin_db import get_conn, query_price_events from mofin_db import get_conn, query_price_events
conn = get_conn() conn = get_conn()
pe_rows = query_price_events(conn, limit=50000) pe_rows = query_price_events(conn, limit=50000)
conn.close() conn.close()
events = {"events": pe_rows} events = {"events": pe_rows}
except Exception: except Exception as e:
events = load_json(EVENTS_PATH, {"events": []}) print(f"[strategy_feedback] DB价格事件读取失败: {e}", file=sys.stderr)
events = {"events": []}
accuracy_stats = load_json(ACCURACY_PATH, {}) accuracy_stats = load_json(ACCURACY_PATH, {})
accuracy_trend = compute_accuracy_trend(accuracy_stats) accuracy_trend = compute_accuracy_trend(accuracy_stats)
@@ -9,7 +9,6 @@ from datetime import datetime, timedelta
from pathlib import Path from pathlib import Path
DATA_DIR = Path("/home/hmo/web-dashboard/data") DATA_DIR = Path("/home/hmo/web-dashboard/data")
EVENTS_PATH = DATA_DIR / "price_events.json"
EVALUATION_PATH = DATA_DIR / "evaluation.json" EVALUATION_PATH = DATA_DIR / "evaluation.json"
ACCURACY_PATH = DATA_DIR / "accuracy_stats.json" ACCURACY_PATH = DATA_DIR / "accuracy_stats.json"
CRON_JOBS = "/home/hmo/.hermes/profiles/position-analyst/cron/jobs.json" CRON_JOBS = "/home/hmo/.hermes/profiles/position-analyst/cron/jobs.json"
@@ -104,10 +103,9 @@ def run():
lines.append(check(False, "MoFin DB 数据读取失败")) lines.append(check(False, "MoFin DB 数据读取失败"))
warn_count += 3 warn_count += 3
# 仍为 JSON 文件的检查 # 仍为 JSON 文件的检查price_events 已迁移到 DB 表,不在此列)
files = { files = {
"market.json": DATA_DIR / "market.json", "market.json": DATA_DIR / "market.json",
"price_events.json": EVENTS_PATH,
"evaluation.json": EVALUATION_PATH, "evaluation.json": EVALUATION_PATH,
"accuracy_stats.json": ACCURACY_PATH, "accuracy_stats.json": ACCURACY_PATH,
} }
@@ -121,7 +119,7 @@ def run():
else: else:
ok_count += 1 ok_count += 1
# 4. 价格事件统计 # 4. 价格事件统计(只读 DB price_events 表,JSON 已退役)
lines.append("") lines.append("")
lines.append("【价格事件】") lines.append("【价格事件】")
try: try:
@@ -130,10 +128,12 @@ def run():
ev_list = query_price_events(conn, limit=50000) ev_list = query_price_events(conn, limit=50000)
today_events = query_price_events_by_date(conn, now.strftime("%Y-%m-%d")) today_events = query_price_events_by_date(conn, now.strftime("%Y-%m-%d"))
conn.close() conn.close()
except Exception: except Exception as e:
events = load_json(EVENTS_PATH, {"events": []}) ev_list = []
ev_list = events.get("events", []) today_events = []
today_events = [e for e in ev_list if e.get("date") == now.strftime("%Y-%m-%d")] lines.append(check(False, f"DB价格事件读取失败: {str(e)[:60]}"))
issues.append(f"price_events DB读取失败: {str(e)[:60]}")
warn_count += 1
lines.append(check(len(ev_list) > 0, f"历史事件: {len(ev_list)}")) lines.append(check(len(ev_list) > 0, f"历史事件: {len(ev_list)}"))
lines.append(check(len(today_events) > 0, f"今日事件: {len(today_events)}")) lines.append(check(len(today_events) > 0, f"今日事件: {len(today_events)}"))
if len(ev_list) == 0: if len(ev_list) == 0:
+1 -1
View File
@@ -21,7 +21,7 @@ from datetime import datetime
from pathlib import Path from pathlib import Path
from typing import Optional, Callable from typing import Optional, Callable
DATA_DIR = Path(__file__).parent / "data" DATA_DIR = Path("/home/hmo/MoFin/data") # 绝对路径:全系统唯一权威数据目录
DB_PATH = DATA_DIR / "mofin.db" DB_PATH = DATA_DIR / "mofin.db"
# ═══════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════
+1 -1
View File
@@ -21,7 +21,7 @@ from datetime import datetime
from pathlib import Path from pathlib import Path
from typing import Optional, Callable from typing import Optional, Callable
DATA_DIR = Path(__file__).parent / "data" DATA_DIR = Path("/home/hmo/MoFin/data") # 绝对路径:全系统唯一权威数据目录
DB_PATH = DATA_DIR / "mofin.db" DB_PATH = DATA_DIR / "mofin.db"
# ═══════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════