fix: 限制单笔报单最大50手,防止以损定仓计算出超大委托

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-24 14:01:55 +08:00
parent 3aa3e1ad30
commit 5af04ef661
2 changed files with 15 additions and 3 deletions
+10 -1
View File
@@ -13,6 +13,7 @@ from kline_stream import sse_format
from position_sizing import ( from position_sizing import (
MODE_FIXED, MODE_FIXED,
MODE_RISK, MODE_RISK,
DEFAULT_MAX_ORDER_LOTS,
calc_lots_by_risk, calc_lots_by_risk,
calc_order_tick_metrics, calc_order_tick_metrics,
normalize_sizing_mode, normalize_sizing_mode,
@@ -540,11 +541,19 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
if sl <= 0: if sl <= 0:
conn.close() conn.close()
return jsonify({"ok": False, "error": "以损定仓模式须填写止损价"}), 400 return jsonify({"ok": False, "error": "以损定仓模式须填写止损价"}), 400
lots_calc, err = calc_lots_by_risk(price, sl, direction, _capital(conn), get_risk_percent(get_setting), sym) lots_calc, err = calc_lots_by_risk(
price, sl, direction, _capital(conn), get_risk_percent(get_setting), sym,
)
if err: if err:
conn.close() conn.close()
return jsonify({"ok": False, "error": err}), 400 return jsonify({"ok": False, "error": err}), 400
lots = lots_calc or lots lots = lots_calc or lots
if lots > DEFAULT_MAX_ORDER_LOTS:
conn.close()
return jsonify({
"ok": False,
"error": f"单笔手数 {lots} 超过上限 {DEFAULT_MAX_ORDER_LOTS},请加大止损距离或改固定手数",
}), 400
try: try:
result = execute_order( result = execute_order(
conn, conn,
+5 -2
View File
@@ -9,6 +9,9 @@ from contract_specs import get_contract_spec
MODE_FIXED = "fixed" MODE_FIXED = "fixed"
MODE_RISK = "risk" MODE_RISK = "risk"
# 单笔报单手数上限(防止以损定仓在止损过近时算出超大手数)
DEFAULT_MAX_ORDER_LOTS = 50
def normalize_sizing_mode(raw: str) -> str: def normalize_sizing_mode(raw: str) -> str:
m = (raw or MODE_RISK).strip().lower() m = (raw or MODE_RISK).strip().lower()
@@ -63,8 +66,8 @@ def calc_lots_by_risk(
if max_by_margin < 1: if max_by_margin < 1:
return None, "可用资金不足以覆盖 1 手保证金" return None, "可用资金不足以覆盖 1 手保证金"
lots = min(lots, max_by_margin) lots = min(lots, max_by_margin)
if max_lots is not None: cap_lots = max_lots if max_lots is not None else DEFAULT_MAX_ORDER_LOTS
lots = min(lots, int(max_lots)) lots = min(lots, cap_lots)
return lots, None return lots, None