diff --git a/CHANGELOG.md b/CHANGELOG.md index 95c53e7..f60f3b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ## 未发布 - Poinbase 现货改为订单簿:价格只取决于当天的累计净买入量,价格 = 参考价 × exp(1.54 × |净买入名义 / 深度|^0.8),冲击随单子变大而增长得比线性慢;拆单不占便宜,同量买进再卖出回到原价。第 38 天买 2 PSC 的平均滑点约 0.1%(原来约 0.24%),卖 200 PSC 约 4%(原来约 21%)。基础深度 50,000 → 600,000,DEX 侧池仍是恒定乘积池,按比例跟着变深;现货与出金手续费 0.2% → 0.1%。NPC 大户每笔 2,000–8,000 → 24,000–96,000,对价格的影响和原来相近。 -- Poinbase 只上架 PSC、CRC、SPARK:作为合规交易所不收黑市的 CRT 和革命军的 CRA,往充值地址转这两种币时钱包拦下(“Poinbase 不收 CRT。”);资金页入金只列这三种,出金另外列出账户里还有余额的其他币(旧存档里已经充进来的)。现货新增 SPARK/CRC 订单簿(深度为主池的一半),行情图只有 PSC、SPARK、CRC,右边的交易对跟着选中的币切换。 +- Poinbase 只上架 PSC、CRC、SPARK:作为合规交易所不收黑市的 CRT 和革命军的 CRA,往充值地址转这两种币时钱包拦下(“Poinbase 不收 CRT。”);资金页入金只列这三种,出金另外列出账户里还有余额的其他币(旧存档里已经充进来的)。现货新增 SPARK/CRC 订单簿(深度为主池的一半),行情图只有 PSC、SPARK、CRC,右边的交易对跟着选中的币切换。交易对一行不再写“(Poinbase)”,互换预览的损耗显示两位小数。 - DEX 稳定币对(CRT/CRC、CRA/CRC)改为 StableSwap 池(Curve 的曲线):手续费 0.3% → 0.04%(参考 Curve 3pool;Uniswap v3 稳定币对用 0.01% / 0.05% 档),放大系数 200,挂钩附近几乎没有滑点。第 38 天 998 CRT 换 CRC 损耗 0.041%(1.0.0 约 4%),5 万约 0.08%;998 CRT 换 PSC 约 0.68%(PSC 池那一跳)。参考价偏离挂钩超过 1% 为脱锚,放大系数降到 20(脱锚到 0.92 时卖 5 万约 0.44%);超过 15% 为崩盘,放大系数 1、深度只剩四分之一(CRA 跌到 0.3 时卖 5 万约 8.7%)。脱锚幅度参考 USDC 2023 年 3 月(最低约 0.87,两三天回到 1)。 - 永续的成交深度单独计算,基数 50,000 → 100,000,滑点减半(perpsim:均值回归策略 3,000 本金 120 天 4,261 → 5,467)。 - Poinbase 交易界面:买入和卖出都输入标的币数量,标签“数量(PSC)”;买入预览改为“约需 X CRC”;交易对一行显示手续费;均价含手续费,滑点不含手续费。 @@ -15,7 +15,7 @@ - 人脉升级降价:混币器 700 → 300,Web3 黑市 1,500 → 600。 - 手册:交易数量的说明、Poinbase 收的币和交易对、稳定币池、NPC 爆仓与爆仓新闻、保险基金见底的条件、赃物出售的污点、收黑币一节、浏览器显示的范围,8 种语言。 - 浏览器:钱包的每一笔进出都记账(统一的记账函数,同时写浏览器和钱包自己的转账记录)。原来只有钱包签名转账、Poinbase 出金和矿机收益,现在还有 DEX 兑换(含黑市自动换币)、质押与解锁、CRA 铸造与销毁、预测盘下注与兑付、情报费、空投领取与钓鱼转走、收益池存取、高息理财、黑市货款放款与退款、混币器提回、Ponero 兑换处换出的币、Tumbler 的谢礼和卖密钥盘的 CRT、用币付款的顾客、收黑币、投毒钱包被转空、地址投毒的 0 币转入。合约和收款方显示名称(DEX、革命军质押池、官方铸造、预测市场、情报贩子、高息理财、Tumbler、空投与收益池的名字)。Ponero 是隐私币,不上浏览器。账本上限 200 → 500 条。 -- 存档数据版本 3:读旧存档时 Poinbase 主池换成订单簿(按当前价格、新手续费),补上 SPARK/CRC 订单簿,DEX 的 CRT、CRA 池换成稳定币池(保持当前价),保险基金补到新初值。 +- 存档数据版本 3:读旧存档时 Poinbase 主池换成订单簿(按当前价格、新手续费),补上 SPARK/CRC 订单簿,DEX 的 CRT、CRA 池换成稳定币池(保持当前价),其他 DEX 池按新深度重设,保险基金补到新初值。 ## 1.0.0 diff --git a/src/Decentralized.Domain/Market.cs b/src/Decentralized.Domain/Market.cs index 3f94ae4..8cc322c 100644 --- a/src/Decentralized.Domain/Market.cs +++ b/src/Decentralized.Domain/Market.cs @@ -82,14 +82,16 @@ namespace Decentralized.Domain public Pool Main => Pools[0]; - /// 旧存档的稳定币对是恒定乘积池:按当前价换成 StableSwap 池。 - public void UpgradeStablePools(int day) + /// 旧存档:稳定币对是恒定乘积池,按当前价换成 StableSwap 池;其他 DEX 池按新深度重设(不等到夜里)。 + public void UpgradeDexPools(int day) { for (int i = 0; i < Pools.Count; i++) { var p = Pools[i]; - if (p.Venue != Venue.Dex || p.Stable || (p.Base != Assets.CRT && p.Base != Assets.CRA)) continue; - Pools[i] = Pool.CreateStable(Venue.Dex, p.Base, p.Quote, p.Price, Tuning.PoolDepth(day) * SideDepthShare, Tuning.StableFee, Tuning.StableAmp); + if (p.Venue != Venue.Dex || p.Stable) continue; + if (p.Base == Assets.CRT || p.Base == Assets.CRA) + Pools[i] = Pool.CreateStable(Venue.Dex, p.Base, p.Quote, p.Price, Tuning.PoolDepth(day) * SideDepthShare, Tuning.StableFee, Tuning.StableAmp); + else p.SetPrice(p.Price, Tuning.PoolDepth(day) * DepthShare(p)); } } diff --git a/src/Decentralized/Session.cs b/src/Decentralized/Session.cs index 230d84c..8e83c21 100644 --- a/src/Decentralized/Session.cs +++ b/src/Decentralized/Session.cs @@ -187,7 +187,7 @@ namespace Decentralized if (!Data.Market.Main.Book) Data.Market.Pools[0] = Pool.CreateBook(Venue.Exchange, Assets.PSC, Assets.CRC, Data.Market.Price, Tuning.PoolDepth(StoreStation.GetDayCounter()), Tuning.ExchangeFee); Data.Market.AddPoinSpark(Data.Stable.Spark, StoreStation.GetDayCounter()); - Data.Market.UpgradeStablePools(StoreStation.GetDayCounter()); + Data.Market.UpgradeDexPools(StoreStation.GetDayCounter()); if (Data.Version < 3) { Data.Version = 3; Log.Info("存档数据升级到版本 3:保险基金、Poinbase 订单簿"); } if (Data.Story == null) Data.Story = new StoryMods(); StoryMods.Current = Data.Story; diff --git a/src/Decentralized/TerminalWindow.cs b/src/Decentralized/TerminalWindow.cs index 136e329..3a86000 100644 --- a/src/Decentralized/TerminalWindow.cs +++ b/src/Decentralized/TerminalWindow.cs @@ -388,7 +388,7 @@ namespace Decentralized 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)); + return q == null ? "" : L.T("swap.preview", Fmt.Num(q.Out), _swapTo, q.Hops, (q.Impact * 100).ToString("0.00", CultureInfo.InvariantCulture)); }, "swap_preview_dim"); b.AddButton(L.T("swap.go"), () => Swap()); } @@ -426,7 +426,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)) + " " + L.T("trade.fee", (p.Fee * 100).ToString("0.0#", CultureInfo.InvariantCulture))); + // 在 Poinbase 页里,交易所名不用再写一遍(行太长会被截断) + b.AddLabel(p.Base + "/" + p.Quote + " " + L.T("trade.price", Fmt.Num(p.Price)) + " " + L.T("trade.fee", (p.Fee * 100).ToString("0.0#", CultureInfo.InvariantCulture))); LiveLabel(b, () => SpotPreview(p, true), "trade_preview_dim"); LiveLabel(b, () => SpotPreview(p, false), "trade_preview_dim"); b.BeginRow(4f); diff --git a/tests/Decentralized.Domain.Tests/Program.cs b/tests/Decentralized.Domain.Tests/Program.cs index 4a539b9..e2a0ab2 100644 --- a/tests/Decentralized.Domain.Tests/Program.cs +++ b/tests/Decentralized.Domain.Tests/Program.cs @@ -1337,7 +1337,7 @@ internal static class Program var old = Market.CreateDefault(38); int i = old.Pools.FindIndex(x => x.Venue == Venue.Dex && x.Base == Assets.CRT); old.Pools[i] = Pool.Create(Venue.Dex, Assets.CRT, Assets.CRC, 0.95, 1000, Tuning.DexFee); - old.UpgradeStablePools(38); + old.UpgradeDexPools(38); Check(old.DexPool(Assets.CRT).Stable && Near(old.DexPool(Assets.CRT).Price, 0.95, 1e-9), "旧存档的池子升级后保持当前价"); });