Fix roll margin validation and SHFE close offset for night positions.
Use CTP account margin for roll cap checks and prefer close-today on SHFE when yesterday close is rejected. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -233,6 +233,22 @@ def calc_margin_usage_pct(
|
||||
return round(total / cap * 100.0, 2)
|
||||
|
||||
|
||||
def current_margin_usage_pct(
|
||||
positions: list[dict],
|
||||
capital: float,
|
||||
*,
|
||||
trading_mode: str | None = None,
|
||||
account_margin_used: float | None = None,
|
||||
) -> float:
|
||||
"""当前保证金占权益(%);优先采用柜台账户占用,避免本地估算偏低。"""
|
||||
cap = float(capital or 0)
|
||||
usage = calc_margin_usage_pct(positions, cap, trading_mode=trading_mode)
|
||||
acct = float(account_margin_used or 0)
|
||||
if cap > 0 and acct > 0:
|
||||
usage = max(usage, round(acct / cap * 100.0, 2))
|
||||
return usage
|
||||
|
||||
|
||||
def cap_lots_for_margin_budget(
|
||||
positions: list[dict],
|
||||
capital: float,
|
||||
@@ -242,29 +258,28 @@ def cap_lots_for_margin_budget(
|
||||
desired_lots: int,
|
||||
max_margin_pct: float,
|
||||
trading_mode: str | None = None,
|
||||
account_margin_used: float | None = None,
|
||||
) -> tuple[int, float]:
|
||||
"""在保证金上限内,返回可加仓手数及占用比例。"""
|
||||
cap = float(capital or 0)
|
||||
desired = max(0, int(desired_lots or 0))
|
||||
baseline_usage = current_margin_usage_pct(
|
||||
positions, cap, trading_mode=trading_mode, account_margin_used=account_margin_used,
|
||||
)
|
||||
if desired <= 0:
|
||||
return 0, calc_margin_usage_pct(positions, capital, trading_mode=trading_mode)
|
||||
return 0, baseline_usage
|
||||
if cap <= 0:
|
||||
return 0, baseline_usage
|
||||
baseline_margin = baseline_usage / 100.0 * cap
|
||||
per_lot = 0.0
|
||||
for lots in range(desired, 0, -1):
|
||||
usage = calc_margin_usage_pct(
|
||||
positions,
|
||||
capital,
|
||||
extra_symbol=symbol,
|
||||
extra_lots=lots,
|
||||
extra_price=price,
|
||||
extra_direction=direction,
|
||||
trading_mode=trading_mode,
|
||||
per_lot, _, _ = margin_one_lot(
|
||||
symbol, price, direction=direction, trading_mode=trading_mode,
|
||||
)
|
||||
if per_lot <= 0:
|
||||
spec = get_contract_spec(symbol)
|
||||
per_lot = price * spec["mult"] * spec["margin_rate"]
|
||||
usage = round((baseline_margin + per_lot * lots) / cap * 100.0, 2)
|
||||
if usage <= max_margin_pct:
|
||||
return lots, usage
|
||||
return 0, calc_margin_usage_pct(
|
||||
positions,
|
||||
capital,
|
||||
extra_symbol=symbol,
|
||||
extra_lots=desired,
|
||||
extra_price=price,
|
||||
extra_direction=direction,
|
||||
trading_mode=trading_mode,
|
||||
)
|
||||
return 0, round((baseline_margin + per_lot * desired) / cap * 100.0, 2)
|
||||
|
||||
Reference in New Issue
Block a user