Prediction markets: news reaction, clues, gas/CRA/era markets, intel broker, bigger stakes
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ca3230e7d2
commit
002606056d
12 files changed
+637
-52
No files matched your search
@@ -4,7 +4,7 @@ using System.Linq;
|
||||
|
||||
namespace Decentralized.Domain
|
||||
{
|
||||
public enum PredictKind { Event, Faction, Purity, Price }
|
||||
public enum PredictKind { Event, Faction, Purity, Price, Gas, Cra, Era }
|
||||
|
||||
public enum PredictResult { Ok, Closed, Amount, Funds, Cap, Opposite, NoPosition }
|
||||
|
||||
@@ -75,6 +75,14 @@ namespace Decentralized.Domain
|
||||
public double Shares, Cost, Taint, Basis, Insider;
|
||||
}
|
||||
|
||||
/// <summary>情报贩子卖的内幕消息:对某个盘口给出"是 / 否"的说法,三档准确率,可能是假的(与真相相反)。</summary>
|
||||
public sealed class PredictTip
|
||||
{
|
||||
public int Market, Tier;
|
||||
public bool Claim;
|
||||
public double Paid;
|
||||
}
|
||||
|
||||
/// <summary>结算记录(盘口列表下面的"最近结果")。</summary>
|
||||
public sealed class PredictRecord
|
||||
{
|
||||
@@ -109,6 +117,7 @@ namespace Decentralized.Domain
|
||||
public List<PredictMarket> Markets = new List<PredictMarket>();
|
||||
public List<PredictPos> Positions = new List<PredictPos>();
|
||||
public List<PredictRecord> Recent = new List<PredictRecord>();
|
||||
public List<PredictTip> Tips = new List<PredictTip>();
|
||||
public int Seq;
|
||||
/// <summary>每晚观测:当天新出现的事件标识(和 "F:派系")。窗口里缺任何一天的观测,盘口作废退款。</summary>
|
||||
public Dictionary<int, List<string>> Started = new Dictionary<int, List<string>>();
|
||||
@@ -222,6 +231,7 @@ namespace Decentralized.Domain
|
||||
else Record(day, m, m.Outcome, 0, false);
|
||||
}
|
||||
Markets.RemoveAll(m => m.Outcome >= 0);
|
||||
Tips.RemoveAll(t => Find(t.Market) == null);
|
||||
return evs;
|
||||
}
|
||||
|
||||
@@ -231,6 +241,34 @@ namespace Decentralized.Domain
|
||||
while (Recent.Count > Tuning.PredictHistory) Recent.RemoveAt(0);
|
||||
}
|
||||
|
||||
public PredictTip TipFor(int market) => Tips.Find(t => t.Market == market);
|
||||
|
||||
/// <summary>造一条内幕消息:假情报(概率 IntelFake)说的与真相相反,否则按这一档的准确率说对或说错。</summary>
|
||||
public static PredictTip MakeTip(PredictMarket m, bool truth, int tier, Rng rng)
|
||||
{
|
||||
bool claim;
|
||||
if (rng.Chance(Tuning.IntelFake)) claim = !truth;
|
||||
else claim = rng.Chance(Tuning.IntelTipAcc[tier]) ? truth : !truth;
|
||||
return new PredictTip { Market = m.Id, Tier = tier, Claim = claim, Paid = Tuning.IntelTipPrice[tier] * m.MaxLoss };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 夜间的消息反应:还能交易的盘口(明天仍开着)向"公开信息下的合理概率"靠拢 PredictDrift,再加 logit 噪声(NPC 流量)。
|
||||
/// 价格在夜里才反应,所以白天先看到报纸、传闻的人可以抢在前面买、等涨价再卖。target 返回 null 表示这个盘口没有新信息。
|
||||
/// </summary>
|
||||
public void Drift(int day, Func<PredictMarket, double?> target, Rng rng)
|
||||
{
|
||||
foreach (var m in Markets.Where(x => x.Outcome < 0 && x.FromDay > day + 1))
|
||||
{
|
||||
double p = m.PYes, t = target(m) ?? p;
|
||||
t = Math.Max(Tuning.PredictPMin, Math.Min(Tuning.PredictPMax, t));
|
||||
double pt = p + Tuning.PredictDrift * (t - p);
|
||||
double lp = Math.Log(pt / (1 - pt)) + Tuning.PredictNoise * rng.Gauss();
|
||||
pt = Math.Max(Tuning.PredictPMin, Math.Min(Tuning.PredictPMax, 1 / (1 + Math.Exp(-lp))));
|
||||
m.QYes = m.QNo + m.B * Math.Log(pt / (1 - pt));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>读观测:窗口里每一天都有记录才能判断;有任何一天缺就返回 null(作废)。</summary>
|
||||
public bool? Happened(PredictMarket m)
|
||||
{
|
||||
@@ -260,7 +298,7 @@ namespace Decentralized.Domain
|
||||
{
|
||||
var c = pool[rng.Range(0, pool.Count - 1)];
|
||||
pool.RemoveAll(x => x.Kind == c.Kind && x.Key == c.Key);
|
||||
int from = c.Tomorrow ? day + 1 : day + 1 + rng.Range(0, 1);
|
||||
int from = c.Tomorrow ? day + 1 : day + 1 + rng.Range(0, 2);
|
||||
int to = c.Tomorrow ? from : from + rng.Range(0, 2);
|
||||
var m = PredictMarket.Create(++Seq, c.Kind, c.Key, c.Title, c.Param, day, from, to, c.Prob(from, to));
|
||||
Markets.Add(m); made.Add(m);
|
||||
@@ -279,6 +317,51 @@ namespace Decentralized.Domain
|
||||
return 1 - Math.Pow(1 - p1, days);
|
||||
}
|
||||
|
||||
/// <summary>某天 gas 不低于阈值的概率(已知相位):周期值 × (1 ± 噪声) 均匀分布。</summary>
|
||||
public static double GasAtLeast(int day, int phase, double threshold)
|
||||
{
|
||||
double c = TxRules.GasCycle(day, phase), hi = c * (1 + Tuning.TxGasNoise), lo = c * (1 - Tuning.TxGasNoise);
|
||||
return Math.Max(0, Math.Min(1, (hi - threshold) / (hi - lo)));
|
||||
}
|
||||
|
||||
/// <summary>不知道相位时的先验:七个相位等可能。</summary>
|
||||
public static double GasFlat(int day, double threshold)
|
||||
{
|
||||
double s = 0;
|
||||
for (int ph = 0; ph < Tuning.TxGasPeriod; ph++) s += GasAtLeast(day, ph, threshold);
|
||||
return s / Tuning.TxGasPeriod;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// CRA 预警在 [from, to] 夜里发出的概率:每晚补贴池先被消耗,归零那晚必发,否则按日概率;
|
||||
/// 窗口之前已经发出的不算(那就是"否")。subsidy / drain 是今天的补贴池和每晚消耗,today 是今晚。
|
||||
/// </summary>
|
||||
public static double CraWarnProb(double subsidy, double drain, int today, int from, int to, double dailyHazard)
|
||||
{
|
||||
double noWarn = 1, inWindow = 0;
|
||||
for (int d = today; d <= to; d++)
|
||||
{
|
||||
subsidy -= drain;
|
||||
double h = subsidy <= 0 ? 1 : dailyHazard;
|
||||
if (d >= from) inWindow += noWarn * h;
|
||||
noWarn *= 1 - h;
|
||||
}
|
||||
return inWindow;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 矿机时代在 [from, to] 开始的概率:没出预警时在 [eraMin, eraMax] 里均匀;预警已出(warnDay >= 0)时落在预警后 EraWarnMin..EraWarnMax 天。
|
||||
/// 只算还没过去的日子(today 之后)。
|
||||
/// </summary>
|
||||
public static double EraProb(int today, int from, int to, int warnDay)
|
||||
{
|
||||
int lo = warnDay >= 0 ? warnDay + Tuning.EraWarnMin : Tuning.EraMin, hi = warnDay >= 0 ? warnDay + Tuning.EraWarnMax : Tuning.EraMax;
|
||||
lo = Math.Max(lo, today + 1);
|
||||
if (hi < lo) return 0;
|
||||
int a = Math.Max(lo, from), b = Math.Min(hi, to);
|
||||
return b < a ? 0 : (b - a + 1) / (double)(hi - lo + 1);
|
||||
}
|
||||
|
||||
public static double FactionProb(int days) => 1 - Math.Pow(1 - Tuning.PredictFactionDaily, days);
|
||||
|
||||
/// <summary>均匀整数 lo..hi 里不低于 threshold 的概率。</summary>
|
||||
|
||||
Reference in new issue
Block a user