Poinbase 只收 PSC、CRC、SPARK,新增 SPARK/CRC;DEX 稳定币对改为 StableSwap

- 钱包拦下往 Poinbase 充值地址转 CRT、CRA;资金页按上架币种列出
- 现货交易对跟着行情图选中的币(PSC/CRC、SPARK/CRC)
- CRT/CRC、CRA/CRC 用 StableSwap:手续费 0.04%、A=200;脱锚 A=20,崩盘 A=1 且深度四分之一
- 旧存档读档时补 SPARK/CRC、升级稳定币池

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ZHU MINCHAOandClaude Opus 5.5 committed 2026-11-07 23:03:59 +08:00
1 parent 6d8b05215c
commit fe82395d32
19 files changed
+192 -26

No files matched your search

+62 -1
View File
@@ -8,6 +8,8 @@ namespace Decentralized.Domain
/// 一个交易对。DEX 是恒定乘积池(x·y = k):Base 是被交易的币,Quote 是计价币,价格 = Quote 储备 / Base 储备。
/// Poinbase 主池是订单簿(<see cref="Book"/>):价格只取决于当天的累计净买入量,冲击随单子变大而增长得比线性慢
/// (价格 = 参考价 × exp(κ · sign(x) · |x|^α),x = 净买入的名义价值 / 深度),拆单不占便宜,同量买进再卖出回到原价。
/// 稳定币对(<see cref="Stable"/>)是 StableSwap 池(Curve 的曲线,放大系数 A):挂钩附近几乎没有滑点,偏离越大越接近恒定乘积;
/// 储备按"价值单位"记(Base 数量 × 挂钩价),挂钩价夜里随参考价重设。
/// 每个交易对各有深度;夜间由 NPC 套利者把价格按比例拉向目标价,订单簿的累计量清零。
/// </summary>
public sealed class Pool
@@ -19,10 +21,53 @@ namespace Decentralized.Domain
/// <summary>订单簿模式:参考价、当天累计净买入的 Base 数量、深度(Quote)。</summary>
public bool Book;
public double Ref, Net, Depth;
/// <summary>StableSwap 模式:放大系数、挂钩价(储备里 Base 一侧按 数量 × 挂钩价 记)。</summary>
public bool Stable;
public double Amp, Peg;
public string Id => $"{Venue}:{Base}/{Quote}";
public double Price => Book ? PriceAt(Net) : QuoteReserve / BaseReserve;
public double Price => Book ? PriceAt(Net) : Stable ? Peg * StableSlope(BaseReserve, QuoteReserve) : QuoteReserve / BaseReserve;
public static Pool CreateStable(Venue venue, string baseAsset, string quote, double price, double depth, double fee, double amp) =>
new Pool { Venue = venue, Base = baseAsset, Quote = quote, Stable = true, Amp = amp, Peg = price, BaseReserve = depth, QuoteReserve = depth, Fee = fee };
// ——— StableSwap(两个币):Ann(x + y) + D = Ann·D + D³ / (4xy),Ann = 4A ———
private double Ann => 4 * Amp;
private double StableD(double x, double y)
{
double s = x + y, d = s;
if (s <= 0) return 0;
for (int i = 0; i < 255; i++)
{
double dp = d * d * d / (4 * x * y), prev = d;
d = (Ann * s + 2 * dp) * d / ((Ann - 1) * d + 3 * dp);
if (Math.Abs(d - prev) <= 1e-12 * d) break;
}
return d;
}
/// <summary>已知一侧储备 x 和不变量 D,求另一侧。</summary>
private double StableOther(double x, double d)
{
double c = d * d / (2 * x) * d / (2 * Ann), b = x + d / Ann, y = d;
for (int i = 0; i < 255; i++)
{
double prev = y;
y = (y * y + c) / (2 * y + b - d);
if (Math.Abs(y - prev) <= 1e-12 * y) break;
}
return y;
}
/// <summary>边际价格(每个价值单位的 Base 换多少 Quote):不变量对两侧偏导之比。平衡时为 1。</summary>
private double StableSlope(double x, double y)
{
double d = StableD(x, y), d3 = d * d * d;
return (Ann + d3 / (4 * x * x * y)) / (Ann + d3 / (4 * x * y * y));
}
public static Pool CreateBook(Venue venue, string baseAsset, string quote, double price, double depth, double fee) =>
new Pool { Venue = venue, Base = baseAsset, Quote = quote, Book = true, Ref = price, Depth = depth, Fee = fee };
@@ -62,6 +107,7 @@ namespace Decentralized.Domain
public double QuoteOut(double baseIn)
{
if (Book) return baseIn > 0 ? Cost(Net - baseIn, Net) * (1 - Fee) : 0;
if (Stable) return baseIn > 0 ? QuoteReserve - StableOther(BaseReserve + baseIn * Peg * (1 - Fee), StableD(BaseReserve, QuoteReserve)) : 0;
double x = BaseReserve + baseIn * (1 - Fee);
return QuoteReserve - BaseReserve * QuoteReserve / x;
}
@@ -70,6 +116,7 @@ namespace Decentralized.Domain
public double BaseOut(double quoteIn)
{
if (Book) return quoteIn > 0 ? BookBaseFor(quoteIn * (1 - Fee)) : 0;
if (Stable) return quoteIn > 0 ? (BaseReserve - StableOther(QuoteReserve + quoteIn * (1 - Fee), StableD(BaseReserve, QuoteReserve))) / Peg : 0;
double y = QuoteReserve + quoteIn * (1 - Fee);
return BaseReserve - BaseReserve * QuoteReserve / y;
}
@@ -79,6 +126,11 @@ namespace Decentralized.Domain
{
if (baseOut <= 0) return 0;
if (Book) return Cost(Net, Net + baseOut) / (1 - Fee);
if (Stable)
{
double x = BaseReserve - baseOut * Peg;
return x <= 0 ? double.PositiveInfinity : (StableOther(x, StableD(BaseReserve, QuoteReserve)) - QuoteReserve) / (1 - Fee);
}
if (baseOut >= BaseReserve) return double.PositiveInfinity;
return (BaseReserve * QuoteReserve / (BaseReserve - baseOut) - QuoteReserve) / (1 - Fee);
}
@@ -89,6 +141,7 @@ namespace Decentralized.Domain
if (baseIn <= 0) return 0;
double out_ = QuoteOut(baseIn);
if (Book) { Net -= baseIn; return out_; }
if (Stable) { BaseReserve += baseIn * Peg; QuoteReserve -= out_; return out_; }
BaseReserve += baseIn;
QuoteReserve -= out_;
return out_;
@@ -100,6 +153,7 @@ namespace Decentralized.Domain
if (quoteIn <= 0) return 0;
double out_ = BaseOut(quoteIn);
if (Book) { Net += out_; return out_; }
if (Stable) { QuoteReserve += quoteIn; BaseReserve -= out_ * Peg; return out_; }
QuoteReserve += quoteIn;
BaseReserve -= out_;
return out_;
@@ -110,6 +164,12 @@ namespace Decentralized.Domain
{
double before = Price;
if (Book) return PriceAt(Net + BaseOut(quoteIn)) / before - 1;
if (Stable)
{
var copy = (Pool)MemberwiseClone();
copy.BuyBase(quoteIn);
return copy.Price / before - 1;
}
double y = QuoteReserve + quoteIn * (1 - Fee);
double x = BaseReserve * QuoteReserve / y;
return (y / x) / before - 1;
@@ -128,6 +188,7 @@ namespace Decentralized.Domain
public void SetPrice(double price, double quoteDepth)
{
if (Book) { Ref = price; Net = 0; Depth = quoteDepth; return; }
if (Stable) { Peg = price; BaseReserve = quoteDepth; QuoteReserve = quoteDepth; return; }
QuoteReserve = quoteDepth;
BaseReserve = quoteDepth / price;
}
+3
View File
@@ -24,6 +24,9 @@ namespace Decentralized.Domain
/// </summary>
public sealed class Exchange
{
/// <summary>Poinbase 上架的币:只有这些能充值、能在现货交易。黑市的 CRT、革命军的 CRA 合规交易所不收。</summary>
public static readonly string[] Listed = { Assets.PSC, Assets.CRC, Assets.SPARK };
/// <summary>最近的出金记录:(天, 金额)。</summary>
public List<KeyValuePair<int, double>> History = new List<KeyValuePair<int, double>>();
+33 -3
View File
@@ -73,14 +73,37 @@ namespace Decentralized.Domain
double depth = Tuning.PoolDepth(day), p = Tuning.PscStartPrice;
m.Pools.Add(Pool.CreateBook(Venue.Exchange, Assets.PSC, Assets.CRC, p, depth, Tuning.ExchangeFee));
m.Pools.Add(Pool.Create(Venue.Dex, Assets.PSC, Assets.CRC, p, depth * SideDepthShare, Tuning.DexFee));
m.Pools.Add(Pool.Create(Venue.Dex, Assets.CRT, Assets.CRC, 1, depth * SideDepthShare, Tuning.DexFee));
m.Pools.Add(Pool.Create(Venue.Dex, Assets.CRA, Assets.CRC, 1, depth * SideDepthShare, Tuning.DexFee));
m.Pools.Add(Pool.CreateStable(Venue.Dex, Assets.CRT, Assets.CRC, 1, depth * SideDepthShare, Tuning.StableFee, Tuning.StableAmp));
m.Pools.Add(Pool.CreateStable(Venue.Dex, Assets.CRA, Assets.CRC, 1, depth * SideDepthShare, Tuning.StableFee, Tuning.StableAmp));
m.Pools.Add(Pool.Create(Venue.Dex, Assets.SPARK, Assets.CRC, Tuning.SparkStart, depth * Tuning.SparkDepthShare, Tuning.DexFee));
m.AddPoinSpark(Tuning.SparkStart, day);
return m;
}
public Pool Main => Pools[0];
/// <summary>旧存档的稳定币对是恒定乘积池:按当前价换成 StableSwap 池。</summary>
public void UpgradeStablePools(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);
}
}
/// <summary>Poinbase 的 SPARK/CRC 订单簿(旧存档没有时按当前价补上)。</summary>
public void AddPoinSpark(double price, int day)
{
if (Find(Venue.Exchange, Assets.SPARK, Assets.CRC) == null)
Pools.Add(Pool.CreateBook(Venue.Exchange, Assets.SPARK, Assets.CRC, price, Tuning.PoolDepth(day) * Tuning.PoinSparkDepthShare, Tuning.ExchangeFee));
}
/// <summary>非主交易对的深度占主池的比例。</summary>
private static double DepthShare(Pool p) =>
p.Base != Assets.SPARK ? SideDepthShare : p.Venue == Venue.Exchange ? Tuning.PoinSparkDepthShare : Tuning.SparkDepthShare;
/// <summary>DEX 上 X/CRC 的池(所有币都以 CRC 计价)。</summary>
public Pool DexPool(string asset) => Find(Venue.Dex, asset, Assets.CRC);
@@ -189,7 +212,14 @@ namespace Decentralized.Domain
double baseCredits = pool.Base == Assets.PSC ? p : stablePrice(pool.Base);
double quoteCredits = pool.Quote == Assets.PSC ? p : stablePrice(pool.Quote);
if (quoteCredits <= 0) continue;
double share = pool.Base == Assets.SPARK ? Tuning.SparkDepthShare : SideDepthShare;
double share = DepthShare(pool);
// 稳定币对:参考价偏离挂钩超过界线时流动性变差(放大系数降低),回到挂钩附近恢复
if (pool.Stable)
{
double dev = Math.Abs(baseCredits / quoteCredits - 1);
pool.Amp = dev > Tuning.StableBrokenBand ? Tuning.StableAmpBroken : dev > Tuning.StableDepegBand ? Tuning.StableAmpDepeg : Tuning.StableAmp;
if (dev > Tuning.StableBrokenBand) share *= Tuning.StableBrokenDepth;
}
pool.Revert(baseCredits / quoteCredits, ArbRate, depth * share / quoteCredits);
}
}
+5
View File
@@ -39,6 +39,9 @@ namespace Decentralized.Domain
public const double BookK = 1.54, BookAlpha = 0.8;
/// <summary>DEX 手续费;Poinbase 现货与出金的手续费(对照头部交易所 taker 约 0.1%)。</summary>
public const double DexFee = 0.003, ExchangeFee = 0.001;
/// <summary>DEX 稳定币对(CRT/CRC、CRA/CRC)的 StableSwap 池:手续费(参考 Curve 3pool 0.04%)、放大系数;
/// 参考价偏离挂钩超过 1% 是脱锚(流动性变差,A 降到 20,参考 USDC 2023 年 3 月最低约 0.87、两三天回到 1),超过 15% 是崩盘(流动性被撤走,A 降到 1、深度只剩四分之一)。</summary>
public const double StableFee = 0.0004, StableAmp = 200, StableAmpDepeg = 20, StableAmpBroken = 1, StableDepegBand = 0.01, StableBrokenBand = 0.15, StableBrokenDepth = 0.25;
/// <summary>NPC 大户每笔成交额(信用点)的范围。</summary>
public const double WhaleMin = 24000, WhaleMax = 96000;
public const double Revert = 0.15;
@@ -115,6 +118,8 @@ namespace Decentralized.Domain
public const double CardFanDust = 0.04, CardFanChipped = 0.12, CardFingersDark = 0.04, CardFingersOxidized = 0.12, CardBracketScratch = 0.02, CardSealMissing = 0.06;
/// <summary>非主交易对每晚被拉回参考价的比例,及其深度占主交易对的比例。</summary>
public const double SideArbRate = 0.75, SideDepthShare = 0.3, SparkDepthShare = 0.15;
/// <summary>Poinbase 的 SPARK/CRC 订单簿深度占主池深度的比例。</summary>
public const double PoinSparkDepthShare = 0.5;
/// <summary>Web3 黑市:开放所需黑市声望,中 / 高档货所需声望,现货每周刷新的天数与基础件数(每高 BmStockPerRep 声望多一件),现货溢价。</summary>
public const int BmOpenRep = 10, BmMidRep = 40, BmHighRep = 80, BmRefreshDays = 7, BmStockBase = 4;
public const double BmStockPerRep = 40, BmPremium = 0.30;
+8
View File
@@ -314,6 +314,7 @@ namespace Decentralized.Domain
["PerpPscLev"] = Tuning.PerpPscLev,
["PerpSparkCap"] = Tuning.PerpSparkCap,
["PerpSparkLev"] = Tuning.PerpSparkLev,
["PoinSparkDepthShare"] = Tuning.PoinSparkDepthShare,
["PoneroDailyCap"] = Tuning.PoneroDailyCap,
["PoneroFee"] = Tuning.PoneroFee,
["PoneroOpenRep"] = Tuning.PoneroOpenRep,
@@ -376,6 +377,13 @@ namespace Decentralized.Domain
["SparkStart"] = Tuning.SparkStart,
["SparkUnrestShock"] = Tuning.SparkUnrestShock,
["SparkVol"] = Tuning.SparkVol,
["StableAmp"] = Tuning.StableAmp,
["StableAmpBroken"] = Tuning.StableAmpBroken,
["StableAmpDepeg"] = Tuning.StableAmpDepeg,
["StableBrokenBand"] = Tuning.StableBrokenBand,
["StableBrokenDepth"] = Tuning.StableBrokenDepth,
["StableDepegBand"] = Tuning.StableDepegBand,
["StableFee"] = Tuning.StableFee,
["StoryBmCrtMult"] = Tuning.StoryBmCrtMult,
["StoryCraSpiralMult"] = Tuning.StoryCraSpiralMult,
["StoryLeakHaircutMult"] = Tuning.StoryLeakHaircutMult,