自选股自动重评机制+000850华茂股份9维分析
fix: per_stock_reassess 现在支持自选股(不在decisions.json)触发的重评 - 不在decisions_map的code→查watchlist_stocks表构建entry - 重评完成后同步回watchlist_stocks表 - is_watchlist=True传给reassess_strategy确保正确分类 fix: stale_detector的[AUTO_REASSESS]路径现在能真正触发自选股重评 - 价格偏离买入区中心>15%→触发per_stock_reassess - 结果写回DB watchlist_stocks表+decisions.json feat: 000850华茂股份完整9维分析 - 横: 大盘偏弱但个股独立/纺织板块/金融资产折价 - 纵: PE72.79虚高(被金融收益摊薄)/PB0.80破净(安全垫) - 消息面: 7/16临时股东会催化 - 技术面: MA5>MA10>MA20多头初成/缩量回踩健康 - 资金流: 量比1.21放量上攻后缩量回踩(正常) - 买入区3.70~3.90现价3.81在区内→策略有效维持 - 止损3.50/止盈4.30/RR=1.6
This commit is contained in:
@@ -34,9 +34,33 @@ def main():
|
||||
for code in codes:
|
||||
entry = decisions_map.get(code)
|
||||
if not entry:
|
||||
print(f"[SKIP] {code}: 不在 decisions.json 中")
|
||||
errors += 1
|
||||
continue
|
||||
# 可能是不在 decisions.json 的自选股 → 从 DB watchlist_stocks 构建entry
|
||||
import sqlite3
|
||||
_db = sqlite3.connect('/home/hmo/web-dashboard/data/mofin.db')
|
||||
_db.row_factory = sqlite3.Row
|
||||
_wl = _db.execute("SELECT * FROM watchlist_stocks WHERE code=? AND is_active=1", (code,)).fetchone()
|
||||
_db.close()
|
||||
if _wl:
|
||||
entry = {
|
||||
"code": code,
|
||||
"name": _wl["name"],
|
||||
"price": _wl["price"] or 0,
|
||||
"cost": 0,
|
||||
"shares": 0,
|
||||
"entry_low": _wl["entry_low"] or 0,
|
||||
"entry_high": _wl["entry_high"] or 0,
|
||||
"stop_loss": _wl["stop_loss"] or 0,
|
||||
"take_profit": 0,
|
||||
"action": "",
|
||||
"type": "自选策略",
|
||||
"is_watchlist": True,
|
||||
"analysis": json.loads(_wl["analysis_json"]) if _wl["analysis_json"] else {}
|
||||
}
|
||||
print(f"[WL] {code} {_wl['name']}: 从自选表构建entry")
|
||||
if not entry:
|
||||
print(f"[SKIP] {code}: 不在 decisions.json 或 watchlist_stocks 中")
|
||||
errors += 1
|
||||
continue
|
||||
|
||||
try:
|
||||
# Always fetch live price for accurate reassessment
|
||||
@@ -156,6 +180,40 @@ def main():
|
||||
with open(DECISIONS_PATH, "w") as f:
|
||||
json.dump(raw, f, ensure_ascii=False, indent=2)
|
||||
|
||||
# 同步自选股更新回 watchlist_stocks 表
|
||||
try:
|
||||
import sqlite3
|
||||
_db2 = sqlite3.connect('/home/hmo/web-dashboard/data/mofin.db')
|
||||
for _code in codes:
|
||||
_entry = decisions_map.get(_code)
|
||||
if _entry and _entry.get("is_watchlist"):
|
||||
_db2.execute("""
|
||||
UPDATE watchlist_stocks
|
||||
SET entry_low=?, entry_high=?, stop_loss=?, price=?,
|
||||
analysis_json=json(?)
|
||||
WHERE code=? AND is_active=1
|
||||
""", (
|
||||
_entry.get("entry_low", 0),
|
||||
_entry.get("entry_high", 0),
|
||||
_entry.get("stop_loss", 0),
|
||||
_entry.get("price", 0),
|
||||
json.dumps({
|
||||
"action": _entry.get("action",""),
|
||||
"take_profit": _entry.get("take_profit", 0),
|
||||
"stop_loss": _entry.get("stop_loss", 0),
|
||||
"tech_snapshot": _entry.get("tech_snapshot", ""),
|
||||
"rr": _entry.get("rr_ratio", 0),
|
||||
"reassessed_at": datetime.now().strftime("%Y-%m-%d")
|
||||
}, ensure_ascii=False),
|
||||
_code
|
||||
))
|
||||
_db2.commit()
|
||||
_db2.close()
|
||||
if any(e.get("is_watchlist") for e in [decisions_map.get(c) for c in codes] if e):
|
||||
print("[SYNC] 自选股策略已同步回 watchlist_stocks 表")
|
||||
except Exception as e:
|
||||
print(f"[SYNC FAIL] watchlist_stocks 同步失败: {e}", file=sys.stderr)
|
||||
|
||||
print(f"[DONE] {ok}成功 {skipped}跳过 {errors}失败")
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user