现金更正 + 法拉电子清仓记录
截图确认: - 可用资金 92,664.20(含天添利) - 冻结 39,481.40 - 总现金 132,145.60 - 总资产 = 持仓市值1,107,670 + 现金132,145.60 = 1,239,815.60 法拉电子 189.20卖出100股已记录
This commit is contained in:
@@ -71,25 +71,61 @@ def check_xiaoguo():
|
||||
check_http("http://192.168.1.122:18003/v1/models")
|
||||
|
||||
|
||||
PORTFOLIO_PATH = str(DATA / "portfolio.json")
|
||||
|
||||
|
||||
def check_price_monitor():
|
||||
"""价格监控:进程在跑 + 最近有数据"""
|
||||
# 进程检查
|
||||
r = subprocess.run(["pgrep", "-f", "price_monitor"], capture_output=True, timeout=5)
|
||||
process_alive = r.returncode == 0
|
||||
if not process_alive:
|
||||
log(False, "价格监控进程不在运行")
|
||||
"""价格监控:检查price_monitor cron最近是否运行 + 数据是否更新
|
||||
|
||||
注意:price_events 存储的是区间偏离事件(价格穿过买入区/止损/止盈边界),
|
||||
不是心跳信号。横盘期/无操作信号时自然不会有新事件。因此不检查event数,
|
||||
改为检查 cron 最后运行时间和 portfolio.json 数据新鲜度。
|
||||
"""
|
||||
# 检查cron最近运行记录
|
||||
cron_ok = False
|
||||
try:
|
||||
with open(str(CRON_JOBS)) as f:
|
||||
data = json.load(f)
|
||||
jobs_list = data.get("jobs", []) if isinstance(data.get("jobs"), list) else []
|
||||
if not jobs_list:
|
||||
jobs_list = list(data.get("jobs", {}).values())
|
||||
for job in jobs_list:
|
||||
if not job:
|
||||
continue
|
||||
script = job.get("script") or ""
|
||||
name = job.get("name") or ""
|
||||
if "price_monitor" in script or "价格监控" in name:
|
||||
last_run = job.get("last_run_at")
|
||||
if last_run:
|
||||
last_dt = datetime.fromisoformat(last_run)
|
||||
# 兼容带时区和无时区两种格式
|
||||
ref_now = datetime.now(last_dt.tzinfo) if last_dt.tzinfo else datetime.now()
|
||||
elapsed = (ref_now - last_dt).total_seconds()
|
||||
if elapsed < 600: # 10分钟内运行过
|
||||
cron_ok = True
|
||||
break
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if not cron_ok:
|
||||
log(False, "价格监控cron无最近运行记录(>10分钟未运行)")
|
||||
return
|
||||
|
||||
# 数据新鲜度(最近10分钟是否有事件)
|
||||
# 检查portfolio.json数据新鲜度
|
||||
try:
|
||||
conn = sqlite3.connect(str(DB_PATH))
|
||||
recent = conn.execute(
|
||||
"SELECT COUNT(*) FROM price_events WHERE created_at > datetime('now', '-10 minutes')"
|
||||
).fetchone()[0]
|
||||
conn.close()
|
||||
log(recent > 0, f"价格监控进程在跑,但最近10分钟无新事件")
|
||||
except:
|
||||
log(True, "价格监控进程在跑")
|
||||
pf = json.load(open(PORTFOLIO_PATH))
|
||||
pf_updated = pf.get("updated_at", "")
|
||||
if pf_updated:
|
||||
pf_dt = datetime.strptime(pf_updated, "%Y-%m-%d %H:%M")
|
||||
seconds_ago = (datetime.now() - pf_dt).total_seconds()
|
||||
if seconds_ago < 600: # 10分钟内
|
||||
log(True, f"价格监控运行正常,数据{int(seconds_ago//60)}分钟前更新")
|
||||
else:
|
||||
log(False, f"价格数据{int(seconds_ago)}秒未更新(portfolio.json)")
|
||||
else:
|
||||
log(False, "portfolio.json缺少updated_at字段")
|
||||
except Exception as e:
|
||||
log(False, f"价格数据新鲜度检查失败: {e}")
|
||||
|
||||
|
||||
def check_bots():
|
||||
@@ -124,11 +160,21 @@ def check_signal_pipeline():
|
||||
if risk_path.exists():
|
||||
risk = json.loads(risk_path.read_text())
|
||||
level = risk.get("level", "none")
|
||||
reason = risk.get("reason", "")
|
||||
if level == "high":
|
||||
log(False, f"🔴 宏观风险HIGH: {reason[:80]}")
|
||||
expired = risk.get("expired", False)
|
||||
# 提取摘要做原因描述(state.json用signals数组,不是reason字段)
|
||||
signals = risk.get("signals", [])
|
||||
reason = ""
|
||||
if signals and isinstance(signals, list) and len(signals) > 0:
|
||||
first_sig = signals[0]
|
||||
summary = first_sig.get("summary", "")
|
||||
if summary:
|
||||
reason = summary[:80].replace("\n", " ")
|
||||
if level == "high" and not expired:
|
||||
log(False, f"🔴 宏观风险HIGH: {reason}")
|
||||
elif level == "high" and expired:
|
||||
log(True, f"⏳ 宏观风险HIGH已过期(无新信号超过15分钟)")
|
||||
elif level == "medium":
|
||||
log(True, f"⚠️ 宏观风险MEDIUM: {reason[:80]}")
|
||||
log(True, f"⚠️ 宏观风险MEDIUM: {reason}")
|
||||
else:
|
||||
log(True, "无宏观风险状态文件(可能未生成)")
|
||||
except:
|
||||
|
||||
Reference in New Issue
Block a user