Sync workspace: config, docs, scripts, CI, operator rules, and submodule pointers.
- Update dbis_core, cross-chain-pmm-lps, explorer-monorepo, metamask-integration, pr-workspace/chains - Omit embedded publish git dirs and empty placeholders from index Made-with: Cursor
This commit is contained in:
154
scripts/analytics/mainnet-truu-pmm-profitability-model.py
Normal file
154
scripts/analytics/mainnet-truu-pmm-profitability-model.py
Normal file
@@ -0,0 +1,154 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Mainnet cW/TRUU PMM — profitability *model* (not trading advice).
|
||||
|
||||
Computes break-even edges, max clip sizes vs reserves, and LP fee ceilings from
|
||||
documented defaults (MAINNET_PMM_TRUU_CWUSD_PEG_AND_BOT_RUNBOOK.md, 04-bot-policy.md).
|
||||
|
||||
Usage:
|
||||
python3 scripts/analytics/mainnet-truu-pmm-profitability-model.py
|
||||
python3 scripts/analytics/mainnet-truu-pmm-profitability-model.py --gas-usd 3 --assume-daily-volume-usd 5000
|
||||
|
||||
All USD notions for the cW leg treat 6-decimal cW as ~1 USD per 1e6 raw (numeraire wrapper).
|
||||
TRUU leg is shown in raw + full tokens only; USD(TRUU) must be supplied via --truu-usd-price.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
from dataclasses import dataclass
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class PoolState:
|
||||
name: str
|
||||
base_raw: int # cW 6 decimals
|
||||
quote_raw: int # TRUU 10 decimals
|
||||
|
||||
|
||||
def fmt_usd_from_cw_raw(raw: int) -> float:
|
||||
return raw / 1_000_000.0
|
||||
|
||||
|
||||
def max_clip_base_raw(base_reserve_raw: int, max_trade_frac: float) -> int:
|
||||
"""Runbook-style cap: fraction of *base* reserve (binding leg is usually tiny USD base)."""
|
||||
return int(base_reserve_raw * max_trade_frac)
|
||||
|
||||
|
||||
def break_even_edge_bps(*, fee_bps_sum: float, gas_usd: float, trade_notional_usd: float) -> float:
|
||||
"""
|
||||
Minimum mid-price edge (in bps of notional) so that fee_bps_sum + gas/trade >= 0 on the margin.
|
||||
edge_bps >= fee_bps_sum + (gas_usd / trade_notional_usd) * 10000
|
||||
"""
|
||||
if trade_notional_usd <= 0:
|
||||
return float("inf")
|
||||
return fee_bps_sum + (gas_usd / trade_notional_usd) * 10_000.0
|
||||
|
||||
|
||||
def main() -> None:
|
||||
p = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||
p.add_argument("--gas-usd", type=float, default=2.0, help="All-in gas cost per tx (USD), rough")
|
||||
p.add_argument("--pmm-fee-bps", type=float, default=30.0, help="PMM pool fee (bps per leg)")
|
||||
p.add_argument(
|
||||
"--uni-fee-bps",
|
||||
type=float,
|
||||
default=5.0,
|
||||
help="Uniswap v3 pool fee tier (bps), if used (500 v3 tier = 5 bps)",
|
||||
)
|
||||
p.add_argument("--truu-usd-price", type=float, default=0.0, help="USD per 1 full TRUU (optional, for quote-leg USD)")
|
||||
p.add_argument("--assume-daily-volume-usd", type=float, default=0.0, help="Hypothetical daily volume through one pool (USD)")
|
||||
p.add_argument(
|
||||
"--pools-json",
|
||||
type=str,
|
||||
default="",
|
||||
help="Optional: path to file with last reserves; otherwise use baked-in snapshot",
|
||||
)
|
||||
args = p.parse_args()
|
||||
|
||||
# Snapshot: update when reserves change (or pass --pools-json later).
|
||||
pools = [
|
||||
PoolState("cWUSDT/TRUU", 1_739_869, 431_892_240_211_824),
|
||||
PoolState("cWUSDC/TRUU", 320_478, 79_553_215_830_929),
|
||||
]
|
||||
|
||||
print("=== Mainnet TRUU PMM — maximum-profitability *inputs* (model) ===\n")
|
||||
print("1) DEPTH (binding leg is usually 6-dec cW ≈ USD numeraire)\n")
|
||||
total_cw_usd = 0.0
|
||||
for pool in pools:
|
||||
usd = fmt_usd_from_cw_raw(pool.base_raw)
|
||||
total_cw_usd += usd
|
||||
truu_full = pool.quote_raw / 1e10
|
||||
line = (
|
||||
f" {pool.name}: base_raw={pool.base_raw} (~${usd:.4f} cW) | "
|
||||
f"quote_raw={pool.quote_raw} ({truu_full:.4f} full TRUU)"
|
||||
)
|
||||
if args.truu_usd_price > 0:
|
||||
line += f" | quote≈${truu_full * args.truu_usd_price:.4f} @ {args.truu_usd_price} USD/TRUU"
|
||||
print(line)
|
||||
print(f" Sum cW legs (USD-ish): ~${total_cw_usd:.4f}\n")
|
||||
|
||||
print("2) MAX ACTIVE CLIP (runbook ballpark: 0.25–0.5% of smaller reserve — here applied to *base* raw)\n")
|
||||
for frac, label in ((0.0025, "0.25%"), (0.005, "0.5%")):
|
||||
print(f" {label} of base reserve:")
|
||||
for pool in pools:
|
||||
clip = max_clip_base_raw(pool.base_raw, frac)
|
||||
print(f" {pool.name}: max_base_raw={clip} (~${fmt_usd_from_cw_raw(clip):.6f})")
|
||||
print()
|
||||
|
||||
print("3) BREAK-EVEN *PRICE EDGE* (bps of notional) after fees + gas\n")
|
||||
print(f" Assumed gas_usd per tx = ${args.gas_usd:.2f}")
|
||||
print(" Fee model (linear bps, simplified): PMM round-trip ≈ 2× PMM fee; PMM+Uni round-trip ≈ PMM+Uni fee.\n")
|
||||
# Two-leg PMM round-trip (sell then buy back): 2 * pmm fee on notional (simplified linear bps model)
|
||||
pmm_round_trip_fee_bps = 2 * args.pmm_fee_bps
|
||||
# PMM + Uniswap round-trip: one PMM + one Uni (minimal 2-hop story)
|
||||
pmm_uni_fee_bps = args.pmm_fee_bps + args.uni_fee_bps
|
||||
|
||||
for pool in pools:
|
||||
n_clip = fmt_usd_from_cw_raw(max_clip_base_raw(pool.base_raw, 0.005))
|
||||
n_full = fmt_usd_from_cw_raw(pool.base_raw)
|
||||
print(f" {pool.name} — runbook clip (0.5% of base): notional≈${n_clip:.6f}; entire base leg≈${n_full:.4f}")
|
||||
for label, n_usd in (("0.5% clip", n_clip), ("100% base leg", n_full)):
|
||||
if n_usd < 1e-12:
|
||||
continue
|
||||
be_pmm_2g = break_even_edge_bps(
|
||||
fee_bps_sum=pmm_round_trip_fee_bps, gas_usd=2 * args.gas_usd, trade_notional_usd=n_usd
|
||||
)
|
||||
be_x_2g = break_even_edge_bps(
|
||||
fee_bps_sum=pmm_uni_fee_bps, gas_usd=2 * args.gas_usd, trade_notional_usd=n_usd
|
||||
)
|
||||
print(f" {label} (${n_usd:.6f}): break-even edge ≥ {be_pmm_2g:.1f} bps (PMM 2×gas) | ≥ {be_x_2g:.1f} bps (PMM+Uni 2×gas)")
|
||||
|
||||
print("\n Scaled notionals (if you add depth + capital — same fee/gas model):\n")
|
||||
print(f" {'N USD':>10} {'PMM 2×gas bps':>16} {'PMM+Uni 2×gas bps':>18}")
|
||||
for n_usd in (10, 50, 100, 500, 1000, 10_000):
|
||||
b1 = break_even_edge_bps(fee_bps_sum=pmm_round_trip_fee_bps, gas_usd=2 * args.gas_usd, trade_notional_usd=n_usd)
|
||||
b2 = break_even_edge_bps(fee_bps_sum=pmm_uni_fee_bps, gas_usd=2 * args.gas_usd, trade_notional_usd=n_usd)
|
||||
print(f" {n_usd:>10.0f} {b1:>16.2f} {b2:>18.2f}")
|
||||
print(" (Below ~$100 notional on L1, gas usually dominates 60 bps fees; depth must rise to trade larger.)\n")
|
||||
|
||||
print("4) LP FEE CEILING (30 bps taker fee — simplified: revenue ≈ 0.003 × volume)\n")
|
||||
f = args.pmm_fee_bps / 10_000.0
|
||||
if args.assume_daily_volume_usd > 0:
|
||||
rev = f * args.assume_daily_volume_usd
|
||||
print(f" If daily volume through *one* pool = ${args.assume_daily_volume_usd:,.2f} → LP fee ~${rev:.2f}/day (theory; split among LPs).")
|
||||
else:
|
||||
print(" Pass --assume-daily-volume-usd N to see $/day; with publicRoutingEnabled=false, N may be ~0.")
|
||||
print()
|
||||
|
||||
print("5) WHAT IS *NECESSARY* FOR (close to) MAXIMUM PROFITABILITY — operational, not a guarantee\n")
|
||||
reqs = [
|
||||
"Edge: repeated |P_reference − P_PMM| large enough to clear fee_bps + gas/notional (see section 3).",
|
||||
"Size: inventory + ETH gas; clip within runbook fraction of smallest reserve (section 2).",
|
||||
"Fair pricing: keep PMM `i` aligned with Uniswap TRUU/USDT TWAP/median + caps on `i` moves.",
|
||||
"Flow: route discovery (routers/aggregators) or deliberate flow; else LP fees stay ~0.",
|
||||
"Execution: minAmountOut, nonce control, pause on oracle divergence / bridge flags (bot policy doc).",
|
||||
"Scale: deeper two-sided liquidity reduces slippage and raises max safe notional per clip.",
|
||||
"Legal/compliance: MM and public claims per internal policy (runbook).",
|
||||
]
|
||||
for r in reqs:
|
||||
print(f" • {r}")
|
||||
print("\nThis script does not fetch live gas or Uni prices; plug fresh numbers for decisions.\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
4634
scripts/analytics/pmm-flash-push-break-even.mjs
Executable file
4634
scripts/analytics/pmm-flash-push-break-even.mjs
Executable file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user