Add feature-aware maker learning

This commit is contained in:
Theodore Song
2026-08-23 08:20:14 -04:00
parent 53141d9071
commit 2d210ffb93
6 changed files with 88 additions and 36 deletions
+1 -1
View File
@@ -35,7 +35,7 @@ jobs:
- run: node scripts/run-autonomous-cycle.mjs - run: node scripts/run-autonomous-cycle.mjs
env: env:
ARENA_URL: https://polymarket-site-eta.vercel.app ARENA_URL: https://polymarket-site-eta.vercel.app
EXPECTED_BUILD: "127" EXPECTED_BUILD: "128"
RUNTIME_BRANCH: runtime-state RUNTIME_BRANCH: runtime-state
RUNTIME_STATE_PATH: runtime/state.json RUNTIME_STATE_PATH: runtime/state.json
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+14 -7
View File
@@ -23,7 +23,7 @@ Offline cycles can apply calibration already earned from live observations, but
the evidence ledger is read-only: cached prices cannot grade pending signals, the evidence ledger is read-only: cached prices cannot grade pending signals,
expire horizons, or create new observations. expire horizons, or create new observations.
Build 127 targets five-minute slots with a serialized, self-chained GitHub Actions runtime. Build 128 targets five-minute slots with a serialized, self-chained GitHub Actions runtime.
The mutable snapshot stays on the dedicated `runtime-state` branch, which is The mutable snapshot stays on the dedicated `runtime-state` branch, which is
explicitly excluded from Vercel Git deployments through explicitly excluded from Vercel Git deployments through
`git.deploymentEnabled`. This prevents high-frequency state commits from `git.deploymentEnabled`. This prevents high-frequency state commits from
@@ -70,7 +70,7 @@ Polymarket event key. Related Ethereum or Bitcoin contracts cannot create
several simultaneous copies of one move, and outcomes from the same underlying several simultaneous copies of one move, and outcomes from the same underlying
three-hour shock window count as one learner event. three-hour shock window count as one learner event.
Each Build 127 cycle also scans the 1,000 most-active Polymarket events for Each Build 128 cycle also scans the 1,000 most-active Polymarket events for
complete negative-risk bundles and logically nested threshold or deadline complete negative-risk bundles and logically nested threshold or deadline
pairs, plus same-market YES/NO complements whose equal shares have a fixed pairs, plus same-market YES/NO complements whose equal shares have a fixed
$1 redemption value. Polymarket's documented complete-set merge converts equal $1 redemption value. Polymarket's documented complete-set merge converts equal
@@ -131,7 +131,7 @@ The Suggestions view stores scan, depth, fee, actionable, and closest
executable-margin counts so an empty lane is evidence rather than an ambiguous executable-margin counts so an empty lane is evidence rather than an ambiguous
failure. failure.
Build 127 retains the directional learner's exact-fee policy, which replaced the blanket half-cent cost with Build 128 retains the directional learner's exact-fee policy, which replaced the blanket half-cent cost with
the market's Gamma fee schedule at both the entry and future checkpoint, plus a the market's Gamma fee schedule at both the entry and future checkpoint, plus a
separate half-cent round-trip slippage allowance. Fee-free markets pay only the separate half-cent round-trip slippage allowance. Fee-free markets pay only the
slippage allowance; an unavailable fee schedule gets a conservative four-cent slippage allowance; an unavailable fee schedule gets a conservative four-cent
@@ -164,7 +164,7 @@ target fell to -44.14% in validation and remained negative in holdout, so it
cannot authorize capital. The reproducible result is stored in cannot authorize capital. The reproducible result is stored in
`research/settlement-calibration-exact-fee-5000-audit.json`. `research/settlement-calibration-exact-fee-5000-audit.json`.
Build 127 retains Build 100's retirement of the old 3-6 day resolution-window Build 128 retains Build 100's retirement of the old 3-6 day resolution-window
capital permission. That audit clustered confidence by event but still averaged capital permission. That audit clustered confidence by event but still averaged
several correlated contracts inside each event, while production could choose several correlated contracts inside each event, while production could choose
only one. The corrected replay chooses the highest-volume eligible contract per event and only one. The corrected replay chooses the highest-volume eligible contract per event and
@@ -284,7 +284,7 @@ evidence proves an edge.
Run `npm run evaluate:sports-favorites` for the retired pregame favorite audit. Run `npm run evaluate:sports-favorites` for the retired pregame favorite audit.
Its 12-hour, 60%-75% cohort had positive point estimates but did not establish a Its 12-hour, 60%-75% cohort had positive point estimates but did not establish a
reliable confidence bound, so Build 127 no longer allocates capital to that rule. reliable confidence bound, so Build 128 no longer allocates capital to that rule.
Strategy 65 also tracks the exact-fee settlement calibration's three-day Sports Strategy 65 also tracks the exact-fee settlement calibration's three-day Sports
NO cohort as a zero-capital forward lane. The corrected 5,000-market run NO cohort as a zero-capital forward lane. The corrected 5,000-market run
@@ -344,14 +344,21 @@ passed the chronological path screen at 25% of the present reward estimate, but
both did so without an adverse historical touch; this prioritizes shadow both did so without an adverse historical touch; this prioritizes shadow
research and does not authorize capital. research and does not authorize capital.
Maker research version 3 lets all ten agents split distinct zero-capital shadow Maker research version 4 lets all ten agents split distinct zero-capital shadow
quote pairs selected by the shared reward-book audit. Token histories are fetched quote pairs selected by the shared reward-book audit. Token histories are fetched
in batches, so the learner no longer silently ignores quotes after the first ten in batches, so the learner no longer silently ignores quotes after the first ten
markets. A live cycle must still verify each touch from public CLOB price history markets. A live cycle must still verify each touch from public CLOB price history
or a current book cross. After the first one-sided touch, the shadow engine now or a current book cross. After the first one-sided touch, the shadow engine now
buys the complement only when the current executable ask locks a positive margin buys the complement only when the current executable ask locks a positive margin
after modeled cost; otherwise it grades an immediate executable exit. It no after modeled cost; otherwise it grades an immediate executable exit. It no
longer waits with adverse one-sided shadow inventory. longer waits with adverse one-sided shadow inventory. Build 128 records seven
reproducible setup cohorts for every completed observation: category, spread,
reward yield, quote-price balance, recent movement, paired locked margin, and
visible competition. Shadow selection adds a bounded novelty score so the ten
agents rotate toward under-sampled configurations instead of repeatedly measuring
one dominant setup. A mature losing cohort vetoes risk; promotion would require
every matching cohort to clear its independent-event confidence and locked-fill
requirements, as well as a separately approved chronological backtest.
The August 21 expanded audit loaded both token histories for all 500 requested The August 21 expanded audit loaded both token histories for all 500 requested
markets, formed 7,335 observations, and tested 6,048 wait and immediate-hedge markets, formed 7,335 observations, and tested 6,048 wait and immediate-hedge
+60 -22
View File
@@ -341,7 +341,7 @@ footer{margin-top:34px;padding-top:22px;border-top:1px solid var(--border);color
<nav class="topnav"> <nav class="topnav">
<div class="brand"> <div class="brand">
<div class="logo">🏆</div> <div class="logo">🏆</div>
<div><div class="brand-name">Polymarket Arena</div><div class="brand-sub">10 agents · 5 core + 5 aggressive</div><div class="build-badge">Adaptive strategy 65 · expanded executable search · build 127</div></div> <div><div class="brand-name">Polymarket Arena</div><div class="brand-sub">10 agents · 5 core + 5 aggressive</div><div class="build-badge">Adaptive strategy 65 · feature-aware maker research · build 128</div></div>
</div> </div>
<div class="tabs" id="tabs"> <div class="tabs" id="tabs">
<button class="tab" data-tab="overview">Overview</button> <button class="tab" data-tab="overview">Overview</button>
@@ -363,7 +363,7 @@ footer{margin-top:34px;padding-top:22px;border-top:1px solid var(--border);color
<div class="personal-banner" id="personalBanner"> <div class="personal-banner" id="personalBanner">
<b>Personal research mode.</b> This copy is for your own analysis, paper tracking, and manual trade research only. It does not pool money, onboard investors, custody funds, bypass eligibility rules, or place orders without your manual approval. <b>Personal research mode.</b> This copy is for your own analysis, paper tracking, and manual trade research only. It does not pool money, onboard investors, custody funds, bypass eligibility rules, or place orders without your manual approval.
</div> </div>
<div class="live-build-banner"><b>Build 127 active:</b> Strategy 65 now exact-depth-checks 200 protected structures per cycle instead of 80, while reserving 40 checks each for complete-NO conversions and binary complements. The larger search preserves every economic gate: duration-aware return hurdles, at least $0.50 of executable locked profit, exact depth and fees, a 0.10c per-unit safety margin, 6-10% sizing, and the 12% event cap. Directional capital remains locked while its forward evidence is negative after exact costs. Phones and computers display the same read-only autonomous state. Profits are not guaranteed.</div> <div class="live-build-banner"><b>Build 128 active:</b> Strategy 65 retains the 200-structure protected search and every executable-profit gate. Maker research now learns separate price-balance, movement, locked-margin, and competition cohorts, preserves those features across restarts, and rotates zero-capital observations toward under-sampled setups. Directional capital remains locked because its independent forward evidence is negative after exact costs, and maker capital remains disabled until a separate chronological backtest approves it. Phones and computers display the same read-only autonomous state. Profits are not guaranteed.</div>
<!-- ============ OVERVIEW ============ --> <!-- ============ OVERVIEW ============ -->
<section class="tabpanel" data-tab="overview"> <section class="tabpanel" data-tab="overview">
@@ -745,7 +745,7 @@ footer{margin-top:34px;padding-top:22px;border-top:1px solid var(--border);color
</section> </section>
<footer> <footer>
Build 127 · Adaptive strategy 65 · Expanded independent-event executable search · Exact-fee complete-NO conversion · Evidence-first bounded snapshots · Six-hour bounded probation with matched executable exits · Serialized self-chained five-minute slots with cron recovery · Oldest-first bounded learning transport · Restart-safe offline runtime · Exact-fee directional learning · Duration-aware, event-capped verified bundles · Scale-aware executable-profit floor · Atomic verified bundle-profit recycling · Conservative intact-bundle accounting · Contest-deduplicated sports shadow research · Corrected one-decision-per-event settlement audit · Autonomous runtime 2 · Offline runtime 3 · Maker research 3 · Agent learning 3 · Paper trading only · Live prices from Polymarket's public Gamma and CLOB APIs · Not financial advice · Build 128 · Adaptive strategy 65 · Feature-aware diversified maker research · Expanded independent-event executable search · Exact-fee complete-NO conversion · Evidence-first bounded snapshots · Six-hour bounded probation with matched executable exits · Serialized self-chained five-minute slots with cron recovery · Oldest-first bounded learning transport · Restart-safe offline runtime · Exact-fee directional learning · Duration-aware, event-capped verified bundles · Scale-aware executable-profit floor · Atomic verified bundle-profit recycling · Conservative intact-bundle accounting · Contest-deduplicated sports shadow research · Corrected one-decision-per-event settlement audit · Autonomous runtime 2 · Offline runtime 3 · Maker research 4 · Agent learning 3 · Paper trading only · Live prices from Polymarket's public Gamma and CLOB APIs · Not financial advice ·
<a class="market-link" href="https://github.com/theodore-song/polymarket-analyst" target="_blank" rel="noopener">Source on GitHub</a> <a class="market-link" href="https://github.com/theodore-song/polymarket-analyst" target="_blank" rel="noopener">Source on GitHub</a>
</footer> </footer>
</div> </div>
@@ -774,10 +774,10 @@ const POLITICS_TREND_MIN_HOLD_HOURS = 72;
const EXIT_CONFIRM_HOURS = 6; const EXIT_CONFIRM_HOURS = 6;
const AGENTS_KEY = "pma_agents_v2"; const AGENTS_KEY = "pma_agents_v2";
const SUG_KEY = "pma_suggestions_v5"; const SUG_KEY = "pma_suggestions_v5";
const BUILD_VERSION = 127; const BUILD_VERSION = 128;
const AGENT_LEARNING_VERSION = 3; const AGENT_LEARNING_VERSION = 3;
const SUGGESTION_ENGINE_VERSION = 65; const SUGGESTION_ENGINE_VERSION = 65;
const MAKER_STRATEGY_VERSION = 3; const MAKER_STRATEGY_VERSION = 4;
const SHOCK_FADE_STRATEGY_VERSION = 4; const SHOCK_FADE_STRATEGY_VERSION = 4;
const RESOLUTION_WEEK_NO_STRATEGY_VERSION = 3; const RESOLUTION_WEEK_NO_STRATEGY_VERSION = 3;
const SPORTS_CONTEST_NO_STRATEGY_VERSION = 1; const SPORTS_CONTEST_NO_STRATEGY_VERSION = 1;
@@ -2333,7 +2333,9 @@ function compactSnapshotsForPublic(rows,limit=PUBLIC_RUNTIME_LIMITS.snapshots){
function compactMakerOutcomeForPublic(row){ function compactMakerOutcomeForPublic(row){
if(!row||typeof row!=="object")return row; if(!row||typeof row!=="object")return row;
return {quote_id:row.quote_id,market_id:row.market_id,event_key:row.event_key,category:row.category, return {quote_id:row.quote_id,market_id:row.market_id,event_key:row.event_key,category:row.category,
spread:row.spread,spread_band:row.spread_band,reward_yield_band:row.reward_yield_band,status:row.status, spread:row.spread,spread_band:row.spread_band,reward_yield_band:row.reward_yield_band,
price_balance_band:row.price_balance_band,day_move_band:row.day_move_band,margin_band:row.margin_band,
competition_band:row.competition_band,status:row.status,
pnl:row.pnl,shadow_only:row.shadow_only,deployed_capital:row.deployed_capital,reserved_capital:row.reserved_capital, pnl:row.pnl,shadow_only:row.shadow_only,deployed_capital:row.deployed_capital,reserved_capital:row.reserved_capital,
completed_at:row.completed_at,strategy_version:row.strategy_version,maker_strategy_version:row.maker_strategy_version}; completed_at:row.completed_at,strategy_version:row.strategy_version,maker_strategy_version:row.maker_strategy_version};
} }
@@ -4099,6 +4101,32 @@ function makerRewardBand(row){
const dailyYield=daily/capital; const dailyYield=daily/capital;
return dailyYield<0.02?"low":dailyYield<0.10?"medium":"high"; return dailyYield<0.02?"low":dailyYield<0.10?"medium":"high";
} }
function makerPriceBalanceBand(row){
const yes=Number(row&&row.yes_quote),no=Number(row&&row.no_quote),smaller=Math.min(yes,no);
if(!Number.isFinite(smaller))return "unknown";
return smaller>=0.35?"balanced":smaller>=0.15?"asymmetric":"extreme";
}
function makerDayMoveBand(row){
const move=Math.abs(Number(row&&row.day_move));
if(!Number.isFinite(move))return "unknown";
return move<=0.005?"stable":move<=0.02?"calm":"moving";
}
function makerMarginBand(row){
const cost=Number(row&&row.paired_cost),margin=1-cost;
if(!Number.isFinite(cost))return "unknown";
return margin<0.005?"thin":margin<0.015?"medium":"thick";
}
function makerCompetitionBand(row){
const competition=Number(row&&row.competitive);
if(!Number.isFinite(competition))return "unknown";
return competition<=0.33?"low":competition<=0.67?"medium":"high";
}
function makerFeatureKeys(row){
return [`category:${row.category||"Other"}`,`spread:${row.spread_band||makerSpreadBand(row.spread)}`,
`reward:${row.reward_yield_band||makerRewardBand(row)}`,`balance:${row.price_balance_band||makerPriceBalanceBand(row)}`,
`move:${row.day_move_band||makerDayMoveBand(row)}`,`margin:${row.margin_band||makerMarginBand(row)}`,
`competition:${row.competition_band||makerCompetitionBand(row)}`];
}
function summarizeMakerOutcomes(rows){ function summarizeMakerOutcomes(rows){
const weighted=[]; const weighted=[];
(rows||[]).forEach(row=>{ (rows||[]).forEach(row=>{
@@ -4131,8 +4159,7 @@ function summarizeMakerOutcomes(rows){
function buildMakerProfile(p,limit=MAKER_OUTCOME_LIMIT){ function buildMakerProfile(p,limit=MAKER_OUTCOME_LIMIT){
const outcomes=(p&&p.maker_outcomes||[]).slice(-limit),buckets={}; const outcomes=(p&&p.maker_outcomes||[]).slice(-limit),buckets={};
const add=(key,row)=>{if(!buckets[key])buckets[key]=[];buckets[key].push(row);}; const add=(key,row)=>{if(!buckets[key])buckets[key]=[];buckets[key].push(row);};
outcomes.forEach(row=>{add(`category:${row.category||"Other"}`,row);add(`spread:${row.spread_band||makerSpreadBand(row.spread)}`,row); outcomes.forEach(row=>makerFeatureKeys(row).forEach(key=>add(key,row)));
add(`reward:${row.reward_yield_band||makerRewardBand(row)}`,row);});
return {version:MAKER_STRATEGY_VERSION,outcomes:outcomes.length,global:summarizeMakerOutcomes(outcomes), return {version:MAKER_STRATEGY_VERSION,outcomes:outcomes.length,global:summarizeMakerOutcomes(outcomes),
buckets:Object.fromEntries(Object.entries(buckets).map(([key,rows])=>[key,summarizeMakerOutcomes(rows)]))}; buckets:Object.fromEntries(Object.entries(buckets).map(([key,rows])=>[key,summarizeMakerOutcomes(rows)]))};
} }
@@ -4141,20 +4168,23 @@ function buildSharedMakerProfile(st){
return buildMakerProfile({maker_outcomes:outcomes},MAKER_OUTCOME_LIMIT*AGENTS.length); return buildMakerProfile({maker_outcomes:outcomes},MAKER_OUTCOME_LIMIT*AGENTS.length);
} }
function makerCandidateLearning(candidate,profile){ function makerCandidateLearning(candidate,profile){
const category=profile.buckets[`category:${candidate.category}`],spread=profile.buckets[`spread:${makerSpreadBand(candidate.spread)}`]; const bands={price_balance_band:makerPriceBalanceBand(candidate),day_move_band:makerDayMoveBand(candidate),
const rewardBand=candidate.reward_yield_band||makerRewardBand(candidate),reward=profile.buckets[`reward:${rewardBand}`]; margin_band:makerMarginBand(candidate),competition_band:makerCompetitionBand(candidate)};
const matching=[profile.global,category,spread,reward].filter(Boolean),mature=matching.filter(stats=>stats.current_events>=MAKER_MIN_COHORT_ATTEMPTS); const enriched=Object.assign({},candidate,bands),keys=makerFeatureKeys(enriched),featureStats=keys.map(key=>profile.buckets[key]);
const losing=mature.some(stats=>stats.upper<0),evidencePromoted=!losing&&category&&spread&&[category,spread].every(stats=> const matching=[profile.global,...featureStats].filter(Boolean),mature=matching.filter(stats=>stats.current_events>=MAKER_MIN_COHORT_ATTEMPTS);
stats.current_events>=MAKER_MIN_COHORT_ATTEMPTS&&stats.current_locked_events>=MAKER_MIN_PROMOTION_LOCKS&&stats.lower>0) const losing=mature.some(stats=>stats.upper<0),evidencePromoted=!losing&&featureStats.length===keys.length&&featureStats.every(stats=>
&&reward&&reward.current_events>=MAKER_MIN_COHORT_ATTEMPTS&&reward.current_locked_events>=MAKER_MIN_PROMOTION_LOCKS&&reward.lower>0; stats&&stats.current_events>=MAKER_MIN_COHORT_ATTEMPTS&&stats.current_locked_events>=MAKER_MIN_PROMOTION_LOCKS&&stats.lower>0);
const promoted=MAKER_CAPITAL_BACKTEST_APPROVED&&evidencePromoted; const promoted=MAKER_CAPITAL_BACKTEST_APPROVED&&evidencePromoted;
const positive=[category,spread,reward].filter(Boolean).sort((a,b)=>b.lower-a.lower)[0]; const positive=featureStats.filter(Boolean).sort((a,b)=>b.lower-a.lower)[0];
const multiplier=promoted?clamp(1+Math.max(0,positive.lower)*6*positive.confidence,1,1.25):1; const multiplier=promoted?clamp(1+Math.max(0,positive.lower)*6*positive.confidence,1,1.25):1;
const units=+(candidate.units*multiplier).toFixed(2),requiredCapital=+(units*candidate.paired_cost).toFixed(2),lockedProfit=+(units*(1-candidate.paired_cost)).toFixed(2); const units=+(candidate.units*multiplier).toFixed(2),requiredCapital=+(units*candidate.paired_cost).toFixed(2),lockedProfit=+(units*(1-candidate.paired_cost)).toFixed(2);
const learned=mature.length?mature.reduce((sum,stats)=>sum+stats.mean,0)/mature.length:0; const learned=mature.length?mature.reduce((sum,stats)=>sum+stats.mean,0)/mature.length:0;
return Object.assign({},candidate,{units,required_capital:requiredCapital,locked_profit:lockedProfit,reward_yield_band:rewardBand, const novelty=featureStats.reduce((sum,stats)=>sum+1/(1+Number(stats&&stats.current_events||0)),0)/Math.max(1,featureStats.length);
return Object.assign({},enriched,{units,required_capital:requiredCapital,locked_profit:lockedProfit,reward_yield_band:candidate.reward_yield_band||makerRewardBand(candidate),
maker_learning_multiplier:+multiplier.toFixed(3),maker_learning_state:promoted?"promoted":losing?"shadow-rejected":evidencePromoted?"shadow-backtest-blocked":"shadow-observing", maker_learning_multiplier:+multiplier.toFixed(3),maker_learning_state:promoted?"promoted":losing?"shadow-rejected":evidencePromoted?"shadow-backtest-blocked":"shadow-observing",
maker_capital_enabled:promoted,maker_expected_return:+learned.toFixed(5),score:+(candidate.score+learned*60+(promoted?positive.lower*100:0)).toFixed(4)}); maker_capital_enabled:promoted,maker_expected_return:+learned.toFixed(5),maker_research_novelty:+novelty.toFixed(4),
maker_research_priority:+(candidate.score+novelty*2+learned*60+(promoted?positive.lower*100:0)).toFixed(4),
score:+(candidate.score+learned*60+(promoted?positive.lower*100:0)).toFixed(4)});
} }
function recordMakerOutcome(p,quote,status,pnl,deployedCapital){ function recordMakerOutcome(p,quote,status,pnl,deployedCapital){
p.maker_outcomes=Array.isArray(p.maker_outcomes)?p.maker_outcomes:[]; p.maker_outcomes=Array.isArray(p.maker_outcomes)?p.maker_outcomes:[];
@@ -4163,6 +4193,8 @@ function recordMakerOutcome(p,quote,status,pnl,deployedCapital){
p.maker_outcomes.push({quote_id:quote.id,market_id:quote.market_id,condition_id:quote.condition_id||"",question:quote.question, p.maker_outcomes.push({quote_id:quote.id,market_id:quote.market_id,condition_id:quote.condition_id||"",question:quote.question,
event_key:String(quote.event_key||quote.url||quote.event||quote.market_id),category:quote.category||"Other",spread:Number(quote.spread||0),spread_band:makerSpreadBand(quote.spread), event_key:String(quote.event_key||quote.url||quote.event||quote.market_id),category:quote.category||"Other",spread:Number(quote.spread||0),spread_band:makerSpreadBand(quote.spread),
reward_yield_band:quote.reward_yield_band||makerRewardBand(quote),estimated_reward_floor_daily:+Number(quote.estimated_reward_floor_daily||0).toFixed(4), reward_yield_band:quote.reward_yield_band||makerRewardBand(quote),estimated_reward_floor_daily:+Number(quote.estimated_reward_floor_daily||0).toFixed(4),
price_balance_band:quote.price_balance_band||makerPriceBalanceBand(quote),day_move_band:quote.day_move_band||makerDayMoveBand(quote),
margin_band:quote.margin_band||makerMarginBand(quote),competition_band:quote.competition_band||makerCompetitionBand(quote),
reward_share_floor:+Number(quote.reward_share_floor||0).toFixed(6),status,pnl:+Number(pnl||0).toFixed(2),shadow_only:Boolean(quote.shadow_only), reward_share_floor:+Number(quote.reward_share_floor||0).toFixed(6),status,pnl:+Number(pnl||0).toFixed(2),shadow_only:Boolean(quote.shadow_only),
deployed_capital:+Number(deployedCapital||0).toFixed(2),reserved_capital:+reserved.toFixed(2),return_on_reserved:+(Number(pnl||0)/reserved).toFixed(5), deployed_capital:+Number(deployedCapital||0).toFixed(2),reserved_capital:+reserved.toFixed(2),return_on_reserved:+(Number(pnl||0)/reserved).toFixed(5),
created_at:quote.created_at,completed_at:cycleIso(),hours_to_outcome:+hoursSince(quote.created_at).toFixed(2), created_at:quote.created_at,completed_at:cycleIso(),hours_to_outcome:+hoursSince(quote.created_at).toFixed(2),
@@ -4204,7 +4236,8 @@ function stageMakerQuotes(p,markets,{profile=null,agentIndex=null,agentCount=1,g
const eq=equity(p),existing=new Set(p.maker_quotes.map(quote=>String(quote.market_id))),held=new Set((p.positions||[]).map(pos=>String(pos.market_id))); const eq=equity(p),existing=new Set(p.maker_quotes.map(quote=>String(quote.market_id))),held=new Set((p.positions||[]).map(pos=>String(pos.market_id)));
let reserved=p.maker_quotes.filter(quote=>!quote.shadow_only).reduce((sum,quote)=>sum+Number(quote.required_capital||0),0),staged=0,shadowStaged=0,capitalStaged=0; let reserved=p.maker_quotes.filter(quote=>!quote.shadow_only).reduce((sum,quote)=>sum+Number(quote.required_capital||0),0),staged=0,shadowStaged=0,capitalStaged=0;
const makerProfile=profile||buildMakerProfile(p); const makerProfile=profile||buildMakerProfile(p);
let candidates=(markets||[]).map(makerPairCandidate).filter(Boolean).map(candidate=>makerCandidateLearning(candidate,makerProfile)).filter(Boolean).sort((a,b)=>b.score-a.score); let candidates=(markets||[]).map(makerPairCandidate).filter(Boolean).map(candidate=>makerCandidateLearning(candidate,makerProfile)).filter(Boolean)
.sort((a,b)=>b.maker_research_priority-a.maker_research_priority||b.score-a.score);
if(Number.isInteger(agentIndex)&&agentCount>1)candidates=candidates.filter((candidate,index)=>index%agentCount===agentIndex); if(Number.isInteger(agentIndex)&&agentCount>1)candidates=candidates.filter((candidate,index)=>index%agentCount===agentIndex);
for(const candidate of candidates){ for(const candidate of candidates){
if(p.maker_quotes.length>=MAKER_MAX_QUOTES)break; if(p.maker_quotes.length>=MAKER_MAX_QUOTES)break;
@@ -4224,7 +4257,7 @@ function stageMakerQuotes(p,markets,{profile=null,agentIndex=null,agentCount=1,g
p.history.push({date:logDay(),action:capitalEnabled?"QUOTE":"SHADOW_QUOTE",question:candidate.question,side:"PAIR", p.history.push({date:logDay(),action:capitalEnabled?"QUOTE":"SHADOW_QUOTE",question:candidate.question,side:"PAIR",
detail:capitalEnabled detail:capitalEnabled
?`Staged ${candidate.units} capital-backed resting YES @ ${pct(candidate.yes_quote)} and NO @ ${pct(candidate.no_quote)} · paired cost ${pct(candidate.paired_cost)} · ${fmtUSD(candidate.locked_profit)} locked settlement margin only if both legs fill · no hypothetical reward credited` ?`Staged ${candidate.units} capital-backed resting YES @ ${pct(candidate.yes_quote)} and NO @ ${pct(candidate.no_quote)} · paired cost ${pct(candidate.paired_cost)} · ${fmtUSD(candidate.locked_profit)} locked settlement margin only if both legs fill · no hypothetical reward credited`
:`Watching resting YES @ ${pct(candidate.yes_quote)} and NO @ ${pct(candidate.no_quote)} for ${MAKER_SHADOW_HORIZON_HOURS}h with zero capital · ${candidate.estimated_reward_floor_daily?`${fmtUSD(candidate.estimated_reward_floor_daily)}/day snapshot reward estimate versus ${fmtUSD(candidate.maximum_one_leg_loss)} maximum one-leg loss; estimate is not P&L · `:""}outcome will train the category, spread, and reward-yield gate`}); :`Watching resting YES @ ${pct(candidate.yes_quote)} and NO @ ${pct(candidate.no_quote)} for ${MAKER_SHADOW_HORIZON_HOURS}h with zero capital · ${candidate.estimated_reward_floor_daily?`${fmtUSD(candidate.estimated_reward_floor_daily)}/day snapshot reward estimate versus ${fmtUSD(candidate.maximum_one_leg_loss)} maximum one-leg loss; estimate is not P&L · `:""}outcome will train category, spread, reward, balance, movement, margin, and competition gates`});
} }
return {staged,shadowStaged,capitalStaged,active:p.maker_quotes.length,shadowActive:p.maker_quotes.filter(quote=>quote.shadow_only).length, return {staged,shadowStaged,capitalStaged,active:p.maker_quotes.length,shadowActive:p.maker_quotes.filter(quote=>quote.shadow_only).length,
capitalActive:p.maker_quotes.filter(quote=>!quote.shadow_only).length,candidates:candidates.length,reserved:+reserved.toFixed(2),profile:makerProfile}; capitalActive:p.maker_quotes.filter(quote=>!quote.shadow_only).length,candidates:candidates.length,reserved:+reserved.toFixed(2),profile:makerProfile};
@@ -7053,7 +7086,8 @@ window.PMA_ENGINE_DIAGNOSTICS=Object.freeze({
makerMinimumPromotionLocks:MAKER_MIN_PROMOTION_LOCKS,makerMaximumLearningMultiplier:1,makerCapitalExplorationPct:0, makerMinimumPromotionLocks:MAKER_MIN_PROMOTION_LOCKS,makerMaximumLearningMultiplier:1,makerCapitalExplorationPct:0,
makerCapitalBacktestApproved:MAKER_CAPITAL_BACKTEST_APPROVED,hypotheticalRewardsCredited:false, makerCapitalBacktestApproved:MAKER_CAPITAL_BACKTEST_APPROVED,hypotheticalRewardsCredited:false,
makerCompetitionSource:"shared public CLOB order-book audit",makerResearchSharedAcrossAgents:true,makerMarketsPartitionedAcrossAgents:true, makerCompetitionSource:"shared public CLOB order-book audit",makerResearchSharedAcrossAgents:true,makerMarketsPartitionedAcrossAgents:true,
makerHistoryRequestsBatched:true,makerPromotionCohorts:["category","spread","reward-yield"],makerRewardPayoutMinimum:1, makerHistoryRequestsBatched:true,makerPromotionCohorts:["category","spread","reward-yield","price-balance","day-move","locked-margin","competition"],
makerResearchPrioritizesUnderSampledCohorts:true,makerRewardPayoutMinimum:1,
emotionCanIncreaseSize:false,dualPromotionPeerBoostPct:5,currentStrategyOnlyCapitalAdaptation:true, emotionCanIncreaseSize:false,dualPromotionPeerBoostPct:5,currentStrategyOnlyCapitalAdaptation:true,
directionalProbation:{horizonHours:DIRECTIONAL_PROBATION_HORIZON_HOURS,minIndependentEvents:DIRECTIONAL_PROBATION_MIN_EVENTS, directionalProbation:{horizonHours:DIRECTIONAL_PROBATION_HORIZON_HOURS,minIndependentEvents:DIRECTIONAL_PROBATION_MIN_EVENTS,
minimumLowerBoundPct:DIRECTIONAL_PROBATION_MIN_LOWER_BOUND*100,positionPct:DIRECTIONAL_PROBATION_POSITION_PCT*100, minimumLowerBoundPct:DIRECTIONAL_PROBATION_MIN_LOWER_BOUND*100,positionPct:DIRECTIONAL_PROBATION_POSITION_PCT*100,
@@ -7630,8 +7664,10 @@ function runEngineSelfTest(){
const unfilledExpiry=manageMakerQuotes(unfilledBook,{"maker-test":touchMarket},{executeTrades:true}); const unfilledExpiry=manageMakerQuotes(unfilledBook,{"maker-test":touchMarket},{executeTrades:true});
const profitableMakerBook=defaultPortfolio(),losingMakerBook=defaultPortfolio(); const profitableMakerBook=defaultPortfolio(),losingMakerBook=defaultPortfolio();
for(let i=0;i<24;i++){ for(let i=0;i<24;i++){
profitableMakerBook.maker_outcomes.push({quote_id:`profit-${i}`,market_id:`profit-${i}`,event_key:`profit-event-${i}`,category:"Politics",spread:0.04,spread_band:"medium",status:"locked",pnl:4,reserved_capital:100,shadow_only:true,strategy_version:SUGGESTION_ENGINE_VERSION,maker_strategy_version:MAKER_STRATEGY_VERSION}); const makerFeatureFixture={category:"Politics",spread:0.04,spread_band:"medium",reward_yield_band:"unmodeled",
losingMakerBook.maker_outcomes.push({quote_id:`loss-${i}`,market_id:`loss-${i}`,event_key:`loss-event-${i}`,category:"Politics",spread:0.04,spread_band:"medium",status:"single-exit",pnl:-4,reserved_capital:100,shadow_only:true,strategy_version:SUGGESTION_ENGINE_VERSION,maker_strategy_version:MAKER_STRATEGY_VERSION}); price_balance_band:"balanced",day_move_band:"calm",margin_band:"thick",competition_band:"high"};
profitableMakerBook.maker_outcomes.push(Object.assign({quote_id:`profit-${i}`,market_id:`profit-${i}`,event_key:`profit-event-${i}`,status:"locked",pnl:4,reserved_capital:100,shadow_only:true,strategy_version:SUGGESTION_ENGINE_VERSION,maker_strategy_version:MAKER_STRATEGY_VERSION},makerFeatureFixture));
losingMakerBook.maker_outcomes.push(Object.assign({quote_id:`loss-${i}`,market_id:`loss-${i}`,event_key:`loss-event-${i}`,status:"single-exit",pnl:-4,reserved_capital:100,shadow_only:true,strategy_version:SUGGESTION_ENGINE_VERSION,maker_strategy_version:MAKER_STRATEGY_VERSION},makerFeatureFixture));
} }
const profitableCandidate=makerCandidateLearning(makerPairCandidate(makerMarket),buildMakerProfile(profitableMakerBook)); const profitableCandidate=makerCandidateLearning(makerPairCandidate(makerMarket),buildMakerProfile(profitableMakerBook));
let blockedMarket=null,explorationMarket=null; let blockedMarket=null,explorationMarket=null;
@@ -8381,6 +8417,8 @@ function runEngineSelfTest(){
outcomesAreDeduplicated:makerDedupeBook.maker_outcomes.length===1, outcomesAreDeduplicated:makerDedupeBook.maker_outcomes.length===1,
makerLearningSurvivesCompaction:compactedMakerBook.maker_quotes.length===1&&compactedMakerBook.maker_outcomes.length===24, makerLearningSurvivesCompaction:compactedMakerBook.maker_quotes.length===1&&compactedMakerBook.maker_outcomes.length===24,
publicMakerCompactionPreservesCalibration:JSON.stringify(makerProfileAfterPublicCompaction)===JSON.stringify(makerProfileBeforePublicCompaction), publicMakerCompactionPreservesCalibration:JSON.stringify(makerProfileAfterPublicCompaction)===JSON.stringify(makerProfileBeforePublicCompaction),
makerOutcomesRetainSetupFeatures:["price_balance_band","day_move_band","margin_band","competition_band"].every(key=>key in publicCompactedMakerBook.maker_outcomes[0]),
makerResearchRanksNovelCohorts:makerQuote.maker_research_priority>makerQuote.score&&makerQuote.maker_research_novelty>0,
sharedLedgerCombinesAgentEvidence:sharedMakerFixture.global.current_events===2&&sharedMakerFixture.global.current_locked_events===2, sharedLedgerCombinesAgentEvidence:sharedMakerFixture.global.current_events===2&&sharedMakerFixture.global.current_locked_events===2,
agentsReceiveDisjointShadowMarkets:distributedA.size===2&&distributedB.size===2&&[...distributedA].every(id=>!distributedB.has(id)), agentsReceiveDisjointShadowMarkets:distributedA.size===2&&distributedB.size===2&&[...distributedA].every(id=>!distributedB.has(id)),
noHypotheticalRewardCredited:makerStage.staged===1&&Math.abs(makerBook.cash-(10000+makerExpectedProfit))<=0.02, noHypotheticalRewardCredited:makerStage.staged===1&&Math.abs(makerBook.cash-(10000+makerExpectedProfit))<=0.02,
+3 -1
View File
@@ -91,7 +91,9 @@ function compactMakerOutcome(row) {
if (!row || typeof row !== "object") return row; if (!row || typeof row !== "object") return row;
return { return {
quote_id: row.quote_id, market_id: row.market_id, event_key: row.event_key, category: row.category, quote_id: row.quote_id, market_id: row.market_id, event_key: row.event_key, category: row.category,
spread: row.spread, spread_band: row.spread_band, reward_yield_band: row.reward_yield_band, status: row.status, spread: row.spread, spread_band: row.spread_band, reward_yield_band: row.reward_yield_band,
price_balance_band: row.price_balance_band, day_move_band: row.day_move_band, margin_band: row.margin_band,
competition_band: row.competition_band, status: row.status,
pnl: row.pnl, shadow_only: row.shadow_only, deployed_capital: row.deployed_capital, reserved_capital: row.reserved_capital, pnl: row.pnl, shadow_only: row.shadow_only, deployed_capital: row.deployed_capital, reserved_capital: row.reserved_capital,
completed_at: row.completed_at, strategy_version: row.strategy_version, maker_strategy_version: row.maker_strategy_version, completed_at: row.completed_at, strategy_version: row.strategy_version, maker_strategy_version: row.maker_strategy_version,
}; };
+9 -4
View File
@@ -16,13 +16,13 @@ const settlementCalibrationAudit = JSON.parse(fs.readFileSync(new URL("../resear
const sportsEvaluator = fs.readFileSync(new URL("./evaluate-sports-favorites.mjs", import.meta.url), "utf8"); const sportsEvaluator = fs.readFileSync(new URL("./evaluate-sports-favorites.mjs", import.meta.url), "utf8");
const build = Number(index.match(/const BUILD_VERSION = (\d+);/)?.[1]); const build = Number(index.match(/const BUILD_VERSION = (\d+);/)?.[1]);
assert.equal(build, 127); assert.equal(build, 128);
assert.equal(vercelConfig.git?.deploymentEnabled?.["runtime-state"], false); assert.equal(vercelConfig.git?.deploymentEnabled?.["runtime-state"], false);
assert.equal(settlementCalibrationAudit.requested_markets, 5000); assert.equal(settlementCalibrationAudit.requested_markets, 5000);
assert.equal(settlementCalibrationAudit.train_passed, 0); assert.equal(settlementCalibrationAudit.train_passed, 0);
assert.equal(settlementCalibrationAudit.validation_selected, 0); assert.equal(settlementCalibrationAudit.validation_selected, 0);
assert.equal(settlementCalibrationAudit.holdout_passed, 0); assert.equal(settlementCalibrationAudit.holdout_passed, 0);
assert.match(index, /Adaptive strategy 65 · expanded executable search · build 127/); assert.match(index, /Adaptive strategy 65 · feature-aware maker research · build 128/);
assert.deepEqual([...ALLOWED_RUNTIME_KEYS].sort(), ["pma_agents_v2", "pma_suggestions_v5"]); assert.deepEqual([...ALLOWED_RUNTIME_KEYS].sort(), ["pma_agents_v2", "pma_suggestions_v5"]);
assert.match(index, /function collectPublicRuntimeItems\(\)/); assert.match(index, /function collectPublicRuntimeItems\(\)/);
assert.match(index, /const PUBLIC_RUNTIME_KEYS=Object\.freeze\(\[AGENTS_KEY,SUG_KEY\]\)/); assert.match(index, /const PUBLIC_RUNTIME_KEYS=Object\.freeze\(\[AGENTS_KEY,SUG_KEY\]\)/);
@@ -72,7 +72,7 @@ assert.match(api, /Buffer\.from\(file\.content/);
assert.match(api, /searchParams\.set\("runtime", `\$\{Date\.now\(\)\}/); assert.match(api, /searchParams\.set\("runtime", `\$\{Date\.now\(\)\}/);
assert.match(workflow, /cron: "2,7,12,17,22,27,32,37,42,47,52,57 \* \* \* \*"/); assert.match(workflow, /cron: "2,7,12,17,22,27,32,37,42,47,52,57 \* \* \* \*"/);
assert.match(workflow, /contents: write/); assert.match(workflow, /contents: write/);
assert.match(workflow, /EXPECTED_BUILD: "127"/); assert.match(workflow, /EXPECTED_BUILD: "128"/);
assert.equal((workflow.match(/if: always\(\)/g) || []).length, 2); assert.equal((workflow.match(/if: always\(\)/g) || []).length, 2);
assert.match(routingReleaseWorkflow, /name: Release expanded executable search after Vercel quota reset/); assert.match(routingReleaseWorkflow, /name: Release expanded executable search after Vercel quota reset/);
assert.match(routingReleaseWorkflow, /BUNDLE_DEPTH_CANDIDATE_LIMIT=200/); assert.match(routingReleaseWorkflow, /BUNDLE_DEPTH_CANDIDATE_LIMIT=200/);
@@ -265,7 +265,8 @@ for (const [index, portfolio] of Object.values(transportState.agents).entries())
portfolio.positions = [{ market_id: `position-${index}`, value: 1000 }]; portfolio.positions = [{ market_id: `position-${index}`, value: 1000 }];
portfolio.history = Array.from({ length: 80 }, (_, row) => ({ date: "2026-08-22", action: "WATCH", question: "q".repeat(180), detail: "d".repeat(500 + row) })); portfolio.history = Array.from({ length: 80 }, (_, row) => ({ date: "2026-08-22", action: "WATCH", question: "q".repeat(180), detail: "d".repeat(500 + row) }));
portfolio.snapshots = Array.from({ length: 240 }, (_, row) => ({ timestamp: new Date(1_700_000_000_000 + row * 300_000).toISOString(), equity: 10000 + row })); portfolio.snapshots = Array.from({ length: 240 }, (_, row) => ({ timestamp: new Date(1_700_000_000_000 + row * 300_000).toISOString(), equity: 10000 + row }));
portfolio.maker_outcomes = Array.from({ length: 45 }, (_, row) => ({ quote_id: `${index}-${row}`, pnl: row / 100 })); portfolio.maker_outcomes = Array.from({ length: 45 }, (_, row) => ({ quote_id: `${index}-${row}`, pnl: row / 100,
price_balance_band: "balanced", day_move_band: "calm", margin_band: "thick", competition_band: "high" }));
} }
transportState.signal_ledger = { transportState.signal_ledger = {
pending: Array.from({ length: 50 }, (_, index) => ({ key: `pending-${index}`, event_key: `event-${index}` })), pending: Array.from({ length: 50 }, (_, index) => ({ key: `pending-${index}`, event_key: `event-${index}` })),
@@ -287,6 +288,10 @@ assert.equal(transportedState.agents.value.snapshots.length, 96);
assert.equal(transportedState.agents.value.snapshots[0].timestamp, transportState.agents.value.snapshots[0].timestamp); assert.equal(transportedState.agents.value.snapshots[0].timestamp, transportState.agents.value.snapshots[0].timestamp);
assert.equal(transportedState.agents.value.snapshots.at(-1).timestamp, transportState.agents.value.snapshots.at(-1).timestamp); assert.equal(transportedState.agents.value.snapshots.at(-1).timestamp, transportState.agents.value.snapshots.at(-1).timestamp);
assert.equal(transportedState.agents.value.maker_outcomes.length, 30); assert.equal(transportedState.agents.value.maker_outcomes.length, 30);
assert.equal(transportedState.agents.value.maker_outcomes[0].price_balance_band, "balanced");
assert.equal(transportedState.agents.value.maker_outcomes[0].day_move_band, "calm");
assert.equal(transportedState.agents.value.maker_outcomes[0].margin_band, "thick");
assert.equal(transportedState.agents.value.maker_outcomes[0].competition_band, "high");
assert.equal(JSON.parse(transportOutput.items.pma_suggestions_v5).suggestions.length, 300); assert.equal(JSON.parse(transportOutput.items.pma_suggestions_v5).suggestions.length, 300);
assert.equal(transportOutput.summary.signal_ledger.pending_retained, 50); assert.equal(transportOutput.summary.signal_ledger.pending_retained, 50);
assert.equal(transportOutput.summary.signal_ledger.outcomes_retained, 144); assert.equal(transportOutput.summary.signal_ledger.outcomes_retained, 144);
+1 -1
View File
@@ -1,4 +1,4 @@
const CACHE_NAME = "polymarket-arena-build-127"; const CACHE_NAME = "polymarket-arena-build-128";
const APP_SHELL = ["/", "/index.html", "/personal.html", "/cycle-worker.js"]; const APP_SHELL = ["/", "/index.html", "/personal.html", "/cycle-worker.js"];
self.addEventListener("install", event => { self.addEventListener("install", event => {