修复翻倍出场/翻倍提醒可能重复推微信:done状态停扫,提醒标记立即提交。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -138,6 +138,11 @@ def run_options_profit_alerts(
|
|||||||
f"UPDATE options_trades SET profit_alert_sent = 1 WHERE id IN ({','.join('?' * len(bucket['ids']))})",
|
f"UPDATE options_trades SET profit_alert_sent = 1 WHERE id IN ({','.join('?' * len(bucket['ids']))})",
|
||||||
tuple(bucket["ids"]),
|
tuple(bucket["ids"]),
|
||||||
)
|
)
|
||||||
|
# 立即提交,避免后续目标/翻倍/同步异常回滚后每轮重推
|
||||||
|
try:
|
||||||
|
conn.commit()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
sent += 1
|
sent += 1
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -125,10 +125,7 @@ def profit_exit_by_inst(conn: sqlite3.Connection) -> dict[str, dict[str, Any]]:
|
|||||||
SELECT inst_id, profit_exit_enabled, profit_exit_mult, profit_exit_state
|
SELECT inst_id, profit_exit_enabled, profit_exit_mult, profit_exit_state
|
||||||
FROM options_trades
|
FROM options_trades
|
||||||
WHERE status = 'open'
|
WHERE status = 'open'
|
||||||
AND (
|
AND COALESCE(profit_exit_state, 'idle') IN ('active', 'closing')
|
||||||
CAST(COALESCE(profit_exit_enabled, 0) AS INTEGER) = 1
|
|
||||||
OR COALESCE(profit_exit_state, 'idle') IN ('active', 'closing')
|
|
||||||
)
|
|
||||||
ORDER BY id DESC
|
ORDER BY id DESC
|
||||||
"""
|
"""
|
||||||
).fetchall()
|
).fetchall()
|
||||||
@@ -139,14 +136,17 @@ def profit_exit_by_inst(conn: sqlite3.Connection) -> dict[str, dict[str, Any]]:
|
|||||||
continue
|
continue
|
||||||
enabled = int(r["profit_exit_enabled"] or 0) == 1
|
enabled = int(r["profit_exit_enabled"] or 0) == 1
|
||||||
state = str(r["profit_exit_state"] or "idle")
|
state = str(r["profit_exit_state"] or "idle")
|
||||||
if not enabled and state not in ("active", "closing"):
|
if state not in ("active", "closing"):
|
||||||
|
continue
|
||||||
|
# closing 需续跑直到全平;active 需仍开启
|
||||||
|
if state == "active" and not enabled:
|
||||||
continue
|
continue
|
||||||
mult = normalize_profit_exit_mult(r["profit_exit_mult"], default=1.0)
|
mult = normalize_profit_exit_mult(r["profit_exit_mult"], default=1.0)
|
||||||
out[inst] = {
|
out[inst] = {
|
||||||
"inst_id": inst,
|
"inst_id": inst,
|
||||||
"profit_exit_enabled": enabled or state in ("active", "closing"),
|
"profit_exit_enabled": enabled or state == "closing",
|
||||||
"profit_exit_mult": mult,
|
"profit_exit_mult": mult,
|
||||||
"profit_exit_state": state if state in ("active", "closing") else ("active" if enabled else "idle"),
|
"profit_exit_state": state,
|
||||||
"required_recycle": None,
|
"required_recycle": None,
|
||||||
}
|
}
|
||||||
for inst, info in out.items():
|
for inst, info in out.items():
|
||||||
@@ -318,9 +318,7 @@ def run_options_profit_exits(
|
|||||||
continue
|
continue
|
||||||
pos = pos_by_inst.get(inst_id)
|
pos = pos_by_inst.get(inst_id)
|
||||||
if not pos:
|
if not pos:
|
||||||
# 持仓已平:收尾
|
# 本轮暂无持仓:不改状态(避免接口抖动误标 done);真正平完由 sync 收尾
|
||||||
_mark_state(conn, inst_id, "done")
|
|
||||||
_commit(conn)
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
state = str(info.get("profit_exit_state") or "active")
|
state = str(info.get("profit_exit_state") or "active")
|
||||||
@@ -329,10 +327,25 @@ def run_options_profit_exits(
|
|||||||
if prem is None or prem <= 0:
|
if prem is None or prem <= 0:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# done/idle 不再扫描(查询层已过滤;此处双保险)
|
||||||
|
if state in ("done", "idle"):
|
||||||
|
continue
|
||||||
|
|
||||||
if state == "closing":
|
if state == "closing":
|
||||||
result = close_fn(inst_id)
|
result = close_fn(inst_id)
|
||||||
if result.get("already_flat") or _result_fully_done(result):
|
if result.get("already_flat") or _result_fully_done(result):
|
||||||
_mark_state(conn, inst_id, "done")
|
_mark_state(conn, inst_id, "done")
|
||||||
|
try:
|
||||||
|
conn.execute(
|
||||||
|
"""
|
||||||
|
UPDATE options_trades
|
||||||
|
SET profit_exit_enabled = 0
|
||||||
|
WHERE inst_id = ? AND status = 'open'
|
||||||
|
""",
|
||||||
|
(inst_id,),
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
_commit(conn)
|
_commit(conn)
|
||||||
else:
|
else:
|
||||||
_mark_state(conn, inst_id, "closing")
|
_mark_state(conn, inst_id, "closing")
|
||||||
@@ -356,6 +369,17 @@ def run_options_profit_exits(
|
|||||||
result = close_fn(inst_id)
|
result = close_fn(inst_id)
|
||||||
if result.get("already_flat"):
|
if result.get("already_flat"):
|
||||||
_mark_state(conn, inst_id, "done")
|
_mark_state(conn, inst_id, "done")
|
||||||
|
try:
|
||||||
|
conn.execute(
|
||||||
|
"""
|
||||||
|
UPDATE options_trades
|
||||||
|
SET profit_exit_enabled = 0
|
||||||
|
WHERE inst_id = ? AND status = 'open'
|
||||||
|
""",
|
||||||
|
(inst_id,),
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
_commit(conn)
|
_commit(conn)
|
||||||
continue
|
continue
|
||||||
if not result.get("ok"):
|
if not result.get("ok"):
|
||||||
@@ -365,6 +389,19 @@ def run_options_profit_exits(
|
|||||||
|
|
||||||
done = _result_fully_done(result)
|
done = _result_fully_done(result)
|
||||||
_mark_state(conn, inst_id, "done" if done else "closing")
|
_mark_state(conn, inst_id, "done" if done else "closing")
|
||||||
|
if done:
|
||||||
|
try:
|
||||||
|
conn.execute(
|
||||||
|
"""
|
||||||
|
UPDATE options_trades
|
||||||
|
SET profit_exit_enabled = 0
|
||||||
|
WHERE inst_id = ? AND status = 'open'
|
||||||
|
""",
|
||||||
|
(inst_id,),
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
# 先落库再推送:同一笔只推一次;closing 重试不再进本分支
|
||||||
_commit(conn)
|
_commit(conn)
|
||||||
triggered += 1
|
triggered += 1
|
||||||
_notify_profit_exit_close(
|
_notify_profit_exit_close(
|
||||||
|
|||||||
Reference in New Issue
Block a user