fix: OKX options buy/close orders with tick alignment and reduceOnly
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -59,6 +59,8 @@ def install_options_trading(app: Flask, repo_root: str, app_module: Any) -> None
|
||||
|
||||
def _build_cfg(app_module: Any) -> dict[str, Any]:
|
||||
from lib.exchange.okx_options_lib import (
|
||||
_pos_side_from_position,
|
||||
_safe_float,
|
||||
build_option_chain,
|
||||
estimate_usdt_to_usdc,
|
||||
execute_convert,
|
||||
@@ -67,6 +69,7 @@ def _build_cfg(app_module: Any) -> dict[str, Any]:
|
||||
format_position_row,
|
||||
options_api_ready,
|
||||
place_option_limit_order,
|
||||
place_option_market_order,
|
||||
quote_option_contract,
|
||||
transfer_ccy,
|
||||
)
|
||||
@@ -91,6 +94,7 @@ def _build_cfg(app_module: Any) -> dict[str, Any]:
|
||||
"build_option_chain": build_option_chain,
|
||||
"quote_option_contract": quote_option_contract,
|
||||
"place_option_limit_order": place_option_limit_order,
|
||||
"place_option_market_order": place_option_market_order,
|
||||
"fetch_option_positions": fetch_option_positions,
|
||||
"fetch_options_balances": fetch_options_balances,
|
||||
"format_position_row": format_position_row,
|
||||
@@ -220,6 +224,7 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None:
|
||||
if not sizing.get("ok"):
|
||||
return jsonify({"ok": False, "msg": sizing.get("msg") or "张数计算失败", "sizing": sizing})
|
||||
sheets = int(sizing["sheets"])
|
||||
tick_sz = q.get("tick_sz")
|
||||
order = cfg["place_option_limit_order"](
|
||||
ex,
|
||||
inst_id=inst_id,
|
||||
@@ -227,6 +232,7 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None:
|
||||
sheets=sheets,
|
||||
price=float(ask),
|
||||
td_mode=cfg["td_mode"],
|
||||
tick_sz=tick_sz,
|
||||
)
|
||||
if not order.get("ok"):
|
||||
return jsonify(order)
|
||||
@@ -291,38 +297,43 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None:
|
||||
pos = next((p for p in raw_positions if str(p.get("instId")) == inst_id), None)
|
||||
if not pos:
|
||||
return jsonify({"ok": False, "msg": "未找到持仓"})
|
||||
avail = float(pos.get("availPos") or pos.get("pos") or 0)
|
||||
close_sheets = int(sheets) if sheets else int(abs(avail))
|
||||
avail = _safe_float(pos.get("availPos"))
|
||||
if avail is None or avail <= 0:
|
||||
avail = abs(_safe_float(pos.get("pos")) or 0)
|
||||
close_sheets = int(sheets) if sheets else int(avail)
|
||||
if close_sheets < 1:
|
||||
return jsonify({"ok": False, "msg": "可平张数不足"})
|
||||
td_mode = str(pos.get("mgnMode") or cfg["td_mode"])
|
||||
pos_side = _pos_side_from_position(pos) or "net"
|
||||
tick_sz = q.get("tick_sz")
|
||||
if use_market:
|
||||
try:
|
||||
resp = ex.private_post_trade_order(
|
||||
{
|
||||
"instId": inst_id,
|
||||
"tdMode": cfg["td_mode"],
|
||||
"side": "sell",
|
||||
"ordType": "market",
|
||||
"sz": str(close_sheets),
|
||||
}
|
||||
)
|
||||
data_rows = (resp or {}).get("data") or []
|
||||
if not data_rows or str(data_rows[0].get("sCode")) != "0":
|
||||
return jsonify({"ok": False, "msg": data_rows[0].get("sMsg") if data_rows else "市价平仓失败"})
|
||||
order = {"ok": True, "data": data_rows[0]}
|
||||
except Exception as e:
|
||||
return jsonify({"ok": False, "msg": str(e)})
|
||||
order = cfg["place_option_market_order"](
|
||||
ex,
|
||||
inst_id=inst_id,
|
||||
side="sell",
|
||||
sheets=close_sheets,
|
||||
td_mode=td_mode,
|
||||
reduce_only=True,
|
||||
pos_side=pos_side,
|
||||
)
|
||||
if not order.get("ok"):
|
||||
return jsonify(order)
|
||||
else:
|
||||
close_px = float(bid)
|
||||
order = cfg["place_option_limit_order"](
|
||||
ex,
|
||||
inst_id=inst_id,
|
||||
side="sell",
|
||||
sheets=close_sheets,
|
||||
price=float(bid),
|
||||
td_mode=cfg["td_mode"],
|
||||
price=close_px,
|
||||
td_mode=td_mode,
|
||||
tick_sz=tick_sz,
|
||||
reduce_only=True,
|
||||
pos_side=pos_side,
|
||||
)
|
||||
if not order.get("ok"):
|
||||
return jsonify(order)
|
||||
bid = order.get("px", close_px)
|
||||
prem_recv = total_premium(float(bid or 0), close_sheets * float(q.get("ct_mult") or 0.01))
|
||||
conn = cfg["get_db"]()
|
||||
try:
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
{% if not options_enabled %}
|
||||
<div class="flash" style="margin-bottom:12px">期权 API 未启用:请在 <code>crypto_monitor_okx/.env</code> 设置 <code>OKX_OPTIONS_ENABLED=true</code> 及主账户 <code>OKX_OPTIONS_API_*</code>,然后 <code>pm2 restart crypto_okx --update-env</code>。</div>
|
||||
{% endif %}
|
||||
<p class="muted options-hint">资金账户兑换 USDT→USDC 后,划转到交易账户即可买入。报价单位为每 1 ETH/BTC;1 张 = 0.01 ETH/BTC。</p>
|
||||
<p class="muted options-hint">资金账户兑换 USDT→USDC 后,划转到交易账户即可买入。报价单位为每 1 ETH/BTC;1 张 = 0.01 ETH/BTC。表格中点「买入」直接下单;或点「选择」后在下方确认张数再买入。</p>
|
||||
|
||||
<div class="options-funds-grid">
|
||||
<div class="options-funds-col">
|
||||
@@ -128,4 +128,4 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/static/options_panel.js?v=1"></script>
|
||||
<script src="/static/options_panel.js?v=2"></script>
|
||||
|
||||
Reference in New Issue
Block a user