feat(risk): add account cooldown and daily freeze after manual/external close

Implements shared account_risk_lib with 4h/1h cooloff and daily freeze rules, wires hooks into all four exchange apps and hub monitor UI, with tests and docs.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-17 17:05:19 +08:00
parent b77741ee21
commit e307eef690
18 changed files with 1015 additions and 5 deletions
+31
View File
@@ -106,6 +106,7 @@ def build_hub_monitor_payload(
trends,
rolls,
enrich=None,
risk_status=None,
) -> dict:
"""合并 enrich 增量字段;enrich 只返回 trends 等局部时不得丢掉 keys/orders。"""
payload = {
@@ -116,6 +117,8 @@ def build_hub_monitor_payload(
"rolls": rolls,
"key_prices": [],
}
if isinstance(risk_status, dict):
payload["risk_status"] = risk_status
if callable(enrich):
extra = enrich(keys=keys, orders=orders, trends=trends, rolls=rolls)
if isinstance(extra, dict):
@@ -209,6 +212,7 @@ def install_on_app(
account_fn=None,
volume_rank_fn=None,
reconcile_hub_flat_fn=None,
risk_status_fn=None,
):
app.config["HUB_CTX"] = {
"exchange": exchange,
@@ -222,6 +226,7 @@ def install_on_app(
"ohlcv_fn": ohlcv_fn,
"volume_rank_fn": volume_rank_fn,
"reconcile_hub_flat_fn": reconcile_hub_flat_fn,
"risk_status_fn": risk_status_fn,
}
install_hub_embed_headers(app)
configure_hub_embed_session(app)
@@ -360,6 +365,23 @@ def register_hub_routes(app):
except Exception as e:
return jsonify({"ok": False, "msg": str(e)}), 500
@app.route("/api/account_risk_status")
@_hub_auth_required
def api_account_risk_status():
c = _ctx()
get_db = c.get("get_db")
risk_fn = c.get("risk_status_fn")
if not callable(get_db) or not callable(risk_fn):
return jsonify({"ok": False, "msg": "未配置风控"}), 501
conn = get_db()
try:
payload = risk_fn(conn)
return jsonify({"ok": True, **(payload if isinstance(payload, dict) else {})})
except Exception as e:
return jsonify({"ok": False, "msg": str(e)}), 500
finally:
conn.close()
@app.route("/api/hub/monitor")
@_hub_auth_required
def api_hub_monitor():
@@ -399,6 +421,13 @@ def register_hub_routes(app):
rolls.append(_row_to_dict(row))
except Exception:
pass
risk_status = None
risk_fn = c.get("risk_status_fn")
if callable(risk_fn):
try:
risk_status = risk_fn(conn)
except Exception:
risk_status = None
conn.close()
enrich = c.get("enrich_monitor")
if callable(enrich):
@@ -410,6 +439,7 @@ def register_hub_routes(app):
trends=trends,
rolls=rolls,
enrich=enrich,
risk_status=risk_status,
)
)
except Exception as e:
@@ -420,6 +450,7 @@ def register_hub_routes(app):
orders=orders,
trends=trends,
rolls=rolls,
risk_status=risk_status,
)
)