第十阶段 stage 2(二):CRA 部分抵押(储备、抵押率、挪用与崩盘线、劫掠补储备)、官方铸造与销毁排队、官方跑路、质押多币种入口
This commit is contained in:
1 parent
3758049dcb
commit
d0dfa93226
17 files changed
+489
-113
No files matched your search
@@ -1,19 +1,43 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Decentralized.Domain
|
namespace Decentralized.Domain
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 三种稳定币的价格与状态:CRC(上层,托管银行出事时脱锚、可能减记),CRT(黑市,镇压或火并时脱锚,
|
/// 三种稳定币的价格与状态:CRC(上层,托管银行出事时脱锚、可能减记),CRT(黑市,镇压或火并时脱锚,
|
||||||
/// 镇压期间按黑市声望出卖客户),CRA(革命军,质押付息,补贴池告急或外生触发时进入三天死亡螺旋)。
|
/// 镇压期间按黑市声望出卖客户),CRA(革命军,部分抵押:流通量 S、储备 R(CRC)、抵押率 c;质押利息以无抵押的新 CRA 付出,
|
||||||
|
/// 稀释储备覆盖率 R/S;革命军挪用储备时 R/S 低于崩盘线进入三天死亡螺旋,劫掠上层补回储备)。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
public enum CraOrderKind { Minted, Burned, Lost }
|
||||||
|
|
||||||
|
/// <summary>官方一级市场的排队单:铸造(存入 CRC 和 SPARK)或销毁(存入 CRA),到期结算,官方可能把它黑掉。</summary>
|
||||||
|
public sealed class CraOrder
|
||||||
|
{
|
||||||
|
public int Id, Due;
|
||||||
|
public string Wallet;
|
||||||
|
public bool Mint;
|
||||||
|
public double Cra, Crc, Spark, C;
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class CraOrderEvent
|
||||||
|
{
|
||||||
|
public CraOrder Order;
|
||||||
|
public CraOrderKind Kind;
|
||||||
|
public double Cra, Crc, Spark;
|
||||||
|
}
|
||||||
|
|
||||||
public sealed class Stablecoins
|
public sealed class Stablecoins
|
||||||
{
|
{
|
||||||
public double Crc = 1, Crt = 1, Cra = 1;
|
public double Crc = 1, Crt = 1, Cra = 1;
|
||||||
public int CrcDepegEnd = -1, CrtDepegEnd = -1;
|
public int CrcDepegEnd = -1, CrtDepegEnd = -1;
|
||||||
public bool CrcHaircutPending;
|
public bool CrcHaircutPending;
|
||||||
public double CraSubsidy = Tuning.CraSubsidy0;
|
/// <summary>CRA 流通量与储备(CRC);c 是现在铸造要求的 CRC 份额(0~1)。</summary>
|
||||||
public int CraWarnDay = -1, CraSpiralDay = -1;
|
public double Supply = Tuning.CraS0, Reserve = Tuning.CraS0 * Tuning.CraC0, C = Tuning.CraC0;
|
||||||
|
/// <summary>预兆日(新闻发出的那天)、预定的挪用日、崩盘开始日(-1 = 没有)。</summary>
|
||||||
|
public int CraWarnDay = -1, CraEventDay = -1, CraCrashDay = -1;
|
||||||
|
public List<CraOrder> Orders = new List<CraOrder>();
|
||||||
|
public int OrderSeq;
|
||||||
public double RevPower = 50;
|
public double RevPower = 50;
|
||||||
/// <summary>平衡代币 SPARK 的价格(信用点);SparkPre 是螺旋开始前一刻的价格,螺旋三天按它的倍数走。</summary>
|
/// <summary>平衡代币 SPARK 的价格(信用点);SparkPre 是螺旋开始前一刻的价格,螺旋三天按它的倍数走。</summary>
|
||||||
public double Spark = Tuning.SparkStart, SparkPre = -1;
|
public double Spark = Tuning.SparkStart, SparkPre = -1;
|
||||||
@@ -45,7 +69,7 @@ namespace Decentralized.Domain
|
|||||||
Crt = rng.Range(Tuning.CrtDepegMin, Tuning.CrtDepegMax);
|
Crt = rng.Range(Tuning.CrtDepegMin, Tuning.CrtDepegMax);
|
||||||
CrtDepegEnd = day + rng.Range(Tuning.CrtDepegDaysMin, Tuning.CrtDepegDaysMax);
|
CrtDepegEnd = day + rng.Range(Tuning.CrtDepegDaysMin, Tuning.CrtDepegDaysMax);
|
||||||
}
|
}
|
||||||
if (ev == MarketEvent.RevRaidUpper) Spark *= Tuning.SparkRaidShock;
|
if (ev == MarketEvent.RevRaidUpper) { Spark *= Tuning.SparkRaidShock; if (CraCrashDay < 0) Reserve += Tuning.CraLoot * Supply; }
|
||||||
if (ev == MarketEvent.LowerUnrest) Spark *= Tuning.SparkUnrestShock;
|
if (ev == MarketEvent.LowerUnrest) Spark *= Tuning.SparkUnrestShock;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -57,36 +81,68 @@ namespace Decentralized.Domain
|
|||||||
/// <summary>镇压开始时是否冻结玩家的 CRT:按黑市声望,声望越低越容易被黑市"出卖"。</summary>
|
/// <summary>镇压开始时是否冻结玩家的 CRT:按黑市声望,声望越低越容易被黑市"出卖"。</summary>
|
||||||
public static bool CrtFrozenByCrackdown(double blackMarketRep, Rng rng) => rng.Chance(CrtFreezeChance(blackMarketRep));
|
public static bool CrtFrozenByCrackdown(double blackMarketRep, Rng rng) => rng.Chance(CrtFreezeChance(blackMarketRep));
|
||||||
|
|
||||||
/// <summary>铸造:用 CRA 按当前价换 SPARK,收手续费。余额不足返回 -1。</summary>
|
/// <summary>储备覆盖率 R/S。</summary>
|
||||||
public double Mint(Wallet w, double cra)
|
public double Ratio => Supply > 0 ? Reserve / Supply : 1;
|
||||||
|
|
||||||
|
/// <summary>崩盘线之上的储备(CRC):吃空即必然崩盘。预测盘和线索用它估预兆。</summary>
|
||||||
|
public double Cushion => Reserve - Tuning.CraCrashRatio * Supply;
|
||||||
|
public static double Cushion0 => Tuning.CraS0 * (Tuning.CraC0 - Tuning.CraCrashRatio);
|
||||||
|
|
||||||
|
/// <summary>每晚的垫子消耗:利息按无抵押的新 CRA 付出,每份把崩盘线抬高 CraCrashRatio。</summary>
|
||||||
|
public static double CushionDrain(double stakedTotal, double rate) => stakedTotal * rate * Tuning.CraCrashRatio;
|
||||||
|
|
||||||
|
/// <summary>储备覆盖率对应的价格:高于安全线为 1,线性降到崩盘线的 1 − CraDiscountMax。</summary>
|
||||||
|
public static double PriceOfRatio(double r)
|
||||||
{
|
{
|
||||||
if (cra <= 0 || Spark <= 0 || w.Avail(Assets.CRA) + 1e-9 < cra) return -1;
|
if (r >= Tuning.CraSafeRatio) return 1;
|
||||||
double got = cra * Cra / Spark * (1 - Tuning.SparkFee);
|
double t = Math.Max(0, (r - Tuning.CraCrashRatio) / (Tuning.CraSafeRatio - Tuning.CraCrashRatio));
|
||||||
w.Add(Assets.CRA, -cra); w.Add(Assets.SPARK, got);
|
return 1 - Tuning.CraDiscountMax * (1 - t);
|
||||||
w.RecordBuy(Assets.SPARK, got, cra * Cra);
|
|
||||||
return got;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>销毁:用 SPARK 按当前价换 CRA,收手续费。余额不足返回 -1。</summary>
|
/// <summary>铸造 cra 个 CRA 要的 CRC 和 SPARK 数量(SPARK 部分按现价折算)。</summary>
|
||||||
public double Burn(Wallet w, double spark)
|
public void Collateral(double cra, out double crc, out double spark)
|
||||||
{
|
{
|
||||||
if (spark <= 0 || Cra <= 0 || w.Avail(Assets.SPARK) + 1e-9 < spark) return -1;
|
crc = cra * C;
|
||||||
double got = spark * Spark / Cra * (1 - Tuning.SparkFee);
|
spark = Spark > 0 ? cra * (1 - C) / Spark : 0;
|
||||||
w.Add(Assets.SPARK, -spark); w.Add(Assets.CRA, got);
|
|
||||||
w.RecordBuy(Assets.CRA, got, spark * Spark);
|
|
||||||
return got;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CraSubsidyLow => CraSubsidy <= Tuning.CraSubsidy0 * Tuning.CraSubsidyWarn;
|
/// <summary>
|
||||||
|
/// 铸造申请:从钱包扣 CRC 和 SPARK,排队 CraMintDaysMin..Max 天,到期铸出 CRA。余额不足返回 null。
|
||||||
|
/// </summary>
|
||||||
|
public CraOrder RequestMint(Wallet w, double cra, int day, Rng rng)
|
||||||
|
{
|
||||||
|
if (cra <= 0) return null;
|
||||||
|
Collateral(cra, out double crc, out double spark);
|
||||||
|
if (w.Avail(Assets.CRC) + 1e-9 < crc || w.Avail(Assets.SPARK) + 1e-9 < spark) return null;
|
||||||
|
w.Add(Assets.CRC, -crc); w.Add(Assets.SPARK, -spark);
|
||||||
|
var o = new CraOrder { Id = ++OrderSeq, Wallet = w.Address, Mint = true, Cra = cra, Crc = crc, Spark = spark, C = C, Due = day + rng.Range(Tuning.CraMintDaysMin, Tuning.CraMintDaysMax) };
|
||||||
|
Orders.Add(o);
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>销毁申请:从钱包扣 CRA,排队 CraUnlockDays 天,到期换回 CRC 和 SPARK。余额不足返回 null。</summary>
|
||||||
|
public CraOrder RequestBurn(Wallet w, double cra, int day)
|
||||||
|
{
|
||||||
|
if (cra <= 0 || w.Avail(Assets.CRA) + 1e-9 < cra) return null;
|
||||||
|
w.Add(Assets.CRA, -cra);
|
||||||
|
var o = new CraOrder { Id = ++OrderSeq, Wallet = w.Address, Mint = false, Cra = cra, C = C, Due = day + Tuning.CraUnlockDays };
|
||||||
|
Orders.Add(o);
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>官方每晚黑掉一笔排队单的概率:系数 × (1 − CRA 价格),价格不低于 1 时为 0。</summary>
|
||||||
|
public double RugChance => Math.Max(0, 1 - Cra) * Tuning.CraRugPerDepeg;
|
||||||
|
|
||||||
|
public bool CraSubsidyLow => Cushion <= Cushion0 * Tuning.CraSubsidyWarn;
|
||||||
|
|
||||||
/// <summary>CRA 的预兆:外生螺旋的新闻已出,或补贴池告急(利率下调)。螺旋开始后不再算预兆。</summary>
|
/// <summary>CRA 的预兆:外生螺旋的新闻已出,或补贴池告急(利率下调)。螺旋开始后不再算预兆。</summary>
|
||||||
public bool CraWarning(int day) => (CraWarnDay >= 0 && CraWarnDay <= day || CraSubsidyLow) && Cra >= 0.97;
|
public bool CraWarning(int day) => (CraWarnDay >= 0 && CraWarnDay <= day || CraSubsidyLow) && CraCrashDay < 0 && Cra >= 0.97;
|
||||||
|
|
||||||
public double CraRate => CraSubsidyLow ? Tuning.CraRateLow : Tuning.CraRate;
|
public double CraRate => CraSubsidyLow ? Tuning.CraRateLow : Tuning.CraRate;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 夜间结算。返回 CRC 持有量要乘的系数(减记兑现时为 0.95,否则为 1)。
|
/// 夜间结算。返回 CRC 持有量要乘的系数(减记兑现时为 0.95,否则为 1)。
|
||||||
/// playerStaked:玩家的 CRA 质押额,用来算补贴支出(玩家的利息由调用方按 <see cref="CraRate"/> 发放)。
|
/// playerStaked:玩家的 CRA 质押额,用来算利息带来的稀释(玩家的利息由调用方按 <see cref="CraRate"/> 发放)。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public double Night(int day, Rng rng, double playerStaked)
|
public double Night(int day, Rng rng, double playerStaked)
|
||||||
{
|
{
|
||||||
@@ -107,32 +163,87 @@ namespace Decentralized.Domain
|
|||||||
if (RevHistory.Count > 7) RevHistory.RemoveAt(0);
|
if (RevHistory.Count > 7) RevHistory.RemoveAt(0);
|
||||||
RevPower = Math.Max(0, Math.Min(100, RevPower + rng.Gauss() * 3));
|
RevPower = Math.Max(0, Math.Min(100, RevPower + rng.Gauss() * 3));
|
||||||
|
|
||||||
if (CraSpiralDay < 0)
|
if (CraCrashDay < 0)
|
||||||
|
{
|
||||||
|
double interest = (Tuning.CraNpcStake + playerStaked) * CraRate;
|
||||||
|
Supply += interest;
|
||||||
|
// 抵押率调整:价格低于 1 上调,回到 1 下调;兑付的 CRC 份额不超过储备均值(见 <see cref="Redeem"/>)
|
||||||
|
if (Cra < 0.995) C = Math.Min(1, C + Tuning.CraCrStep);
|
||||||
|
else if (Cra >= 0.999) C = Math.Max(Tuning.CraCrMin, C - Tuning.CraCrStep);
|
||||||
|
if (CraEventDay < 0)
|
||||||
{
|
{
|
||||||
CraSubsidy -= (Tuning.CraNpcStake + playerStaked) * CraRate;
|
|
||||||
bool revFalling = RevHistory.Count == 7 && RevPower < RevHistory[0] - 5;
|
bool revFalling = RevHistory.Count == 7 && RevPower < RevHistory[0] - 5;
|
||||||
double weekly = Tuning.CraSpiralWeekly * (revFalling ? 3 : 1) * StoryMods.Current.CraSpiral(day);
|
double weekly = Tuning.CraSpiralWeekly * (revFalling ? 3 : 1) * StoryMods.Current.CraSpiral(day);
|
||||||
double daily = 1 - Math.Pow(1 - weekly, 1.0 / 7);
|
double daily = 1 - Math.Pow(1 - weekly, 1.0 / 7);
|
||||||
if (CraWarnDay < 0 && (rng.Chance(daily) || CraSubsidy <= 0))
|
if (rng.Chance(daily) || Cushion <= 0)
|
||||||
{
|
{
|
||||||
CraWarnDay = day;
|
CraWarnDay = day;
|
||||||
CraSpiralDay = day + rng.Range(Tuning.CraWarnLeadMin, Tuning.CraWarnLeadMax);
|
CraEventDay = day + rng.Range(Tuning.CraWarnLeadMin, Tuning.CraWarnLeadMax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (CraSpiralDay > 0 && day >= CraSpiralDay)
|
else if (day >= CraEventDay)
|
||||||
{
|
{
|
||||||
int k = Math.Min(day - CraSpiralDay, Tuning.CraSpiralPath.Length - 1);
|
// 挪用:储备被革命军拿走一部分,R/S 掉到崩盘线以下就是挤兑
|
||||||
|
Reserve *= 1 - rng.Range(Tuning.CraEmbezzleMin, Tuning.CraEmbezzleMax);
|
||||||
|
CraEventDay = -1; CraWarnDay = -1;
|
||||||
|
if (Ratio < Tuning.CraCrashRatio) CraCrashDay = day;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (CraCrashDay >= 0)
|
||||||
|
{
|
||||||
|
int k = Math.Min(day - CraCrashDay, Tuning.CraSpiralPath.Length - 1);
|
||||||
Cra = Tuning.CraSpiralPath[k];
|
Cra = Tuning.CraSpiralPath[k];
|
||||||
if (SparkPre < 0) SparkPre = Spark;
|
if (SparkPre < 0) SparkPre = Spark;
|
||||||
Spark = SparkPre * Tuning.SparkSpiralPath[Math.Min(day - CraSpiralDay, Tuning.SparkSpiralPath.Length - 1)];
|
Spark = SparkPre * Tuning.SparkSpiralPath[Math.Min(day - CraCrashDay, Tuning.SparkSpiralPath.Length - 1)];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Cra = PriceOfRatio(Ratio);
|
||||||
Spark *= Math.Exp(rng.Gauss() * Tuning.SparkVol) * StoryMods.Current.TakeSparkPush();
|
Spark *= Math.Exp(rng.Gauss() * Tuning.SparkVol) * StoryMods.Current.TakeSparkPush();
|
||||||
Spark += (Tuning.SparkStart - Spark) * Tuning.SparkRevert;
|
Spark += (Tuning.SparkStart - Spark) * Tuning.SparkRevert;
|
||||||
Spark = Math.Max(Tuning.SparkStart * Tuning.SparkMinMult, Math.Min(Tuning.SparkStart * Tuning.SparkMaxMult, Spark));
|
Spark = Math.Max(Tuning.SparkStart * Tuning.SparkMinMult, Math.Min(Tuning.SparkStart * Tuning.SparkMaxMult, Spark));
|
||||||
}
|
}
|
||||||
return crcFactor;
|
return crcFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 销毁一份 CRA 的兑付:CRC 份额 = min(申请时的 c, 储备均值 R/S),其余按现价用新增发的 SPARK 补。
|
||||||
|
/// 返回 (CRC 数量, SPARK 数量),并扣减储备和流通量。
|
||||||
|
/// </summary>
|
||||||
|
public void Redeem(double cra, double c, out double crc, out double spark)
|
||||||
|
{
|
||||||
|
double share = Math.Min(c, Ratio);
|
||||||
|
crc = Math.Min(Reserve, cra * share);
|
||||||
|
spark = Spark > 0 ? cra * (1 - crc / Math.Max(1e-9, cra)) / Spark : 0;
|
||||||
|
Reserve -= crc; Supply = Math.Max(0, Supply - cra);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 夜间处理排队单:先对每一笔掷官方跑路(整笔丢失),再结算到期的。
|
||||||
|
/// 铸造到期:CRC 进储备、SPARK 销毁、流通量增加;销毁到期:按 <see cref="Redeem"/> 兑付。
|
||||||
|
/// </summary>
|
||||||
|
public List<CraOrderEvent> NightOrders(int day, Rng rng)
|
||||||
|
{
|
||||||
|
var evs = new List<CraOrderEvent>();
|
||||||
|
foreach (var o in Orders.ToList())
|
||||||
|
{
|
||||||
|
if (rng.Chance(RugChance)) { Orders.Remove(o); evs.Add(new CraOrderEvent { Order = o, Kind = CraOrderKind.Lost }); continue; }
|
||||||
|
if (day < o.Due) continue;
|
||||||
|
Orders.Remove(o);
|
||||||
|
var ev = new CraOrderEvent { Order = o };
|
||||||
|
if (o.Mint)
|
||||||
|
{
|
||||||
|
Supply += o.Cra; Reserve += o.Crc;
|
||||||
|
ev.Kind = CraOrderKind.Minted; ev.Cra = o.Cra;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Redeem(o.Cra, o.C, out ev.Crc, out ev.Spark);
|
||||||
|
ev.Kind = CraOrderKind.Burned;
|
||||||
|
}
|
||||||
|
evs.Add(ev);
|
||||||
|
}
|
||||||
|
return evs;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -51,8 +51,15 @@ namespace Decentralized.Domain
|
|||||||
public const double CrtSwapFee = 0.02;
|
public const double CrtSwapFee = 0.02;
|
||||||
public const double CraRate = 0.005, CraRateLow = 0.002;
|
public const double CraRate = 0.005, CraRateLow = 0.002;
|
||||||
public const int CraUnlockDays = 4;
|
public const int CraUnlockDays = 4;
|
||||||
public const double CraSubsidy0 = 30000, CraSubsidyWarn = 0.2, CraNpcStake = 20000;
|
public const double CraSubsidyWarn = 0.2, CraNpcStake = 20000;
|
||||||
public const double CraSpiralWeekly = 0.02;
|
/// <summary>CRA 部分抵押:初始流通量与抵押率、抵押率下限与每晚调整步长;R/S 安全线、崩盘线、安全线到崩盘线之间的最大折价;
|
||||||
|
/// 挪用储备的比例范围;劫掠上层补回的储备(占流通量);一级市场铸造等待天数;官方跑路系数(× (1 − CRA 价格))。数值由 research/crasim 定。</summary>
|
||||||
|
public const double CraS0 = 60000, CraC0 = 0.8, CraCrMin = 0.5, CraCrStep = 0.02;
|
||||||
|
public const double CraSafeRatio = 0.6, CraCrashRatio = 0.35, CraDiscountMax = 0.15;
|
||||||
|
public const double CraEmbezzleMin = 0.4, CraEmbezzleMax = 0.8, CraLoot = 0.09;
|
||||||
|
public const int CraMintDaysMin = 1, CraMintDaysMax = 2;
|
||||||
|
public const double CraRugPerDepeg = 1;
|
||||||
|
public const double CraSpiralWeekly = 0.03;
|
||||||
public const int CraWarnLeadMin = 4, CraWarnLeadMax = 7;
|
public const int CraWarnLeadMin = 4, CraWarnLeadMax = 7;
|
||||||
public static readonly double[] CraSpiralPath = { 0.85, 0.30, 0.02 };
|
public static readonly double[] CraSpiralPath = { 0.85, 0.30, 0.02 };
|
||||||
/// <summary>平衡代币 SPARK:起始价与长期锚(信用点)、日波动率、每晚向锚回归的比例、价格上下限(锚的倍数);铸销手续费;
|
/// <summary>平衡代币 SPARK:起始价与长期锚(信用点)、日波动率、每晚向锚回归的比例、价格上下限(锚的倍数);铸销手续费;
|
||||||
|
|||||||
@@ -172,11 +172,23 @@ namespace Decentralized.Domain
|
|||||||
["CoinPayCrt"] = Tuning.CoinPayCrt,
|
["CoinPayCrt"] = Tuning.CoinPayCrt,
|
||||||
["CoinPayPremium"] = Tuning.CoinPayPremium,
|
["CoinPayPremium"] = Tuning.CoinPayPremium,
|
||||||
["CoinPayPsc"] = Tuning.CoinPayPsc,
|
["CoinPayPsc"] = Tuning.CoinPayPsc,
|
||||||
|
["CraC0"] = Tuning.CraC0,
|
||||||
|
["CraCrMin"] = Tuning.CraCrMin,
|
||||||
|
["CraCrStep"] = Tuning.CraCrStep,
|
||||||
|
["CraCrashRatio"] = Tuning.CraCrashRatio,
|
||||||
|
["CraDiscountMax"] = Tuning.CraDiscountMax,
|
||||||
|
["CraEmbezzleMax"] = Tuning.CraEmbezzleMax,
|
||||||
|
["CraEmbezzleMin"] = Tuning.CraEmbezzleMin,
|
||||||
|
["CraLoot"] = Tuning.CraLoot,
|
||||||
|
["CraMintDaysMax"] = Tuning.CraMintDaysMax,
|
||||||
|
["CraMintDaysMin"] = Tuning.CraMintDaysMin,
|
||||||
["CraNpcStake"] = Tuning.CraNpcStake,
|
["CraNpcStake"] = Tuning.CraNpcStake,
|
||||||
["CraRate"] = Tuning.CraRate,
|
["CraRate"] = Tuning.CraRate,
|
||||||
["CraRateLow"] = Tuning.CraRateLow,
|
["CraRateLow"] = Tuning.CraRateLow,
|
||||||
|
["CraRugPerDepeg"] = Tuning.CraRugPerDepeg,
|
||||||
|
["CraS0"] = Tuning.CraS0,
|
||||||
|
["CraSafeRatio"] = Tuning.CraSafeRatio,
|
||||||
["CraSpiralWeekly"] = Tuning.CraSpiralWeekly,
|
["CraSpiralWeekly"] = Tuning.CraSpiralWeekly,
|
||||||
["CraSubsidy0"] = Tuning.CraSubsidy0,
|
|
||||||
["CraSubsidyWarn"] = Tuning.CraSubsidyWarn,
|
["CraSubsidyWarn"] = Tuning.CraSubsidyWarn,
|
||||||
["CraUnlockDays"] = Tuning.CraUnlockDays,
|
["CraUnlockDays"] = Tuning.CraUnlockDays,
|
||||||
["CraWarnLeadMax"] = Tuning.CraWarnLeadMax,
|
["CraWarnLeadMax"] = Tuning.CraWarnLeadMax,
|
||||||
|
|||||||
@@ -89,8 +89,8 @@ namespace Decentralized
|
|||||||
var d = Session.Data; int day = StoreStation.GetDayCounter(); var bk = d.Predict;
|
var d = Session.Data; int day = StoreStation.GetDayCounter(); var bk = d.Predict;
|
||||||
bk.Markets.Add(PredictMarket.Create(++bk.Seq, PredictKind.Era, "era", L.T("predict.era"), 0, day, day + 1, day + 3, PredictMath.EraProb(day, day + 1, day + 3, -1) + 0.05));
|
bk.Markets.Add(PredictMarket.Create(++bk.Seq, PredictKind.Era, "era", L.T("predict.era"), 0, day, day + 1, day + 3, PredictMath.EraProb(day, day + 1, day + 3, -1) + 0.05));
|
||||||
double h = 1 - System.Math.Pow(1 - Tuning.CraSpiralWeekly, 1.0 / 7);
|
double h = 1 - System.Math.Pow(1 - Tuning.CraSpiralWeekly, 1.0 / 7);
|
||||||
bk.Markets.Add(PredictMarket.Create(++bk.Seq, PredictKind.Cra, "cra", "CRA", 0, day, day + 1, day + 3, PredictMath.CraWarnProb(d.Stable.CraSubsidy, (Tuning.CraNpcStake + d.Staking.Earning) * d.Stable.CraRate, day, day + 1, day + 3, h)));
|
bk.Markets.Add(PredictMarket.Create(++bk.Seq, PredictKind.Cra, "cra", "CRA", 0, day, day + 1, day + 3, PredictMath.CraWarnProb(d.Stable.Cushion, Stablecoins.CushionDrain(Tuning.CraNpcStake + d.Staking.Earning, d.Stable.CraRate), day, day + 1, day + 3, h)));
|
||||||
Log.Info($"测试:矿机时代 {d.Network.EraDay},CRA 补贴池 {d.Stable.CraSubsidy:0}");
|
Log.Info($"测试:矿机时代 {d.Network.EraDay},CRA 储备 {d.Stable.Reserve:0}(R/S {d.Stable.Ratio:0.00})");
|
||||||
});
|
});
|
||||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Informant: queue power shortage in 3 days (test)", () => Log.Guard("线人测试", () =>
|
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Informant: queue power shortage in 3 days (test)", () => Log.Guard("线人测试", () =>
|
||||||
{
|
{
|
||||||
@@ -186,8 +186,8 @@ namespace Decentralized
|
|||||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "CRA spiral warning (test)", () =>
|
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "CRA spiral warning (test)", () =>
|
||||||
{
|
{
|
||||||
var st = Session.Data.Stable; int day = StoreStation.GetDayCounter();
|
var st = Session.Data.Stable; int day = StoreStation.GetDayCounter();
|
||||||
st.CraWarnDay = day; st.CraSpiralDay = day + 3;
|
st.CraWarnDay = day; st.CraEventDay = day + 3;
|
||||||
Log.Info($"测试:CRA 预兆今天,螺旋第 {st.CraSpiralDay} 天");
|
Log.Info($"测试:CRA 预兆今天,挪用日第 {st.CraEventDay} 天");
|
||||||
});
|
});
|
||||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Give terminal (test)", () => { Items.Give(ModHelper.SpawnItem(Items.Terminal)); });
|
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Give terminal (test)", () => { Items.Give(ModHelper.SpawnItem(Items.Terminal)); });
|
||||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Hardware wallets (test)", () => { Items.Give(Items.NewHwWallet(false)); Items.Give(Items.NewHwWallet(true)); Log.Info("测试:给了一个正品、一个被投毒的硬件钱包"); });
|
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Hardware wallets (test)", () => { Items.Give(Items.NewHwWallet(false)); Items.Give(Items.NewHwWallet(true)); Log.Info("测试:给了一个正品、一个被投毒的硬件钱包"); });
|
||||||
|
|||||||
@@ -460,9 +460,6 @@ stake.ops,{0}
|
|||||||
stake.avail,CRA {0} Gestakt {1}
|
stake.avail,CRA {0} Gestakt {1}
|
||||||
stake.do,Staken
|
stake.do,Staken
|
||||||
stake.undo,Auszahlung beantragen
|
stake.undo,Auszahlung beantragen
|
||||||
spark.h,Ausgleichstoken
|
|
||||||
spark.mint,SPARK prägen
|
|
||||||
spark.burn,SPARK verbrennen
|
|
||||||
stake.sum.in,{0} CRA staken
|
stake.sum.in,{0} CRA staken
|
||||||
stake.sum.out,Auszahlung von {0} CRA beantragen (Gutschrift in {1} Tagen)
|
stake.sum.out,Auszahlung von {0} CRA beantragen (Gutschrift in {1} Tagen)
|
||||||
stake.done.in,{0} CRA gestakt.
|
stake.done.in,{0} CRA gestakt.
|
||||||
@@ -470,9 +467,7 @@ stake.done.out,Auszahlung von {0} CRA beantragt; Rückkehr in die Wallet an Tag
|
|||||||
nightlog.stakeint,Staking-Zinsen +{0} CRA.
|
nightlog.stakeint,Staking-Zinsen +{0} CRA.
|
||||||
nightlog.unstaked,{0} CRA aus dem Staking wurden an {1} zurückgebucht.
|
nightlog.unstaked,{0} CRA aus dem Staking wurden an {1} zurückgebucht.
|
||||||
news.crawarn.title,Unruhe im Revolution-Staking-Pool
|
news.crawarn.title,Unruhe im Revolution-Staking-Pool
|
||||||
news.crawarn.desc,"Großanleger ziehen Kapital ab und der Staking-Subventionspool leert sich. Die Entsperrung dauert vier Tage; manche meinen, es sei Zeit zu handeln."
|
|
||||||
news.cralow.title,Revolution senkt Staking-Zinssatz
|
news.cralow.title,Revolution senkt Staking-Zinssatz
|
||||||
news.cralow.desc,Der Subventionspool ist fast leer und die Revolution hat den CRA-Staking-Zins auf einen Bruchteil gekürzt.
|
|
||||||
stake.avail2,SPARK {0}
|
stake.avail2,SPARK {0}
|
||||||
poin.sub.spot,Spot
|
poin.sub.spot,Spot
|
||||||
poin.sub.perp,Perps
|
poin.sub.perp,Perps
|
||||||
@@ -906,3 +901,21 @@ swap.get,Erhalten
|
|||||||
swap.preview,"Ca. {0} {1} {2} Pool(s), Verlust {3} %"
|
swap.preview,"Ca. {0} {1} {2} Pool(s), Verlust {3} %"
|
||||||
swap.go,Tauschen
|
swap.go,Tauschen
|
||||||
swap.same,Zahlungs- und Empfangswährung müssen verschieden sein.
|
swap.same,Zahlungs- und Empfangswährung müssen verschieden sein.
|
||||||
|
cra.mint,Prägen
|
||||||
|
cra.burn,Einlösen
|
||||||
|
mint.h,Offizielle Prägung (CRC + SPARK)
|
||||||
|
mint.need,Benötigt {0} CRC und {1} SPARK
|
||||||
|
mint.reserve,Reservedeckung {0} % Besicherung {1} %
|
||||||
|
mint.queue,Offene Aufträge
|
||||||
|
mint.order,"{0} {1} CRA, Tag {2}"
|
||||||
|
mint.sum.in,{0} CRA mit {1} CRC und {2} SPARK prägen ({3}–{4} Tage)
|
||||||
|
mint.sum.out,{0} CRA gegen CRC und SPARK einlösen ({1} Tage)
|
||||||
|
mint.done.in,Prägeauftrag erteilt; fällig an Tag {0}.
|
||||||
|
mint.done.out,Einlöseauftrag erteilt; fällig an Tag {0}.
|
||||||
|
stake.coin,Einzahlungswährung
|
||||||
|
stake.sum.via,{0} {1} tauschen → ca. {2} CRA und staken
|
||||||
|
nightlog.cra.minted,{0} CRA geprägt und gestakt ({1}).
|
||||||
|
nightlog.cra.burned,"{0} CRA eingelöst: +{1} CRC, +{2} SPARK ({3})."
|
||||||
|
nightlog.cra.lost,Der Herausgeber hat nicht reagiert: Der Auftrag ({1}) über {0} CRA ist verloren.
|
||||||
|
news.crawarn.desc,"Jemand zählt die Reserve der Revolution nach; gestaktes CRA lässt sich womöglich nicht vollständig einlösen. Das Entsperren dauert vier Tage; manche sagen, es sei Zeit zu handeln."
|
||||||
|
news.cralow.desc,Die Reservedeckung wird knapp; die Revolution hat den CRA-Staking-Zins auf einen Bruchteil gesenkt.
|
||||||
|
@@ -460,9 +460,6 @@ stake.ops,{0}
|
|||||||
stake.avail,CRA {0} Staked {1}
|
stake.avail,CRA {0} Staked {1}
|
||||||
stake.do,Stake
|
stake.do,Stake
|
||||||
stake.undo,Request withdrawal
|
stake.undo,Request withdrawal
|
||||||
spark.h,Balance token
|
|
||||||
spark.mint,Mint SPARK
|
|
||||||
spark.burn,Burn SPARK
|
|
||||||
stake.sum.in,Stake {0} CRA
|
stake.sum.in,Stake {0} CRA
|
||||||
stake.sum.out,Request withdrawal of {0} CRA (arrives in {1} days)
|
stake.sum.out,Request withdrawal of {0} CRA (arrives in {1} days)
|
||||||
stake.done.in,Staked {0} CRA.
|
stake.done.in,Staked {0} CRA.
|
||||||
@@ -470,9 +467,7 @@ stake.done.out,Requested withdrawal of {0} CRA; back in the wallet on day {1}.
|
|||||||
nightlog.stakeint,Staking interest +{0} CRA.
|
nightlog.stakeint,Staking interest +{0} CRA.
|
||||||
nightlog.unstaked,{0} CRA withdrawn from staking returned to {1}.
|
nightlog.unstaked,{0} CRA withdrawn from staking returned to {1}.
|
||||||
news.crawarn.title,Unrest at the Revolution staking pool
|
news.crawarn.title,Unrest at the Revolution staking pool
|
||||||
news.crawarn.desc,Big holders are pulling out and the staking subsidy pool is running dry. Unlocking takes four days; some say it is time to move.
|
|
||||||
news.cralow.title,Revolution cuts staking rate
|
news.cralow.title,Revolution cuts staking rate
|
||||||
news.cralow.desc,"The subsidy pool is nearly empty, and the Revolution has cut the CRA staking rate to a fraction."
|
|
||||||
stake.avail2,SPARK {0}
|
stake.avail2,SPARK {0}
|
||||||
poin.sub.spot,Spot
|
poin.sub.spot,Spot
|
||||||
poin.sub.perp,Perps
|
poin.sub.perp,Perps
|
||||||
@@ -906,3 +901,21 @@ swap.get,Receive
|
|||||||
swap.preview,"Receive about {0} {1} {2} pool(s), loss {3}%"
|
swap.preview,"Receive about {0} {1} {2} pool(s), loss {3}%"
|
||||||
swap.go,Swap
|
swap.go,Swap
|
||||||
swap.same,Pay and receive must be different coins.
|
swap.same,Pay and receive must be different coins.
|
||||||
|
cra.mint,Mint
|
||||||
|
cra.burn,Redeem
|
||||||
|
mint.h,Official mint (CRC + SPARK)
|
||||||
|
mint.need,Needs {0} CRC and {1} SPARK
|
||||||
|
mint.reserve,Reserve ratio {0}% Collateral ratio {1}%
|
||||||
|
mint.queue,Pending orders
|
||||||
|
mint.order,"{0} {1} CRA, day {2}"
|
||||||
|
mint.sum.in,Mint {0} CRA with {1} CRC and {2} SPARK ({3}–{4} days)
|
||||||
|
mint.sum.out,Redeem {0} CRA for CRC and SPARK ({1} days)
|
||||||
|
mint.done.in,Mint order placed; due on day {0}.
|
||||||
|
mint.done.out,Redeem order placed; due on day {0}.
|
||||||
|
stake.coin,Deposit coin
|
||||||
|
stake.sum.via,"Swap {0} {1} → about {2} CRA, then stake"
|
||||||
|
nightlog.cra.minted,"Minted {0} CRA, now staked ({1})."
|
||||||
|
nightlog.cra.burned,"Redeemed {0} CRA: +{1} CRC, +{2} SPARK ({3})."
|
||||||
|
nightlog.cra.lost,The issuer did not respond: the {1} order of {0} CRA is lost.
|
||||||
|
news.crawarn.desc,"Someone is counting the Revolution's reserve, and staked CRA may not be redeemable in full. Unlocking takes four days; some say it is time to move."
|
||||||
|
news.cralow.desc,"The reserve ratio is running low, and the Revolution has cut the CRA staking rate to a fraction."
|
||||||
|
@@ -460,9 +460,6 @@ stake.ops,{0}
|
|||||||
stake.avail,CRA {0} En staking {1}
|
stake.avail,CRA {0} En staking {1}
|
||||||
stake.do,Hacer staking
|
stake.do,Hacer staking
|
||||||
stake.undo,Solicitar retiro
|
stake.undo,Solicitar retiro
|
||||||
spark.h,Token de balance
|
|
||||||
spark.mint,Acuñar SPARK
|
|
||||||
spark.burn,Quemar SPARK
|
|
||||||
stake.sum.in,Poner {0} CRA en staking
|
stake.sum.in,Poner {0} CRA en staking
|
||||||
stake.sum.out,Solicitar retiro de {0} CRA (llega en {1} día(s))
|
stake.sum.out,Solicitar retiro de {0} CRA (llega en {1} día(s))
|
||||||
stake.done.in,{0} CRA puestos en staking.
|
stake.done.in,{0} CRA puestos en staking.
|
||||||
@@ -470,9 +467,7 @@ stake.done.out,Retiro de {0} CRA solicitado; vuelve a la billetera el día {1}.
|
|||||||
nightlog.stakeint,Interés de staking +{0} CRA.
|
nightlog.stakeint,Interés de staking +{0} CRA.
|
||||||
nightlog.unstaked,Los {0} CRA retirados de staking volvieron a {1}.
|
nightlog.unstaked,Los {0} CRA retirados de staking volvieron a {1}.
|
||||||
news.crawarn.title,Agitación en el fondo de staking de la Revolución
|
news.crawarn.title,Agitación en el fondo de staking de la Revolución
|
||||||
news.crawarn.desc,Los grandes inversores están retirándose y el fondo de subsidio de staking se agota. El desbloqueo tarda cuatro días; algunos dicen que es hora de actuar.
|
|
||||||
news.cralow.title,La Revolución reduce la tasa de staking
|
news.cralow.title,La Revolución reduce la tasa de staking
|
||||||
news.cralow.desc,"El fondo de subsidio está casi vacío, y la Revolución redujo la tasa de staking de CRA a una fracción."
|
|
||||||
stake.avail2,SPARK {0}
|
stake.avail2,SPARK {0}
|
||||||
poin.sub.spot,Spot
|
poin.sub.spot,Spot
|
||||||
poin.sub.perp,Perpetuos
|
poin.sub.perp,Perpetuos
|
||||||
@@ -906,3 +901,21 @@ swap.get,Recibir
|
|||||||
swap.preview,"Aprox. {0} {1} {2} pool(s), pérdida {3} %"
|
swap.preview,"Aprox. {0} {1} {2} pool(s), pérdida {3} %"
|
||||||
swap.go,Canjear
|
swap.go,Canjear
|
||||||
swap.same,Las monedas a pagar y recibir deben ser distintas.
|
swap.same,Las monedas a pagar y recibir deben ser distintas.
|
||||||
|
cra.mint,Acuñar
|
||||||
|
cra.burn,Redimir
|
||||||
|
mint.h,Acuñación oficial (CRC + SPARK)
|
||||||
|
mint.need,Requiere {0} CRC y {1} SPARK
|
||||||
|
mint.reserve,Cobertura {0} % Colateral {1} %
|
||||||
|
mint.queue,Órdenes pendientes
|
||||||
|
mint.order,"{0} {1} CRA, día {2}"
|
||||||
|
mint.sum.in,Acuñar {0} CRA con {1} CRC y {2} SPARK ({3}–{4} días)
|
||||||
|
mint.sum.out,Redimir {0} CRA por CRC y SPARK ({1} días)
|
||||||
|
mint.done.in,Orden de acuñación enviada; vence el día {0}.
|
||||||
|
mint.done.out,Orden de redención enviada; vence el día {0}.
|
||||||
|
stake.coin,Moneda a depositar
|
||||||
|
stake.sum.via,Canjear {0} {1} → aprox. {2} CRA y apostar
|
||||||
|
nightlog.cra.minted,{0} CRA acuñados y apostados ({1}).
|
||||||
|
nightlog.cra.burned,"{0} CRA redimidos: +{1} CRC, +{2} SPARK ({3})."
|
||||||
|
nightlog.cra.lost,El emisor no respondió: la orden ({1}) de {0} CRA se perdió.
|
||||||
|
news.crawarn.desc,Alguien está contando la reserva de la Revolución y quizá los CRA apostados no se puedan redimir por completo. Desbloquear tarda cuatro días; algunos dicen que es hora de actuar.
|
||||||
|
news.cralow.desc,La cobertura de la reserva se agota y la Revolución ha recortado el tipo de apuesta de CRA a una fracción.
|
||||||
|
@@ -460,9 +460,6 @@ stake.ops,{0}
|
|||||||
stake.avail,CRA {0} Staké {1}
|
stake.avail,CRA {0} Staké {1}
|
||||||
stake.do,Staker
|
stake.do,Staker
|
||||||
stake.undo,Demander un retrait
|
stake.undo,Demander un retrait
|
||||||
spark.h,Jeton d'équilibre
|
|
||||||
spark.mint,Frapper SPARK
|
|
||||||
spark.burn,Brûler SPARK
|
|
||||||
stake.sum.in,Staker {0} CRA
|
stake.sum.in,Staker {0} CRA
|
||||||
stake.sum.out,Demander le retrait de {0} CRA (disponible dans {1} jours)
|
stake.sum.out,Demander le retrait de {0} CRA (disponible dans {1} jours)
|
||||||
stake.done.in,{0} CRA stakés.
|
stake.done.in,{0} CRA stakés.
|
||||||
@@ -470,9 +467,7 @@ stake.done.out,Retrait de {0} CRA demandé ; retour au portefeuille le jour {1}.
|
|||||||
nightlog.stakeint,Intérêts de staking +{0} CRA.
|
nightlog.stakeint,Intérêts de staking +{0} CRA.
|
||||||
nightlog.unstaked,Les {0} CRA retirés du staking sont revenus sur {1}.
|
nightlog.unstaked,Les {0} CRA retirés du staking sont revenus sur {1}.
|
||||||
news.crawarn.title,Troubles au pool de staking de la Révolution
|
news.crawarn.title,Troubles au pool de staking de la Révolution
|
||||||
news.crawarn.desc,Les gros détenteurs se retirent et le pool de subvention de staking s'épuise. Le déverrouillage prend quatre jours ; certains disent qu'il est temps d'agir.
|
|
||||||
news.cralow.title,La Révolution réduit le taux de staking
|
news.cralow.title,La Révolution réduit le taux de staking
|
||||||
news.cralow.desc,"Le pool de subvention est presque vide, et la Révolution a réduit le taux de staking du CRA à une fraction de sa valeur."
|
|
||||||
stake.avail2,SPARK {0}
|
stake.avail2,SPARK {0}
|
||||||
poin.sub.spot,Spot
|
poin.sub.spot,Spot
|
||||||
poin.sub.perp,Perps
|
poin.sub.perp,Perps
|
||||||
@@ -906,3 +901,21 @@ swap.get,Recevoir
|
|||||||
swap.preview,"Environ {0} {1} {2} pool(s), perte {3} %"
|
swap.preview,"Environ {0} {1} {2} pool(s), perte {3} %"
|
||||||
swap.go,Échanger
|
swap.go,Échanger
|
||||||
swap.same,Les monnaies payée et reçue doivent différer.
|
swap.same,Les monnaies payée et reçue doivent différer.
|
||||||
|
cra.mint,Frapper
|
||||||
|
cra.burn,Racheter
|
||||||
|
mint.h,Frappe officielle (CRC + SPARK)
|
||||||
|
mint.need,Nécessite {0} CRC et {1} SPARK
|
||||||
|
mint.reserve,Couverture {0} % Collatéral {1} %
|
||||||
|
mint.queue,Ordres en attente
|
||||||
|
mint.order,"{0} {1} CRA, jour {2}"
|
||||||
|
mint.sum.in,Frapper {0} CRA avec {1} CRC et {2} SPARK ({3}–{4} jours)
|
||||||
|
mint.sum.out,Racheter {0} CRA contre CRC et SPARK ({1} jours)
|
||||||
|
mint.done.in,Ordre de frappe passé ; échéance au jour {0}.
|
||||||
|
mint.done.out,Ordre de rachat passé ; échéance au jour {0}.
|
||||||
|
stake.coin,Monnaie déposée
|
||||||
|
stake.sum.via,Échanger {0} {1} → environ {2} CRA puis staker
|
||||||
|
nightlog.cra.minted,{0} CRA frappés et stakés ({1}).
|
||||||
|
nightlog.cra.burned,"{0} CRA rachetés : +{1} CRC, +{2} SPARK ({3})."
|
||||||
|
nightlog.cra.lost,L'émetteur n'a pas répondu : l'ordre ({1}) de {0} CRA est perdu.
|
||||||
|
news.crawarn.desc,Quelqu'un fait l'inventaire de la réserve de la Révolution ; les CRA stakés pourraient ne pas être remboursés en totalité. Le déblocage prend quatre jours ; certains disent qu'il est temps d'agir.
|
||||||
|
news.cralow.desc,La couverture de la réserve s'amenuise ; la Révolution a réduit le taux de staking du CRA à une fraction.
|
||||||
|
@@ -460,9 +460,6 @@ stake.ops,{0}
|
|||||||
stake.avail,CRA {0} ステーキング中 {1}
|
stake.avail,CRA {0} ステーキング中 {1}
|
||||||
stake.do,ステーキング
|
stake.do,ステーキング
|
||||||
stake.undo,出金申請
|
stake.undo,出金申請
|
||||||
spark.h,バランストークン
|
|
||||||
spark.mint,SPARKをミント
|
|
||||||
spark.burn,SPARKをバーン
|
|
||||||
stake.sum.in,{0} CRA をステーキング
|
stake.sum.in,{0} CRA をステーキング
|
||||||
stake.sum.out,{0} CRA の出金申請({1}日後に着金)
|
stake.sum.out,{0} CRA の出金申請({1}日後に着金)
|
||||||
stake.done.in,{0} CRA をステーキングしました。
|
stake.done.in,{0} CRA をステーキングしました。
|
||||||
@@ -470,9 +467,7 @@ stake.done.out,{0} CRA の出金を申請しました。{1}日目にウォレッ
|
|||||||
nightlog.stakeint,ステーキング利息 +{0} CRA。
|
nightlog.stakeint,ステーキング利息 +{0} CRA。
|
||||||
nightlog.unstaked,ステーキングから出金された {0} CRA が {1} に戻った。
|
nightlog.unstaked,ステーキングから出金された {0} CRA が {1} に戻った。
|
||||||
news.crawarn.title,革命家のステーキングプールに不穏な動き
|
news.crawarn.title,革命家のステーキングプールに不穏な動き
|
||||||
news.crawarn.desc,大口保有者が相次いで資金を引き揚げており、補助金プールが枯渇寸前だ。ロック解除には4日かかるため、今すぐ動くべきだとの声も上がっている。
|
|
||||||
news.cralow.title,革命家がステーキングの日利を引き下げ
|
news.cralow.title,革命家がステーキングの日利を引き下げ
|
||||||
news.cralow.desc,補助金プールがほぼ底をつき、革命家はCRAステーキングの日利を従来のごくわずかな水準まで引き下げた。
|
|
||||||
stake.avail2,SPARK {0}
|
stake.avail2,SPARK {0}
|
||||||
poin.sub.spot,現物
|
poin.sub.spot,現物
|
||||||
poin.sub.perp,無期限先物
|
poin.sub.perp,無期限先物
|
||||||
@@ -906,3 +901,21 @@ swap.get,受取
|
|||||||
swap.preview,約 {0} {1} プール {2} 個、損失 {3}%
|
swap.preview,約 {0} {1} プール {2} 個、損失 {3}%
|
||||||
swap.go,スワップ
|
swap.go,スワップ
|
||||||
swap.same,支払いと受取は別の通貨にしてください。
|
swap.same,支払いと受取は別の通貨にしてください。
|
||||||
|
cra.mint,発行
|
||||||
|
cra.burn,償還
|
||||||
|
mint.h,公式発行(CRC+SPARK)
|
||||||
|
mint.need,必要:{0} CRC と {1} SPARK
|
||||||
|
mint.reserve,準備率 {0}% 担保率 {1}%
|
||||||
|
mint.queue,処理待ち
|
||||||
|
mint.order,{0} {1} CRA、{2} 日目
|
||||||
|
mint.sum.in,{1} CRC と {2} SPARK で {0} CRA を発行({3}~{4} 日)
|
||||||
|
mint.sum.out,{0} CRA を償還して CRC と SPARK に({1} 日)
|
||||||
|
mint.done.in,発行を申請しました。{0} 日目に決済されます。
|
||||||
|
mint.done.out,償還を申請しました。{0} 日目に決済されます。
|
||||||
|
stake.coin,預入通貨
|
||||||
|
stake.sum.via,{0} {1} をスワップ → 約 {2} CRA をステーク
|
||||||
|
nightlog.cra.minted,発行した {0} CRA をステークしました({1})。
|
||||||
|
nightlog.cra.burned,{0} CRA を償還:+{1} CRC、+{2} SPARK({3})。
|
||||||
|
nightlog.cra.lost,発行元から応答がありません:{0} CRA の{1}注文は失われました。
|
||||||
|
news.crawarn.desc,革命軍の準備金を数え直す者がいる。ステークした CRA は全額償還できないかもしれない。解除には四日かかる。動くなら今だという声もある。
|
||||||
|
news.cralow.desc,準備率が危うくなり、革命軍は CRA のステーキング日利を元の数分の一に引き下げた。
|
||||||
|
Can't render this file because it contains an unexpected character in line 511 and column 24.
|
@@ -460,9 +460,6 @@ stake.ops,{0}
|
|||||||
stake.avail,CRA {0} W stakingu {1}
|
stake.avail,CRA {0} W stakingu {1}
|
||||||
stake.do,Stakuj
|
stake.do,Stakuj
|
||||||
stake.undo,Zgłoś wypłatę
|
stake.undo,Zgłoś wypłatę
|
||||||
spark.h,Token równoważący
|
|
||||||
spark.mint,Wybij SPARK
|
|
||||||
spark.burn,Spal SPARK
|
|
||||||
stake.sum.in,Zastakuj {0} CRA
|
stake.sum.in,Zastakuj {0} CRA
|
||||||
stake.sum.out,Zgłoś wypłatę {0} CRA (dostępne za: {1} d.)
|
stake.sum.out,Zgłoś wypłatę {0} CRA (dostępne za: {1} d.)
|
||||||
stake.done.in,Zastakowano {0} CRA.
|
stake.done.in,Zastakowano {0} CRA.
|
||||||
@@ -470,9 +467,7 @@ stake.done.out,Zgłoszono wypłatę {0} CRA; powrót do portfela w dniu {1}.
|
|||||||
nightlog.stakeint,Odsetki ze stakingu +{0} CRA.
|
nightlog.stakeint,Odsetki ze stakingu +{0} CRA.
|
||||||
nightlog.unstaked,{0} CRA wycofane ze stakingu zwrócono do {1}.
|
nightlog.unstaked,{0} CRA wycofane ze stakingu zwrócono do {1}.
|
||||||
news.crawarn.title,Niepokoje wokół puli stakingowej Rewolucji
|
news.crawarn.title,Niepokoje wokół puli stakingowej Rewolucji
|
||||||
news.crawarn.desc,"Duzi posiadacze wycofują środki, a pula dotacji stakingowych wysycha. Odblokowanie trwa cztery dni; niektórzy mówią, że czas działać."
|
|
||||||
news.cralow.title,Rewolucja obniża stawkę stakingu
|
news.cralow.title,Rewolucja obniża stawkę stakingu
|
||||||
news.cralow.desc,"Pula dotacji jest niemal pusta, a Rewolucja obniżyła stawkę stakingu CRA do ułamka pierwotnej wartości."
|
|
||||||
stake.avail2,SPARK {0}
|
stake.avail2,SPARK {0}
|
||||||
poin.sub.spot,Spot
|
poin.sub.spot,Spot
|
||||||
poin.sub.perp,Wieczyste
|
poin.sub.perp,Wieczyste
|
||||||
@@ -906,3 +901,21 @@ swap.get,Otrzymuję
|
|||||||
swap.preview,"Około {0} {1} pule: {2}, strata {3}%"
|
swap.preview,"Około {0} {1} pule: {2}, strata {3}%"
|
||||||
swap.go,Wymień
|
swap.go,Wymień
|
||||||
swap.same,Waluty płatności i odbioru muszą się różnić.
|
swap.same,Waluty płatności i odbioru muszą się różnić.
|
||||||
|
cra.mint,Wybij
|
||||||
|
cra.burn,Umorz
|
||||||
|
mint.h,Oficjalna emisja (CRC + SPARK)
|
||||||
|
mint.need,Wymaga {0} CRC i {1} SPARK
|
||||||
|
mint.reserve,Pokrycie rezerwy {0}% Zabezpieczenie {1}%
|
||||||
|
mint.queue,Oczekujące zlecenia
|
||||||
|
mint.order,"{0} {1} CRA, dzień {2}"
|
||||||
|
mint.sum.in,Wybij {0} CRA za {1} CRC i {2} SPARK ({3}–{4} dni)
|
||||||
|
mint.sum.out,Umorz {0} CRA na CRC i SPARK ({1} dni)
|
||||||
|
mint.done.in,Zlecenie emisji złożone; termin: dzień {0}.
|
||||||
|
mint.done.out,Zlecenie umorzenia złożone; termin: dzień {0}.
|
||||||
|
stake.coin,Waluta wpłaty
|
||||||
|
stake.sum.via,Wymień {0} {1} → około {2} CRA i stakuj
|
||||||
|
nightlog.cra.minted,Wybito {0} CRA i zastakowano ({1}).
|
||||||
|
nightlog.cra.burned,"Umorzono {0} CRA: +{1} CRC, +{2} SPARK ({3})."
|
||||||
|
nightlog.cra.lost,Emitent nie odpowiedział: zlecenie ({1}) na {0} CRA przepadło.
|
||||||
|
news.crawarn.desc,"Ktoś liczy rezerwę Rewolucji i zastakowane CRA mogą nie zostać w pełni wypłacone. Odblokowanie trwa cztery dni; niektórzy mówią, że czas działać."
|
||||||
|
news.cralow.desc,"Pokrycie rezerwy maleje, a Rewolucja obniżyła stopę stakingu CRA do ułamka."
|
||||||
|
@@ -460,9 +460,6 @@ stake.ops,{0}
|
|||||||
stake.avail,CRA {0} В стейкинге {1}
|
stake.avail,CRA {0} В стейкинге {1}
|
||||||
stake.do,В стейкинг
|
stake.do,В стейкинг
|
||||||
stake.undo,Запросить вывод
|
stake.undo,Запросить вывод
|
||||||
spark.h,Балансовый токен
|
|
||||||
spark.mint,Минт SPARK
|
|
||||||
spark.burn,Сжигание SPARK
|
|
||||||
stake.sum.in,Внести {0} CRA в стейкинг
|
stake.sum.in,Внести {0} CRA в стейкинг
|
||||||
stake.sum.out,Запросить вывод {0} CRA (дней до зачисления: {1})
|
stake.sum.out,Запросить вывод {0} CRA (дней до зачисления: {1})
|
||||||
stake.done.in,{0} CRA внесено в стейкинг.
|
stake.done.in,{0} CRA внесено в стейкинг.
|
||||||
@@ -470,9 +467,7 @@ stake.done.out,Запрошен вывод {0} CRA; возврат в кошел
|
|||||||
nightlog.stakeint,Доход от стейкинга: +{0} CRA.
|
nightlog.stakeint,Доход от стейкинга: +{0} CRA.
|
||||||
nightlog.unstaked,Выведенные из стейкинга {0} CRA вернулись в {1}.
|
nightlog.unstaked,Выведенные из стейкинга {0} CRA вернулись в {1}.
|
||||||
news.crawarn.title,Волнения вокруг пула стейкинга Революционеров
|
news.crawarn.title,Волнения вокруг пула стейкинга Революционеров
|
||||||
news.crawarn.desc,"Крупные держатели выводят средства, и пул субсидий для стейкинга истощается. Разблокировка занимает четыре дня; ходят слухи, что пора действовать."
|
|
||||||
news.cralow.title,Революционеры снижают ставку стейкинга
|
news.cralow.title,Революционеры снижают ставку стейкинга
|
||||||
news.cralow.desc,"Пул субсидий почти опустел, и Революционеры снизили ставку стейкинга CRA до малой доли прежней."
|
|
||||||
stake.avail2,SPARK {0}
|
stake.avail2,SPARK {0}
|
||||||
poin.sub.spot,Спот
|
poin.sub.spot,Спот
|
||||||
poin.sub.perp,Бессрочные
|
poin.sub.perp,Бессрочные
|
||||||
@@ -906,3 +901,21 @@ swap.get,Получаю
|
|||||||
swap.preview,"Около {0} {1} пулов: {2}, потери {3}%"
|
swap.preview,"Около {0} {1} пулов: {2}, потери {3}%"
|
||||||
swap.go,Обменять
|
swap.go,Обменять
|
||||||
swap.same,Монеты оплаты и получения должны различаться.
|
swap.same,Монеты оплаты и получения должны различаться.
|
||||||
|
cra.mint,Выпустить
|
||||||
|
cra.burn,Погасить
|
||||||
|
mint.h,Официальный выпуск (CRC + SPARK)
|
||||||
|
mint.need,Нужно {0} CRC и {1} SPARK
|
||||||
|
mint.reserve,Покрытие резерва {0}% Залог {1}%
|
||||||
|
mint.queue,Очередь
|
||||||
|
mint.order,"{0} {1} CRA, день {2}"
|
||||||
|
mint.sum.in,Выпустить {0} CRA за {1} CRC и {2} SPARK ({3}–{4} дн.)
|
||||||
|
mint.sum.out,Погасить {0} CRA в CRC и SPARK ({1} дн.)
|
||||||
|
mint.done.in,Заявка на выпуск подана; срок — день {0}.
|
||||||
|
mint.done.out,Заявка на погашение подана; срок — день {0}.
|
||||||
|
stake.coin,Монета для вклада
|
||||||
|
stake.sum.via,Обменять {0} {1} → около {2} CRA и внести в стейкинг
|
||||||
|
nightlog.cra.minted,"Выпущено {0} CRA, внесены в стейкинг ({1})."
|
||||||
|
nightlog.cra.burned,"Погашено {0} CRA: +{1} CRC, +{2} SPARK ({3})."
|
||||||
|
nightlog.cra.lost,Эмитент не ответил: заявка ({1}) на {0} CRA потеряна.
|
||||||
|
news.crawarn.desc,"Кто-то пересчитывает резерв Революции, и CRA в стейкинге могут не выкупить полностью. Разблокировка занимает четыре дня; кое-кто говорит, что пора действовать."
|
||||||
|
news.cralow.desc,"Покрытие резерва тает, и Революция снизила ставку по стейкингу CRA до малой доли."
|
||||||
|
@@ -459,9 +459,6 @@ stake.ops,"{0}"
|
|||||||
stake.avail,"CRA {0} 已质押 {1}"
|
stake.avail,"CRA {0} 已质押 {1}"
|
||||||
stake.do,质押
|
stake.do,质押
|
||||||
stake.undo,申请取出
|
stake.undo,申请取出
|
||||||
spark.h,平衡代币
|
|
||||||
spark.mint,铸造 SPARK
|
|
||||||
spark.burn,销毁 SPARK
|
|
||||||
stake.sum.in,"质押 {0} CRA"
|
stake.sum.in,"质押 {0} CRA"
|
||||||
stake.sum.out,"申请取出 {0} CRA({1} 天后到账)"
|
stake.sum.out,"申请取出 {0} CRA({1} 天后到账)"
|
||||||
stake.done.in,"已质押 {0} CRA。"
|
stake.done.in,"已质押 {0} CRA。"
|
||||||
@@ -469,9 +466,7 @@ stake.done.out,"已申请取出 {0} CRA,第 {1} 天回到钱包。"
|
|||||||
nightlog.stakeint,"质押利息 +{0} CRA。"
|
nightlog.stakeint,"质押利息 +{0} CRA。"
|
||||||
nightlog.unstaked,"质押取出的 {0} CRA 回到了{1}。"
|
nightlog.unstaked,"质押取出的 {0} CRA 回到了{1}。"
|
||||||
news.crawarn.title,革命军质押池传出异动
|
news.crawarn.title,革命军质押池传出异动
|
||||||
news.crawarn.desc,有大户在大量撤出,质押补贴池告急。解锁需要四天,有人说该动手了。
|
|
||||||
news.cralow.title,革命军下调质押日息
|
news.cralow.title,革命军下调质押日息
|
||||||
news.cralow.desc,补贴池余额见底,革命军把 CRA 质押日息降到了原来的零头。
|
|
||||||
stake.avail2,"SPARK {0}"
|
stake.avail2,"SPARK {0}"
|
||||||
poin.sub.spot,现货
|
poin.sub.spot,现货
|
||||||
poin.sub.perp,永续
|
poin.sub.perp,永续
|
||||||
@@ -905,3 +900,21 @@ swap.get,获得
|
|||||||
swap.preview,约得 {0} {1} 经 {2} 个池,损耗 {3}%
|
swap.preview,约得 {0} {1} 经 {2} 个池,损耗 {3}%
|
||||||
swap.go,兑换
|
swap.go,兑换
|
||||||
swap.same,支付和获得的币种不能相同。
|
swap.same,支付和获得的币种不能相同。
|
||||||
|
cra.mint,铸造
|
||||||
|
cra.burn,销毁
|
||||||
|
mint.h,官方铸造(CRC 加 SPARK)
|
||||||
|
mint.need,需要 {0} CRC 和 {1} SPARK
|
||||||
|
mint.reserve,储备覆盖率 {0}% 抵押率 {1}%
|
||||||
|
mint.queue,待处理
|
||||||
|
mint.order,{0} {1} CRA,第 {2} 天
|
||||||
|
mint.sum.in,用 {1} CRC 和 {2} SPARK 铸造 {0} CRA({3}~{4} 天)
|
||||||
|
mint.sum.out,销毁 {0} CRA 换回 CRC 和 SPARK({1} 天)
|
||||||
|
mint.done.in,已提交铸造,第 {0} 天结算。
|
||||||
|
mint.done.out,已提交销毁,第 {0} 天结算。
|
||||||
|
stake.coin,存入币种
|
||||||
|
stake.sum.via,兑换 {0} {1} → 约 {2} CRA 并质押
|
||||||
|
nightlog.cra.minted,铸造的 {0} CRA 已进入质押({1})。
|
||||||
|
nightlog.cra.burned,销毁 {0} CRA:收回 {1} CRC、{2} SPARK({3})。
|
||||||
|
nightlog.cra.lost,官方没有回应:{0} CRA 的{1}单丢失。
|
||||||
|
news.crawarn.desc,有人在清点革命军的储备,质押的 CRA 恐怕兑付不了。解锁需要四天,有人说该动手了。
|
||||||
|
news.cralow.desc,储备覆盖率告急,革命军把 CRA 质押日息降到了原来的零头。
|
||||||
|
@@ -228,6 +228,13 @@ namespace Decentralized
|
|||||||
if (perpEvents.Any(e => e.Kind == "seize")) SeizeForDebt(d, day);
|
if (perpEvents.Any(e => e.Kind == "seize")) SeizeForDebt(d, day);
|
||||||
var stakeEvents = d.Staking.Night(day, d.Stable.CraRate, d.WalletAt);
|
var stakeEvents = d.Staking.Night(day, d.Stable.CraRate, d.WalletAt);
|
||||||
double crcFactor = d.Stable.Night(day, d.Rng, d.Staking.Earning);
|
double crcFactor = d.Stable.Night(day, d.Rng, d.Staking.Earning);
|
||||||
|
var orderEvents = d.Stable.NightOrders(day, d.Rng);
|
||||||
|
foreach (var oe in orderEvents)
|
||||||
|
{
|
||||||
|
var ow = d.WalletAt(oe.Order.Wallet);
|
||||||
|
if (oe.Kind == CraOrderKind.Minted) { ow.Add(Assets.CRA, oe.Cra); d.Staking.Stake(ow, oe.Cra, Session.Price); }
|
||||||
|
else if (oe.Kind == CraOrderKind.Burned) { ow.Add(Assets.CRC, oe.Crc); ow.Add(Assets.SPARK, oe.Spark); }
|
||||||
|
}
|
||||||
if (d.Stable.CraWarnDay == day) News.Show("pd_news_crawarn_" + day, L.T("news.crawarn.title"), L.T("news.crawarn.desc"), 4);
|
if (d.Stable.CraWarnDay == day) News.Show("pd_news_crawarn_" + day, L.T("news.crawarn.title"), L.T("news.crawarn.desc"), 4);
|
||||||
if (d.Stable.CraSubsidyLow && !d.CraLowNews) { d.CraLowNews = true; News.Show("pd_news_cralow_" + day, L.T("news.cralow.title"), L.T("news.cralow.desc"), 3); }
|
if (d.Stable.CraSubsidyLow && !d.CraLowNews) { d.CraLowNews = true; News.Show("pd_news_cralow_" + day, L.T("news.cralow.title"), L.T("news.cralow.desc"), 3); }
|
||||||
if (crcFactor < 1)
|
if (crcFactor < 1)
|
||||||
@@ -326,6 +333,14 @@ namespace Decentralized
|
|||||||
var sw = d.Own(e.Wallet);
|
var sw = d.Own(e.Wallet);
|
||||||
if (e.Released > 0) ps.AddNightLog(L.T("nightlog.unstaked", Fmt.Num(e.Released), sw != null ? WalletWindow.NameOf(sw) : e.Wallet));
|
if (e.Released > 0) ps.AddNightLog(L.T("nightlog.unstaked", Fmt.Num(e.Released), sw != null ? WalletWindow.NameOf(sw) : e.Wallet));
|
||||||
}
|
}
|
||||||
|
foreach (var oe in orderEvents)
|
||||||
|
{
|
||||||
|
var ow = d.Own(oe.Order.Wallet);
|
||||||
|
string wn = ow != null ? WalletWindow.NameOf(ow) : oe.Order.Wallet;
|
||||||
|
if (oe.Kind == CraOrderKind.Minted) ps.AddNightLog(L.T("nightlog.cra.minted", Fmt.Num(oe.Cra), wn));
|
||||||
|
else if (oe.Kind == CraOrderKind.Burned) ps.AddNightLog(L.T("nightlog.cra.burned", Fmt.Num(oe.Order.Cra), Fmt.Num(oe.Crc), Fmt.Num(oe.Spark), wn));
|
||||||
|
else ps.AddNightLog(L.T("nightlog.cra.lost", Fmt.Num(oe.Order.Cra), oe.Order.Mint ? L.T("cra.mint") : L.T("cra.burn")), "cc7755");
|
||||||
|
}
|
||||||
double interest = stakeEvents.Sum(e => e.Interest);
|
double interest = stakeEvents.Sum(e => e.Interest);
|
||||||
if (interest > 0) ps.AddNightLog(L.T("nightlog.stakeint", Fmt.Num(interest)));
|
if (interest > 0) ps.AddNightLog(L.T("nightlog.stakeint", Fmt.Num(interest)));
|
||||||
foreach (var name in report.Burnt) ps.AddNightLog(L.T("nightlog.burnt", name), "cc7755");
|
foreach (var name in report.Burnt) ps.AddNightLog(L.T("nightlog.burnt", name), "cc7755");
|
||||||
|
|||||||
@@ -120,8 +120,8 @@ namespace Decentralized
|
|||||||
double thr = t;
|
double thr = t;
|
||||||
list.Add(new PredictCandidate { Kind = PredictKind.Gas, Key = "gas", Title = "Gas", Param = thr, Tomorrow = true, Prob = (a, b) => GasPublic(d, day + 1, thr) });
|
list.Add(new PredictCandidate { Kind = PredictKind.Gas, Key = "gas", Title = "Gas", Param = thr, Tomorrow = true, Prob = (a, b) => GasPublic(d, day + 1, thr) });
|
||||||
}
|
}
|
||||||
if (d.Stable.CraWarnDay < 0 && d.Stable.CraSpiralDay < 0)
|
if (d.Stable.CraWarnDay < 0 && d.Stable.CraCrashDay < 0)
|
||||||
list.Add(new PredictCandidate { Kind = PredictKind.Cra, Key = "cra", Title = "CRA", Prob = (from, to) => PredictMath.CraWarnProb(d.Stable.CraSubsidy, CraDrain(d), day, from, to, CraHazard) });
|
list.Add(new PredictCandidate { Kind = PredictKind.Cra, Key = "cra", Title = "CRA", Prob = (from, to) => PredictMath.CraWarnProb(d.Stable.Cushion, CraDrain(d), day, from, to, CraHazard) });
|
||||||
if (!d.Network.EraDone && d.Network.EraDay > 0 && day + 4 >= (d.Network.EraWarned ? d.Network.EraWarnDay : Tuning.EraMin))
|
if (!d.Network.EraDone && d.Network.EraDay > 0 && day + 4 >= (d.Network.EraWarned ? d.Network.EraWarnDay : Tuning.EraMin))
|
||||||
list.Add(new PredictCandidate { Kind = PredictKind.Era, Key = "era", Title = L.T("predict.era"), Prob = (from, to) => PredictMath.EraProb(day, from, to, d.Network.EraWarned ? d.Network.EraWarnDay : -1) });
|
list.Add(new PredictCandidate { Kind = PredictKind.Era, Key = "era", Title = L.T("predict.era"), Prob = (from, to) => PredictMath.EraProb(day, from, to, d.Network.EraWarned ? d.Network.EraWarnDay : -1) });
|
||||||
return list;
|
return list;
|
||||||
@@ -132,7 +132,7 @@ namespace Decentralized
|
|||||||
d.GasPhase < 0 ? PredictMath.GasFlat(day, thr) : (1 - Tuning.PredictGasBlind) * PredictMath.GasAtLeast(day, d.GasPhase, thr) + Tuning.PredictGasBlind * PredictMath.GasFlat(day, thr);
|
d.GasPhase < 0 ? PredictMath.GasFlat(day, thr) : (1 - Tuning.PredictGasBlind) * PredictMath.GasAtLeast(day, d.GasPhase, thr) + Tuning.PredictGasBlind * PredictMath.GasFlat(day, thr);
|
||||||
|
|
||||||
private static double CraHazard => 1 - Math.Pow(1 - Tuning.CraSpiralWeekly, 1.0 / 7);
|
private static double CraHazard => 1 - Math.Pow(1 - Tuning.CraSpiralWeekly, 1.0 / 7);
|
||||||
private static double CraDrain(SaveData d) => (Tuning.CraNpcStake + d.Staking.Earning) * d.Stable.CraRate;
|
private static double CraDrain(SaveData d) => Stablecoins.CushionDrain(Tuning.CraNpcStake + d.Staking.Earning, d.Stable.CraRate);
|
||||||
|
|
||||||
/// <summary>开门后补盘。价格盘一次只留一个(阈值不同的盘口会互相对冲)。</summary>
|
/// <summary>开门后补盘。价格盘一次只留一个(阈值不同的盘口会互相对冲)。</summary>
|
||||||
public static void Morning(SaveData d, int day)
|
public static void Morning(SaveData d, int day)
|
||||||
@@ -199,8 +199,8 @@ namespace Decentralized
|
|||||||
case PredictKind.Gas:
|
case PredictKind.Gas:
|
||||||
return d.GasPhase < 0 ? (double?)null : GasPublic(d, m.ToDay, m.Param);
|
return d.GasPhase < 0 ? (double?)null : GasPublic(d, m.ToDay, m.Param);
|
||||||
case PredictKind.Cra:
|
case PredictKind.Cra:
|
||||||
if (d.Stable.CraWarnDay >= 0 || d.Stable.CraSpiralDay >= 0) return 0.02;
|
if (d.Stable.CraWarnDay >= 0 || d.Stable.CraCrashDay >= 0) return 0.02;
|
||||||
return PredictMath.CraWarnProb(d.Stable.CraSubsidy, CraDrain(d), day + 1, m.FromDay, m.ToDay, CraHazard);
|
return PredictMath.CraWarnProb(d.Stable.Cushion, CraDrain(d), day + 1, m.FromDay, m.ToDay, CraHazard);
|
||||||
case PredictKind.Era:
|
case PredictKind.Era:
|
||||||
return PredictMath.EraProb(day, m.FromDay, m.ToDay, d.Network.EraWarned ? d.Network.EraWarnDay : -1);
|
return PredictMath.EraProb(day, m.FromDay, m.ToDay, d.Network.EraWarned ? d.Network.EraWarnDay : -1);
|
||||||
}
|
}
|
||||||
@@ -309,7 +309,7 @@ namespace Decentralized
|
|||||||
if (d.GasHist.Count > 0) list.Add(L.T("predict.clue.gas", string.Join(" ", d.GasHist.Skip(Math.Max(0, d.GasHist.Count - 7)).Select(x => x.ToString("0.0", System.Globalization.CultureInfo.InvariantCulture)))));
|
if (d.GasHist.Count > 0) list.Add(L.T("predict.clue.gas", string.Join(" ", d.GasHist.Skip(Math.Max(0, d.GasHist.Count - 7)).Select(x => x.ToString("0.0", System.Globalization.CultureInfo.InvariantCulture)))));
|
||||||
break;
|
break;
|
||||||
case PredictKind.Cra:
|
case PredictKind.Cra:
|
||||||
list.Add(L.T("predict.clue.subsidy", (d.Stable.CraSubsidy / Tuning.CraSubsidy0 * 100).ToString("0")));
|
list.Add(L.T("predict.clue.subsidy", (d.Stable.Cushion / Stablecoins.Cushion0 * 100).ToString("0")));
|
||||||
list.Add(L.T("predict.clue.drain", Fmt.Num(CraDrain(d))));
|
list.Add(L.T("predict.clue.drain", Fmt.Num(CraDrain(d))));
|
||||||
break;
|
break;
|
||||||
case PredictKind.Era:
|
case PredictKind.Era:
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace Decentralized
|
|||||||
private static void Apply(SaveData d, int day, string key)
|
private static void Apply(SaveData d, int day, string key)
|
||||||
{
|
{
|
||||||
if (!d.Story.Apply(key, day)) return;
|
if (!d.Story.Apply(key, day)) return;
|
||||||
if (key == "serpico_rev") d.Stable.CraSubsidy += Tuning.StoryRevSubsidy;
|
if (key == "serpico_rev") d.Stable.Reserve += Tuning.StoryRevSubsidy;
|
||||||
News.Show("pd_news_story_" + key, L.T("news.story." + key + ".title"), L.T("news.story." + key + ".desc"), 4, 9);
|
News.Show("pd_news_story_" + key, L.T("news.story." + key + ".title"), L.T("news.story." + key + ".desc"), 4, 9);
|
||||||
Log.Info($"剧情联动生效:{key}(第 {day} 天)");
|
Log.Info($"剧情联动生效:{key}(第 {day} 天)");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2234,7 +2234,15 @@ namespace Decentralized
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
l.AddSeparator();
|
l.AddSeparator();
|
||||||
|
l.AddLabel(L.T("mint.reserve", (st.Ratio * 100).ToString("0", CultureInfo.InvariantCulture), (st.C * 100).ToString("0", CultureInfo.InvariantCulture)), "mint_reserve_dim");
|
||||||
l.AddLabel(L.T("spark.price", Fmt.Num(st.Spark)));
|
l.AddLabel(L.T("spark.price", Fmt.Num(st.Spark)));
|
||||||
|
var mine = st.Orders.Where(o => d.Own(o.Wallet) != null).ToList();
|
||||||
|
if (mine.Count > 0)
|
||||||
|
{
|
||||||
|
l.AddSeparator();
|
||||||
|
l.AddLabel(L.T("mint.queue"));
|
||||||
|
foreach (var o in mine) l.AddLabel(L.T("mint.order", L.T(o.Mint ? "cra.mint" : "cra.burn"), Fmt.Num(o.Cra), o.Due), "mint_order_dim");
|
||||||
|
}
|
||||||
}, r =>
|
}, r =>
|
||||||
{
|
{
|
||||||
r.AddHeader(L.T("stake.ops", WalletWindow.NameOf(w)));
|
r.AddHeader(L.T("stake.ops", WalletWindow.NameOf(w)));
|
||||||
@@ -2242,19 +2250,35 @@ namespace Decentralized
|
|||||||
r.AddLabel(L.T("stake.avail2", Fmt.Num(w.Avail(Assets.SPARK))), "stake_avail2_dim");
|
r.AddLabel(L.T("stake.avail2", Fmt.Num(w.Avail(Assets.SPARK))), "stake_avail2_dim");
|
||||||
AmountRow(r);
|
AmountRow(r);
|
||||||
r.AddSpace(4f);
|
r.AddSpace(4f);
|
||||||
|
r.AddLabel(L.T("stake.coin"));
|
||||||
|
r.BeginRow(4f);
|
||||||
|
foreach (var c in StakeCoins)
|
||||||
|
{
|
||||||
|
var coin = c;
|
||||||
|
PledgerSkin.Pick(r, coin, coin == _stakeCoin, () => { _stakeCoin = coin; Open(); }, _picked);
|
||||||
|
}
|
||||||
|
r.End();
|
||||||
r.BeginRow(6f);
|
r.BeginRow(6f);
|
||||||
r.AddButton(L.T("stake.do"), () => StakeCall(true));
|
r.AddButton(L.T("stake.do"), () => StakeCall(true));
|
||||||
r.AddButton(L.T("stake.undo"), () => StakeCall(false));
|
r.AddButton(L.T("stake.undo"), () => StakeCall(false));
|
||||||
r.End();
|
r.End();
|
||||||
r.AddSeparator();
|
r.AddSeparator();
|
||||||
r.AddHeader(L.T("spark.h"));
|
r.AddHeader(L.T("mint.h"));
|
||||||
|
if (double.TryParse((_amount ?? "").Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out double mv) && mv > 0)
|
||||||
|
{
|
||||||
|
st.Collateral(mv, out double needCrc, out double needSpark);
|
||||||
|
r.AddLabel(L.T("mint.need", Fmt.Num(needCrc), Fmt.Num(needSpark)), "mint_need_dim");
|
||||||
|
}
|
||||||
r.BeginRow(6f);
|
r.BeginRow(6f);
|
||||||
r.AddButton(L.T("spark.mint"), () => SparkCall(true));
|
r.AddButton(L.T("cra.mint"), () => MintCall(true));
|
||||||
r.AddButton(L.T("spark.burn"), () => SparkCall(false));
|
r.AddButton(L.T("cra.burn"), () => MintCall(false));
|
||||||
r.End();
|
r.End();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static readonly string[] StakeCoins = { Assets.CRA, Assets.CRC, Assets.CRT, Assets.SPARK };
|
||||||
|
private static string _stakeCoin = Assets.CRA;
|
||||||
|
|
||||||
/// <summary>手续费用钱包里价值最高的那种币付。</summary>
|
/// <summary>手续费用钱包里价值最高的那种币付。</summary>
|
||||||
private static string BestFeeAsset(Wallet w) =>
|
private static string BestFeeAsset(Wallet w) =>
|
||||||
w.Balances.Where(k => k.Value > 1e-9 && Session.Price(k.Key) > 0).OrderByDescending(k => k.Value * Session.Price(k.Key)).Select(k => k.Key).FirstOrDefault() ?? Assets.PSC;
|
w.Balances.Where(k => k.Value > 1e-9 && Session.Price(k.Key) > 0).OrderByDescending(k => k.Value * Session.Price(k.Key)).Select(k => k.Key).FirstOrDefault() ?? Assets.PSC;
|
||||||
@@ -2264,42 +2288,57 @@ namespace Decentralized
|
|||||||
if (!ReadAmount(out double v)) return;
|
if (!ReadAmount(out double v)) return;
|
||||||
var d = Session.Data;
|
var d = Session.Data;
|
||||||
var w = d.Hot;
|
var w = d.Hot;
|
||||||
if (into ? w.Avail(Assets.CRA) + 1e-9 < v : (d.Staking.Of(w.Address)?.Amount ?? 0) + 1e-9 < v) { _message = L.T("msg.balance"); Open(); return; }
|
string coin = into ? _stakeCoin : Assets.CRA;
|
||||||
|
if (into ? w.Avail(coin) + 1e-9 < v : (d.Staking.Of(w.Address)?.Amount ?? 0) + 1e-9 < v) { _message = L.T("msg.balance"); Open(); return; }
|
||||||
|
var q = into && coin != Assets.CRA ? d.Market.Quote(coin, Assets.CRA, v) : null;
|
||||||
_message = L.T("hw.wait");
|
_message = L.T("hw.wait");
|
||||||
Open();
|
Open();
|
||||||
WalletWindow.OpenForBill(new WalletWindow.Bill
|
WalletWindow.OpenForBill(new WalletWindow.Bill
|
||||||
{
|
{
|
||||||
Contract = true, Asset = Assets.CRA, Amount = v, Spend = into ? v : 0, FeeAsset = into ? null : BestFeeAsset(w),
|
Contract = true, Asset = coin, Amount = v, Spend = into ? v : 0, FeeAsset = into ? null : BestFeeAsset(w),
|
||||||
Summary = L.T(into ? "stake.sum.in" : "stake.sum.out", Fmt.Num(v), Tuning.CraUnlockDays),
|
Summary = into && q != null ? L.T("stake.sum.via", Fmt.Num(v), coin, Fmt.Num(q.Out)) : L.T(into ? "stake.sum.in" : "stake.sum.out", Fmt.Num(v), Tuning.CraUnlockDays),
|
||||||
Execute = pw =>
|
Execute = pw =>
|
||||||
{
|
{
|
||||||
int day = StoreStation.GetDayCounter();
|
int day = StoreStation.GetDayCounter();
|
||||||
bool ok = into ? d.Staking.Stake(pw, v, Session.Price) : d.Staking.RequestUnstake(pw.Address, v, day);
|
double cra = v;
|
||||||
_message = ok ? L.T(into ? "stake.done.in" : "stake.done.out", Fmt.Num(v), day + Tuning.CraUnlockDays) : L.T("msg.balance");
|
if (into && coin != Assets.CRA)
|
||||||
|
{
|
||||||
|
if (pw.Avail(coin) + 1e-9 < v) { _message = L.T("msg.balance"); Open(); return; }
|
||||||
|
double spent = v * Session.Price(coin);
|
||||||
|
cra = d.Market.Swap(coin, Assets.CRA, v);
|
||||||
|
pw.Add(coin, -v); pw.Add(Assets.CRA, cra); pw.RecordBuy(Assets.CRA, cra, spent);
|
||||||
|
CandleChart.Trade(coin, spent); CandleChart.Trade(Assets.CRA, spent);
|
||||||
|
}
|
||||||
|
bool ok = into ? d.Staking.Stake(pw, cra, Session.Price) : d.Staking.RequestUnstake(pw.Address, v, day);
|
||||||
|
_message = ok ? L.T(into ? "stake.done.in" : "stake.done.out", Fmt.Num(cra), day + Tuning.CraUnlockDays) : L.T("msg.balance");
|
||||||
Session.Save();
|
Session.Save();
|
||||||
Open();
|
Open();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SparkCall(bool mint)
|
/// <summary>官方一级市场:存入 CRC 和 SPARK 铸造 CRA(铸出后直接进质押),或销毁 CRA 换回两者。排队等待,官方可能不兑现。</summary>
|
||||||
|
private static void MintCall(bool mint)
|
||||||
{
|
{
|
||||||
if (!ReadAmount(out double v)) return;
|
if (!ReadAmount(out double v)) return;
|
||||||
var d = Session.Data;
|
var d = Session.Data;
|
||||||
var w = d.Hot;
|
var w = d.Hot;
|
||||||
string pay = mint ? Assets.CRA : Assets.SPARK, get = mint ? Assets.SPARK : Assets.CRA;
|
var st = d.Stable;
|
||||||
if (w.Avail(pay) + 1e-9 < v) { _message = L.T("msg.balance"); Open(); return; }
|
st.Collateral(v, out double needCrc, out double needSpark);
|
||||||
double quote = mint ? v * d.Stable.Cra / d.Stable.Spark * (1 - Tuning.SparkFee) : v * d.Stable.Spark / d.Stable.Cra * (1 - Tuning.SparkFee);
|
bool enough = mint ? w.Avail(Assets.CRC) + 1e-9 >= needCrc && w.Avail(Assets.SPARK) + 1e-9 >= needSpark : w.Avail(Assets.CRA) + 1e-9 >= v;
|
||||||
|
if (!enough) { _message = L.T("msg.balance"); Open(); return; }
|
||||||
|
int minD = Tuning.CraMintDaysMin, maxD = Tuning.CraMintDaysMax;
|
||||||
_message = L.T("hw.wait");
|
_message = L.T("hw.wait");
|
||||||
Open();
|
Open();
|
||||||
WalletWindow.OpenForBill(new WalletWindow.Bill
|
WalletWindow.OpenForBill(new WalletWindow.Bill
|
||||||
{
|
{
|
||||||
Contract = true, Asset = pay, Amount = v, Summary = L.T("hw.swap", Fmt.Num(v), pay, Fmt.Num(quote), get),
|
Contract = true, Asset = mint ? Assets.CRC : Assets.CRA, Amount = mint ? needCrc : v, Spend = mint ? needCrc : v,
|
||||||
|
Summary = mint ? L.T("mint.sum.in", Fmt.Num(v), Fmt.Num(needCrc), Fmt.Num(needSpark), minD, maxD) : L.T("mint.sum.out", Fmt.Num(v), Tuning.CraUnlockDays),
|
||||||
Execute = pw =>
|
Execute = pw =>
|
||||||
{
|
{
|
||||||
double got = mint ? d.Stable.Mint(pw, v) : d.Stable.Burn(pw, v);
|
int day = StoreStation.GetDayCounter();
|
||||||
if (got >= 0) { double cr = v * Session.Price(pay); CandleChart.Trade(Assets.SPARK, cr); CandleChart.Trade(Assets.CRA, cr); }
|
var o = mint ? st.RequestMint(pw, v, day, d.Rng) : st.RequestBurn(pw, v, day);
|
||||||
_message = got < 0 ? L.T("msg.balance") : L.T("msg.trade", Fmt.Num(v), pay, Fmt.Num(got), get);
|
_message = o == null ? L.T("msg.balance") : L.T(mint ? "mint.done.in" : "mint.done.out", o.Due);
|
||||||
Session.Save();
|
Session.Save();
|
||||||
Open();
|
Open();
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -376,18 +376,108 @@ internal static class Program
|
|||||||
"CRT 冻结概率:声望 0 为 40%,25 为 20%,50 为 0");
|
"CRT 冻结概率:声望 0 为 40%,25 为 20%,50 为 0");
|
||||||
});
|
});
|
||||||
|
|
||||||
Test("稳定币:CRA 补贴池告急即为预兆;螺旋三天 0.85 / 0.30 / 0.02", () =>
|
Test("稳定币:CRA 垫子告急即为预兆;储备吃空必崩,螺旋三天 0.85 / 0.30 / 0.02", () =>
|
||||||
{
|
{
|
||||||
var s = new Stablecoins { CraSubsidy = Tuning.CraSubsidy0 * 0.19 };
|
var s = new Stablecoins { Reserve = Tuning.CraCrashRatio * Tuning.CraS0 + Stablecoins.Cushion0 * 0.19 };
|
||||||
Check(s.CraWarning(1) && s.CraRate == Tuning.CraRateLow, "补贴池低于 20%:预兆出现、利率降到 0.2%");
|
Check(s.CraWarning(1) && s.CraRate == Tuning.CraRateLow, "垫子低于 20%:预兆出现、利率降到 0.2%");
|
||||||
var t = new Stablecoins { CraSubsidy = 1 };
|
var t = new Stablecoins { Reserve = Tuning.CraS0 * 0.2 };
|
||||||
var rng = new Rng(3);
|
var rng = new Rng(3);
|
||||||
t.Night(1, rng, 100000);
|
t.Night(1, rng, 100000);
|
||||||
Check(t.CraWarnDay == 1 && t.CraSpiralDay >= 5 && t.CraSpiralDay <= 8, $"补贴池吃空触发螺旋,提前 4–7 天:第 {t.CraSpiralDay} 天开始");
|
Check(t.CraWarnDay == 1 && t.CraEventDay >= 5 && t.CraEventDay <= 8, $"垫子吃空触发预兆,提前 4–7 天:第 {t.CraEventDay} 天挪用");
|
||||||
|
int ev = t.CraEventDay;
|
||||||
var path = new List<double>();
|
var path = new List<double>();
|
||||||
for (int d = 2; d <= t.CraSpiralDay + 3; d++) { t.Night(d, rng, 0); if (d >= t.CraSpiralDay) path.Add(t.Cra); }
|
for (int d = 2; d <= ev + 3; d++) { t.Night(d, rng, 0); if (d >= ev) path.Add(t.Cra); }
|
||||||
Check(path.Take(3).SequenceEqual(new[] { 0.85, 0.30, 0.02 }), $"螺旋路径:{string.Join(" / ", path)}");
|
Check(t.CraCrashDay == ev && path.Take(3).SequenceEqual(new[] { 0.85, 0.30, 0.02 }), $"崩盘路径:{string.Join(" / ", path)}");
|
||||||
Check(!t.CraWarning(t.CraSpiralDay + 1), "螺旋开始后不再算预兆");
|
Check(!t.CraWarning(ev + 1), "崩盘开始后不再算预兆");
|
||||||
|
});
|
||||||
|
|
||||||
|
Test("稳定币:挪用后 R/S 低于崩盘线才崩,否则只是折价;劫掠上层补回储备", () =>
|
||||||
|
{
|
||||||
|
int crashes = 0, discounts = 0;
|
||||||
|
for (ulong seed = 1; seed <= 60; seed++)
|
||||||
|
{
|
||||||
|
var s = new Stablecoins { Supply = 100000, Reserve = 100000, C = 0.8, CraWarnDay = 1, CraEventDay = 2 };
|
||||||
|
s.Night(2, new Rng(seed), 0);
|
||||||
|
double r = s.Ratio;
|
||||||
|
Check(r >= 1 - Tuning.CraEmbezzleMax - 0.01 && r <= 1 - Tuning.CraEmbezzleMin + 0.01 && s.CraEventDay < 0 && s.CraWarnDay < 0, $"储备被拿走 40%–80%:R/S {r:0.00}");
|
||||||
|
if (r < Tuning.CraCrashRatio) { crashes++; Check(s.CraCrashDay == 2 && s.Cra == Tuning.CraSpiralPath[0], "R/S 跌破崩盘线:当天进入螺旋"); }
|
||||||
|
else { discounts++; Check(s.CraCrashDay < 0 && Near(s.Cra, Stablecoins.PriceOfRatio(r), 1e-9), $"折价:{s.Cra:0.000}"); }
|
||||||
|
}
|
||||||
|
Check(crashes > 5 && discounts > 5, $"两种结果都会出现:崩盘 {crashes}、折价 {discounts}");
|
||||||
|
var t = new Stablecoins(); double before = t.Reserve;
|
||||||
|
t.OnEventStart(MarketEvent.RevRaidUpper, 3, new Rng(1));
|
||||||
|
Check(Near(t.Reserve, before + Tuning.CraLoot * t.Supply, 1e-6), "劫掠上层把流通量 × 9% 的 CRC 并入储备");
|
||||||
|
Check(Stablecoins.PriceOfRatio(Tuning.CraSafeRatio) == 1 && Near(Stablecoins.PriceOfRatio(Tuning.CraCrashRatio), 1 - Tuning.CraDiscountMax, 1e-9), "价格曲线:安全线 1,崩盘线折价 15%");
|
||||||
|
});
|
||||||
|
|
||||||
|
Test("CRA 长期行为:200 天里有的局崩盘有的不崩,质押越多崩得越多,崩盘前有预兆", () =>
|
||||||
|
{
|
||||||
|
Func<double, (double crash, double lead)> run = staked =>
|
||||||
|
{
|
||||||
|
int crashes = 0, n = 300; double leadSum = 0; int leads = 0;
|
||||||
|
for (int i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
var s = new Stablecoins(); var rng = new Rng((ulong)(i + 1));
|
||||||
|
int warn = -1;
|
||||||
|
for (int d = 1; d <= 200 && s.CraCrashDay < 0; d++)
|
||||||
|
{
|
||||||
|
if (rng.Chance(0.03)) s.OnEventStart(MarketEvent.RevRaidUpper, d, rng);
|
||||||
|
s.Night(d, rng, staked);
|
||||||
|
if (warn < 0 && s.CraWarnDay >= 0) warn = s.CraWarnDay;
|
||||||
|
if (s.CraWarnDay < 0 && s.CraCrashDay < 0) warn = -1;
|
||||||
|
}
|
||||||
|
if (s.CraCrashDay >= 0) { crashes++; if (warn >= 0) { leadSum += s.CraCrashDay - warn; leads++; } }
|
||||||
|
}
|
||||||
|
return (crashes / (double)n, leads > 0 ? leadSum / leads : 0);
|
||||||
|
};
|
||||||
|
var lo = run(0); var hi = run(100000);
|
||||||
|
Check(lo.crash > 0.02 && lo.crash < 0.9, $"无质押 200 天崩盘比例 {lo.crash:P0}");
|
||||||
|
Check(hi.crash >= lo.crash, $"质押 10 万:{hi.crash:P0} ≥ 无质押 {lo.crash:P0}");
|
||||||
|
Check(lo.lead >= Tuning.CraWarnLeadMin - 0.01 && lo.lead <= Tuning.CraWarnLeadMax + 0.01, $"预兆到崩盘平均 {lo.lead:0.0} 天");
|
||||||
|
});
|
||||||
|
|
||||||
|
Test("CRA 一级市场:铸造按抵押率存 CRC 加 SPARK,排队后进流通量与储备;销毁按 min(c, R/S) 兑付", () =>
|
||||||
|
{
|
||||||
|
var s = new Stablecoins(); var rng = new Rng(2);
|
||||||
|
var w = new Wallet { Address = "w" };
|
||||||
|
s.Collateral(1000, out double crc, out double spark);
|
||||||
|
Check(Near(crc, 1000 * Tuning.CraC0, 1e-9) && Near(spark * s.Spark, 1000 * (1 - Tuning.CraC0), 1e-9), $"抵押:CRC {crc:0},SPARK {spark:0.##}");
|
||||||
|
Check(s.RequestMint(w, 1000, 1, rng) == null, "钱包里没有币:拒绝");
|
||||||
|
w.Add(Assets.CRC, crc); w.Add(Assets.SPARK, spark);
|
||||||
|
double S0 = s.Supply, R0 = s.Reserve;
|
||||||
|
var o = s.RequestMint(w, 1000, 1, rng);
|
||||||
|
Check(o != null && w.Get(Assets.CRC) == 0 && w.Get(Assets.SPARK) == 0 && o.Due >= 2 && o.Due <= 3, "存入后排队 1~2 天");
|
||||||
|
var evs = s.NightOrders(1, rng);
|
||||||
|
Check(evs.Count == 0 && s.Supply == S0, "没到期不结算");
|
||||||
|
evs = s.NightOrders(o.Due, rng);
|
||||||
|
Check(evs.Count == 1 && evs[0].Kind == CraOrderKind.Minted && Near(s.Supply, S0 + 1000, 1e-9) && Near(s.Reserve, R0 + crc, 1e-9), "到期:流通量加 1000,储备加 CRC 部分");
|
||||||
|
w.Add(Assets.CRA, 500);
|
||||||
|
double ratio = s.Ratio;
|
||||||
|
var b = s.RequestBurn(w, 500, 5);
|
||||||
|
Check(b != null && b.Due == 5 + Tuning.CraUnlockDays && w.Get(Assets.CRA) == 0, "销毁排队解锁期");
|
||||||
|
evs = s.NightOrders(b.Due, rng);
|
||||||
|
Check(evs.Count == 1 && evs[0].Kind == CraOrderKind.Burned && Near(evs[0].Crc, 500 * Math.Min(Tuning.CraC0, ratio), 1e-6) && evs[0].Spark > 0, $"兑付 CRC {evs[0].Crc:0}、SPARK {evs[0].Spark:0.##}");
|
||||||
|
var low = new Stablecoins { Supply = 1000, Reserve = 200 };
|
||||||
|
low.Redeem(100, 0.8, out double c2, out double sp2);
|
||||||
|
Check(Near(c2, 20, 1e-9) && Near(sp2 * low.Spark, 80, 1e-9), "储备只有 R/S = 0.2:CRC 份额降到 0.2,其余用 SPARK 补");
|
||||||
|
});
|
||||||
|
|
||||||
|
Test("CRA 一级市场:官方跑路概率 = 系数 × (1 − CRA 价格),命中整笔丢失", () =>
|
||||||
|
{
|
||||||
|
var s = new Stablecoins();
|
||||||
|
Check(s.RugChance == 0, "价格 1 时不会跑路");
|
||||||
|
s.Cra = 0.9;
|
||||||
|
Check(Near(s.RugChance, Tuning.CraRugPerDepeg * 0.1, 1e-9), "价格 0.9 时概率 10%");
|
||||||
|
int lost = 0, n = 4000;
|
||||||
|
for (int i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
var t = new Stablecoins { Cra = 0.9, Supply = 1000, Reserve = 800 };
|
||||||
|
var w = new Wallet { Address = "w" }; w.Add(Assets.CRA, 10);
|
||||||
|
t.RequestBurn(w, 10, 1);
|
||||||
|
var ev = t.NightOrders(1, new Rng((ulong)i));
|
||||||
|
if (ev.Count == 1 && ev[0].Kind == CraOrderKind.Lost) { lost++; Check(t.Orders.Count == 0 && w.Get(Assets.CRA) == 0, "丢失不退款"); }
|
||||||
|
}
|
||||||
|
Check(Math.Abs(lost / (double)n - 0.1) < 0.03, $"命中率 {lost / (double)n:P1}");
|
||||||
});
|
});
|
||||||
|
|
||||||
Test("合规出金:干净小额不查;污点高时重度命中记罪证;轻度命中只没收污点部分;只对收益计税", () =>
|
Test("合规出金:干净小额不查;污点高时重度命中记罪证;轻度命中只没收污点部分;只对收益计税", () =>
|
||||||
@@ -599,7 +689,7 @@ internal static class Program
|
|||||||
Check(Near(back.Market.Price, m.Price, 1e-9) && back.Market.Pools.Count == m.Pools.Count && back.Market.Pools[1].Id == m.Pools[1].Id, "交易对与价格");
|
Check(Near(back.Market.Price, m.Price, 1e-9) && back.Market.Pools.Count == m.Pools.Count && back.Market.Pools[1].Id == m.Pools[1].Id, "交易对与价格");
|
||||||
Check(back.Hot.Get(Assets.PSC) == 5 && back.Hot.Taint == 12 && back.Hot.Basis == 34, "钱包余额、污点、成本");
|
Check(back.Hot.Get(Assets.PSC) == 5 && back.Hot.Taint == 12 && back.Hot.Basis == 34, "钱包余额、污点、成本");
|
||||||
Check(back.Exchange.History.Count == 1 && back.Exchange.History[0].Value == 100, "出金记录");
|
Check(back.Exchange.History.Count == 1 && back.Exchange.History[0].Value == 100, "出金记录");
|
||||||
Check(Near(back.Network.NpcHash, net.NpcHash, 1e-9) && Near(back.Stable.CraSubsidy, st.CraSubsidy, 1e-9), "全网算力、CRA 补贴池");
|
Check(Near(back.Network.NpcHash, net.NpcHash, 1e-9) && Near(back.Stable.Reserve, st.Reserve, 1e-9), "全网算力、CRA 储备");
|
||||||
for (int d = 6; d <= 10; d++)
|
for (int d = 6; d <= 10; d++)
|
||||||
{
|
{
|
||||||
m.Night(new MarketEvent[0], rng, d, a => 1);
|
m.Night(new MarketEvent[0], rng, d, a => 1);
|
||||||
@@ -1042,12 +1132,12 @@ internal static class Program
|
|||||||
Check(Math.Abs(w.Get(Assets.CRA) - 700) < 1e-6, $"到期自动回钱包 200:{w.Get(Assets.CRA):0.##}");
|
Check(Math.Abs(w.Get(Assets.CRA) - 700) < 1e-6, $"到期自动回钱包 200:{w.Get(Assets.CRA):0.##}");
|
||||||
Check(w.Taint > 400 - lotTaint + 1, "污点按比例回来");
|
Check(w.Taint > 400 - lotTaint + 1, "污点按比例回来");
|
||||||
// 螺旋:质押的 CRA 取回后只值当时的价格
|
// 螺旋:质押的 CRA 取回后只值当时的价格
|
||||||
var s = new Stablecoins(); s.CraSpiralDay = 5;
|
var s = new Stablecoins(); s.CraCrashDay = 5;
|
||||||
for (int d = 5; d <= 7; d++) s.Night(d, new Rng(1), 0);
|
for (int d = 5; d <= 7; d++) s.Night(d, new Rng(1), 0);
|
||||||
Check(s.Cra < 0.05 && s.Spark < Tuning.SparkStart * 0.1, $"螺旋后 CRA {s.Cra},SPARK {s.Spark:0.00}");
|
Check(s.Cra < 0.05 && s.Spark < Tuning.SparkStart * 0.1, $"螺旋后 CRA {s.Cra},SPARK {s.Spark:0.00}");
|
||||||
});
|
});
|
||||||
|
|
||||||
Test("SPARK:随机游走有界,铸销来回只损手续费,事件冲击", () =>
|
Test("SPARK:随机游走有界,铸销事件冲击", () =>
|
||||||
{
|
{
|
||||||
double lo = 99, hi = 0;
|
double lo = 99, hi = 0;
|
||||||
for (ulong seed = 1; seed <= 20; seed++)
|
for (ulong seed = 1; seed <= 20; seed++)
|
||||||
@@ -1056,9 +1146,7 @@ internal static class Program
|
|||||||
for (int d = 1; d <= 150 && s.CraWarnDay < 0; d++) { s.Night(d, rng, 0); lo = Math.Min(lo, s.Spark); hi = Math.Max(hi, s.Spark); } // 螺旋前
|
for (int d = 1; d <= 150 && s.CraWarnDay < 0; d++) { s.Night(d, rng, 0); lo = Math.Min(lo, s.Spark); hi = Math.Max(hi, s.Spark); } // 螺旋前
|
||||||
}
|
}
|
||||||
Check(lo >= Tuning.SparkStart * Tuning.SparkMinMult - 1e-9 && hi <= Tuning.SparkStart * Tuning.SparkMaxMult + 1e-9 && hi / lo > 1.5, $"螺旋前的范围 {lo:0.0}–{hi:0.0}");
|
Check(lo >= Tuning.SparkStart * Tuning.SparkMinMult - 1e-9 && hi <= Tuning.SparkStart * Tuning.SparkMaxMult + 1e-9 && hi / lo > 1.5, $"螺旋前的范围 {lo:0.0}–{hi:0.0}");
|
||||||
var s2 = new Stablecoins(); var w = new Wallet { Address = "w" }; w.Add(Assets.CRA, 100);
|
var s2 = new Stablecoins();
|
||||||
double sp = s2.Mint(w, 100), back = s2.Burn(w, sp);
|
|
||||||
Check(Math.Abs(back - 100 * Math.Pow(1 - Tuning.SparkFee, 2)) < 1e-6 && s2.Mint(w, 1e6) < 0, $"来回 100 → {back:0.00},余额不足返回 -1");
|
|
||||||
double before = s2.Spark; s2.OnEventStart(MarketEvent.RevRaidUpper, 1, new Rng(1));
|
double before = s2.Spark; s2.OnEventStart(MarketEvent.RevRaidUpper, 1, new Rng(1));
|
||||||
Check(Math.Abs(s2.Spark - before * Tuning.SparkRaidShock) < 1e-9, "袭击上层 +15%");
|
Check(Math.Abs(s2.Spark - before * Tuning.SparkRaidShock) < 1e-9, "袭击上层 +15%");
|
||||||
});
|
});
|
||||||
@@ -1333,7 +1421,7 @@ internal static class Program
|
|||||||
Check(Math.Abs(hit / (double)runs - PredictMath.GasAtLeast(10, 3, 1.3)) < 0.02, "gas 概率和真实抽样对得上");
|
Check(Math.Abs(hit / (double)runs - PredictMath.GasAtLeast(10, 3, 1.3)) < 0.02, "gas 概率和真实抽样对得上");
|
||||||
double h = 1 - Math.Pow(1 - Tuning.CraSpiralWeekly, 1.0 / 7);
|
double h = 1 - Math.Pow(1 - Tuning.CraSpiralWeekly, 1.0 / 7);
|
||||||
Check(Math.Abs(PredictMath.CraWarnProb(1e9, 100, 10, 12, 14, h) - (1 - Math.Pow(1 - h, 3)) * Math.Pow(1 - h, 2)) < 1e-9, "补贴池充足时按日概率,窗口前发出的不算");
|
Check(Math.Abs(PredictMath.CraWarnProb(1e9, 100, 10, 12, 14, h) - (1 - Math.Pow(1 - h, 3)) * Math.Pow(1 - h, 2)) < 1e-9, "补贴池充足时按日概率,窗口前发出的不算");
|
||||||
Check(PredictMath.CraWarnProb(150, 100, 10, 11, 12, h) > 0.99, "补贴池撑不过窗口前一晚就必发");
|
Check(Math.Abs(PredictMath.CraWarnProb(150, 100, 10, 11, 12, h) - (1 - h)) < 1e-9, "垫子撑不过窗口前一晚:窗口第一晚必发,只要之前没按日概率发出");
|
||||||
Check(PredictMath.CraWarnProb(50, 100, 10, 10, 10, h) == 1, "归零那晚必发");
|
Check(PredictMath.CraWarnProb(50, 100, 10, 10, 10, h) == 1, "归零那晚必发");
|
||||||
Check(PredictMath.EraProb(60, 61, 63, -1) > 0 && PredictMath.EraProb(60, 61, 63, -1) < 0.2, "没预警时在 50–90 里均匀,3 天窗口很小");
|
Check(PredictMath.EraProb(60, 61, 63, -1) > 0 && PredictMath.EraProb(60, 61, 63, -1) < 0.2, "没预警时在 50–90 里均匀,3 天窗口很小");
|
||||||
Check(Math.Abs(PredictMath.EraProb(60, 62, 63, 58) - 0.5) < 1e-9 || PredictMath.EraProb(60, 62, 63, 58) > 0, "预警后落在 4–7 天内");
|
Check(Math.Abs(PredictMath.EraProb(60, 62, 63, 58) - 0.5) < 1e-9 || PredictMath.EraProb(60, 62, 63, 58) > 0, "预警后落在 4–7 天内");
|
||||||
|
|||||||
Reference in new issue
Block a user