fix: HK currency→CNY + portfolio_summary + LLM prompt evaluation.json→DB
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
"""收盘后全面数据审计"""
|
||||
import sys, sqlite3
|
||||
sys.path.insert(0, '/home/hmo/MoFin')
|
||||
from mo_models import is_hk_stock, get_hk_rate, calc_total_assets, calc_total_mv, calc_position_pct
|
||||
from mo_data import read_portfolio, read_decisions, read_watchlist
|
||||
|
||||
pf = read_portfolio()
|
||||
dec = read_decisions()
|
||||
wl = read_watchlist()
|
||||
rate = get_hk_rate()
|
||||
|
||||
print(f"HK_RATE: {rate}")
|
||||
print()
|
||||
|
||||
# ── 1. 持仓数据审计 ──
|
||||
print("=== 持仓 Holdings ===")
|
||||
errors = []
|
||||
hk_cny_issues = []
|
||||
total_mv = 0
|
||||
total_cost = 0
|
||||
|
||||
for h in pf.get('holdings', []):
|
||||
code = str(h.get('code', ''))
|
||||
name = h.get('name', '?')
|
||||
cost = h.get('cost') or 0
|
||||
price = h.get('price') or 0
|
||||
shares = h.get('shares') or 0
|
||||
curr = h.get('currency', h.get('_currency', '?'))
|
||||
mv = price * shares
|
||||
total_mv += mv
|
||||
total_cost += cost * shares
|
||||
|
||||
is_hk = is_hk_stock(code)
|
||||
flag = 'HK' if is_hk else 'A '
|
||||
|
||||
# 检查币种
|
||||
if is_hk and curr != 'CNY':
|
||||
hk_cny_issues.append(f"{code} {name}: currency={curr} (应为CNY)")
|
||||
|
||||
# 检查 cost=0 的股票
|
||||
if cost <= 0 and shares > 0:
|
||||
errors.append(f"{code} {name}: cost=0 但持仓{shares}股")
|
||||
|
||||
pnl_pct = (price - cost) / cost * 100 if cost > 0 else 0
|
||||
print(f" [{flag}] {code} {name}: cost={cost:.2f} price={price:.2f} shares={shares} mv={mv:.0f} pnl={pnl_pct:+.1f}% curr={curr}")
|
||||
|
||||
total_pnl = total_mv - total_cost
|
||||
print(f"\n total_mv={total_mv:.2f} total_cost={total_cost:.2f} total_pnl={total_pnl:.2f}")
|
||||
|
||||
# ── 2. 汇总数据审计 ──
|
||||
print("\n=== Portfolio Summary ===")
|
||||
print(f" stored total_assets: {pf.get('total_assets')}")
|
||||
print(f" stored total_mv: {pf.get('total_mv')}")
|
||||
print(f" stored cash: {pf.get('cash')}")
|
||||
print(f" stored frozen_cash: {pf.get('frozen_cash')}")
|
||||
print(f" stored total_pnl: {pf.get('total_pnl')}")
|
||||
|
||||
calc_ta = total_mv + (pf.get('cash') or 0) + (pf.get('frozen_cash') or 0)
|
||||
print(f" calculated total_assets: {calc_ta:.2f}")
|
||||
|
||||
if abs((pf.get('total_assets') or 0) - calc_ta) > 1:
|
||||
errors.append(f"total_assets mismatch: stored={pf.get('total_assets')} vs calc={calc_ta:.2f}")
|
||||
|
||||
# ── 3. 决策数据审计 ──
|
||||
print("\n=== Decisions ===")
|
||||
cnys = 0
|
||||
hkds = 0
|
||||
none_curr = 0
|
||||
for d in dec.get('decisions', []):
|
||||
c = d.get('currency', '')
|
||||
if c == 'CNY': cnys += 1
|
||||
elif c == 'HKD': hkds += 1
|
||||
else: none_curr += 1
|
||||
print(f" CNY: {cnys} HKD: {hkds} None: {none_curr}")
|
||||
if hkds > 0:
|
||||
errors.append(f"Decisions: {hkds} entries still have currency=HKD")
|
||||
|
||||
# ── 4. 错误汇总 ──
|
||||
print(f"\n{'='*40}")
|
||||
if hk_cny_issues:
|
||||
print("HK币种问题:")
|
||||
for i in hk_cny_issues: print(f" ❌ {i}")
|
||||
if errors:
|
||||
print("其他问题:")
|
||||
for e in errors: print(f" ❌ {e}")
|
||||
if not hk_cny_issues and not errors:
|
||||
print("✅ 数据审计全部通过")
|
||||
@@ -0,0 +1,42 @@
|
||||
"""Fix: HK stock currency=CYN, recalc portfolio_summary"""
|
||||
import sqlite3, sys
|
||||
sys.path.insert(0, '/home/hmo/MoFin')
|
||||
from mo_models import is_hk_stock
|
||||
from datetime import datetime
|
||||
|
||||
db = sqlite3.connect('/home/hmo/web-dashboard/data/mofin.db')
|
||||
|
||||
# 1. Fix all HK stock currency to CNY
|
||||
fixed = 0
|
||||
for r in db.execute("SELECT code, name, cost, price, shares, currency FROM holdings WHERE is_active=1"):
|
||||
code, name, cost, price, shares, curr = r
|
||||
if is_hk_stock(str(code)):
|
||||
db.execute("UPDATE holdings SET currency='CNY' WHERE code=?", (code,))
|
||||
print(f" FIXED HK currency: {code} {name}: {curr} -> CNY")
|
||||
fixed += 1
|
||||
print(f"Fixed {fixed} HK stock currencies\n")
|
||||
|
||||
# 2. Recalc portfolio_summary
|
||||
rows = db.execute("SELECT code, shares, cost, price FROM holdings WHERE is_active=1").fetchall()
|
||||
total_mv = sum((r[3] or 0) * (r[1] or 0) for r in rows)
|
||||
total_cost = sum((r[2] or 0) * (r[1] or 0) for r in rows)
|
||||
total_pnl = total_mv - total_cost
|
||||
|
||||
sr = db.execute("SELECT cash, frozen_cash FROM portfolio_summary WHERE id=1").fetchone()
|
||||
cash = sr[0] or 0
|
||||
frozen = sr[1] or 0
|
||||
total_assets = total_mv + cash + frozen
|
||||
position_pct = round(total_mv / total_assets * 100, 2) if total_assets > 0 else 0
|
||||
|
||||
db.execute("UPDATE portfolio_summary SET total_mv=?, total_assets=?, total_pnl=?, position_pct=?, updated_at=? WHERE id=1",
|
||||
(round(total_mv,2), round(total_assets,2), round(total_pnl,2), position_pct, datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
|
||||
print(f"portfolio_summary: mv={total_mv:.2f} ta={total_assets:.2f} pnl={total_pnl:.2f} pos={position_pct}%")
|
||||
|
||||
# 3. Check 00700 cost
|
||||
r = db.execute("SELECT cost FROM holdings WHERE code='00700'").fetchone()
|
||||
if r and (r[0] is None or r[0] == 0):
|
||||
print("\n⚠️ 00700 腾讯 cost=0 — 需要从 holding.xls 重新导入")
|
||||
|
||||
db.commit()
|
||||
db.close()
|
||||
print("\nDone.")
|
||||
@@ -0,0 +1,6 @@
|
||||
import sqlite3
|
||||
db = sqlite3.connect('/home/hmo/web-dashboard/data/mofin.db')
|
||||
n = db.execute("UPDATE holding_strategies SET currency='CNY' WHERE currency='HKD'").rowcount
|
||||
db.commit()
|
||||
print(f"Fixed {n} decision currencies")
|
||||
db.close()
|
||||
Reference in New Issue
Block a user