Show option expiry countdown and widen settings for ultrawide/tablet.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+209
-188
@@ -112,7 +112,7 @@ export default function SettingsPage() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{ maxWidth: 560 }}>
|
||||
<div className="settings-page">
|
||||
<h2 style={{ marginTop: 0 }}>系统设置</h2>
|
||||
<div className="tabs">
|
||||
<button
|
||||
@@ -132,207 +132,228 @@ export default function SettingsPage() {
|
||||
</div>
|
||||
|
||||
{tab === "strategy" ? (
|
||||
<div className="card">
|
||||
<p style={{ color: "var(--muted)", marginTop: 0 }}>
|
||||
<div className="card settings-card">
|
||||
<p className="settings-lead">
|
||||
无开仓时间窗;期权按剩余时长选到期 → 平值 → 校验杠杆;出场可选固定金额或权利金倍数。
|
||||
</p>
|
||||
{stratOk ? <div style={{ color: "var(--up)", marginBottom: 12 }}>{stratOk}</div> : null}
|
||||
{stratOk ? <div className="settings-ok">{stratOk}</div> : null}
|
||||
{err && tab === "strategy" ? <div className="err">{err}</div> : null}
|
||||
<form onSubmit={onSaveStrategy}>
|
||||
<h3 style={{ margin: "0 0 10px", fontSize: 14, color: "var(--muted)" }}>资金</h3>
|
||||
<div className="field">
|
||||
<label htmlFor="lev">永续杠杆倍数</label>
|
||||
<input
|
||||
id="lev"
|
||||
className="mono"
|
||||
type="number"
|
||||
step="1"
|
||||
min="1"
|
||||
value={leverage}
|
||||
onChange={(e) => setLeverage(Number(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
<section className="settings-section">
|
||||
<h3>资金</h3>
|
||||
<div className="settings-fields">
|
||||
<div className="field">
|
||||
<label htmlFor="lev">永续杠杆倍数</label>
|
||||
<input
|
||||
id="lev"
|
||||
className="mono"
|
||||
type="number"
|
||||
step="1"
|
||||
min="1"
|
||||
value={leverage}
|
||||
onChange={(e) => setLeverage(Number(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="perp">永续 ETH 数量</label>
|
||||
<input
|
||||
id="perp"
|
||||
className="mono"
|
||||
type="number"
|
||||
step="0.01"
|
||||
min="0.01"
|
||||
value={perpQty}
|
||||
onChange={(e) => setPerpQty(Number(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="opt">期权 ETH 数量</label>
|
||||
<input
|
||||
id="opt"
|
||||
className="mono"
|
||||
type="number"
|
||||
step="0.01"
|
||||
min="0.01"
|
||||
value={optQty}
|
||||
onChange={(e) => setOptQty(Number(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<h3 style={{ margin: "18px 0 10px", fontSize: 14, color: "var(--muted)" }}>策略</h3>
|
||||
<div className="field">
|
||||
<label htmlFor="hours">期权最小剩余小时</label>
|
||||
<input
|
||||
id="hours"
|
||||
className="mono"
|
||||
type="number"
|
||||
step="1"
|
||||
min="1"
|
||||
value={minHours}
|
||||
onChange={(e) => setMinHours(Number(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="olev">期权杠杆下限(现价÷卖一权利金)</label>
|
||||
<input
|
||||
id="olev"
|
||||
className="mono"
|
||||
type="number"
|
||||
step="1"
|
||||
min="1"
|
||||
value={minOptLev}
|
||||
onChange={(e) => setMinOptLev(Number(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="exitMode">出场规则</label>
|
||||
<select
|
||||
id="exitMode"
|
||||
className="mono"
|
||||
value={exitMode}
|
||||
onChange={(e) =>
|
||||
setExitMode(
|
||||
e.target.value === "premium_multiple"
|
||||
? "premium_multiple"
|
||||
: "fixed_usdt",
|
||||
)
|
||||
}
|
||||
>
|
||||
<option value="fixed_usdt">固定净盈利(USDT)</option>
|
||||
<option value="premium_multiple">权利金倍数</option>
|
||||
</select>
|
||||
</div>
|
||||
{exitMode === "fixed_usdt" ? (
|
||||
<div className="field">
|
||||
<label htmlFor="netTarget">净盈利出场目标(USDT)</label>
|
||||
<input
|
||||
id="netTarget"
|
||||
className="mono"
|
||||
type="number"
|
||||
step="0.1"
|
||||
min="0.1"
|
||||
value={netTarget}
|
||||
onChange={(e) => setNetTarget(Number(e.target.value))}
|
||||
/>
|
||||
<section className="settings-section">
|
||||
<h3>选约</h3>
|
||||
<div className="settings-fields">
|
||||
<div className="field">
|
||||
<label htmlFor="hours">期权最小剩余小时</label>
|
||||
<input
|
||||
id="hours"
|
||||
className="mono"
|
||||
type="number"
|
||||
step="1"
|
||||
min="1"
|
||||
value={minHours}
|
||||
onChange={(e) => setMinHours(Number(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="olev">期权杠杆下限(现价÷卖一权利金)</label>
|
||||
<input
|
||||
id="olev"
|
||||
className="mono"
|
||||
type="number"
|
||||
step="1"
|
||||
min="1"
|
||||
value={minOptLev}
|
||||
onChange={(e) => setMinOptLev(Number(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="field">
|
||||
<label htmlFor="premMult">权利金倍数(1 = 一倍权利金)</label>
|
||||
<input
|
||||
id="premMult"
|
||||
className="mono"
|
||||
type="number"
|
||||
step="0.1"
|
||||
min="0.1"
|
||||
value={premMult}
|
||||
onChange={(e) => setPremMult(Number(e.target.value))}
|
||||
/>
|
||||
</section>
|
||||
|
||||
<section className="settings-section">
|
||||
<h3>出场与风控</h3>
|
||||
<div className="settings-fields">
|
||||
<div className="field">
|
||||
<label htmlFor="exitMode">出场规则</label>
|
||||
<select
|
||||
id="exitMode"
|
||||
className="mono"
|
||||
value={exitMode}
|
||||
onChange={(e) =>
|
||||
setExitMode(
|
||||
e.target.value === "premium_multiple"
|
||||
? "premium_multiple"
|
||||
: "fixed_usdt",
|
||||
)
|
||||
}
|
||||
>
|
||||
<option value="fixed_usdt">固定净盈利(USDT)</option>
|
||||
<option value="premium_multiple">权利金倍数</option>
|
||||
</select>
|
||||
</div>
|
||||
{exitMode === "fixed_usdt" ? (
|
||||
<div className="field">
|
||||
<label htmlFor="netTarget">净盈利出场目标(USDT)</label>
|
||||
<input
|
||||
id="netTarget"
|
||||
className="mono"
|
||||
type="number"
|
||||
step="0.1"
|
||||
min="0.1"
|
||||
value={netTarget}
|
||||
onChange={(e) => setNetTarget(Number(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="field">
|
||||
<label htmlFor="premMult">权利金倍数(1 = 一倍权利金)</label>
|
||||
<input
|
||||
id="premMult"
|
||||
className="mono"
|
||||
type="number"
|
||||
step="0.1"
|
||||
min="0.1"
|
||||
value={premMult}
|
||||
onChange={(e) => setPremMult(Number(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className="field">
|
||||
<label htmlFor="closeDev">平仓买一/标记最大偏差(%)</label>
|
||||
<input
|
||||
id="closeDev"
|
||||
className="mono"
|
||||
type="number"
|
||||
step="1"
|
||||
min="1"
|
||||
value={closeDevPct}
|
||||
onChange={(e) => setCloseDevPct(Number(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="rest">轮间休息秒数</label>
|
||||
<input
|
||||
id="rest"
|
||||
className="mono"
|
||||
type="number"
|
||||
step="1"
|
||||
value={rest}
|
||||
onChange={(e) => setRest(Number(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="fee">手续费率</label>
|
||||
<input
|
||||
id="fee"
|
||||
className="mono"
|
||||
type="number"
|
||||
step="0.0001"
|
||||
value={fee}
|
||||
onChange={(e) => setFee(Number(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="field">
|
||||
<label htmlFor="closeDev">平仓买一/标记最大偏差(%)</label>
|
||||
<input
|
||||
id="closeDev"
|
||||
className="mono"
|
||||
type="number"
|
||||
step="1"
|
||||
min="1"
|
||||
value={closeDevPct}
|
||||
onChange={(e) => setCloseDevPct(Number(e.target.value))}
|
||||
/>
|
||||
</section>
|
||||
|
||||
<div className="settings-actions">
|
||||
<button className="btn" type="submit">
|
||||
保存策略
|
||||
</button>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="perp">永续 ETH 数量</label>
|
||||
<input
|
||||
id="perp"
|
||||
className="mono"
|
||||
type="number"
|
||||
step="0.01"
|
||||
min="0.01"
|
||||
value={perpQty}
|
||||
onChange={(e) => setPerpQty(Number(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="opt">期权 ETH 数量</label>
|
||||
<input
|
||||
id="opt"
|
||||
className="mono"
|
||||
type="number"
|
||||
step="0.01"
|
||||
min="0.01"
|
||||
value={optQty}
|
||||
onChange={(e) => setOptQty(Number(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="rest">轮间休息秒数</label>
|
||||
<input
|
||||
id="rest"
|
||||
className="mono"
|
||||
type="number"
|
||||
step="1"
|
||||
value={rest}
|
||||
onChange={(e) => setRest(Number(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="fee">手续费率</label>
|
||||
<input
|
||||
id="fee"
|
||||
className="mono"
|
||||
type="number"
|
||||
step="0.0001"
|
||||
value={fee}
|
||||
onChange={(e) => setFee(Number(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
<button className="btn" type="submit">
|
||||
保存策略
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
) : (
|
||||
<div className="card">
|
||||
<div className="card settings-card settings-card-narrow">
|
||||
{err ? <div className="err">{err}</div> : null}
|
||||
{ok ? <div style={{ color: "var(--up)", marginBottom: 12 }}>{ok}</div> : null}
|
||||
<form onSubmit={onSaveCreds}>
|
||||
<div className="field">
|
||||
<label htmlFor="user">新用户名</label>
|
||||
<input
|
||||
id="user"
|
||||
value={newUsername}
|
||||
onChange={(e) => setNewUsername(e.target.value)}
|
||||
required
|
||||
/>
|
||||
{ok ? <div className="settings-ok">{ok}</div> : null}
|
||||
<form onSubmit={onSaveCreds} className="settings-account-form">
|
||||
<div className="settings-fields">
|
||||
<div className="field">
|
||||
<label htmlFor="user">新用户名</label>
|
||||
<input
|
||||
id="user"
|
||||
value={newUsername}
|
||||
onChange={(e) => setNewUsername(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="cur">当前密码</label>
|
||||
<input
|
||||
id="cur"
|
||||
type="password"
|
||||
value={currentPassword}
|
||||
onChange={(e) => setCurrentPassword(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="np">新密码</label>
|
||||
<input
|
||||
id="np"
|
||||
type="password"
|
||||
value={newPassword}
|
||||
onChange={(e) => setNewPassword(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="cp">确认新密码</label>
|
||||
<input
|
||||
id="cp"
|
||||
type="password"
|
||||
value={confirmPassword}
|
||||
onChange={(e) => setConfirmPassword(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="cur">当前密码</label>
|
||||
<input
|
||||
id="cur"
|
||||
type="password"
|
||||
value={currentPassword}
|
||||
onChange={(e) => setCurrentPassword(e.target.value)}
|
||||
required
|
||||
/>
|
||||
<div className="settings-actions">
|
||||
<button className="btn" type="submit" disabled={loading}>
|
||||
{loading ? "保存中…" : "保存账号"}
|
||||
</button>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="np">新密码</label>
|
||||
<input
|
||||
id="np"
|
||||
type="password"
|
||||
value={newPassword}
|
||||
onChange={(e) => setNewPassword(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="cp">确认新密码</label>
|
||||
<input
|
||||
id="cp"
|
||||
type="password"
|
||||
value={confirmPassword}
|
||||
onChange={(e) => setConfirmPassword(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<button className="btn" type="submit" disabled={loading}>
|
||||
{loading ? "保存中…" : "保存账号"}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user