chore: 清理残留mo_data.py+数据文件

This commit is contained in:
知微
2026-07-10 01:30:27 +08:00
parent c4de7d6516
commit 9905294496
4 changed files with 958 additions and 581 deletions
+270
View File
@@ -4339,6 +4339,276 @@
"event_label": "止盈区间",
"timestamp": "2026-07-09T13:35:18.747119",
"date": "2026-07-09"
},
{
"code": "01888",
"name": "建滔积层板",
"event_type": "entry_zone",
"price": 65.65,
"trigger_value": "64.58~67.22",
"event_label": "加仓区间",
"timestamp": "2026-07-09T13:38:58.113244",
"date": "2026-07-09"
},
{
"code": "600563",
"name": "法拉电子",
"event_type": "entry_zone",
"price": 147.03,
"trigger_value": "0.0~148.72",
"event_label": "止盈区间",
"timestamp": "2026-07-09T13:43:00.275642",
"date": "2026-07-09"
},
{
"code": "01211",
"name": "比亚迪股份",
"event_type": "entry_zone",
"price": 82.4,
"trigger_value": "0.0~82.56",
"event_label": "止盈区间",
"timestamp": "2026-07-09T13:46:03.118468",
"date": "2026-07-09"
},
{
"code": "06869",
"name": "长飞光纤光缆",
"event_type": "entry_zone",
"price": 158.7,
"trigger_value": "155.62~161.98",
"event_label": "加仓区间",
"timestamp": "2026-07-09T13:54:13.097656",
"date": "2026-07-09"
},
{
"code": "01211",
"name": "比亚迪股份",
"event_type": "entry_zone",
"price": 82.4,
"trigger_value": "0.0~82.42",
"event_label": "止盈区间",
"timestamp": "2026-07-09T13:56:17.168207",
"date": "2026-07-09"
},
{
"code": "600563",
"name": "法拉电子",
"event_type": "entry_zone",
"price": 148.43,
"trigger_value": "0.0~148.72",
"event_label": "止盈区间",
"timestamp": "2026-07-09T13:56:19.051542",
"date": "2026-07-09"
},
{
"code": "000518",
"name": "四环生物",
"event_type": "entry_zone",
"price": 3.93,
"trigger_value": "0.0~3.93",
"event_label": "止盈区间",
"timestamp": "2026-07-09T13:58:22.933836",
"date": "2026-07-09"
},
{
"code": "000711",
"name": "ST京蓝",
"event_type": "entry_zone",
"price": 5.58,
"trigger_value": "5.58~5.6",
"event_label": "加仓区间",
"timestamp": "2026-07-09T13:58:25.015873",
"date": "2026-07-09"
},
{
"code": "000657",
"name": "中钨高新",
"event_type": "entry_zone",
"price": 75.42,
"trigger_value": "72.47~75.43",
"event_label": "加仓区间",
"timestamp": "2026-07-09T14:02:37.818729",
"date": "2026-07-09"
},
{
"code": "000700",
"name": "模塑科技",
"event_type": "entry_zone",
"price": 15.05,
"trigger_value": "0.0~15.42",
"event_label": "止盈区间",
"timestamp": "2026-07-09T14:02:45.560659",
"date": "2026-07-09"
},
{
"code": "600563",
"name": "法拉电子",
"event_type": "entry_zone",
"price": 148.76,
"trigger_value": "0.0~153.18",
"event_label": "止盈区间",
"timestamp": "2026-07-09T14:02:49.034256",
"date": "2026-07-09"
},
{
"code": "688411",
"name": "海博思创",
"event_type": "entry_zone",
"price": 248.6,
"trigger_value": "0.0~255.09",
"event_label": "止盈区间",
"timestamp": "2026-07-09T14:02:53.697878",
"date": "2026-07-09"
},
{
"code": "688639",
"name": "华恒生物",
"event_type": "entry_zone",
"price": 16.26,
"trigger_value": "0.0~16.93",
"event_label": "止盈区间",
"timestamp": "2026-07-09T14:03:01.081412",
"date": "2026-07-09"
},
{
"code": "000518",
"name": "四环生物",
"event_type": "entry_zone",
"price": 3.93,
"trigger_value": "0.0~3.93",
"event_label": "止盈区间",
"timestamp": "2026-07-09T14:12:55.195062",
"date": "2026-07-09"
},
{
"code": "000518",
"name": "四环生物",
"event_type": "entry_zone",
"price": 3.93,
"trigger_value": "0.0~3.93",
"event_label": "止盈区间",
"timestamp": "2026-07-09T14:17:06.706160",
"date": "2026-07-09"
},
{
"code": "01888",
"name": "建滔积层板",
"event_type": "stop_loss",
"price": 65.35,
"trigger_value": "65.52",
"event_label": "",
"timestamp": "2026-07-09T14:18:11.729296",
"date": "2026-07-09"
},
{
"code": "01088",
"name": "中国神华",
"event_type": "entry_zone",
"price": 41.18,
"trigger_value": "40.88~41.26",
"event_label": "加仓区间",
"timestamp": "2026-07-09T14:20:15.844154",
"date": "2026-07-09"
},
{
"code": "01888",
"name": "建滔积层板",
"event_type": "entry_zone",
"price": 66.2,
"trigger_value": "64.09~66.71",
"event_label": "加仓区间",
"timestamp": "2026-07-09T14:20:22.220550",
"date": "2026-07-09"
},
{
"code": "01888",
"name": "建滔积层板",
"event_type": "entry_zone",
"price": 67.95,
"trigger_value": "66.15~68.85",
"event_label": "加仓区间",
"timestamp": "2026-07-09T14:26:23.388720",
"date": "2026-07-09"
},
{
"code": "01211",
"name": "比亚迪股份",
"event_type": "entry_zone",
"price": 82.9,
"trigger_value": "0.0~84.79",
"event_label": "止盈区间",
"timestamp": "2026-07-09T14:48:11.862007",
"date": "2026-07-09"
},
{
"code": "300750",
"name": "宁德时代",
"event_type": "entry_zone",
"price": 375.81,
"trigger_value": "0.0~384.7",
"event_label": "止盈区间",
"timestamp": "2026-07-09T14:48:19.477610",
"date": "2026-07-09"
},
{
"code": "601899",
"name": "紫金矿业",
"event_type": "entry_zone",
"price": 27.63,
"trigger_value": "0.0~28.33",
"event_label": "止盈区间",
"timestamp": "2026-07-09T14:48:25.964779",
"date": "2026-07-09"
},
{
"code": "000700",
"name": "模塑科技",
"event_type": "entry_zone",
"price": 15.17,
"trigger_value": "14.9~15.18",
"event_label": "加仓区间",
"timestamp": "2026-07-09T14:54:22.002129",
"date": "2026-07-09"
},
{
"code": "000700",
"name": "模塑科技",
"event_type": "entry_zone",
"price": 15.18,
"trigger_value": "0.0~15.42",
"event_label": "止盈区间",
"timestamp": "2026-07-09T15:02:40.447650",
"date": "2026-07-09"
},
{
"code": "300035",
"name": "中科电气",
"event_type": "entry_zone",
"price": 13.1,
"trigger_value": "0.0~13.28",
"event_label": "止盈区间",
"timestamp": "2026-07-09T15:02:41.664662",
"date": "2026-07-09"
},
{
"code": "518880",
"name": "黄金ETF华安",
"event_type": "entry_zone",
"price": 8.54,
"trigger_value": "0.0~8.83",
"event_label": "止盈区间",
"timestamp": "2026-07-09T15:02:46.381981",
"date": "2026-07-09"
},
{
"code": "688639",
"name": "华恒生物",
"event_type": "entry_zone",
"price": 16.34,
"trigger_value": "0.0~16.6",
"event_label": "止盈区间",
"timestamp": "2026-07-09T15:02:49.588923",
"date": "2026-07-09"
}
]
}
+334 -84
View File
@@ -4,19 +4,19 @@
"date": "2026-07-09",
"high": 15.75,
"low": 14.86,
"close": 14.98,
"volume": 444216.0,
"amount": 67570.0
"close": 15.18,
"volume": 570457.0,
"amount": 86672.0
}
],
"00700": [
{
"date": "2026-07-09",
"high": 485.0,
"low": 470.2,
"close": 470.2,
"volume": 26422991.0,
"amount": 12632308619.838
"low": 467.2,
"close": 469.6,
"volume": 42402152.0,
"amount": 20136358005.238
}
],
"01088": [
@@ -24,19 +24,19 @@
"date": "2026-07-09",
"high": 41.64,
"low": 40.82,
"close": 41.24,
"volume": 7332972.0,
"amount": 302862748.4
"close": 41.14,
"volume": 14046969.0,
"amount": 579255213.92
}
],
"01211": [
{
"date": "2026-07-09",
"high": 86.55,
"low": 82.55,
"low": 82.2,
"close": 82.65,
"volume": 18326386.0,
"amount": 1550084205.15
"volume": 38997358.0,
"amount": 3261050507.8
}
],
"01478": [
@@ -44,9 +44,9 @@
"date": "2026-07-09",
"high": 6.97,
"low": 6.79,
"close": 6.82,
"volume": 2527000.0,
"amount": 17355670.0
"close": 6.95,
"volume": 5386000.0,
"amount": 37091059.0
}
],
"01888": [
@@ -54,9 +54,9 @@
"date": "2026-07-09",
"high": 71.0,
"low": 63.4,
"close": 65.85,
"volume": 59047903.0,
"amount": 3957642009.85
"close": 67.7,
"volume": 102823013.0,
"amount": 6908608777.7
}
],
"02202": [
@@ -64,9 +64,9 @@
"date": "2026-07-09",
"high": 2.28,
"low": 2.23,
"close": 2.24,
"volume": 8649200.0,
"amount": 19491995.6
"close": 2.26,
"volume": 13355400.0,
"amount": 30069732.6
}
],
"06869": [
@@ -74,9 +74,9 @@
"date": "2026-07-09",
"high": 163.5,
"low": 146.0,
"close": 156.0,
"volume": 24880313.0,
"amount": 3855569879.8
"close": 160.2,
"volume": 45112427.0,
"amount": 7086960142.8
}
],
"300035": [
@@ -84,59 +84,59 @@
"date": "2026-07-09",
"high": 13.44,
"low": 12.68,
"close": 12.97,
"volume": 145833.0,
"amount": 18946.0
"close": 13.1,
"volume": 207556.0,
"amount": 27007.0
}
],
"300308": [
{
"date": "2026-07-09",
"high": 1168.95,
"high": 1199.99,
"low": 1117.01,
"close": 1159.0,
"volume": 234082.0,
"amount": 2677710.0
"close": 1194.9,
"volume": 358884.0,
"amount": 4160873.0
}
],
"300548": [
{
"date": "2026-07-09",
"high": 227.76,
"high": 233.51,
"low": 213.1,
"close": 226.28,
"volume": 109292.0,
"amount": 239836.0
"close": 232.7,
"volume": 170364.0,
"amount": 380906.0
}
],
"300750": [
{
"date": "2026-07-09",
"high": 370.68,
"high": 376.66,
"low": 360.07,
"close": 366.77,
"volume": 246690.0,
"amount": 900969.0
"close": 375.5,
"volume": 377942.0,
"amount": 1390578.0
}
],
"518880": [
{
"date": "2026-07-09",
"high": 8.504,
"high": 8.55,
"low": 8.446,
"close": 8.479,
"volume": 1504923.0,
"amount": 127577.0
"close": 8.544,
"volume": 2454207.0,
"amount": 208479.0
}
],
"600563": [
{
"date": "2026-07-09",
"high": 147.68,
"high": 151.6,
"low": 140.33,
"close": 146.08,
"volume": 57531.0,
"amount": 82717.0
"close": 150.88,
"volume": 95323.0,
"amount": 139212.0
}
],
"601899": [
@@ -144,19 +144,19 @@
"date": "2026-07-09",
"high": 27.7,
"low": 26.55,
"close": 26.97,
"volume": 1784624.0,
"amount": 483471.0
"close": 27.62,
"volume": 2514997.0,
"amount": 683733.0
}
],
"688411": [
{
"date": "2026-07-09",
"high": 248.86,
"high": 249.5,
"low": 239.0,
"close": 246.75,
"volume": 2194854.0,
"amount": 53748.0
"close": 249.01,
"volume": 3170558.0,
"amount": 77981.0
}
],
"688639": [
@@ -164,39 +164,39 @@
"date": "2026-07-09",
"high": 16.53,
"low": 16.22,
"close": 16.3,
"volume": 2307747.0,
"amount": 3758.0
"close": 16.34,
"volume": 3415772.0,
"amount": 5562.0
}
],
"688981": [
{
"date": "2026-07-09",
"high": 166.58,
"high": 174.51,
"low": 152.1,
"close": 165.66,
"volume": 96555603.0,
"amount": 1543952.0
"close": 173.0,
"volume": 144629617.0,
"amount": 2364591.0
}
],
"00981": [
{
"date": "2026-07-09",
"high": 83.45,
"high": 85.8,
"low": 76.65,
"close": 81.55,
"volume": 126183931.0,
"amount": 10157585460.2
"close": 83.55,
"volume": 227477167.0,
"amount": 18651146410.85
}
],
"688041": [
{
"date": "2026-07-09",
"high": 354.97,
"high": 363.85,
"low": 335.5,
"close": 350.57,
"volume": 22812082.0,
"amount": 789683.0
"close": 363.46,
"volume": 42754499.0,
"amount": 1501760.0
}
],
"688795": [
@@ -204,9 +204,9 @@
"date": "2026-07-09",
"high": 769.5,
"low": 666.66,
"close": 741.88,
"volume": 5633346.0,
"amount": 405585.0
"close": 759.0,
"volume": 7025157.0,
"amount": 510168.0
}
],
"688802": [
@@ -214,29 +214,279 @@
"date": "2026-07-09",
"high": 1008.0,
"low": 855.0,
"close": 958.0,
"volume": 4048232.0,
"amount": 375987.0
"close": 981.88,
"volume": 5491609.0,
"amount": 514329.0
}
],
"000657": [
{
"date": "2026-07-09",
"high": 76.0,
"high": 76.46,
"low": 71.06,
"close": 72.67,
"volume": 356301.0,
"amount": 261932.0
"close": 75.99,
"volume": 672849.0,
"amount": 499850.0
}
],
"301308": [
{
"date": "2026-07-09",
"high": 622.1,
"high": 624.3,
"low": 589.73,
"close": 605.89,
"volume": 110818.0,
"amount": 672825.0
"close": 620.0,
"volume": 201711.0,
"amount": 1234713.0
}
],
"000518": [
{
"date": "2026-07-09",
"high": 4.15,
"low": 3.65,
"close": 3.99,
"volume": 1610368.0,
"amount": 63780.0
}
],
"000711": [
{
"date": "2026-07-09",
"high": 5.93,
"low": 5.28,
"close": 5.28,
"volume": 1532289.0,
"amount": 86156.0
}
],
"001309": [
{
"date": "2026-07-09",
"high": 867.88,
"low": 798.88,
"close": 860.48,
"volume": 163888.0,
"amount": 1365118.0
}
],
"002396": [
{
"date": "2026-07-09",
"high": 29.2,
"low": 26.45,
"close": 28.96,
"volume": 1428423.0,
"amount": 400163.0
}
],
"002594": [
{
"date": "2026-07-09",
"high": 87.77,
"low": 85.8,
"close": 86.87,
"volume": 377393.0,
"amount": 327088.0
}
],
"000949": [
{
"date": "2026-07-09",
"high": 5.8,
"low": 5.4,
"close": 5.7,
"volume": 810560.0,
"amount": 45364.0
}
],
"600519": [
{
"date": "2026-07-09",
"high": 1191.99,
"low": 1178.0,
"close": 1182.19,
"volume": 34096.0,
"amount": 403522.0
}
],
"300124": [
{
"date": "2026-07-09",
"high": 64.47,
"low": 62.26,
"close": 64.32,
"volume": 375976.0,
"amount": 238428.0
}
],
"601318": [
{
"date": "2026-07-09",
"high": 49.61,
"low": 48.91,
"close": 49.49,
"volume": 662369.0,
"amount": 325989.0
}
],
"000850": [
{
"date": "2026-07-09",
"high": 3.86,
"low": 3.71,
"close": 3.75,
"volume": 114481.0,
"amount": 4306.0
}
],
"688510": [
{
"date": "2026-07-09",
"high": 24.48,
"low": 22.99,
"close": 24.0,
"volume": 4103947.0,
"amount": 9706.0
}
],
"688513": [
{
"date": "2026-07-09",
"high": 53.8,
"low": 50.39,
"close": 51.5,
"volume": 3296562.0,
"amount": 16996.0
}
],
"688518": [
{
"date": "2026-07-09",
"high": 25.6,
"low": 23.9,
"close": 25.09,
"volume": 20986390.0,
"amount": 51634.0
}
],
"688533": [
{
"date": "2026-07-09",
"high": 21.33,
"low": 20.75,
"close": 21.11,
"volume": 1065153.0,
"amount": 2238.0
}
],
"688566": [
{
"date": "2026-07-09",
"high": 25.8,
"low": 24.95,
"close": 25.29,
"volume": 1948187.0,
"amount": 4942.0
}
],
"688588": [
{
"date": "2026-07-09",
"high": 9.09,
"low": 8.77,
"close": 8.99,
"volume": 3790020.0,
"amount": 3378.0
}
],
"688621": [
{
"date": "2026-07-09",
"high": 50.7,
"low": 47.73,
"close": 49.25,
"volume": 1883753.0,
"amount": 9227.0
}
],
"688696": [
{
"date": "2026-07-09",
"high": 61.94,
"low": 59.95,
"close": 60.81,
"volume": 1112977.0,
"amount": 6762.0
}
],
"688755": [
{
"date": "2026-07-09",
"high": 25.37,
"low": 24.51,
"close": 24.78,
"volume": 898367.0,
"amount": 2224.0
}
],
"688789": [
{
"date": "2026-07-09",
"high": 49.8,
"low": 48.6,
"close": 49.0,
"volume": 1124631.0,
"amount": 5510.0
}
],
"600111": [
{
"date": "2026-07-09",
"high": 45.98,
"low": 41.42,
"close": 42.98,
"volume": 1623791.0,
"amount": 697536.0
}
],
"601101": [
{
"date": "2026-07-09",
"high": 11.96,
"low": 11.15,
"close": 11.3,
"volume": 403168.0,
"amount": 46115.0
}
],
"002371": [
{
"date": "2026-07-09",
"high": 880.98,
"low": 815.0,
"close": 878.43,
"volume": 158615.0,
"amount": 1333947.0
}
],
"603501": [
{
"date": "2026-07-09",
"high": 107.75,
"low": 99.44,
"close": 107.14,
"volume": 474716.0,
"amount": 493524.0
}
],
"688630": [
{
"date": "2026-07-09",
"high": 523.35,
"low": 468.88,
"close": 517.8,
"volume": 5958884.0,
"amount": 293798.0
}
]
}
-221
View File
@@ -1,221 +0,0 @@
#!/usr/bin/env python3
"""
mo_data.py — MoFin 统一数据层(纯 DB)
所有数据从 SQLite 读取。不做 JSON fallback。
JSON 文件已弃用,仅保留为历史备份。
用法:
from mo_data import read_portfolio, read_decisions, read_watchlist
pf = read_portfolio() # 返回和 portfolio.json 一样的 dict 结构
dec = read_decisions() # 返回和 decisions.json 一样的 dict 结构
wl = read_watchlist() # 返回和 watchlist.json 一样的 dict 结构
"""
import sqlite3, json
from datetime import datetime
DB_PATH = '/home/hmo/web-dashboard/data/mofin.db'
def _get_db():
"""获取数据库连接(WAL 模式,15秒超时防并发锁)"""
db = sqlite3.connect(DB_PATH, timeout=15)
db.row_factory = sqlite3.Row
db.execute("PRAGMA journal_mode=WAL")
db.execute("PRAGMA busy_timeout=15000")
return db
# ── portfolio ─────────────────────────────────────────────────────
def read_portfolio():
"""返回 portfolio.json 等价 dict。纯 DB。
总市值从 holdings 实时计算(shares × price,港股 × 汇率),
不信任 portfolio_summary 的存储值,因为可能未及时更新。
"""
db = _get_db()
rows = db.execute(
"SELECT code, name, shares, cost, price, market_value, "
"change_pct, currency, position_pct "
"FROM holdings WHERE is_active=1"
).fetchall()
holdings = []
for r in rows:
h = dict(r)
h['_currency'] = h.get('currency', 'CNY')
holdings.append(h)
sum_row = db.execute("SELECT * FROM portfolio_summary WHERE id=1").fetchone()
summary = dict(sum_row) if sum_row else {}
db.close()
# ── 总市值从 holdings 实时计算 ────────────────────
cash = float(summary.get('cash', 0) or 0)
frozen = float(summary.get('frozen_cash', 0) or 0)
# 获取港股汇率
import subprocess, os as _os
rate = 0.865 # 默认值
try:
hk_rate_py = _os.path.join(_os.path.dirname(_os.path.dirname(__file__)), 'hk_rate.py')
if _os.path.exists(hk_rate_py):
r = subprocess.run(
[_os.path.join(_os.path.dirname(_os.path.dirname(__file__)), 'venv', 'bin', 'python3'),
hk_rate_py, '--rate'],
capture_output=True, text=True, timeout=10
)
if r.returncode == 0 and r.stdout.strip():
rate = float(r.stdout.strip())
except Exception:
pass
total_mv = 0.0
for h in holdings:
p = float(h.get('price', 0) or 0)
s = float(h.get('shares', 0) or 0)
if h.get('currency') == 'HKD' or (len(str(h.get('code',''))) == 5 and str(h.get('code',''))[0] in ('0','1')):
total_mv += s * p * rate
else:
total_mv += s * p
total_mv = round(total_mv, 2)
total_assets = round(total_mv + cash + frozen, 2)
position_pct = round(total_mv / total_assets * 100, 2) if total_assets > 0 else 0
return {
"holdings": holdings,
"total_assets": total_assets,
"total_mv": total_mv,
"stock_value": total_mv,
"cash": cash,
"frozen_cash": frozen,
"position_pct": position_pct,
"currency": summary.get("currency", "CNY"),
"updated_at": summary.get("updated_at", ""),
}
# ── decisions ─────────────────────────────────────────────────────
def _parse_json(val, default):
if val:
try: return json.loads(val)
except: pass
return default
def read_decisions():
"""返回 decisions.json 等价 dict。纯 DB。"""
db = _get_db()
rows = db.execute(
"SELECT code, name, version, price, cost, shares, "
"stop_loss, take_profit, entry_low, entry_high, "
"currency, strategy_type, action, timing_signal, "
"rr_ratio, tech_snapshot, stock_category, sector_context, "
"status, trigger_json, changelog_json, source, reason, "
"created_at, updated_at, "
"avg_price, decision_timestamp, note, quality_check, "
"quality_checked_at, quality_issues_json, position_advice, "
"signal_factors_json, time_horizon, decision_type "
"FROM holding_strategies WHERE status IN ('active','updated') "
"ORDER BY code"
).fetchall()
decisions = []
for r in rows:
d = dict(r)
d['trigger'] = _parse_json(r['trigger_json'], {})
d['changelog'] = _parse_json(r['changelog_json'], [])
d['quality_issues'] = _parse_json(r['quality_issues_json'], {})
d['signal_factors'] = _parse_json(r['signal_factors_json'], [])
d['timestamp'] = r['decision_timestamp'] or r['created_at'] or ''
d['type'] = r['decision_type'] or r['strategy_type'] or '持仓策略'
decisions.append(d)
db.close()
return {
"decisions": decisions,
"total": len(decisions),
"regenerated_at": datetime.now().strftime('%Y-%m-%d %H:%M'),
}
# ── watchlist ─────────────────────────────────────────────────────
def read_watchlist():
"""返回 watchlist.json 等价 dict。纯 DB。"""
db = _get_db()
rows = db.execute(
"SELECT code, name, price, entry_low, entry_high, "
"stop_loss, currency, source, source_detail, notes, "
"added_by, added_at, analysis_json "
"FROM watchlist_stocks WHERE is_active=1"
).fetchall()
stocks = []
for r in rows:
s = dict(r)
s['source_detail'] = _parse_json(r['source_detail'], None)
if r['analysis_json']:
s['analysis'] = _parse_json(r['analysis_json'], {})
else:
s['analysis'] = {}
stocks.append(s)
db.close()
return {
"stocks": stocks,
"updated_at": datetime.now().strftime('%Y-%m-%d %H:%M'),
}
# ── 便捷别名 ───────────────────────────────────────────────────────
def read_portfolio_json():
return read_portfolio()
def read_decisions_json():
return read_decisions()
def read_watchlist_json():
return read_watchlist()
# ── cash_log 写入 ──────────────────────────────────────────────────
def write_cash_log(cash_before, cash_after, frozen_before, frozen_after,
source, note, verified=0):
"""记录现金变更到 cash_log 表。"""
change_amount = round(cash_after - cash_before, 2) if cash_after is not None and cash_before is not None else 0
db = sqlite3.connect(DB_PATH)
try:
cur = db.execute(
"""INSERT INTO cash_log
(timestamp, cash_before, cash_after, frozen_before, frozen_after,
change_amount, source, note, verified)
VALUES (datetime('now','localtime'), ?, ?, ?, ?, ?, ?, ?, ?)""",
(cash_before, cash_after, frozen_before, frozen_after,
change_amount, source, note, verified)
)
db.commit()
return cur.lastrowid
finally:
db.close()
# ── 自检 ───────────────────────────────────────────────────────────
if __name__ == "__main__":
pf = read_portfolio()
print(f"portfolio: {len(pf.get('holdings',[]))} holdings, total_assets={pf.get('total_assets',0)}")
dec = read_decisions()
print(f"decisions: {len(dec.get('decisions',[]))} entries")
wl = read_watchlist()
print(f"watchlist: {len(wl.get('stocks',[]))} stocks")
+354 -276
View File
File diff suppressed because it is too large Load Diff