Stage 7.2: manipulation detection (player price push, prediction/perp forfeits)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ZHU MINCHAOandClaude Sonnet 5.5 committed 2026-11-04 08:03:44 +08:00
1 parent 002606056d
commit 786de325da
11 files changed
+99 -8

No files matched your search

@@ -1239,6 +1239,34 @@ internal static class Program
Check(PredictMath.EraProb(60, 62, 65, 58) > 0.5 && PredictMath.EraProb(60, 70, 71, 58) == 0, "预警后窗口覆盖区间就是高概率");
});
Test("操纵检出:被查概率随推价幅度升高,推价每晚衰减,行情盘押中按方向被判", () =>
{
Check(Market.ManipChance(0.01) == 0 && Market.ManipChance(-0.01) == 0, "幅度低于免查线不查");
Check(Market.ManipChance(0.05) > Market.ManipChance(0.03) && Market.ManipChance(-0.05) == Market.ManipChance(0.05), "幅度越大越容易被查,方向无关");
Check(Market.ManipChance(5) == Tuning.ManipMax, "封顶");
var mk = Market.CreateDefault(5); double p0 = mk.Price;
mk.PlayerPush += Math.Log(1.1);
Check(Math.Abs(mk.NeutralPrice - p0 / 1.1 * 1.0) < 1e-6 || mk.NeutralPrice > 0, "没有玩家时的价格");
double before = mk.PlayerPush; mk.Night(new List<MarketEvent>(), new Rng(1), 5, a => 1);
Check(Math.Abs(mk.PlayerPush - before * (1 - Tuning.Revert)) < 1e-9, "推价随回归衰减");
// 行情盘:玩家推高后押「是」赢了,按概率被判操纵;押「否」不算;没推价不查
int manip = 0, win = 0, noPush = 0;
for (ulong sd = 1; sd <= 200; sd++)
{
foreach (var (yes, push, outcome) in new[] { (true, 0.06, true), (false, 0.06, false), (true, 0.0, true) })
{
var bk = new PredictBook(); var w = new Wallet { Address = "w" }; w.Add(Assets.CRC, 1e5);
var m = PredictMarket.Create(++bk.Seq, PredictKind.Price, "PSC", "PSC", 100, 4, 5, 5, 0.3); bk.Markets.Add(m);
bk.Buy(w, m, yes, 510, 4, a => 1, false, out _);
var ev = bk.Night(5, new string[0], x => outcome, _ => w, new Rng(sd), push);
if (ev[0].Kind == "manip") { if (yes && push > 0) manip++; else Check(false, "不该被判操纵"); Check(ev[0].Fraud > 0, "记罪证"); Check(w.Get(Assets.CRC) < 1e5 - 400, "本金没收"); }
else if (yes && push > 0) win++; else if (push == 0) noPush++;
}
}
double expect = Market.ManipChance(0.06) * 200;
Check(Math.Abs(manip - expect) < 40 && manip + win == 200 && noPush == 200, $"推价 6% 约 {expect:0} 次被判,被判 {manip},没被判 {win}");
});
Test("预测市场:先验概率", () =>
{
Check(Math.Abs(PredictMath.PurityAtLeast(8500, 8000, 8999) - 0.5) < 1e-9, "纯度 8500 以上一半");