From c80f8146322c84624b8fd263027c0d1c11e57f16 Mon Sep 17 00:00:00 2001 From: hmo Date: Sat, 20 Jun 2026 20:45:30 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20K=E7=BA=BF=E8=BF=81=E7=A7=BB=20+=20?= =?UTF-8?q?=E6=B8=85=E7=90=86=E9=87=8D=E5=A4=8D=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit migrate_all.py: - 新增 migrate_klines(): multi_tf_cache.json → stock_daily/weekly/monthly + stock_fundamentals - 迁移量: daily=5520, weekly=1104, monthly=552 (46只股票) - 验证表新增 stock_daily/weekly/monthly/fundamentals 清理: - 删除 web/static/ (与根目录 static/ 重复,server.py 使用 static/) --- migrate_all.py | 95 +++- web/static/index.html | 1106 ---------------------------------------- web/static/upload.html | 247 --------- 3 files changed, 94 insertions(+), 1354 deletions(-) delete mode 100644 web/static/index.html delete mode 100644 web/static/upload.html diff --git a/migrate_all.py b/migrate_all.py index 2775ca4..ed51660 100644 --- a/migrate_all.py +++ b/migrate_all.py @@ -479,6 +479,88 @@ def migrate_strategy_feedback(conn, sf: dict) -> int: return count +def migrate_klines(conn) -> tuple[int, int, int]: + """multi_tf_cache.json → stock_daily + stock_weekly + stock_monthly + stock_fundamentals""" + data = load_json("multi_tf_cache.json") + if not data: + return 0, 0, 0 + + daily_count, weekly_count, monthly_count = 0, 0, 0 + + for code, stock in data.items(): + code = _normalize_code(code) + if not code or code.startswith("_"): + continue + + name = code # 从 stocks 表或 profiles 获取名称 + try: + row = conn.execute("SELECT name FROM stocks WHERE code = ?", (code,)).fetchone() + if row: + name = row[0] + except Exception: + pass + + # K线数据 + for period, table, key in [ + ("daily", "stock_daily", "daily"), + ("weekly", "stock_weekly", "weekly"), + ("monthly", "stock_monthly", "monthly"), + ]: + bars = stock.get(key, []) + if not bars or isinstance(bars, dict): + continue + rows = [] + for b in bars: + if not isinstance(b, dict): + continue + d = b.get("date", "") + if not d: + continue + if period == "daily": + rows.append((code, d, b.get("open"), b.get("close"), + b.get("high"), b.get("low"), b.get("volume"), + b.get("amount"))) + else: + rows.append((code, d, b.get("open"), b.get("close"), + b.get("high"), b.get("low"), b.get("volume"))) + + if rows: + try: + if period == "daily": + conn.executemany( + "INSERT OR REPLACE INTO stock_daily (code, date, open, close, high, low, volume, amount) " + "VALUES (?, ?, ?, ?, ?, ?, ?, ?)", rows) + daily_count += len(rows) + elif period == "weekly": + conn.executemany( + "INSERT OR REPLACE INTO stock_weekly (code, date, open, close, high, low, volume) " + "VALUES (?, ?, ?, ?, ?, ?, ?)", rows) + weekly_count += len(rows) + else: + conn.executemany( + "INSERT OR REPLACE INTO stock_monthly (code, date, open, close, high, low, volume) " + "VALUES (?, ?, ?, ?, ?, ?, ?)", rows) + monthly_count += len(rows) + except Exception: + pass + + # 基本面 + fundamentals = stock.get("fundamentals") + if fundamentals and isinstance(fundamentals, dict): + try: + conn.execute( + "INSERT OR REPLACE INTO stock_fundamentals (code, pe, pb, eps, mcap_total, mcap_flow, updated_at) " + "VALUES (?, ?, ?, ?, ?, ?, ?)", + (code, fundamentals.get("pe"), fundamentals.get("pb"), + fundamentals.get("eps"), fundamentals.get("mcap_total"), + fundamentals.get("mcap_flow"), datetime.now().isoformat())) + except Exception: + pass + + conn.commit() + return daily_count, weekly_count, monthly_count + + def main(): print("=" * 60) print(" MoFin 数据迁移 → mofin.db") @@ -572,7 +654,14 @@ def main(): if sf: n = migrate_strategy_feedback(conn, sf) totals["strategy_feedback"] = n - print(f"[12/12] strategy_feedback: {n} 条") + print(f"[12/13] strategy_feedback: {n} 条") + + # 13. K线数据 + dc, wc, mc = migrate_klines(conn) + totals["daily_klines"] = dc + totals["weekly_klines"] = wc + totals["monthly_klines"] = mc + print(f"[13/13] K-lines: daily={dc}, weekly={wc}, monthly={mc}") conn.commit() @@ -594,6 +683,10 @@ def main(): "advice_timeline": "SELECT COUNT(*) FROM advice_timeline", "accuracy_stats": "SELECT COUNT(*) FROM accuracy_stats", "strategy_feedback": "SELECT COUNT(*) FROM strategy_feedback", + "stock_daily": "SELECT COUNT(*) FROM stock_daily", + "stock_weekly": "SELECT COUNT(*) FROM stock_weekly", + "stock_monthly": "SELECT COUNT(*) FROM stock_monthly", + "stock_fundamentals": "SELECT COUNT(*) FROM stock_fundamentals", } for name, sql in tables.items(): n = conn.execute(sql).fetchone()[0] diff --git a/web/static/index.html b/web/static/index.html deleted file mode 100644 index 119a1ed..0000000 --- a/web/static/index.html +++ /dev/null @@ -1,1106 +0,0 @@ - - - - - -MoFin · 莫荷情报 - - - - - - -
- -
-
- 📊 -

MoFin

- 知微 -
-
- - -
-
- - -
- - - - - - - - - 📸 上传 -
- - -
- - - - - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/web/static/upload.html b/web/static/upload.html deleted file mode 100644 index a1cf1a2..0000000 --- a/web/static/upload.html +++ /dev/null @@ -1,247 +0,0 @@ - - - - - -MoFin - 持仓截图解析 - - - -
-

📸 持仓截图解析

-

← 返回仪表盘 · 上传持仓截图或自选截图,知微自动识别并更新数据

- -
-
📤
-
点击上传、拖拽图片、或 Ctrl+V 粘贴
-
支持 PNG / JPG / JPEG,建议清晰截图
-
- - - - -
-
-
🔍 知微正在分析图片...
-
- -
- -
-
- 持仓 -

-
-
-
- - -
-
-
- - -
- - - - \ No newline at end of file