完全DB版: 移除JSON写入/回退,所有操作直走SQLite
- price_monitor: 完全DB版,不再读写 portfolio.json/watchlist.json - holdings代码从DB读取(SELECT code FROM holdings WHERE is_active=1) - 价格写入DB holdings表 + portfolio_summary + live_prices - 3次重试+指数退避防锁 - server.py: 移除API的JSON回退,DB失败直接返回500 - mofin_db.py: execute_with_retry/commit_with_retry + 15s timeout + busy_timeout - mo_data.py: 已是纯DB模式(无JSON fallback) 这是推进的完全DB化。下一步可删除 data/portfolio.json data/decisions.json data/watchlist.json 等遗留JSON。
This commit is contained in:
+20
-52
@@ -100,77 +100,45 @@ def fetch_all_prices(codes):
|
||||
|
||||
|
||||
def refresh_data_prices():
|
||||
"""一次性刷新portfolio.json和watchlist.json的所有实时价"""
|
||||
"""一次性刷新所有持仓+自选股的实时价(完全DB版,不写JSON)"""
|
||||
all_codes = set()
|
||||
|
||||
# 收集所有需要拉取的代码
|
||||
# 从DB读所有需要拉取价格的代码
|
||||
try:
|
||||
pf = json.load(open(PORTFOLIO_PATH))
|
||||
for s in pf.get('holdings', []):
|
||||
all_codes.add(s['code'])
|
||||
except:
|
||||
pf = {"holdings": []}
|
||||
|
||||
try:
|
||||
wl = json.load(open(WATCHLIST_PATH))
|
||||
for s in wl.get('stocks', []):
|
||||
all_codes.add(s['code'])
|
||||
except:
|
||||
wl = {"stocks": []}
|
||||
conn = get_conn()
|
||||
for r in conn.execute("SELECT code FROM holdings WHERE is_active=1"):
|
||||
all_codes.add(r['code'])
|
||||
for r in conn.execute("SELECT code FROM watchlist_stocks"):
|
||||
all_codes.add(r['code'])
|
||||
conn.close()
|
||||
except Exception as e:
|
||||
print(f"⚠️ 从DB读代码失败: {e}", file=sys.stderr)
|
||||
return 0
|
||||
|
||||
if not all_codes:
|
||||
return 0
|
||||
|
||||
# 一次性批量拉取
|
||||
prices = fetch_all_prices(list(all_codes))
|
||||
updated = 0
|
||||
|
||||
# 更新portfolio(只在价格变化时写入,避免触发文件变更通知)
|
||||
changed = False
|
||||
for s in pf.get('holdings', []):
|
||||
if s['code'] in prices:
|
||||
price, _, change_pct = prices[s['code']]
|
||||
if price > 0:
|
||||
old = s.get('price', 0)
|
||||
if abs(old - price) > 0.001:
|
||||
s['price'] = round(price, 2)
|
||||
s['change_pct'] = float(change_pct) if change_pct else 0
|
||||
updated += 1
|
||||
changed = True
|
||||
if changed:
|
||||
json.dump(pf, open(PORTFOLIO_PATH, 'w'), ensure_ascii=False, indent=2)
|
||||
|
||||
# 更新watchlist(只在价格变化时写入)
|
||||
changed = False
|
||||
for s in wl.get('stocks', []):
|
||||
if s['code'] in prices:
|
||||
price, _, change_pct = prices[s['code']]
|
||||
if price > 0:
|
||||
old = s.get('price', 0)
|
||||
if abs(old - price) > 0.001:
|
||||
s['price'] = round(price, 2)
|
||||
s['change_pct'] = float(change_pct) if change_pct else 0
|
||||
updated += 1
|
||||
changed = True
|
||||
if changed:
|
||||
wl['updated_at'] = datetime.now().isoformat()
|
||||
json.dump(wl, open(WATCHLIST_PATH, 'w'), ensure_ascii=False, indent=2)
|
||||
updated = len(prices)
|
||||
|
||||
# === 同步实时价到 mofin.db(带重试防锁) ===
|
||||
if HAS_DB and prices:
|
||||
for db_attempt in range(3):
|
||||
try:
|
||||
conn = get_conn()
|
||||
# 直接从 portfolio.json 构建更新数据(保留已有的 market_value/currency)
|
||||
|
||||
# 构建 holdings 更新数据
|
||||
db_holdings = []
|
||||
for s in pf.get('holdings', []):
|
||||
code = str(s.get('code', ''))
|
||||
for r in conn.execute("SELECT * FROM holdings WHERE is_active=1"):
|
||||
h = dict(r)
|
||||
code = str(h.get('code', ''))
|
||||
if code in prices:
|
||||
price_val, _, change_pct = prices[code]
|
||||
if price_val > 0:
|
||||
s['price'] = round(price_val, 2)
|
||||
s['change_pct'] = float(change_pct) if change_pct else 0
|
||||
db_holdings.append(s)
|
||||
h['price'] = round(price_val, 2)
|
||||
h['change_pct'] = float(change_pct) if change_pct else 0
|
||||
db_holdings.append(h)
|
||||
|
||||
# 写入DB持仓价格(write_holdings_batch 用 ON CONFLICT UPDATE 只改价格字段)
|
||||
ok, msg = write_holdings_batch(conn, db_holdings)
|
||||
|
||||
Reference in New Issue
Block a user