Expand default strike rows and add hedge fund transfer / sell-coin.

Show the default five chain rows without a scroll box, add funding transfer under manual pick, and wire sell-back-coin above positions via hedge APIs.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-10-14 19:11:44 +08:00
parent d40a0d25be
commit fc83905cf6
6 changed files with 287 additions and 34 deletions
+78
View File
@@ -1244,6 +1244,80 @@ def register_hedge_plan_routes(app: Flask, cfg: dict[str, Any]) -> None:
conn.close()
return jsonify(out)
@app.route("/api/hedge-plan/transfer", methods=["POST"])
@lr
def api_hedge_transfer():
"""账户内划转(资金↔交易);USDT/ETH/BTC.本仓不依赖单独期权 UI."""
if not _hedge_enabled():
return jsonify({"ok": False, "msg": "对冲模块未启用"}), 400
ex = cfg.get("exchange_options") or cfg.get("exchange")
if ex is None:
return jsonify({"ok": False, "msg": "交易所未配置"}), 400
data = request.get_json(silent=True) or {}
ccy = str(data.get("ccy") or "USDT").strip().upper()
if ccy not in ("USDT", "ETH", "BTC"):
return jsonify({"ok": False, "msg": "币种仅支持 USDT/ETH/BTC"}), 400
from_acct = str(data.get("from") or "funding").strip().lower()
to_acct = str(data.get("to") or "trading").strip().lower()
if from_acct not in ("funding", "trading") or to_acct not in ("funding", "trading"):
return jsonify({"ok": False, "msg": "账户仅支持 funding/trading"}), 400
if from_acct == to_acct:
return jsonify({"ok": False, "msg": "划出与划入账户不能相同"}), 400
try:
amount = float(data.get("amount"))
except (TypeError, ValueError):
return jsonify({"ok": False, "msg": "数量无效"}), 400
if amount <= 0:
return jsonify({"ok": False, "msg": "数量须大于 0"}), 400
from lib.exchange.okx_options_lib import transfer_ccy
result = transfer_ccy(ex, ccy, amount, from_acct, to_acct)
if result.get("ok"):
try:
from lib.exchange.okx_options_lib import invalidate_options_balance_cache
invalidate_options_balance_cache()
except Exception:
pass
return jsonify(result)
@app.route("/api/hedge-plan/sell-coin", methods=["POST"])
@lr
def api_hedge_sell_coin():
"""手动卖回币:市价卖出交易账户全部可用标的币换 USDT."""
if not _hedge_enabled():
return jsonify({"ok": False, "msg": "对冲模块未启用"}), 400
ex = cfg.get("exchange_options") or cfg.get("exchange")
if ex is None:
return jsonify({"ok": False, "msg": "交易所未配置"}), 400
data = request.get_json(silent=True) or {}
underlying = str(data.get("underlying") or cfg.get("default_underly") or "ETH").strip().upper()
if underlying not in ("ETH", "BTC"):
return jsonify({"ok": False, "msg": "标的仅支持 ETH/BTC"}), 400
conn = cfg["get_db"]()
try:
from lib.options.options_db import init_options_tables
from lib.options.options_spot_bridge_lib import sell_residual_after_option_flat
init_options_tables(conn)
out = sell_residual_after_option_flat(
conn,
ex,
underlying=underlying,
inst_id=(str(data.get("inst_id") or "").strip() or None),
)
if out.get("ok"):
conn.commit()
try:
from lib.exchange.okx_options_lib import invalidate_options_balance_cache
invalidate_options_balance_cache()
except Exception:
pass
return jsonify(out)
finally:
conn.close()
@app.route("/api/hedge-plan/monitor-tick", methods=["POST"])
@lr
def api_hedge_monitor_tick():
@@ -1479,6 +1553,10 @@ def _options_account_snapshot(cfg: dict[str, Any]) -> dict[str, Any]:
"funding_usdt": pack.get("funding_usdt"),
"trading_usdt_avail": pack.get("trading_usdt_avail", pack.get("trading_usdt")),
"perp_margin_usdt": pack.get("perp_margin_usdt"),
"funding_eth": pack.get("funding_eth"),
"trading_eth": pack.get("trading_eth"),
"funding_btc": pack.get("funding_btc"),
"trading_btc": pack.get("trading_btc"),
}
)
except Exception:
+29 -1
View File
@@ -101,6 +101,32 @@
</table>
</div>
<div id="hp-opt-bal-line" class="muted hp-po-meta hp-opt-bal-line"></div>
<div class="hp-oo-transfer hp-oo-transfer--compact" id="hp-po-transfer">
<div class="hp-oo-transfer-bals muted">
<span>资金 <strong id="hp-po-funding-usdt">—</strong></span>
<span class="hp-oo-transfer-sep">·</span>
<span>交易 <strong id="hp-po-trading-usdt">—</strong></span>
<span class="hp-oo-transfer-unit">USDT</span>
<span class="muted" id="hp-po-xfer-msg"></span>
</div>
<div class="form-row hp-oo-transfer-form" autocomplete="off">
<input type="text" name="username" autocomplete="username" tabindex="-1" aria-hidden="true"
style="position:absolute;left:-9999px;width:1px;height:1px;opacity:0" value="">
<select id="hp-po-xfer-ccy" aria-label="币种" autocomplete="off">
<option value="USDT" selected>USDT</option>
<option value="ETH">ETH</option>
<option value="BTC">BTC</option>
</select>
<select id="hp-po-xfer-dir" aria-label="划转方向" autocomplete="off">
<option value="funding_to_trading" selected>资金 → 交易</option>
<option value="trading_to_funding">交易 → 资金</option>
</select>
<input type="number" id="hp-po-xfer-amount" name="cm_hp_po_xfer_amt" min="0.01" step="any" placeholder="数量"
autocomplete="off" inputmode="decimal" data-lpignore="true" data-1p-ignore="true" data-bwignore="true" data-form-type="other" readonly />
<button type="button" class="btn-secondary btn-sm" id="hp-po-xfer-all">全部</button>
<button type="button" class="btn-primary btn-sm" id="hp-po-xfer-btn">划转</button>
</div>
</div>
<!-- 弹窗下单:宽屏左测算 / 右下单 -->
<div id="hp-order-panel-host" class="opt-order-backdrop" hidden aria-hidden="true">
@@ -208,9 +234,11 @@
<div class="options-pos-head">
<h2>持仓</h2>
<div class="options-pos-head-actions">
<button type="button" class="btn-secondary" id="hp-sell-coin-btn" title="市价卖出交易账户全部可用标的币(当前选中 ETH/BTC)换回 USDT">手动卖回币</button>
<button type="button" class="btn-secondary" id="hp-pos-refresh" title="刷新持仓与历史">刷新</button>
</div>
</div>
<div class="muted" id="hp-sell-coin-msg" style="font-size:.72rem;margin:0 0 6px"></div>
<div class="options-pos-tabs" role="tablist" aria-label="永期持仓面板">
<button type="button" class="btn-secondary opt-pos-tab hp-pos-tab active" data-hp-pos-tab="live" role="tab" aria-selected="true">当前持仓</button>
<button type="button" class="btn-secondary opt-pos-tab hp-pos-tab" data-hp-pos-tab="plans" role="tab" aria-selected="false">对冲计划</button>
@@ -466,4 +494,4 @@
</div>
</div>
</div>
<script src="/static/hedge_plan.js?v=60"></script>
<script src="/static/hedge_plan.js?v=61"></script>