migrate: remove JSON, DB-only — mo_data, server, scripts, prompts (27 files)
This commit is contained in:
+65
-31
@@ -141,33 +141,44 @@ def init_all_tables(conn: sqlite3.Connection):
|
||||
|
||||
-- 持仓策略(对应 decisions.json decisions[])
|
||||
CREATE TABLE IF NOT EXISTS holding_strategies (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
code TEXT NOT NULL REFERENCES holdings(code),
|
||||
name TEXT,
|
||||
version INTEGER DEFAULT 1,
|
||||
price REAL, -- 当前价格
|
||||
cost REAL, -- 成本价
|
||||
shares INTEGER DEFAULT 0,
|
||||
stop_loss REAL,
|
||||
take_profit REAL,
|
||||
entry_low REAL,
|
||||
entry_high REAL,
|
||||
currency TEXT NOT NULL DEFAULT 'CNY' CHECK(currency IN ('CNY','HKD')),
|
||||
strategy_type TEXT DEFAULT 'holding',
|
||||
action TEXT, -- 买入/持有/卖出/观望
|
||||
timing_signal TEXT, -- 时机信号
|
||||
rr_ratio REAL, -- 盈亏比
|
||||
tech_snapshot TEXT, -- 技术面快照
|
||||
stock_category TEXT, -- 股票分类
|
||||
sector_context TEXT, -- 板块背景
|
||||
status TEXT DEFAULT 'active', -- active/updated/closed
|
||||
trigger_json TEXT, -- trigger JSON (entry_zone/stop_loss/take_profit_zone)
|
||||
changelog_json TEXT, -- changelog JSON 数组
|
||||
source TEXT,
|
||||
reason TEXT,
|
||||
created_at TEXT DEFAULT (datetime('now','localtime')),
|
||||
updated_at TEXT,
|
||||
superseded_at TEXT
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
code TEXT NOT NULL REFERENCES holdings(code),
|
||||
name TEXT,
|
||||
version INTEGER DEFAULT 1,
|
||||
price REAL,
|
||||
cost REAL,
|
||||
shares INTEGER DEFAULT 0,
|
||||
stop_loss REAL,
|
||||
take_profit REAL,
|
||||
entry_low REAL,
|
||||
entry_high REAL,
|
||||
currency TEXT NOT NULL DEFAULT 'CNY' CHECK(currency IN ('CNY','HKD')),
|
||||
strategy_type TEXT DEFAULT 'holding',
|
||||
action TEXT,
|
||||
timing_signal TEXT,
|
||||
rr_ratio REAL,
|
||||
tech_snapshot TEXT,
|
||||
stock_category TEXT,
|
||||
sector_context TEXT,
|
||||
status TEXT DEFAULT 'active',
|
||||
trigger_json TEXT,
|
||||
changelog_json TEXT,
|
||||
source TEXT,
|
||||
reason TEXT,
|
||||
created_at TEXT DEFAULT (datetime('now','localtime')),
|
||||
updated_at TEXT,
|
||||
superseded_at TEXT,
|
||||
-- 以下为 decisions.json→DB 迁移新增列
|
||||
avg_price REAL,
|
||||
decision_timestamp TEXT,
|
||||
note TEXT,
|
||||
quality_check TEXT,
|
||||
quality_checked_at TEXT,
|
||||
quality_issues_json TEXT,
|
||||
position_advice TEXT,
|
||||
signal_factors_json TEXT,
|
||||
time_horizon TEXT,
|
||||
decision_type TEXT
|
||||
);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_strategy_code ON holding_strategies(code);
|
||||
CREATE INDEX IF NOT EXISTS idx_strategy_status ON holding_strategies(status);
|
||||
@@ -954,7 +965,14 @@ def write_holding_strategy(conn, code: str, name: str, data: dict) -> tuple[bool
|
||||
"""写入持仓策略(替代 decisions.json 单条写入)。data 必须包含 currency。"""
|
||||
try:
|
||||
currency = data.get('currency', 'CNY')
|
||||
# DELETE + INSERT(避免依赖 code 的 UNIQUE 约束)
|
||||
# Serialize JSON fields
|
||||
import json as _json
|
||||
trigger_j = _json.dumps(data.get('trigger', {}), ensure_ascii=False) if isinstance(data.get('trigger'), dict) else str(data.get('trigger', '{}'))
|
||||
changelog_j = _json.dumps(data.get('changelog', []), ensure_ascii=False) if isinstance(data.get('changelog'), list) else str(data.get('changelog', '[]'))
|
||||
quality_issues_j = _json.dumps(data.get('quality_issues', {}), ensure_ascii=False) if isinstance(data.get('quality_issues'), dict) else data.get('quality_issues_json', '')
|
||||
signal_factors_j = _json.dumps(data.get('signal_factors', []), ensure_ascii=False) if isinstance(data.get('signal_factors'), list) else data.get('signal_factors_json', '')
|
||||
|
||||
# DELETE + INSERT
|
||||
conn.execute("DELETE FROM holding_strategies WHERE code=?", (code,))
|
||||
conn.execute("""
|
||||
INSERT INTO holding_strategies
|
||||
@@ -962,8 +980,13 @@ def write_holding_strategy(conn, code: str, name: str, data: dict) -> tuple[bool
|
||||
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, updated_at)
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,datetime('now','localtime'))
|
||||
source, reason, updated_at,
|
||||
avg_price, decision_timestamp, note, quality_check,
|
||||
quality_checked_at, quality_issues_json, position_advice,
|
||||
signal_factors_json, time_horizon, decision_type)
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,
|
||||
datetime('now','localtime'),
|
||||
?,?,?,?,?,?,?,?,?)
|
||||
""", (
|
||||
code, name,
|
||||
data.get('version', 1), data.get('price'), data.get('cost'),
|
||||
@@ -973,8 +996,19 @@ def write_holding_strategy(conn, code: str, name: str, data: dict) -> tuple[bool
|
||||
data.get('timing_signal'), data.get('rr_ratio'),
|
||||
data.get('tech_snapshot'), data.get('stock_category'),
|
||||
data.get('sector_context'), data.get('status', 'active'),
|
||||
data.get('trigger_json'), data.get('changelog_json'),
|
||||
trigger_j, changelog_j,
|
||||
data.get('source'), data.get('reason'),
|
||||
# new columns
|
||||
data.get('avg_price', 0),
|
||||
data.get('timestamp') or data.get('created_at', ''),
|
||||
data.get('note', ''),
|
||||
data.get('quality_check', ''),
|
||||
data.get('quality_checked_at', ''),
|
||||
quality_issues_j,
|
||||
data.get('position_advice', ''),
|
||||
signal_factors_j,
|
||||
data.get('time_horizon', ''),
|
||||
data.get('type', data.get('strategy_type', 'holding')),
|
||||
))
|
||||
conn.commit()
|
||||
return True, f"策略 {code} 已写入"
|
||||
|
||||
Reference in New Issue
Block a user