第十一阶段 stage 3:自营混币器
- Domain/OwnMixer:注资开张、NPC 客户存入、按匿名集洗污点出款(和普通混币器同一套抽象,匿名集主要是本金和收入)、手续费收入取回全额带污点、本金带自己的污点;客流按"费率 + 出款剩下的污点"和 Tumbler 比,乘黑市声望;风声累积按概率查封(全部没收、记 FENCING、停业)、便衣存入(记 FENCING)、卷款跑路(全额污点、记 FRAUD、黑市声望下降、永久关闭) - 灰网页"自营混币器"标签(买下场外换币台就有;TerminalWindow 拆成 partial,页面在 TerminalWindow.OwnMix.cs):状态、费率、口碑、风声、匿名集、各币种本金/收入/客户在途;费率、开张/暂停、注资(账单转账)、取回、卷款跑路(合约签名) - 夜间结算、日志、报纸新闻;浏览器显示"自营混币器"地址名 - Tuning.OwnMix*(research/mixsim 标定),单元测试,手册与 8 种语言 - 实测:注资 20 PSC 开张,三晚各一笔存入、一次便衣 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
9d95e1f760
commit
71002cbced
17 files changed
+820
-16
No files matched your search
@@ -1419,6 +1419,55 @@ internal static class Program
|
||||
Check(desk.Volume == 1000 && desk.Deals == 2, "成交统计");
|
||||
});
|
||||
|
||||
Test("自营混币器:注资取回的污点、匿名集与清洗率、客流、出款、查封、卷款跑路", () =>
|
||||
{
|
||||
Func<string, double> pr = a => 1;
|
||||
var w = new Wallet { Address = "w" }; w.Add(Assets.CRT, 30000);
|
||||
var m = new OwnMixer();
|
||||
Check(m.Inject(w, Assets.CRT, 20000, pr) && m.Pool(Assets.CRT).Capital == 20000 && m.Pool(Assets.CRT).CapTaint == 0, "干净的币注资,本金不带污点");
|
||||
Check(!m.Inject(w, Assets.CRT, 1e6, pr) && !m.Inject(w, Assets.SPARK, 1, pr), "余额不够、币种不支持被拒");
|
||||
Check(OwnMixer.RoundRate(40000) > OwnMixer.RoundRate(10000) && OwnMixer.RoundRate(1e9) <= Tuning.MixerCleanRate + 1e-9 && OwnMixer.RoundRate(0) == 0, "匿名集越大清洗率越高,封顶基准清洗率");
|
||||
m.Start(pr);
|
||||
Check(m.Open && Near(m.Rating, OwnMixer.Remain(OwnMixer.RoundRate(20000)), 1e-9), "开张时口碑按匿名集估");
|
||||
double rr = 0.29;
|
||||
var cheap = new OwnMixer { Fee = 0.01, Rating = 0.3 }; var dear = new OwnMixer { Fee = 0.08, Rating = 0.3 }; var dirty = new OwnMixer { Fee = 0.01, Rating = 0.9 };
|
||||
Check(cheap.Share(0.03, rr, true) > dear.Share(0.03, rr, true) && cheap.Share(0.03, rr, true) > dirty.Share(0.03, rr, true), "费率低、出款干净的分到的客流多");
|
||||
Check(cheap.Share(0.03, rr, false) > cheap.Share(0.03, rr, true), "对手关停时客流更多");
|
||||
// 营业几晚:有存入、有手续费,到期的出款
|
||||
var rng = new Rng(4);
|
||||
double fees0 = m.FeesTotal;
|
||||
int deposits = 0, payouts = 0;
|
||||
for (int day = 40; day < 50; day++)
|
||||
foreach (var e in m.Night(day, pr, 60, Tuning.MixerFee, rr, true, 1, false, rng))
|
||||
{
|
||||
if (e.Kind == "deposit") deposits++;
|
||||
if (e.Kind == "payout") payouts++;
|
||||
if (e.Kind == "seized") Check(m.Pools.Count == 0 && m.Pending.Count == 0, "查封清空池子");
|
||||
}
|
||||
Check(deposits > 0 && payouts > 0 && m.FeesTotal > fees0, $"营业中有存入和出款:{deposits} / {payouts},手续费 {m.FeesTotal - fees0:0}");
|
||||
Check(m.Pending.All(x => x.ReadyDay >= 50), "到期的都出款了");
|
||||
// 取回:收入全额带污点,本金按本金的污点
|
||||
var m2 = new OwnMixer(); var w2 = new Wallet { Address = "w2" }; w2.Add(Assets.PSC, 1000); w2.Taint = 500;
|
||||
m2.Inject(w2, Assets.PSC, 1000, pr);
|
||||
Check(Near(m2.Pool(Assets.PSC).CapTaint, 500, 1e-9) && w2.Taint < 1e-9, "脏币注资,污点跟着进本金");
|
||||
m2.Pool(Assets.PSC).Earned = 100;
|
||||
var w3 = new Wallet { Address = "w3" }; w3.Add(Assets.CRC, 10000);
|
||||
Check(m2.Withdraw(w3, Assets.PSC, 100, pr, out double o1) && Near(w3.Taint, 100, 1e-9) && o1 == 0, "先取收入:全额带污点");
|
||||
Check(m2.Withdraw(w3, Assets.PSC, 500, pr, out _) && Near(w3.Taint, 100 + 250, 1e-9), "再取本金:按本金的污点比例");
|
||||
Check(!m2.Withdraw(w3, Assets.PSC, 1000, pr, out _), "不能超过可取回的数量");
|
||||
m2.Pending.Add(new OwnMixDeposit { Asset = Assets.PSC, Amount = 300, Taint = 200, Rounds = 2, ReadyDay = 99 });
|
||||
Check(Near(m2.Free(Assets.PSC), 500, 1e-9) && Near(m2.Total(Assets.PSC), 800, 1e-9), "客户在途的币不能取");
|
||||
// 卷款跑路:连同客户的币全部卷走、全额带污点,永久关闭
|
||||
var w4 = new Wallet { Address = "w4" };
|
||||
var got = m2.Rug(w4, pr, out double o4);
|
||||
Check(Near(w4.Get(Assets.PSC), 800, 1e-9) && Near(w4.Taint, 800, 1e-9) && m2.Closed && !m2.Open && got.Count == 1, "卷走全部、全额污点、关闭");
|
||||
Check(m2.Night(100, pr, 60, Tuning.MixerFee, rr, true, 1, false, new Rng(1)).Count == 0, "关闭后不再有夜间事件");
|
||||
// 查封:风声足够大时被查封,停业若干天
|
||||
var m3 = new OwnMixer { Heat = 1e6 }; m3.Inject(new Wallet { Address = "x", Balances = { [Assets.CRT] = 5000 } }, Assets.CRT, 5000, pr); m3.Start(pr);
|
||||
var ev = m3.Night(60, pr, 60, Tuning.MixerFee, rr, true, 1, false, new Rng(2));
|
||||
Check(ev.Any(e => e.Kind == "seized" && e.Crime > 0 && e.Crime <= Tuning.CrimeEventCap) && m3.Seized(60 + Tuning.OwnMixSeizeDays) && !m3.Seized(61 + Tuning.OwnMixSeizeDays) && !m3.Open, "风声大时被查封、记罪证、停业");
|
||||
});
|
||||
|
||||
Test("预测市场:LMSR 定价、最大亏损、买卖", () =>
|
||||
{
|
||||
// 流动性:第 38 天在 5% 的盘口押 50,均价比现价贵约 10%(与先验无关,50% 盘口押 50 约 0.5%)
|
||||
|
||||
Reference in new issue
Block a user