feat: 持仓保证金占比与止盈止损自动委托守护

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-24 14:20:15 +08:00
parent 23d0f1d6fa
commit 73b9dfdfdb
8 changed files with 751 additions and 60 deletions
+26 -3
View File
@@ -30,10 +30,12 @@ def refresh_recommend_cache(
conn,
capital: float,
quote_fn: Callable[[str], Optional[dict]],
*,
trading_mode: str = "simulation",
) -> list[dict]:
"""后台拉行情、筛选并写入数据库。"""
ensure_recommend_tables(conn)
all_rows = list_product_recommendations(capital, quote_fn)
all_rows = list_product_recommendations(capital, quote_fn, trading_mode=trading_mode)
rows = filter_affordable_recommendations(all_rows)
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
conn.execute(
@@ -49,18 +51,39 @@ def refresh_recommend_cache(
return rows
def recommend_cache_stale(updated_at: Optional[str], *, now: Optional[datetime] = None) -> bool:
"""缓存是否不是今日更新(需重新拉行情计算)。"""
if not updated_at:
return True
try:
cached_day = datetime.strptime(str(updated_at)[:10], "%Y-%m-%d").date()
except ValueError:
return True
today = (now or datetime.now()).date()
return cached_day != today
def load_recommend_cache(conn) -> dict:
"""优先从数据库读取推荐列表。"""
ensure_recommend_tables(conn)
row = conn.execute("SELECT capital, rows_json, updated_at FROM product_recommend_cache WHERE id=1").fetchone()
if not row:
return {"capital": 0.0, "rows": [], "updated_at": None}
return {"capital": 0.0, "rows": [], "updated_at": None, "stale": True}
try:
rows = json.loads(row["rows_json"] or "[]")
except (TypeError, ValueError, json.JSONDecodeError):
rows = []
updated_at = row["updated_at"]
return {
"capital": float(row["capital"] or 0),
"rows": rows if isinstance(rows, list) else [],
"updated_at": row["updated_at"],
"updated_at": updated_at,
"stale": recommend_cache_stale(updated_at),
}
def recommend_payload(conn, *, live_capital: float) -> dict:
"""读取缓存并附带当前权益(展示用,可能与缓存计算时不同)。"""
payload = load_recommend_cache(conn)
payload["capital"] = float(live_capital or 0)
return payload