fix: watchlist_auto_exit/batch_reassess conn加timeout=30+busy_timeout(整点写锁不再崩,t_a44b6e16)
This commit is contained in:
@@ -25,7 +25,8 @@ STALE_HOURS = 20 # 分析超过20小时视为过期,需要重评
|
||||
|
||||
def has_llm_analysis(code):
|
||||
"""检查是否为LLM生成的12维分析(>500字)"""
|
||||
conn = sqlite3.connect(DB)
|
||||
conn = sqlite3.connect(DB, timeout=30)
|
||||
conn.execute("PRAGMA busy_timeout=30000")
|
||||
r = conn.execute("SELECT LENGTH(full_analysis) FROM holding_strategies WHERE code=? AND status='active'", (code,)).fetchone()
|
||||
conn.close()
|
||||
return r and r[0] and r[0] > 500
|
||||
@@ -36,7 +37,7 @@ def in_cooldown(code):
|
||||
"""冷却期检查(--force 时全量强制重评)"""
|
||||
if FORCE_REASSESS:
|
||||
return False
|
||||
conn = sqlite3.connect(DB)
|
||||
conn = sqlite3.connect(DB, timeout=30)
|
||||
r = conn.execute("SELECT reassessed_at FROM holding_strategies WHERE code=? AND status='active'", (code,)).fetchone()
|
||||
conn.close()
|
||||
if not r or not r[0]:
|
||||
@@ -49,8 +50,7 @@ def in_cooldown(code):
|
||||
return False
|
||||
|
||||
def analysis_stale(code, force_today=False):
|
||||
"""分析是否过期(>STALE_HOURS 或 force_today 时今早4点前未重评)"""
|
||||
conn = sqlite3.connect(DB)
|
||||
"""分析是否过期(>STALE_HOURS 或 force_today 时今早4点前未重评)"""sqlite3.connect(DB, timeout=30).connect(DB)
|
||||
r = conn.execute("SELECT reassessed_at FROM holding_strategies WHERE code=? AND status='active'", (code,)).fetchone()
|
||||
conn.close()
|
||||
if not r or not r[0]:
|
||||
@@ -66,8 +66,7 @@ def analysis_stale(code, force_today=False):
|
||||
|
||||
def get_portfolio():
|
||||
"""从 portfolio_summary 读实时现金/总资产(不再硬编码)"""
|
||||
try:
|
||||
conn = sqlite3.connect(DB)
|
||||
sqlite3.connect(DB, timeout=30)nn = sqlite3.connect(DB)
|
||||
r = conn.execute("SELECT cash, total_assets FROM portfolio_summary WHERE id=1").fetchone()
|
||||
conn.close()
|
||||
if r and r[1]:
|
||||
@@ -80,7 +79,7 @@ def collect_data(code):
|
||||
"""收集最新数据(含完整策略原文)"""
|
||||
data = {"code": code}
|
||||
|
||||
# 从DB读策略(含 full_analysis / changelog_json / position_advice)
|
||||
# 从DB读策略(含 full_analysis / changelogsqlite3.connect(DB, timeout=30)vice)
|
||||
conn = sqlite3.connect(DB)
|
||||
r = conn.execute("SELECT name, entry_low, entry_high, stop_loss, take_profit, timing_signal, action, rr_ratio, tech_snapshot, sector_context, stock_category, full_analysis, changelog_json, reassessed_at, position_advice FROM holding_strategies WHERE code=? AND status='active'", (code,)).fetchone()
|
||||
if r:
|
||||
@@ -132,8 +131,7 @@ def collect_data(code):
|
||||
# 未映射的股票明确标注"行业未映射"(不让大盘指标伪装成行业信息)
|
||||
_sector_ctx = data.get('sector_context', '') or ''
|
||||
if (not _sector_ctx) or _sector_ctx.startswith('大盘上涨比') or len(_sector_ctx) < 4:
|
||||
_resolved = ""
|
||||
try:
|
||||
sqlite3.connect(DB, timeout=30) try:
|
||||
_sdb = sqlite3.connect(DB)
|
||||
_sr = _sdb.execute("SELECT sector_name FROM stock_sectors WHERE code=? LIMIT 1", (code,)).fetchone()
|
||||
_sdb.close()
|
||||
@@ -142,7 +140,7 @@ def collect_data(code):
|
||||
except Exception:
|
||||
pass
|
||||
_sector_ctx = _resolved if _resolved else "行业未映射(仅大盘环境参考)"
|
||||
data['sector_context'] = _sector_ctx
|
||||
data['sectsqlite3.connect(DB, timeout=30)tor_ctx
|
||||
# 大盘
|
||||
try:
|
||||
conn = sqlite3.connect(DB)
|
||||
@@ -291,8 +289,7 @@ def build_prompt(data):
|
||||
f"禁止出现「已持仓者」视角的建议。")
|
||||
|
||||
# ── 换仓上下文(2026-07-24 老爸:现金不足时给出具体换股建议)──
|
||||
_rotation_context = ""
|
||||
if not data.get('held'):
|
||||
_rotation_csqlite3.connect(DB, timeout=30)not data.get('held'):
|
||||
try:
|
||||
_rc = sqlite3.connect(DB)
|
||||
_weak = _rc.execute("""
|
||||
@@ -500,8 +497,7 @@ def parse_response(text):
|
||||
def save_result(code, full_text, parsed, ta_levels=None):
|
||||
"""保存LLM结果到DB(先快照再UPDATE)。空分析拒绝写入。
|
||||
ta_levels: collect_data 计算的确定性技术位,用于止损锚定校验。"""
|
||||
if not (full_text or "").strip():
|
||||
print(f" \u274c 拒绝写入空分析(LLM输出为空,保护已有数据)")
|
||||
if not (full_text or "").stsqlite3.connect(DB, timeout=30)t(f" \u274c 拒绝写入空分析(LLM输出为空,保护已有数据)")
|
||||
return
|
||||
conn = sqlite3.connect(DB)
|
||||
now = datetime.now().isoformat()
|
||||
@@ -684,7 +680,7 @@ def main():
|
||||
idx = sys.argv.index("--code")
|
||||
codes = [sys.argv[idx+1]]
|
||||
else:
|
||||
# 按类型筛选 active 策略
|
||||
sqlite3.connect(DB, timeout=30)略
|
||||
type_map = {"holding": "持仓策略", "watchlist": "自选策略"}
|
||||
conn = sqlite3.connect(DB)
|
||||
if dtype in type_map:
|
||||
|
||||
Reference in New Issue
Block a user