Apply 200k scope when CTP offline; trailing breakeven order UX.
When SimNow or live CTP is disconnected, default to the four-product whitelist regardless of reference capital. Trailing breakeven defaults off; when enabled hide take-profit and risk-reward, monitor exits via trailing stop only. Document both behaviors in TRADING.md and FEATURES.md. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+48
-6
@@ -24,8 +24,13 @@ SMALL_ACCOUNT_PRODUCT_THS = frozenset({"c", "m", "MA", "rb"})
|
||||
SMALL_ACCOUNT_SCOPE_LABEL = "玉米、豆粕、甲醇、螺纹钢"
|
||||
|
||||
|
||||
def small_account_scope_hint() -> str:
|
||||
def small_account_scope_hint(*, ctp_connected: bool = True) -> str:
|
||||
wan = int(SMALL_ACCOUNT_CAPITAL_MAX // 10_000)
|
||||
if not ctp_connected:
|
||||
return (
|
||||
f"未连接 CTP,默认按 {wan} 万以下账户:"
|
||||
f"仅显示并可交易 {SMALL_ACCOUNT_SCOPE_LABEL}"
|
||||
)
|
||||
return f"权益 {wan} 万以下仅显示并可交易:{SMALL_ACCOUNT_SCOPE_LABEL}"
|
||||
|
||||
|
||||
@@ -34,6 +39,28 @@ def small_account_scope_status_label() -> str:
|
||||
return f"权益{wan}万以下限{SMALL_ACCOUNT_SCOPE_LABEL}"
|
||||
|
||||
|
||||
def should_apply_small_account_scope(
|
||||
capital: float,
|
||||
*,
|
||||
ctp_connected: bool,
|
||||
) -> bool:
|
||||
"""SimNow/实盘一致:未连接 CTP 时默认按 20 万以下四品种范围。"""
|
||||
if not ctp_connected:
|
||||
return True
|
||||
return is_small_account(capital)
|
||||
|
||||
|
||||
def filter_rows_for_account_scope(
|
||||
rows: list[dict],
|
||||
capital: float,
|
||||
*,
|
||||
ctp_connected: bool,
|
||||
) -> list[dict]:
|
||||
if not should_apply_small_account_scope(capital, ctp_connected=ctp_connected):
|
||||
return rows
|
||||
return [r for r in rows if product_in_small_account_whitelist(r.get("ths") or "")]
|
||||
|
||||
|
||||
def normalize_product_ths(ths: str) -> str:
|
||||
import re
|
||||
s = (ths or "").strip()
|
||||
@@ -60,18 +87,30 @@ def product_in_small_account_whitelist(ths_or_product) -> bool:
|
||||
return upper in {x.upper() for x in SMALL_ACCOUNT_PRODUCT_THS}
|
||||
|
||||
|
||||
def assert_product_allowed_for_capital(ths: str, capital: float) -> Optional[str]:
|
||||
def assert_product_allowed_for_capital(
|
||||
ths: str,
|
||||
capital: float,
|
||||
*,
|
||||
ctp_connected: bool = True,
|
||||
) -> Optional[str]:
|
||||
"""小账户品种白名单校验;通过返回 None。"""
|
||||
if not is_small_account(capital):
|
||||
if not should_apply_small_account_scope(capital, ctp_connected=ctp_connected):
|
||||
return None
|
||||
if product_in_small_account_whitelist(ths):
|
||||
return None
|
||||
wan = int(SMALL_ACCOUNT_CAPITAL_MAX // 10_000)
|
||||
if not ctp_connected:
|
||||
return f"未连接 CTP,仅可交易:{SMALL_ACCOUNT_SCOPE_LABEL}"
|
||||
return f"权益 {wan} 万以下仅可交易:{SMALL_ACCOUNT_SCOPE_LABEL}"
|
||||
|
||||
|
||||
def filter_products_for_capital(products: list[dict], capital: float) -> list[dict]:
|
||||
if not is_small_account(capital):
|
||||
def filter_products_for_capital(
|
||||
products: list[dict],
|
||||
capital: float,
|
||||
*,
|
||||
ctp_connected: bool = True,
|
||||
) -> list[dict]:
|
||||
if not should_apply_small_account_scope(capital, ctp_connected=ctp_connected):
|
||||
return list(products)
|
||||
return [p for p in products if product_in_small_account_whitelist(p)]
|
||||
|
||||
@@ -103,6 +142,7 @@ def assess_product_for_capital(
|
||||
default_stop_ticks: int = 20,
|
||||
reward_risk_ratio: float = 2.0,
|
||||
trading_mode: str = "simulation",
|
||||
ctp_connected: bool = True,
|
||||
) -> dict:
|
||||
"""评估单品种在当前资金下是否可交易。"""
|
||||
ths = product.get("ths") or ""
|
||||
@@ -117,7 +157,7 @@ def assess_product_for_capital(
|
||||
cap = float(capital or 0)
|
||||
margin_pct = max(1.0, min(100.0, float(max_margin_pct or 30.0)))
|
||||
|
||||
if is_small_account(cap) and not product_in_small_account_whitelist(product):
|
||||
if should_apply_small_account_scope(cap, ctp_connected=ctp_connected) and not product_in_small_account_whitelist(product):
|
||||
return {
|
||||
"ths": ths,
|
||||
"name": name,
|
||||
@@ -210,6 +250,7 @@ def list_product_recommendations(
|
||||
*,
|
||||
max_margin_pct: float = 30.0,
|
||||
trading_mode: str = "simulation",
|
||||
ctp_connected: bool = True,
|
||||
) -> list[dict]:
|
||||
"""扫描全部品种并排序:可开且纪律友好 > 可开 > 不足。quote_fn(品种代码) -> {price, ths_code, ...}"""
|
||||
|
||||
@@ -222,6 +263,7 @@ def list_product_recommendations(
|
||||
product, capital, price,
|
||||
max_margin_pct=max_margin_pct,
|
||||
trading_mode=trading_mode,
|
||||
ctp_connected=ctp_connected,
|
||||
)
|
||||
main_code = (quote.get("ths_code") or "").strip()
|
||||
row["main_code"] = main_code
|
||||
|
||||
Reference in New Issue
Block a user