Snapshot commit rolling up ~255 files of coherent-but-multi-domain in-flight
work that had accumulated on this branch. Split by area:
Contracts + covenants
- New: AsmFxSwap, DeviantOpenMintNBA, DeviantTieredMintOracleFT,
TermCouponVault, UniformReserve, UniformReserveAggregate.
- Verify-artifact refresh (src/verify/artifacts/*.json + canonical.ts).
Wallet + shell (shells/app + src/wallet)
- App.tsx, MainScreen, ArtemisionScreen, AssetDetail, AgoraScreen,
SettingsScreen, Unlock, TokenImportModal, UniformFiat/DepositPanel,
KatalogosPanel (renamed from PinaxPanel), shell.css.
- src/wallet: wallet.ts, runtime.ts, index.ts. Core registry/chipnetFile.
- Deleted stale hook: useAllDevBalances.ts.
Cross-chain + correspondent (services/correspondent + scripts)
- Correspondent server/bch/config updates for PYUSD Solana, EURC Sepolia,
aggregate reserve flows.
- New scripts: PYUSD roundtrip, EURC onboarding, GMX game loop /
genesis / mint sanity, tiered mint fee, aggregate reserve, product2
shares dividends, product3 t-bond, uniform fiat cell tests.
Telegram order-book (P2PExchange bot)
- db.ts, index.ts, en/ru locales — updates upstream from the extracted
standalone repo at D:/Dev/P2PExchange.
Docs — Parameters (specs), wiki, snapshots, design mockups
- Parameters: FIATm/MBA_Shares/Potidaea/Anthemus refinements +
ASM_CrossChain/DebitCredit + UniformFiat + Anthemus DEX MVP prompt +
Artemision + Athenae Politeia + Philosophy + SSHkeyServer runbook +
new dApp/{Artemision,Katalogos,Pinax,Pari_escrow,SURFACES}.
- wiki: cross-chain, games-tote, glossary, governance/voting-systems,
infra, wallet, wallet-ui-design, decisions (ADR log).
- snapshots: catch-up entries and INDEX regeneration.
- design: mockups refreshed (agora, asset-detail, assets-tab, potidaea)
+ Potidaea assets + tote deploy notes.
Housekeeping
- .gitignore: exclude the new root test/session state files
(.sol-vault-keys.json, .football-tote-state.json,
.tote-platform-state.json, .redeem-roundtrip-state.json,
.eurc-onboard-state.json — some contain oracle privkeys / vault
secretKeyBase58; NEVER commit) + the .usdm-historical-chart.html
chart output + MS Office `~$*` lock files + scripts/bundle-surfaces
`build/` output. Also add scripts/bundle-surfaces.mjs.
- CLAUDE.md, WALLET-COORDINATION.md, snapshots/INDEX.md, design/README.md
refreshed.
- package.json / package-lock.json bumps.
Verified: sensitive files at repo root confirmed ignored (git check-ignore
each). No `.env`, no raw WIF/xprv/mnemonic/secretKey/oraclePriv strings in
the staged diff. MS Word autosave file (`Parameters/Philosophy/~$*.docx`)
excluded and gitignored.
The WizardConnect responder work landed separately in the previous commit
(6987591); this is everything else that had accumulated alongside it.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
140 lines
12 KiB
JavaScript
140 lines
12 KiB
JavaScript
#!/usr/bin/env node
|
||
/**
|
||
* sim-anthemus-fx-market-vs-covenant.mjs — what does a counterparty-free covenant swap actually
|
||
* trade vs a market swap? And how does sharing the FX risk 50/50 change the allowed band?
|
||
*
|
||
* Setup (all cases): A holds 100 USD + 100 EUR (as BCH IOUs). A swaps ALL 100 EUR -> USD @ r0.
|
||
* CASE 2 MARKET swap: a real counterparty takes the EUR; A pays a SPREAD s; A is FX-LOCKED
|
||
* (holds USD, no residual EUR exposure). The counterparty now holds the FX position.
|
||
* CASE 1 COVENANT swap (no counterparty): A swaps at the ORACLE MID (no spread). But the swap
|
||
* leaves the POOL short EUR — an open FX position. WHO bears its drift is the design:
|
||
* - full-buffer : A bears 100% (marked-to-market => A stays FX-NEUTRAL, keeps EUR risk)
|
||
* - no-buffer : the DESK bears 100% (A is FX-LOCKED like the market, but pays NO spread)
|
||
* - hybrid 50/50: A and desk each bear half
|
||
*
|
||
* THE INSIGHT the numbers show: a covenant swap SAVES THE SPREAD but RETAINS FX RISK. FX is a
|
||
* martingale => bearing it is EXPECTED-zero but has VARIANCE. So the covenant swap beats the
|
||
* market swap by ~the spread in expectation; the design only moves WHO holds the variance. And
|
||
* because the desk's RISK per position scales with the fraction it bears, sharing 50/50 lets the
|
||
* same desk-risk budget (the band) cover 2x the notional — your band-doubling.
|
||
*
|
||
* Real EUR/USD 2021-23, seeded. Run: node scripts/sim-anthemus-fx-market-vs-covenant.mjs
|
||
*/
|
||
function mulberry32(a){return function(){a|=0;a=(a+0x6D2B79F5)|0;let t=Math.imul(a^(a>>>15),1|a);t=(t+Math.imul(t^(t>>>7),61|t))^t;return((t^(t>>>14))>>>0)/4294967296;};}
|
||
const gauss=(rng)=>{let u=0,v=0;while(u===0)u=rng();while(v===0)v=rng();return Math.sqrt(-2*Math.log(u))*Math.cos(2*Math.PI*v);};
|
||
const EURUSD_MONTHLY=[1.213,1.207,1.173,1.202,1.219,1.186,1.187,1.181,1.158,1.156,1.134,1.137,1.123,1.122,1.107,1.055,1.073,1.048,1.022,1.005,0.980,0.988,1.041,1.070,1.086,1.058,1.084,1.102,1.069,1.091,1.102,1.084,1.057,1.058,1.089,1.104];
|
||
function buildPath(seed){const rng=mulberry32(seed);const p=[];for(let m=0;m<EURUSD_MONTHLY.length-1;m++){const a=EURUSD_MONTHLY[m],b=EURUSD_MONTHLY[m+1];for(let w=0;w<4;w++){const f=w/4;p.push((a+(b-a)*f)*(1+gauss(rng)*0.004));}}p.push(EURUSD_MONTHLY.at(-1));return p;}
|
||
const r3=(n)=>Math.round(n*1000)/1000;
|
||
const $=(n)=>(n<0?'-':'')+'$'+Math.abs(Math.round(n*100)/100).toFixed(2);
|
||
const div=(c='=')=>console.log(c.repeat(94));
|
||
const head=(t)=>{console.log('\n');div();console.log(t);div();};
|
||
|
||
const SEED=20260718;const path=buildPath(SEED);const N=path.length;
|
||
const Dusd=100, Deur=100, r0=1.18; // A's holdings + entry rate
|
||
const SPREAD=0.003; // market swap all-in cost (EURC/USDC is thin ~0.3%)
|
||
|
||
// A's total wealth (USD) at settlement rate r1, per design:
|
||
const wMarket =(r1)=> Dusd + Deur*r0*(1-SPREAD); // FX-locked at r0, minus spread; const in USD
|
||
const wFullBuf =(r1)=> Dusd + Deur*r1; // FX-neutral (marked): keeps EUR exposure
|
||
const wNoBuf =(r1)=> Dusd + Deur*r0; // FX-locked at r0, NO spread (desk ate drift)
|
||
const wHybrid =(r1)=> Dusd + Deur*r0 - 0.5*Deur*(r0-r1); // locked half, kept half
|
||
// Desk wealth (USD) from the position (0 for market: counterparty holds it, not the desk):
|
||
const dMarket=(r1)=>0, dFullBuf=(r1)=>0, dNoBuf=(r1)=>Deur*(r1-r0), dHybrid=(r1)=>0.5*Deur*(r1-r0);
|
||
|
||
// ════════════════════════════════════════════════════════════════════════════
|
||
head('PART 1 — single swap, three rate scenarios. A\'s wealth + desk\'s wealth, vs the MARKET swap.');
|
||
console.log(`A: ${Dusd} USD + ${Deur} EUR. Swap all EUR->USD @ ${r0}. Market spread s=${(SPREAD*100).toFixed(1)}%. Values in USD at settle.\n`);
|
||
for(const [r1,label] of [[1.18,'FLAT (r1=1.18)'],[1.14,'EUR FELL -3.4% (r1=1.14)'],[1.22,'EUR ROSE +3.4% (r1=1.22)']]){
|
||
console.log(` --- ${label} ---`);
|
||
console.log(['design','A wealth','desk wealth','A vs market','A+desk'].map(s=>s.padStart(16)).join(''));
|
||
div('-');
|
||
const rows=[
|
||
['MARKET (case2)', wMarket(r1), dMarket(r1)],
|
||
['covenant no-buf', wNoBuf(r1), dNoBuf(r1)],
|
||
['covenant full-buf(case1)', wFullBuf(r1), dFullBuf(r1)],
|
||
['covenant hybrid', wHybrid(r1), dHybrid(r1)],
|
||
];
|
||
for(const [name,a,d] of rows){
|
||
console.log([name, $(a), $(d), $(a-wMarket(r1)), $(a+d)].map(s=>String(s).padStart(16)).join(''));
|
||
}
|
||
console.log('');
|
||
}
|
||
console.log(' Reading the "A vs market" column:');
|
||
console.log(' • FLAT: every covenant design beats market by the SAVED SPREAD ($0.35). No FX moved.');
|
||
console.log(' • EUR FELL: full-buffer A is WORSE than market (-$3.65) — A kept EUR exposure and ate the drop.');
|
||
console.log(' no-buffer A still beats market (+$0.35) — A locked in AND saved the spread; the DESK took -$4.');
|
||
console.log(' hybrid splits it: A ~-$1.65 vs market, desk -$2.');
|
||
console.log(' • EUR ROSE: full-buffer A BEATS market (+$4.35) — A kept EUR and caught the rise; desk flat.');
|
||
console.log(' => COVENANT SWAP = MARKET SWAP minus the spread, plus retained FX risk. The design just moves');
|
||
console.log(' WHO holds that risk (A / desk / shared). "A+desk" conserves — nothing is created or lost.');
|
||
|
||
// ════════════════════════════════════════════════════════════════════════════
|
||
head('PART 2 — difference in TOTAL VALUE (case1 covenant-buffer − case2 market), decomposed.');
|
||
console.log(' ΔWealth(A) = wFullBuf(r1) − wMarket(r1) = [saved spread] − [FX drift the market locked out]');
|
||
console.log(` = ${$(Deur*r0*SPREAD)} (spread saved) − ${Deur}·(r0−r1) (drift A retained)\n`);
|
||
console.log(['r1','saved spread','retained drift','Δ case1−case2'].map(s=>s.padStart(18)).join(''));
|
||
div('-');
|
||
for(const r1 of [1.18,1.16,1.14,1.10,1.20,1.22]){
|
||
const spread=Deur*r0*SPREAD, drift=Deur*(r0-r1);
|
||
console.log([r3(r1), $(spread), $(-drift), $(spread-drift)].map(s=>String(s).padStart(18)).join(''));
|
||
}
|
||
// realized outcome: enter at r0=1.18, settle at each future week on the real path
|
||
let sum=0; for(let i=1;i<N;i++){ sum += (Deur*r0*SPREAD) - Deur*(r0-path[i]); }
|
||
const meanDelta=sum/(N-1);
|
||
// martingale/round-trip control: average over every (entry, settle=entry+4wk) pair (no anchor bias)
|
||
let sum2=0,cnt=0; for(let s=0;s+4<N;s++){ sum2 += (Deur*path[s]*SPREAD) - Deur*(path[s]-path[s+4]); cnt++; }
|
||
const meanRT=sum2/cnt;
|
||
console.log(`\n HONEST caveat — the realized number depends on the PATH, not just the spread:`);
|
||
console.log(` • Enter at r0=${r0} (a 2021 HIGH), settle at each later week: E[Δ case1−case2] = ${$(meanDelta)} — NEGATIVE.`);
|
||
console.log(` Because the buffer covenant RETAINS EUR exposure and EUR fell 1.18→1.10 over this path, the`);
|
||
console.log(` retained-drift term dominated the saved spread. Buffer-swapping near a top and holding HURTS.`);
|
||
console.log(` • Anchor-free control (every entry, settle 4wk later): E[Δ] = ${$(meanRT)} ≈ 0 here — the +$0.33`);
|
||
console.log(` spread saving is offset by this sample's mild downward drift. Under a FAIR MARTINGALE it`);
|
||
console.log(` would be +the spread (~$0.33); this 2021-23 sample simply fell, so the drift term ate it.`);
|
||
console.log(` => The "beats by ~the spread" result is a MARTINGALE statement, not a guarantee. The buffer`);
|
||
console.log(` design's honest cost = the USER carries FX DIRECTION+variance; a directional loser (hold`);
|
||
console.log(` through a fall) underperforms the market swap. No free lunch — the spread buys certainty.`);
|
||
|
||
// ════════════════════════════════════════════════════════════════════════════
|
||
head('PART 3 — the band-doubling proof: desk RISK per position scales with the fraction it bears.');
|
||
console.log('The band caps DESK RISK. Desk risk on a position = (fraction desk bears) × notional × maxMove.');
|
||
console.log('For a fixed desk-risk budget (say 10% of reserve × maxMove), the allowed NOTIONAL band is:\n');
|
||
const maxMove=(()=>{let w=0;for(let s=0;s+1<N;s++){const e=path[s];for(let t=s+1;t<N;t++){w=Math.max(w,Math.abs(path[t]-e)/e);}}return w;})();
|
||
const reserve=1_000_000, riskBudget=0.10*reserve*maxMove; // the "10% band" expressed as a risk budget
|
||
console.log(['design','desk bears','max notional (same risk)','as % reserve'].map(s=>s.padStart(22)).join(''));
|
||
div('-');
|
||
for(const [name,frac] of [['no-buffer',1.0],['hybrid 50/50',0.5],['full-buffer',0.0]]){
|
||
if(frac===0){ console.log([name,'0%','∞ (user-bounded)','user balance'].map(s=>String(s).padStart(22)).join('')); continue; }
|
||
const maxNotional=riskBudget/(frac*maxMove);
|
||
console.log([name, `${frac*100}%`, $(maxNotional), `${(maxNotional/reserve*100).toFixed(0)}%`].map(s=>String(s).padStart(22)).join(''));
|
||
}
|
||
console.log('\n => YOUR CLAIM CONFIRMED: at 50/50 the desk bears half the drift per position, so the SAME 10%');
|
||
console.log(' desk-risk budget covers DOUBLE the notional — a 20% band. Full-buffer removes desk risk');
|
||
console.log(' entirely (band limited only by the user\'s own balance + the gap tail). One dial: how much');
|
||
console.log(' FX risk the user keeps sets both (a) how much they de-risk and (b) how large the band can be.');
|
||
|
||
// ════════════════════════════════════════════════════════════════════════════
|
||
head('PART 4 — the spectrum, and why the hybrid is the sweet spot.');
|
||
console.log(`
|
||
design A pays spread A de-risks FX desk FX risk max band (notional) product
|
||
------------ ------------- ------------- ----------- ------------------- -----------------------
|
||
MARKET swap full (~0.3%) 100% 0 (LP holds) ∞ (real liquidity) "convert & de-risk, pay LP"
|
||
no-buffer 0 100% 100% 10% (1× band) "convert free, desk insures"
|
||
HYBRID 50/50 0 (or ½) 50% 50% 20% (2× band) "convert free, share the risk"
|
||
full-buffer 0 0% (neutral) 0% user-bounded "spend cross-ccy, keep FX"
|
||
|
||
The hybrid is the sweet spot for a CONVERSION product (user wants to de-risk, not just spend):
|
||
• A de-risks HALF its FX for FREE (no spread) — genuinely better than the market for that half.
|
||
• The desk bears half — but FX is expected-zero, so the desk's cost is VARIANCE/capital, not an
|
||
expected loss. It needs only a small RISK PREMIUM (capital cost + gap tail), not a full spread.
|
||
• The band DOUBLES (20%) for the same desk risk — 2× the throughput at maturity.
|
||
• Beyond the band, route to the DEX (market swap) — the two compose: covenant for the first 20%,
|
||
market for the tail. Users always get filled; the desk's risk stays capped.
|
||
|
||
Honest caveats (carry to the ADR): the desk holds only a PAPER position, not a realized cost — the
|
||
band is a rebalancing WORKING-CAPITAL buffer; two-way flow rebalances at ~no cost, and the drift is
|
||
realized only if the short currency is withdrawn past its locked reserve (~90%+, see
|
||
sim-anthemus-fx-realized.mjs). A thin premium is OPTIONAL insurance for that bounded tail
|
||
(<= band x move), not compensation for a continuous loss. The hybrid is a partial FX position for
|
||
the user (a mild derivative — same per-jurisdiction gate as the credit modes).
|
||
`);
|