Add key-level auto trade, AI analysis, and trading UX improvements.

Key monitors use 5m close triggers with WeChat alerts and box/convergence auto orders; add pending-order worker, structured WeChat notify, AI settings/messages, session clock, CTP margin sizing, and dual-layer position limits.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-28 10:36:56 +08:00
parent 0109b59f27
commit 840e88daad
33 changed files with 2514 additions and 143 deletions
+16 -24
View File
@@ -12,7 +12,7 @@ import math
from datetime import datetime
from typing import Callable, Optional
from contract_specs import get_contract_spec
from contract_specs import get_contract_spec, margin_one_lot
from fee_specs import ensure_fee_rates_schema
from product_recommend import (
_attach_turnover,
@@ -128,16 +128,7 @@ def enrich_recommend_rows(
cap = float(capital or 0)
pct = max(1.0, min(100.0, float(max_margin_pct or 30.0)))
budget = cap * pct / 100.0 if cap > 0 else 0.0
ctp_connected = False
ctp_lookup_spec = None
ctp_estimate_margin_one_lot_fn = None
try:
from vnpy_bridge import ctp_estimate_margin_one_lot, ctp_lookup_contract_spec, ctp_status
ctp_connected = bool(ctp_status(trading_mode).get("connected"))
ctp_lookup_spec = ctp_lookup_contract_spec
ctp_estimate_margin_one_lot_fn = ctp_estimate_margin_one_lot
except Exception:
pass
ctp_connected = _ctp_connected_for_mode(trading_mode)
enriched: list[dict] = []
for raw in rows:
row = dict(raw)
@@ -150,26 +141,27 @@ def enrich_recommend_rows(
row["mult"] = spec["mult"]
if row.get("tick_size") in (None, ""):
row["tick_size"] = float(spec.get("tick_size") or 1.0)
if ctp_connected and main_code and ctp_lookup_spec:
ctp_spec = ctp_lookup_spec(trading_mode, main_code)
if ctp_spec:
if ctp_spec.get("mult"):
row["mult"] = ctp_spec["mult"]
if ctp_spec.get("tick_size"):
row["tick_size"] = ctp_spec["tick_size"]
row["spec_source"] = "ctp"
margin_one = 0.0
try:
margin_one = float(row.get("margin_one_lot") or 0)
except (TypeError, ValueError):
margin_one = 0.0
price = float(row.get("price") or 0)
if ctp_connected and main_code and price > 0 and ctp_estimate_margin_one_lot_fn:
ctp_margin = ctp_estimate_margin_one_lot_fn(trading_mode, main_code, price)
if ctp_margin and ctp_margin > 0:
margin_one = ctp_margin
row["margin_one_lot"] = ctp_margin
code_for_margin = main_code or spec_code
if price > 0 and code_for_margin:
margin_one, margin_source, spec_used = margin_one_lot(
code_for_margin,
price,
trading_mode=trading_mode if ctp_connected else None,
)
if spec_used.get("mult"):
row["mult"] = spec_used["mult"]
if spec_used.get("tick_size"):
row["tick_size"] = spec_used["tick_size"]
row["margin_one_lot"] = margin_one
if margin_source == "ctp":
row["margin_source"] = "ctp"
row["spec_source"] = "ctp"
if margin_one > 0 and budget > 0:
lots = int(math.floor(budget / margin_one))
else: