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
+37 -3
View File
@@ -11,7 +11,7 @@ import math
from concurrent.futures import ThreadPoolExecutor
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 calc_fee_breakdown
from recommend_trend import analyze_product_daily, sort_recommend_by_trend
from symbols import PRODUCTS, product_category, product_has_night_session
@@ -24,6 +24,22 @@ SMALL_ACCOUNT_CAPITAL_MAX = 200_000.0
DISCONNECTED_RECOMMEND_CAPITAL = 100_000.0
SMALL_ACCOUNT_PRODUCT_THS = frozenset({"c", "m", "MA", "rb"})
SMALL_ACCOUNT_SCOPE_LABEL = "玉米、豆粕、甲醇、螺纹钢"
SMALL_ACCOUNT_RECOMMENDED_OPEN_MARGIN_PCT = 30.0
SMALL_ACCOUNT_RECOMMENDED_ROLL_MARGIN_PCT = 40.0
def small_account_margin_recommendations() -> dict:
"""20 万以下账户建议的保证金比例(供系统设置参考)。"""
wan = int(SMALL_ACCOUNT_CAPITAL_MAX // 10_000)
return {
"open_margin_pct": SMALL_ACCOUNT_RECOMMENDED_OPEN_MARGIN_PCT,
"roll_margin_pct": SMALL_ACCOUNT_RECOMMENDED_ROLL_MARGIN_PCT,
"label": (
f"权益 {wan} 万以下建议:开仓保证金上限 "
f"{int(SMALL_ACCOUNT_RECOMMENDED_OPEN_MARGIN_PCT)}%"
f"滚仓总保证金不超过 {int(SMALL_ACCOUNT_RECOMMENDED_ROLL_MARGIN_PCT)}%"
),
}
def small_account_scope_hint(*, ctp_connected: bool = True) -> str:
@@ -146,6 +162,7 @@ def assess_product_for_capital(
reward_risk_ratio: float = 2.0,
trading_mode: str = "simulation",
ctp_connected: bool = True,
main_code: str = "",
) -> dict:
"""评估单品种在当前资金下是否可交易。"""
ths = product.get("ths") or ""
@@ -194,7 +211,18 @@ def assess_product_for_capital(
"has_night_session": product_has_night_session(product),
}
margin_one = p * mult * margin_rate
margin_source = None
code_for_margin = (main_code or "").strip() or (ths + "8888")
if p > 0 and ctp_connected:
margin_one, margin_source, spec_used = margin_one_lot(
code_for_margin, p, trading_mode=trading_mode,
)
if spec_used.get("mult"):
mult = spec_used["mult"]
if spec_used.get("tick_size"):
tick = float(spec_used["tick_size"])
else:
margin_one = p * mult * margin_rate
min_capital = margin_one / (margin_pct / 100.0) if margin_pct > 0 else margin_one
margin_budget = cap * margin_pct / 100.0 if cap > 0 else 0.0
max_lots = int(math.floor(margin_budget / margin_one)) if margin_one > 0 and margin_budget > 0 else 0
@@ -221,8 +249,10 @@ def assess_product_for_capital(
status, label = "margin_ok", f"最大 {max_lots} 手·止损偏宽"
else:
status, label = "blocked", "资金不足"
if margin_source == "ctp" and can_margin:
label += "(柜台保证金)"
return {
row_out = {
"ths": ths,
"name": name,
"exchange": exchange,
@@ -245,6 +275,9 @@ def assess_product_for_capital(
"status_label": label,
"has_night_session": product_has_night_session(product),
}
if margin_source:
row_out["margin_source"] = margin_source
return row_out
def list_product_recommendations(
@@ -267,6 +300,7 @@ def list_product_recommendations(
max_margin_pct=max_margin_pct,
trading_mode=trading_mode,
ctp_connected=ctp_connected,
main_code=main_code,
)
main_code = (quote.get("ths_code") or "").strip()
row["main_code"] = main_code