币本位买币改为按最大可开张数×权利金×可配缓冲,不全额兑换USDT

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-08-20 14:33:48 +08:00
parent 4fb3be35ef
commit 87910ed71a
9 changed files with 309 additions and 63 deletions
+40 -51
View File
@@ -553,12 +553,11 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None:
# 币本位:报价预览走 USDT 预算→估币→张数,禁止再查 USDC
try:
from lib.options.options_margin_mode_lib import (
calc_sheets_from_coin_balance,
is_coin_margin_mode,
margin_mode_from_inst_id,
)
from lib.options.options_coin_open_lib import coin_budget_preview
from lib.exchange.okx_options_lib import cap_option_buy_sheets_to_ask_depth, option_buy_liquidity_ok
from lib.exchange.okx_options_lib import option_buy_liquidity_ok
if is_coin_margin_mode():
ask = q.get("ask")
@@ -637,61 +636,31 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None:
)
idx = _safe_float(q.get("index_px")) or _safe_float(q.get("idxPx"))
budget_usdt = float(budget_info["budget_usdt"])
est_coin = (budget_usdt / float(idx)) if idx and float(idx) > 0 else None
if est_coin is None or est_coin <= 0:
return jsonify(
{
**q,
"ok": True,
"can_open": False,
"msg": "无法用指数估算可买币量",
"options_margin_mode": "coin",
"coin_budget": budget_info,
"sizing": {
"ok": False,
"msg": "缺少指数价,无法预估张数",
"sheets": 0,
"eth_amount": 0.0,
"total_premium": 0.0,
},
}
)
sizing = calc_sheets_from_coin_balance(
target_sheets = sheet_count if mode == "sheets" and sheet_count is not None else None
if mode == "eth" and request.args.get("eth"):
# 指定币量:按币量反推张数后再走统一规划
try:
eth_want = float(request.args.get("eth"))
except (TypeError, ValueError):
eth_want = 0.0
if eth_want > 0 and float(ct_mult) > 0:
import math
target_sheets = max(int(min_sz), int(math.floor(eth_want / float(ct_mult) + 1e-12)))
from lib.options.options_margin_mode_lib import plan_coin_open_by_budget
sizing = plan_coin_open_by_budget(
quote_per_unit=float(ask),
ct_mult=float(ct_mult),
min_sz=int(min_sz),
coin_available=float(est_coin),
budget_usdt=budget_usdt,
index_px=float(idx or 0),
ask_sz=ask_sz,
target_sheets=target_sheets,
)
if sizing.get("ok"):
capped, cap_msg = cap_option_buy_sheets_to_ask_depth(
int(sizing.get("sheets") or 0),
ask_sz,
min_sz=int(min_sz),
)
if capped is None:
sizing = {
"ok": False,
"msg": cap_msg,
"sheets": 0,
"eth_amount": 0.0,
"total_premium": 0.0,
}
elif capped < int(sizing.get("sheets") or 0):
sizing = calc_sheets_from_coin_balance(
quote_per_unit=float(ask),
ct_mult=float(ct_mult),
min_sz=int(min_sz),
coin_available=float(capped) * float(ask) * float(ct_mult),
)
if sizing.get("ok"):
sizing["ask_depth_capped"] = True
sizing["ask_sz"] = ask_sz
sizing["msg"] = f"已按卖一深度限制为 {capped}"
if sizing.get("ok"):
sizing["total_premium"] = sizing.get("coin_premium")
sizing["premium_ccy"] = (inst_id.split("-")[0] if inst_id else "ETH").upper()
sizing["est_coin"] = round(float(est_coin), 8)
sizing["est_note"] = "张数为预算估币预览;实盘按买币后可用量开满"
sizing["est_coin"] = sizing.get("buy_coin")
q = _attach_close_preview(
cfg,
ex,
@@ -1025,6 +994,25 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None:
from lib.options.options_coin_open_lib import open_coin_option_buy_full
if is_coin_margin_mode():
want_sheets = None
if mode == "sheets":
try:
want_sheets = int(data.get("sheets") or 0) or None
except (TypeError, ValueError):
want_sheets = None
elif mode == "eth":
try:
eth_want = float(data.get("eth") or 0)
except (TypeError, ValueError):
eth_want = 0.0
if eth_want > 0:
q0 = cfg["quote_option_contract"](ex, inst_id)
ct0 = float((q0 or {}).get("ct_mult") or 0.01)
min0 = int((q0 or {}).get("min_sz") or 1)
if ct0 > 0:
import math
want_sheets = max(min0, int(math.floor(eth_want / ct0 + 1e-12)))
result = open_coin_option_buy_full(
cfg,
ex,
@@ -1033,6 +1021,7 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None:
target_index=target_index,
profit_exit_enabled=profit_exit_enabled,
profit_exit_mult=profit_exit_mult,
target_sheets=want_sheets,
)
if result.get("ok"):
from lib.exchange.okx_options_lib import invalidate_option_positions_cache