ad992ee262
Co-authored-by: Cursor <cursoragent@cursor.com>
169 lines
7.8 KiB
HTML
169 lines
7.8 KiB
HTML
{# 系统设置 · 模拟资金 #}
|
|
<div class="sim-funds-panel" id="sim-funds-panel">
|
|
<h2>模拟资金</h2>
|
|
<p class="settings-subcard-desc">
|
|
在本地 SQLite 钱包中模拟撮合: 用 OKX <strong>公开行情</strong> 吃买卖一结算盈亏,
|
|
<strong>不会向交易所下真实订单</strong>.
|
|
</p>
|
|
<p class="muted" style="margin:0.5rem 0 1rem">
|
|
当前模式:
|
|
<strong id="sim-mode-label">…</strong>
|
|
<span id="sim-mode-badge" class="sim-mode-badge" style="display:none;margin-left:0.5rem;padding:0.1rem 0.45rem;border:1px solid currentColor;font-size:0.85em">模拟</span>
|
|
</p>
|
|
|
|
<div class="sim-mode-toggle" style="display:flex;gap:0.75rem;flex-wrap:wrap;margin-bottom:1rem">
|
|
<button type="button" class="btn" id="sim-btn-sim" onclick="simSetMode('sim')">切换到模拟资金</button>
|
|
<button type="button" class="btn" id="sim-btn-live" onclick="simSetMode('live')">切换到实盘</button>
|
|
</div>
|
|
|
|
<div id="sim-wallets-block" style="display:none">
|
|
<h3>钱包余额</h3>
|
|
<div class="sim-wallet-grid" style="display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:0.75rem;margin:0.75rem 0 1.25rem">
|
|
<div><div class="muted">资金 USDT</div><div id="sim-bal-funding-usdt">—</div></div>
|
|
<div><div class="muted">交易 USDT</div><div id="sim-bal-trading-usdt">—</div></div>
|
|
<div><div class="muted">资金 USDC</div><div id="sim-bal-funding-usdc">—</div></div>
|
|
<div><div class="muted">交易 USDC</div><div id="sim-bal-trading-usdc">—</div></div>
|
|
</div>
|
|
<p class="muted" id="sim-fee-rate-line">手续费率: —</p>
|
|
|
|
<h3>重置权益</h3>
|
|
<div style="display:flex;gap:0.5rem;flex-wrap:wrap;align-items:center;margin-bottom:1rem">
|
|
<label>USDT <input type="number" id="sim-reset-equity" value="10000" min="0" step="1" style="width:8rem"></label>
|
|
<button type="button" class="btn" onclick="simReset(false)">重置(需无仓)</button>
|
|
<button type="button" class="btn" onclick="simReset(true)">强制重置(清仓)</button>
|
|
</div>
|
|
|
|
<h3>账户划转</h3>
|
|
<div style="display:flex;gap:0.5rem;flex-wrap:wrap;align-items:center;margin-bottom:1rem">
|
|
<select id="sim-xfer-ccy"><option>USDT</option><option>USDC</option></select>
|
|
<select id="sim-xfer-from"><option value="funding">资金</option><option value="trading">交易</option></select>
|
|
<span>→</span>
|
|
<select id="sim-xfer-to"><option value="trading">交易</option><option value="funding">资金</option></select>
|
|
<input type="number" id="sim-xfer-amt" min="0" step="0.01" placeholder="金额" style="width:7rem">
|
|
<button type="button" class="btn" onclick="simTransfer()">划转</button>
|
|
</div>
|
|
|
|
<h3>USDT ↔ USDC(交易账户 · USDC/USDT 市价)</h3>
|
|
<div style="display:flex;gap:0.5rem;flex-wrap:wrap;align-items:center;margin-bottom:1rem">
|
|
<select id="sim-conv-account"><option value="trading">交易账户</option><option value="funding">资金账户</option></select>
|
|
<select id="sim-conv-from"><option value="USDT">USDT</option><option value="USDC">USDC</option></select>
|
|
<span>→</span>
|
|
<select id="sim-conv-to"><option value="USDC">USDC</option><option value="USDT">USDT</option></select>
|
|
<input type="number" id="sim-conv-amt" min="0" step="0.01" placeholder="金额" style="width:7rem">
|
|
<button type="button" class="btn" onclick="simConvert()">兑换</button>
|
|
</div>
|
|
</div>
|
|
|
|
<p id="sim-funds-msg" class="muted" style="min-height:1.2em"></p>
|
|
</div>
|
|
<script>
|
|
(function () {
|
|
function $(id) { return document.getElementById(id); }
|
|
function msg(t, ok) {
|
|
var el = $("sim-funds-msg");
|
|
if (!el) return;
|
|
el.textContent = t || "";
|
|
el.style.color = ok === false ? "#c0392b" : "";
|
|
}
|
|
function applyStatus(d) {
|
|
if (!d) return;
|
|
var mode = d.mode || (d.is_sim ? "sim" : "live");
|
|
var label = $("sim-mode-label");
|
|
if (label) label.textContent = mode === "sim" ? "模拟资金" : "实盘";
|
|
var badge = $("sim-mode-badge");
|
|
if (badge) badge.style.display = mode === "sim" ? "inline" : "none";
|
|
var block = $("sim-wallets-block");
|
|
if (block) block.style.display = mode === "sim" ? "block" : "none";
|
|
var w = d.wallets || {};
|
|
function setBal(id, v) {
|
|
var el = $(id);
|
|
if (el) el.textContent = (v == null || v === undefined) ? "—" : Number(v).toFixed(4);
|
|
}
|
|
setBal("sim-bal-funding-usdt", w.funding_usdt);
|
|
setBal("sim-bal-trading-usdt", w.trading_usdt);
|
|
setBal("sim-bal-funding-usdc", w.funding_usdc);
|
|
setBal("sim-bal-trading-usdc", w.trading_usdc);
|
|
var fee = $("sim-fee-rate-line");
|
|
if (fee && d.fee_rate != null) fee.textContent = "手续费率: " + d.fee_rate;
|
|
}
|
|
window.simRefreshStatus = function () {
|
|
return fetch("/api/sim/status", { credentials: "same-origin" })
|
|
.then(function (r) { return r.json(); })
|
|
.then(function (d) {
|
|
if (d && d.ok) applyStatus(d);
|
|
else msg((d && d.msg) || "状态加载失败", false);
|
|
})
|
|
.catch(function (e) { msg(String(e), false); });
|
|
};
|
|
window.simSetMode = function (mode) {
|
|
msg("切换中…");
|
|
fetch("/api/sim/mode", {
|
|
method: "POST",
|
|
credentials: "same-origin",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ mode: mode })
|
|
}).then(function (r) { return r.json(); }).then(function (d) {
|
|
if (!d.ok) { msg(d.msg || "切换失败", false); return; }
|
|
applyStatus(d);
|
|
msg("已切换为 " + (mode === "sim" ? "模拟资金" : "实盘"), true);
|
|
}).catch(function (e) { msg(String(e), false); });
|
|
};
|
|
window.simReset = function (force) {
|
|
var equity = parseFloat(($("sim-reset-equity") || {}).value || "10000");
|
|
msg("重置中…");
|
|
fetch("/api/sim/reset", {
|
|
method: "POST",
|
|
credentials: "same-origin",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ equity_usdt: equity, force: !!force })
|
|
}).then(function (r) { return r.json(); }).then(function (d) {
|
|
if (!d.ok) { msg(d.detail || d.msg || "重置失败", false); return; }
|
|
applyStatus(d);
|
|
msg("已重置权益", true);
|
|
}).catch(function (e) { msg(String(e), false); });
|
|
};
|
|
window.simTransfer = function () {
|
|
var body = {
|
|
ccy: ($("sim-xfer-ccy") || {}).value || "USDT",
|
|
from: ($("sim-xfer-from") || {}).value || "funding",
|
|
to: ($("sim-xfer-to") || {}).value || "trading",
|
|
amount: parseFloat(($("sim-xfer-amt") || {}).value || "0")
|
|
};
|
|
fetch("/api/sim/transfer", {
|
|
method: "POST",
|
|
credentials: "same-origin",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify(body)
|
|
}).then(function (r) { return r.json(); }).then(function (d) {
|
|
if (!d.ok) { msg(d.detail || d.msg || "划转失败", false); return; }
|
|
applyStatus(d);
|
|
msg("划转成功", true);
|
|
}).catch(function (e) { msg(String(e), false); });
|
|
};
|
|
window.simConvert = function () {
|
|
var body = {
|
|
account: ($("sim-conv-account") || {}).value || "trading",
|
|
from_ccy: ($("sim-conv-from") || {}).value || "USDT",
|
|
to_ccy: ($("sim-conv-to") || {}).value || "USDC",
|
|
amount: parseFloat(($("sim-conv-amt") || {}).value || "0")
|
|
};
|
|
fetch("/api/sim/convert", {
|
|
method: "POST",
|
|
credentials: "same-origin",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify(body)
|
|
}).then(function (r) { return r.json(); }).then(function (d) {
|
|
if (!d.ok) { msg(d.detail || d.msg || "兑换失败", false); return; }
|
|
applyStatus(d);
|
|
var px = d.fill_px != null ? (" @" + Number(d.fill_px).toFixed(6)) : "";
|
|
msg("兑换成功" + px, true);
|
|
}).catch(function (e) { msg(String(e), false); });
|
|
};
|
|
if (document.readyState === "loading") {
|
|
document.addEventListener("DOMContentLoaded", window.simRefreshStatus);
|
|
} else {
|
|
window.simRefreshStatus();
|
|
}
|
|
})();
|
|
</script>
|