下单预览实时更新:现货买卖、永续开平仓、互换
This commit is contained in:
1 parent
465e46c6bb
commit
df57c417d9
10 files changed
+121
-20
No files matched your search
@@ -1,5 +1,9 @@
|
||||
# Changelog
|
||||
|
||||
## 未发布
|
||||
|
||||
- 下单时的预览改成输入时实时更新(不重建页面,输入框不会失焦):Poinbase 现货每个交易对显示买入、卖出的预估得到数量、平均成交价和滑点;永续开仓显示名义价值、预估平均成交价(含滑点)、手续费和强平价;有仓位时显示平仓的预估成交价、手续费、回到账户的 CRC 和盈亏;Web3 互换的预览也改为实时。
|
||||
|
||||
## 1.0.0-rc10
|
||||
|
||||
- 浏览器:转出、转入分成两列,按列宽显示完整地址和名称,放不下时先去名称、再用缩写,鼠标悬停显示完整地址和名称。
|
||||
|
||||
@@ -464,7 +464,6 @@ perp.rate,{0} Preis {1} Finanzierungsgebühr {2}%/Nacht
|
||||
perp.fund,Versicherungsfonds {0}
|
||||
perp.open,Eröffnen
|
||||
perp.margin,Margin-Betrag (CRC)
|
||||
perp.preview,Nominalwert {0} Ausführung {1}
|
||||
perp.do.open,Eröffnen
|
||||
perp.do.add,+ Margin
|
||||
perp.do.close,Schließen
|
||||
@@ -953,3 +952,8 @@ explorer.col.from,Von
|
||||
explorer.col.to,An
|
||||
rig.st.cond,Zustand
|
||||
asic.st.dead,Durchgebrannt
|
||||
perp.preview,Nominalwert {0} gesch. Ø-Preis {1} (Slippage {2}%)
|
||||
perp.sim.close,Schließen Nominalwert {0} gesch. Ø-Preis {1} (Slippage {2}%)
|
||||
perp.sim.close2,Gebühr {0} ca. {1} CRC zurück (G/V {2})
|
||||
trade.sim.buy,Kauf ergibt ca. {0} {1} Ø {2} Slippage {3}%
|
||||
trade.sim.sell,Verkauf ergibt ca. {0} {1} Ø {2} Slippage {3}%
|
||||
|
@@ -464,7 +464,6 @@ perp.rate,{0} price {1} funding {2}%/night
|
||||
perp.fund,Insurance fund {0}
|
||||
perp.open,Open
|
||||
perp.margin,Margin amount (CRC)
|
||||
perp.preview,Notional Value {0} fill {1}
|
||||
perp.do.open,Open
|
||||
perp.do.add,Add margin
|
||||
perp.do.close,Close
|
||||
@@ -953,3 +952,8 @@ explorer.col.from,From
|
||||
explorer.col.to,To
|
||||
rig.st.cond,Condition
|
||||
asic.st.dead,Burnt out
|
||||
perp.preview,Notional {0} est. avg price {1} (slippage {2}%)
|
||||
perp.sim.close,Close notional {0} est. avg price {1} (slippage {2}%)
|
||||
perp.sim.close2,Fee {0} about {1} CRC back (P/L {2})
|
||||
trade.sim.buy,Buy gets about {0} {1} avg {2} slippage {3}%
|
||||
trade.sim.sell,Sell gets about {0} {1} avg {2} slippage {3}%
|
||||
|
@@ -464,7 +464,6 @@ perp.rate,{0} precio {1} financiación {2}%/noche
|
||||
perp.fund,Fondo de seguro {0}
|
||||
perp.open,Abrir
|
||||
perp.margin,Monto de margen (CRC)
|
||||
perp.preview,Valor nocional {0} ejecución {1}
|
||||
perp.do.open,Abrir
|
||||
perp.do.add,+ Margen
|
||||
perp.do.close,Cerrar
|
||||
@@ -953,3 +952,8 @@ explorer.col.from,De
|
||||
explorer.col.to,A
|
||||
rig.st.cond,Condición
|
||||
asic.st.dead,Quemado
|
||||
perp.preview,Valor nominal {0} precio medio est. {1} (deslizamiento {2}%)
|
||||
perp.sim.close,Cierre valor nominal {0} precio medio est. {1} (deslizamiento {2}%)
|
||||
perp.sim.close2,Comisión {0} se recuperan unos {1} CRC (G/P {2})
|
||||
trade.sim.buy,La compra da unos {0} {1} medio {2} deslizamiento {3}%
|
||||
trade.sim.sell,La venta da unos {0} {1} medio {2} deslizamiento {3}%
|
||||
|
@@ -464,7 +464,6 @@ perp.rate,{0} prix {1} financement {2} %/nuit
|
||||
perp.fund,Fonds d'assurance {0}
|
||||
perp.open,Ouvrir
|
||||
perp.margin,Montant de la marge (CRC)
|
||||
perp.preview,Valeur notionnelle {0} exécution {1}
|
||||
perp.do.open,Ouvrir
|
||||
perp.do.add,+ Marge
|
||||
perp.do.close,Fermer
|
||||
@@ -953,3 +952,8 @@ explorer.col.from,De
|
||||
explorer.col.to,Vers
|
||||
rig.st.cond,Condition
|
||||
asic.st.dead,Grillé
|
||||
perp.preview,Valeur notionnelle {0} prix moyen est. {1} (glissement {2}%)
|
||||
perp.sim.close,Clôture valeur notionnelle {0} prix moyen est. {1} (glissement {2}%)
|
||||
perp.sim.close2,Frais {0} environ {1} CRC récupérés (P/L {2})
|
||||
trade.sim.buy,L'achat donne environ {0} {1} moy. {2} glissement {3}%
|
||||
trade.sim.sell,La vente donne environ {0} {1} moy. {2} glissement {3}%
|
||||
|
@@ -464,7 +464,6 @@ perp.rate,{0} 価格 {1} 資金調達料 {2}%/夜
|
||||
perp.fund,保険基金 {0}
|
||||
perp.open,新規建て
|
||||
perp.margin,証拠金額(CRC)
|
||||
perp.preview,想定元本 {0} 約定価格 {1}
|
||||
perp.do.open,新規建て
|
||||
perp.do.add,証拠金追加
|
||||
perp.do.close,決済
|
||||
@@ -953,3 +952,8 @@ explorer.col.from,送信元
|
||||
explorer.col.to,送信先
|
||||
rig.st.cond,コンディション
|
||||
asic.st.dead,焼損
|
||||
perp.preview,想定元本 {0} 推定平均価格 {1}(スリッページ {2}%)
|
||||
perp.sim.close,決済 想定元本 {0} 推定平均価格 {1}(スリッページ {2}%)
|
||||
perp.sim.close2,手数料 {0} 約 {1} CRC が戻る(損益 {2})
|
||||
trade.sim.buy,購入で約 {0} {1} 平均 {2} スリッページ {3}%
|
||||
trade.sim.sell,売却で約 {0} {1} 平均 {2} スリッページ {3}%
|
||||
|
Can't render this file because it contains an unexpected character in line 487 and column 24.
|
@@ -464,7 +464,6 @@ perp.rate,{0} cena {1} finansowanie {2}%/noc
|
||||
perp.fund,Fundusz ubezpieczeniowy {0}
|
||||
perp.open,Otwórz
|
||||
perp.margin,Kwota depozytu (CRC)
|
||||
perp.preview,Wartość nominalna {0} realizacja {1}
|
||||
perp.do.open,Otwórz
|
||||
perp.do.add,+ Depozyt
|
||||
perp.do.close,Zamknij
|
||||
@@ -953,3 +952,8 @@ explorer.col.from,Od
|
||||
explorer.col.to,Do
|
||||
rig.st.cond,Kondycja
|
||||
asic.st.dead,Spalony
|
||||
perp.preview,Wartość nominalna {0} szac. śr. cena {1} (poślizg {2}%)
|
||||
perp.sim.close,Zamknięcie wartość nominalna {0} szac. śr. cena {1} (poślizg {2}%)
|
||||
perp.sim.close2,Opłata {0} zwrot ok. {1} CRC (zysk/strata {2})
|
||||
trade.sim.buy,Zakup da ok. {0} {1} śr. {2} poślizg {3}%
|
||||
trade.sim.sell,Sprzedaż da ok. {0} {1} śr. {2} poślizg {3}%
|
||||
|
@@ -464,7 +464,6 @@ perp.rate,{0} цена {1} ставка финансирования {2}%/но
|
||||
perp.fund,Страховой фонд {0}
|
||||
perp.open,Открыть
|
||||
perp.margin,Сумма маржи (CRC)
|
||||
perp.preview,Номинальная стоимость {0} цена исполнения {1}
|
||||
perp.do.open,Открыть
|
||||
perp.do.add,+ Маржа
|
||||
perp.do.close,Закрыть
|
||||
@@ -953,3 +952,8 @@ explorer.col.from,От
|
||||
explorer.col.to,Кому
|
||||
rig.st.cond,Состояние
|
||||
asic.st.dead,Сгорел
|
||||
perp.preview,Номинал {0} ожид. ср. цена {1} (проскальзывание {2}%)
|
||||
perp.sim.close,Закрытие номинал {0} ожид. ср. цена {1} (проскальзывание {2}%)
|
||||
perp.sim.close2,Комиссия {0} вернётся около {1} CRC (П/У {2})
|
||||
trade.sim.buy,Покупка даст около {0} {1} ср. {2} проскальзывание {3}%
|
||||
trade.sim.sell,Продажа даст около {0} {1} ср. {2} проскальзывание {3}%
|
||||
|
@@ -463,7 +463,6 @@ perp.rate,"{0} 现价 {1} 资金费 {2}%/晚"
|
||||
perp.fund,"保险基金 {0}"
|
||||
perp.open,开仓
|
||||
perp.margin,保证金金额(CRC)
|
||||
perp.preview,名义价值 {0} 成交价 {1}
|
||||
perp.do.open,开仓
|
||||
perp.do.add,追加保证金
|
||||
perp.do.close,平仓
|
||||
@@ -952,3 +951,8 @@ explorer.col.from,转出
|
||||
explorer.col.to,转入
|
||||
rig.st.cond,成色
|
||||
asic.st.dead,已烧毁
|
||||
perp.preview,名义价值 {0} 预估均价 {1}(滑点 {2}%)
|
||||
perp.sim.close,平仓 名义价值 {0} 预估均价 {1}(滑点 {2}%)
|
||||
perp.sim.close2,手续费 {0} 约回 {1} CRC(盈亏 {2})
|
||||
trade.sim.buy,买入约得 {0} {1} 均价 {2} 滑点 {3}%
|
||||
trade.sim.sell,卖出约得 {0} {1} 均价 {2} 滑点 {3}%
|
||||
|
@@ -110,7 +110,7 @@ namespace Decentralized
|
||||
{
|
||||
var b = CustomUIManager.Window(Id, L.T("term.title"));
|
||||
if (b == null) return;
|
||||
_picked.Clear(); _clear.Clear(); _rows.Clear();
|
||||
_picked.Clear(); _clear.Clear(); _rows.Clear(); _live.Clear();
|
||||
b.SetSize(WinW, WinH).SetDraggable(true).SetCloseOnEscape(true).UseMachineryStyle();
|
||||
// 黑色外边框包裹墨水屏
|
||||
b.BeginPanel(ScreenW + Bezel * 2, ScreenH + Bezel * 2, TextAnchor.MiddleCenter, Bezel + 3f, 0f);
|
||||
@@ -148,7 +148,7 @@ namespace Decentralized
|
||||
private static void Rebuild()
|
||||
{
|
||||
var m = CustomUIManager.Instance;
|
||||
_picked.Clear(); _clear.Clear(); _rows.Clear();
|
||||
_picked.Clear(); _clear.Clear(); _rows.Clear(); _live.Clear();
|
||||
CustomUIBuilder.ClearContainer(_topRoot);
|
||||
CustomUIBuilder.ClearContainer(_bodyRoot);
|
||||
CustomUIBuilder.ClearContainer(_noteRoot);
|
||||
@@ -285,12 +285,36 @@ namespace Decentralized
|
||||
b.End();
|
||||
}
|
||||
|
||||
// 输入时实时更新的预览文字:输入框每次输入只改这些文字,不重建页面(重建会让输入框失焦)。
|
||||
private static readonly List<KeyValuePair<CustomUIElement, Func<string>>> _live = new List<KeyValuePair<CustomUIElement, Func<string>>>();
|
||||
|
||||
/// <summary>加一行实时预览:文字由 text() 算,输入框内容变化时刷新;没有内容时是一个空行占位。</summary>
|
||||
private static void LiveLabel(CustomUIBuilder b, Func<string> text, string style)
|
||||
{
|
||||
string t = text();
|
||||
b.AddLabel(string.IsNullOrEmpty(t) ? " " : t, style);
|
||||
if (b.Last != null && b.Last.text != null) _live.Add(new KeyValuePair<CustomUIElement, Func<string>>(b.Last, text));
|
||||
}
|
||||
|
||||
private static void RefreshLive()
|
||||
{
|
||||
foreach (var kv in _live)
|
||||
{
|
||||
if (kv.Key == null || kv.Key.text == null) continue;
|
||||
string t = kv.Value();
|
||||
kv.Key.text.text = string.IsNullOrEmpty(t) ? " " : t;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool ParseAmount(out double v) =>
|
||||
double.TryParse((_amount ?? "").Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out v) && v > 0;
|
||||
|
||||
private static void AmountRow(CustomUIBuilder b, bool label = true)
|
||||
{
|
||||
if (label) b.AddLabel(L.T("trade.amount"));
|
||||
b.BeginPanel(RightW - 30f, -1f, TextAnchor.MiddleCenter, 0f, 0f);
|
||||
_clear.Add(b.Last.image);
|
||||
b.AddInput("0", _amount, s => _amount = s, "amount", s => _amount = s);
|
||||
b.AddInput("0", _amount, s => { _amount = s; RefreshLive(); }, "amount", s => { _amount = s; RefreshLive(); });
|
||||
b.End();
|
||||
}
|
||||
|
||||
@@ -361,10 +385,11 @@ namespace Decentralized
|
||||
AmountRow(b);
|
||||
picker(L.T("swap.pay"), _swapFrom, true);
|
||||
picker(L.T("swap.get"), _swapTo, false);
|
||||
double v;
|
||||
bool ok = double.TryParse((_amount ?? "").Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out v) && v > 0;
|
||||
var q = ok ? m.Quote(_swapFrom, _swapTo, v) : null;
|
||||
if (q != null) b.AddLabel(L.T("swap.preview", Fmt.Num(q.Out), _swapTo, q.Hops, (q.Impact * 100).ToString("0.0", CultureInfo.InvariantCulture)), "swap_preview_dim");
|
||||
LiveLabel(b, () =>
|
||||
{
|
||||
var q = ParseAmount(out double v) ? m.Quote(_swapFrom, _swapTo, v) : null;
|
||||
return q == null ? "" : L.T("swap.preview", Fmt.Num(q.Out), _swapTo, q.Hops, (q.Impact * 100).ToString("0.0", CultureInfo.InvariantCulture));
|
||||
}, "swap_preview_dim");
|
||||
b.AddButton(L.T("swap.go"), () => Swap());
|
||||
}
|
||||
|
||||
@@ -403,6 +428,8 @@ namespace Decentralized
|
||||
{
|
||||
var p = pool;
|
||||
b.AddLabel(L.T("trade.pair", p.Base, p.Quote, L.T("venue." + p.Venue)) + " " + L.T("trade.price", Fmt.Num(p.Price)));
|
||||
LiveLabel(b, () => SpotPreview(p, true), "trade_preview_dim");
|
||||
LiveLabel(b, () => SpotPreview(p, false), "trade_preview_dim");
|
||||
b.BeginRow(4f);
|
||||
b.AddButton(L.T("trade.buy"), () => Trade(p, buy: true));
|
||||
b.AddButton(L.T("trade.sell"), () => Trade(p, buy: false));
|
||||
@@ -410,6 +437,17 @@ namespace Decentralized
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>现货模拟:按输入数量算买入或卖出能得到多少、平均成交价、相对现价的滑点(不改池子)。买入数量是计价币,卖出数量是标的币。</summary>
|
||||
private static string SpotPreview(Pool p, bool buy)
|
||||
{
|
||||
if (!ParseAmount(out double v)) return "";
|
||||
double got = buy ? p.BaseOut(v) : p.QuoteOut(v);
|
||||
if (got <= 0) return "";
|
||||
double avg = buy ? v / got : got / v;
|
||||
double slip = buy ? avg / p.Price - 1 : 1 - avg / p.Price;
|
||||
return L.T(buy ? "trade.sim.buy" : "trade.sim.sell", Fmt.Num(got), buy ? p.Base : p.Quote, Fmt.Num(avg), (Math.Max(0, slip) * 100).ToString("0.0", CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
private static readonly float[] HoldWBase = new[] { 80f, 100f, 110f, 110f };
|
||||
private static float[] HoldW => Sc(HoldWBase);
|
||||
private static readonly TextAnchor[] HoldAligns = { TextAnchor.MiddleLeft, TextAnchor.MiddleRight, TextAnchor.MiddleRight, TextAnchor.MiddleRight };
|
||||
@@ -641,12 +679,15 @@ namespace Decentralized
|
||||
}
|
||||
r.AddLabel(L.T("perp.margin"));
|
||||
AmountRow(r, false);
|
||||
if (held == null && double.TryParse((_amount ?? "").Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out double m) && m > 0)
|
||||
if (held == null)
|
||||
{
|
||||
double notional = m * _perpLev, spot = PerpSpot(_perpProduct), exec = bk.Exec(spot, notional, _perpLong, day);
|
||||
var ghost = new PerpPosition { Long = _perpLong, Entry = exec, Size = notional / exec, Margin = m };
|
||||
r.AddLabel(L.T("perp.preview", Fmt.Credits(notional), Fmt.Num(exec)), "perp_preview_dim");
|
||||
r.AddLabel(L.T("perp.preview2", Fmt.Num(notional * Tuning.PerpFee), Fmt.Num(ghost.LiqPrice)), "perp_preview_dim");
|
||||
LiveLabel(r, () => PerpOpenPreview(1), "perp_preview_dim");
|
||||
LiveLabel(r, () => PerpOpenPreview(2), "perp_preview_dim");
|
||||
}
|
||||
else
|
||||
{
|
||||
LiveLabel(r, () => PerpClosePreview(held, 1), "perp_preview_dim");
|
||||
LiveLabel(r, () => PerpClosePreview(held, 2), "perp_preview_dim");
|
||||
}
|
||||
r.BeginRow(6f);
|
||||
if (held == null) r.AddButton(L.T("perp.do.open"), PerpOpen);
|
||||
@@ -656,6 +697,30 @@ namespace Decentralized
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>开仓模拟:名义价值、预估平均成交价(含滑点)、手续费、强平价。line 1 是价格行,2 是费用和强平价行。</summary>
|
||||
private static string PerpOpenPreview(int line)
|
||||
{
|
||||
if (!ParseAmount(out double m)) return "";
|
||||
var bk = Session.Data.Perps;
|
||||
int day = StoreStation.GetDayCounter();
|
||||
double notional = m * _perpLev, spot = PerpSpot(_perpProduct), exec = bk.Exec(spot, notional, _perpLong, day);
|
||||
if (line == 1) return L.T("perp.preview", Fmt.Credits(notional), Fmt.Num(exec), ((exec / spot - 1) * 100).ToString("+0.0;-0.0;0.0", CultureInfo.InvariantCulture));
|
||||
var ghost = new PerpPosition { Long = _perpLong, Entry = exec, Size = notional / exec, Margin = m };
|
||||
return L.T("perp.preview2", Fmt.Num(notional * Tuning.PerpFee), Fmt.Num(ghost.LiqPrice));
|
||||
}
|
||||
|
||||
/// <summary>平仓模拟:按现价平掉整个仓位的预估成交价(含滑点)、手续费、回到账户的 CRC 和盈亏。</summary>
|
||||
private static string PerpClosePreview(PerpPosition pos, int line)
|
||||
{
|
||||
var bk = Session.Data.Perps;
|
||||
double spot = PerpSpot(pos.Product);
|
||||
double exec = bk.Exec(spot, pos.Notional(spot), !pos.Long, StoreStation.GetDayCounter());
|
||||
double fee = pos.Notional(exec) * Tuning.PerpFee;
|
||||
double payout = Math.Max(0, pos.Equity(exec) - fee);
|
||||
if (line == 1) return L.T("perp.sim.close", Fmt.Credits(pos.Notional(spot)), Fmt.Num(exec), ((exec / spot - 1) * 100).ToString("+0.0;-0.0;0.0", CultureInfo.InvariantCulture));
|
||||
return L.T("perp.sim.close2", Fmt.Num(fee), Fmt.Num(payout), (payout - pos.Margin >= 0 ? "+" : "") + Fmt.Num(payout - pos.Margin));
|
||||
}
|
||||
|
||||
private static readonly float[] PoolWBase = new[] { 110f, 50f, 64f, 64f, 50f, 78f };
|
||||
private static float[] PoolW => Sc(PoolWBase);
|
||||
private static readonly TextAnchor[] PoolAligns = { TextAnchor.MiddleLeft, TextAnchor.MiddleRight, TextAnchor.MiddleRight, TextAnchor.MiddleRight, TextAnchor.MiddleRight, TextAnchor.MiddleRight };
|
||||
|
||||
Reference in new issue
Block a user