修复期权到期结算漏推企业微信:页面同步与模拟盘结算一并通知。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -371,9 +371,47 @@ def sync_open_options_trades(
|
|||||||
)
|
)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
if notify_cfg is not None:
|
||||||
|
_notify_recent_unsent_expiry_closes(conn, notify_cfg)
|
||||||
return updated
|
return updated
|
||||||
|
|
||||||
|
|
||||||
|
def _notify_recent_unsent_expiry_closes(
|
||||||
|
conn: sqlite3.Connection,
|
||||||
|
notify_cfg: dict[str, Any],
|
||||||
|
*,
|
||||||
|
within_hours: float = 48.0,
|
||||||
|
) -> None:
|
||||||
|
"""页面同步曾漏推时,补发近期到期结算."""
|
||||||
|
try:
|
||||||
|
from lib.options.options_notify_lib import notify_options_close_trade_ids
|
||||||
|
from lib.options.options_time_lib import options_wall_clock_to_ms
|
||||||
|
|
||||||
|
now_ms = int(time.time() * 1000)
|
||||||
|
by_inst: dict[str, list[int]] = {}
|
||||||
|
rows = conn.execute(
|
||||||
|
"""
|
||||||
|
SELECT id, inst_id, closed_at
|
||||||
|
FROM options_trades
|
||||||
|
WHERE status = 'closed'
|
||||||
|
AND COALESCE(wechat_close_sent, 0) = 0
|
||||||
|
AND COALESCE(signal_note, '') = '到期结算'
|
||||||
|
ORDER BY id DESC
|
||||||
|
LIMIT 20
|
||||||
|
"""
|
||||||
|
).fetchall()
|
||||||
|
for r in rows:
|
||||||
|
closed_ms = options_wall_clock_to_ms(r["closed_at"])
|
||||||
|
if closed_ms is None or now_ms - int(closed_ms) > float(within_hours) * 3600 * 1000:
|
||||||
|
continue
|
||||||
|
inst = str(r["inst_id"] or "")
|
||||||
|
by_inst.setdefault(inst, []).append(int(r["id"]))
|
||||||
|
for ids in by_inst.values():
|
||||||
|
notify_options_close_trade_ids(notify_cfg, conn, ids, reason="到期结算")
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def reconcile_live_open_trades(
|
def reconcile_live_open_trades(
|
||||||
conn: sqlite3.Connection,
|
conn: sqlite3.Connection,
|
||||||
*,
|
*,
|
||||||
|
|||||||
@@ -58,6 +58,38 @@ def ensure_options_notify_columns(conn: sqlite3.Connection) -> None:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
_BOUND_NOTIFY_CFG: dict[str, Any] | None = None
|
||||||
|
|
||||||
|
|
||||||
|
def bind_options_notify_cfg(cfg: dict[str, Any] | None) -> None:
|
||||||
|
global _BOUND_NOTIFY_CFG
|
||||||
|
_BOUND_NOTIFY_CFG = cfg
|
||||||
|
|
||||||
|
|
||||||
|
def active_options_notify_cfg(cfg: dict[str, Any] | None = None) -> dict[str, Any]:
|
||||||
|
if cfg is not None and callable(cfg.get("send_wechat")):
|
||||||
|
return cfg
|
||||||
|
if _BOUND_NOTIFY_CFG is not None and callable(_BOUND_NOTIFY_CFG.get("send_wechat")):
|
||||||
|
return _BOUND_NOTIFY_CFG
|
||||||
|
import os
|
||||||
|
|
||||||
|
from lib.common.wechat_notify_lib import send_wechat_webhook
|
||||||
|
|
||||||
|
webhook = (os.getenv("WECHAT_WEBHOOK") or "").strip()
|
||||||
|
try:
|
||||||
|
timeout = int(float(os.getenv("WECHAT_TIMEOUT_SECONDS") or "10"))
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
timeout = 10
|
||||||
|
label = (
|
||||||
|
os.getenv("OKX_OPTIONS_ACCOUNT_LABEL") or os.getenv("OKX_ACCOUNT_LABEL") or "OKX期权"
|
||||||
|
).strip()
|
||||||
|
|
||||||
|
def send(content: str) -> None:
|
||||||
|
send_wechat_webhook(webhook, content, timeout=timeout)
|
||||||
|
|
||||||
|
return {"send_wechat": send, "account_label": label}
|
||||||
|
|
||||||
|
|
||||||
def notify_options_send(cfg: dict[str, Any], content: str) -> bool:
|
def notify_options_send(cfg: dict[str, Any], content: str) -> bool:
|
||||||
send: Optional[Callable[[str], Any]] = cfg.get("send_wechat")
|
send: Optional[Callable[[str], Any]] = cfg.get("send_wechat")
|
||||||
if not callable(send):
|
if not callable(send):
|
||||||
|
|||||||
@@ -63,6 +63,12 @@ def install_options_trading(app: Flask, repo_root: str, app_module: Any) -> None
|
|||||||
patch_options_cfg(cfg)
|
patch_options_cfg(cfg)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
try:
|
||||||
|
from lib.options.options_notify_lib import bind_options_notify_cfg
|
||||||
|
|
||||||
|
bind_options_notify_cfg(cfg)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
app.extensions["options_cfg"] = cfg
|
app.extensions["options_cfg"] = cfg
|
||||||
register_options_routes(app, cfg)
|
register_options_routes(app, cfg)
|
||||||
_register_options_hub_bridge(app, cfg)
|
_register_options_hub_bridge(app, cfg)
|
||||||
@@ -438,7 +444,12 @@ def _sync_options_trades(
|
|||||||
try:
|
try:
|
||||||
init_options_tables(conn)
|
init_options_tables(conn)
|
||||||
reconcile_live_open_trades(conn, live_inst_ids=live_ids)
|
reconcile_live_open_trades(conn, live_inst_ids=live_ids)
|
||||||
sync_open_options_trades(conn, live_inst_ids=live_ids, fetch_history_fn=_hist)
|
sync_open_options_trades(
|
||||||
|
conn,
|
||||||
|
live_inst_ids=live_ids,
|
||||||
|
fetch_history_fn=_hist,
|
||||||
|
notify_cfg=cfg,
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
hist_all = fetch_all_option_positions_history(ex, limit=200)
|
hist_all = fetch_all_option_positions_history(ex, limit=200)
|
||||||
backfill_closed_options_realized_pnl_from_history(conn, hist_all)
|
backfill_closed_options_realized_pnl_from_history(conn, hist_all)
|
||||||
|
|||||||
@@ -760,6 +760,13 @@ class SimBroker:
|
|||||||
conn.execute("DELETE FROM sim_option_positions WHERE inst_id=?", (inst_id,))
|
conn.execute("DELETE FROM sim_option_positions WHERE inst_id=?", (inst_id,))
|
||||||
try:
|
try:
|
||||||
closed_at = _now()
|
closed_at = _now()
|
||||||
|
open_ids = [
|
||||||
|
int(r["id"])
|
||||||
|
for r in conn.execute(
|
||||||
|
"SELECT id FROM options_trades WHERE inst_id=? AND status='open'",
|
||||||
|
(inst_id,),
|
||||||
|
).fetchall()
|
||||||
|
]
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"""
|
"""
|
||||||
UPDATE options_trades
|
UPDATE options_trades
|
||||||
@@ -783,6 +790,18 @@ class SimBroker:
|
|||||||
inst_id,
|
inst_id,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
if open_ids:
|
||||||
|
from lib.options.options_notify_lib import (
|
||||||
|
active_options_notify_cfg,
|
||||||
|
notify_options_close_trade_ids,
|
||||||
|
)
|
||||||
|
|
||||||
|
notify_options_close_trade_ids(
|
||||||
|
active_options_notify_cfg(),
|
||||||
|
conn,
|
||||||
|
open_ids,
|
||||||
|
reason="到期结算",
|
||||||
|
)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|||||||
Reference in New Issue
Block a user