Start fee-policy observations without migration delay

This commit is contained in:
Theodore Song
2026-08-21 21:00:38 -04:00
parent 4539456ac2
commit 5c7c0440a7
6 changed files with 24 additions and 15 deletions
+1 -1
View File
@@ -34,7 +34,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: "103" EXPECTED_BUILD: "104"
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 }}
+4 -4
View File
@@ -20,7 +20,7 @@ market snapshots. During an outage, cycles continue locally; cached entries are
allowed for 90 minutes, older snapshots become mark-only, and all cached data allowed for 90 minutes, older snapshots become mark-only, and all cached data
expires after 24 hours. expires after 24 hours.
Build 103 runs the headless GitHub Actions runtime every five minutes, continues Build 104 runs the headless GitHub Actions runtime every five minutes, continues
from the previous agent snapshot, from the previous agent snapshot,
and runs the next due paper cycle even when no browser is open. It writes a and runs the next due paper cycle even when no browser is open. It writes a
sanitized snapshot to the `runtime-state` branch and `/api/state` uses that as a sanitized snapshot to the `runtime-state` branch and `/api/state` uses that as a
@@ -41,7 +41,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 103 cycle also scans the 1,000 most-active Polymarket events for Each Build 104 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. Gamma's market-specific fee flag replaces the old blanket 0.5-cent fee pairs. Gamma's market-specific fee flag replaces the old blanket 0.5-cent fee
reserve for markets declared fee-free. The closest 60 structures are then reserve for markets declared fee-free. The closest 60 structures are then
@@ -57,7 +57,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 103 also replaces the directional learner's blanket half-cent cost with Build 104 also replaces the directional learner's 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
@@ -71,7 +71,7 @@ directional evidence under fee policy 2 and keeps those lanes observation-only
until current independent 24-hour and 72-hour cohorts pass the existing until current independent 24-hour and 72-hour cohorts pass the existing
promotion gate. promotion gate.
Build 103 retains Build 100's retirement of the old 3-6 day resolution-window Build 104 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
+15 -6
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 61 · exact-fee learning · build 103</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 61 · exact-fee learning · build 104</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 103 active:</b> The public paper agents run autonomously every five minutes while every user device is closed. Each cycle scans the 1,000 most-active events for complete negative-risk and same-event dominance bundles, then checks the closest 60 against live CLOB depth for at least a $50 equal-unit order. Directional research now carries Gamma fee schedules through cloud and offline caches and grades each future checkpoint with exact entry and exit taker fees plus a half-cent slippage allowance. The latest disjoint audits rejected broad directional, shock, and near-settlement rules, so they remain zero-capital until independent forward cohorts prove an edge. Phones and computers display the same read-only autonomous state. Profits are not guaranteed.</div> <div class="live-build-banner"><b>Build 104 active:</b> The public paper agents run autonomously every five minutes while every user device is closed. Each cycle scans the 1,000 most-active events for complete negative-risk and same-event dominance bundles, then checks the closest 60 against live CLOB depth for at least a $50 equal-unit order. Directional research now carries Gamma fee schedules through cloud and offline caches and grades each future checkpoint with exact entry and exit taker fees plus a half-cent slippage allowance. The latest disjoint audits rejected broad directional, shock, and near-settlement rules, so they remain zero-capital until independent forward cohorts prove an edge. 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 103 · Adaptive strategy 61 · Five-minute autonomous scans · Exact-fee directional learning · Live depth, fee, and size-verified bundle audit · Corrected one-decision-per-event settlement audit · Zero capital before independent positive evidence · Autonomous runtime 1 · Offline runtime 2 · Maker research 3 · Agent learning 3 · Paper trading only · Live prices from Polymarket's public Gamma and CLOB APIs · Not financial advice · Build 104 · Adaptive strategy 61 · Five-minute autonomous scans · Exact-fee directional learning · Live depth, fee, and size-verified bundle audit · Corrected one-decision-per-event settlement audit · Zero capital before independent positive evidence · Autonomous runtime 1 · Offline runtime 2 · Maker research 3 · 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,7 +774,7 @@ 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 = 103; const BUILD_VERSION = 104;
const AGENT_LEARNING_VERSION = 3; const AGENT_LEARNING_VERSION = 3;
const SUGGESTION_ENGINE_VERSION = 61; const SUGGESTION_ENGINE_VERSION = 61;
const MAKER_STRATEGY_VERSION = 3; const MAKER_STRATEGY_VERSION = 3;
@@ -2297,14 +2297,14 @@ function updateSignalLedger(st,markets,suggestions){
} }
} }
stillPending.sort((a,b)=>new Date(a.observed_at||0)-new Date(b.observed_at||0)); stillPending.sort((a,b)=>new Date(a.observed_at||0)-new Date(b.observed_at||0));
const existing=new Set(stillPending.map(x=>x.key)),pendingPairs=new Set(stillPending const existing=new Set(stillPending.map(x=>x.key)),pendingPairs=new Set(stillPending.filter(currentSignalPolicy)
.filter(x=>!Object.prototype.hasOwnProperty.call(x||{},"eligible_agent_ids")||(Array.isArray(x.eligible_agent_ids)&&x.eligible_agent_ids.length>0)) .filter(x=>!Object.prototype.hasOwnProperty.call(x||{},"eligible_agent_ids")||(Array.isArray(x.eligible_agent_ids)&&x.eligible_agent_ids.length>0))
.map(x=>`${x.market_id}:${x.side}`)); .map(x=>`${x.market_id}:${x.side}`));
const bucket=Math.floor(now/(6*3600000)); const bucket=Math.floor(now/(6*3600000));
const observable=prioritizeSignalObservations((suggestions||[]) const observable=prioritizeSignalObservations((suggestions||[])
.filter(x=>!x.jump_risk&&["trend","reversal"].includes(x.signal_type)&&Number(x.signal_confidence||0)>=0.56),ledger,stillPending); .filter(x=>!x.jump_risk&&["trend","reversal"].includes(x.signal_type)&&Number(x.signal_confidence||0)>=0.56),ledger,stillPending);
for(const s of observable){ for(const s of observable){
const pair=`${s.market_id}:${s.side}`,key=`${pair}:${bucket}:l${AGENT_LEARNING_VERSION}`;if(existing.has(key)||pendingPairs.has(pair))continue; const pair=`${s.market_id}:${s.side}`,key=`${pair}:${bucket}:p${DIRECTIONAL_SIGNAL_POLICY_VERSION}:l${AGENT_LEARNING_VERSION}`;if(existing.has(key)||pendingPairs.has(pair))continue;
if(stillPending.length>=SIGNAL_LEDGER_PENDING_LIMIT)break; if(stillPending.length>=SIGNAL_LEDGER_PENDING_LIMIT)break;
existing.add(key);pendingPairs.add(pair);stillPending.push({key,market_id:String(s.market_id),event_key:String(s.url||s.event||s.market_id),observed_at:nowIso(),graded_horizons:[],side:s.side,entry_price:Number(s.entry_price), existing.add(key);pendingPairs.add(pair);stillPending.push({key,market_id:String(s.market_id),event_key:String(s.url||s.event||s.market_id),observed_at:nowIso(),graded_horizons:[],side:s.side,entry_price:Number(s.entry_price),
signal_type:s.signal_type||"unknown",quality:s.quality||"unknown",category:s.category||"Other",conviction:Number(s.conviction||0), signal_type:s.signal_type||"unknown",quality:s.quality||"unknown",category:s.category||"Other",conviction:Number(s.conviction||0),
@@ -6458,6 +6458,13 @@ function runEngineSelfTest(){
signal_confidence:0.62,trade_ready:false,jump_risk:false,category:"Politics",days_to_resolution:45}]); signal_confidence:0.62,trade_ready:false,jump_risk:false,category:"Politics",days_to_resolution:45}]);
updateSignalLedger(observationLedgerState,[],[{market_id:"observation-only",side:"YES",entry_price:0.43,signal_type:"trend",quality:"watch", updateSignalLedger(observationLedgerState,[],[{market_id:"observation-only",side:"YES",entry_price:0.43,signal_type:"trend",quality:"watch",
signal_confidence:0.64,trade_ready:false,jump_risk:false,category:"Politics",days_to_resolution:45}]); signal_confidence:0.64,trade_ready:false,jump_risk:false,category:"Politics",days_to_resolution:45}]);
const priorPolicyReplacementState={signal_ledger:{pending:[{key:"prior-policy",market_id:"policy-replacement",event_key:"policy-event",
observed_at:hoursAgo(1),graded_horizons:[],side:"YES",entry_price:0.42,signal_type:"trend",quality:"watch",category:"Politics",
eligible_agent_ids:["value"],signal_policy_version:DIRECTIONAL_SIGNAL_POLICY_VERSION-1,strategy_version:PREVIOUS_STRATEGY_VERSION}],outcomes:[]}};
updateSignalLedger(priorPolicyReplacementState,[],[{market_id:"policy-replacement",event_key:"policy-event",side:"YES",entry_price:0.42,
signal_type:"trend",quality:"watch",signal_confidence:0.64,signal_strength:0.72,evidence_score:0.52,evidence_source_count:1,
price_change_1d:0.02,conviction:74,trade_ready:false,jump_risk:false,category:"Politics",days_to_resolution:45,fees_enabled:false,
fee_schedule:{rate:0,exponent:1,takerOnly:true}}]);
const nonDirectionalLedgerState={signal_ledger:defaultSignalLedger()}; const nonDirectionalLedgerState={signal_ledger:defaultSignalLedger()};
updateSignalLedger(nonDirectionalLedgerState,[],[ updateSignalLedger(nonDirectionalLedgerState,[],[
{market_id:"priced-bundle",side:"NO",entry_price:0.80,signal_type:"bundle-arb",quality:"bundle-arb",signal_confidence:1,trade_ready:true,jump_risk:false}, {market_id:"priced-bundle",side:"NO",entry_price:0.80,signal_type:"bundle-arb",quality:"bundle-arb",signal_confidence:1,trade_ready:true,jump_risk:false},
@@ -6976,6 +6983,8 @@ function runEngineSelfTest(){
&&observationLedgerState.signal_ledger.pending[0].trade_ready_at_observation===false &&observationLedgerState.signal_ledger.pending[0].trade_ready_at_observation===false
&&observationLedgerState.signal_ledger.pending[0].signal_policy_version===DIRECTIONAL_SIGNAL_POLICY_VERSION, &&observationLedgerState.signal_ledger.pending[0].signal_policy_version===DIRECTIONAL_SIGNAL_POLICY_VERSION,
deduplicatesPendingMarketSide:observationLedgerState.signal_ledger.pending.length===1, deduplicatesPendingMarketSide:observationLedgerState.signal_ledger.pending.length===1,
priorFeePolicyDoesNotDelayReplacement:priorPolicyReplacementState.signal_ledger.pending.length===2
&&priorPolicyReplacementState.signal_ledger.pending.some(item=>item.signal_policy_version===DIRECTIONAL_SIGNAL_POLICY_VERSION),
oldestPendingSignalsSurviveCapacity:queueLedgerState.signal_ledger.pending.length===SIGNAL_LEDGER_PENDING_LIMIT oldestPendingSignalsSurviveCapacity:queueLedgerState.signal_ledger.pending.length===SIGNAL_LEDGER_PENDING_LIMIT
&&queueLedgerState.signal_ledger.pending.some(x=>x.market_id==="old-market-0") &&queueLedgerState.signal_ledger.pending.some(x=>x.market_id==="old-market-0")
&&queueLedgerState.signal_ledger.pending.some(x=>x.market_id==="new-market-0") &&queueLedgerState.signal_ledger.pending.some(x=>x.market_id==="new-market-0")
+1 -1
View File
@@ -128,7 +128,7 @@ async function main() {
const branch = process.env.RUNTIME_BRANCH || "runtime-state"; const branch = process.env.RUNTIME_BRANCH || "runtime-state";
const pathname = process.env.RUNTIME_STATE_PATH || "runtime/state.json"; const pathname = process.env.RUNTIME_STATE_PATH || "runtime/state.json";
const arenaUrl = (process.env.ARENA_URL || "https://polymarket-site-eta.vercel.app").replace(/\/$/, ""); const arenaUrl = (process.env.ARENA_URL || "https://polymarket-site-eta.vercel.app").replace(/\/$/, "");
const expectedBuild = Number(required("EXPECTED_BUILD", "103")); const expectedBuild = Number(required("EXPECTED_BUILD", "104"));
await ensureRuntimeBranch(repository, branch); await ensureRuntimeBranch(repository, branch);
const prior = await readRuntimeFile(repository, branch, pathname); const prior = await readRuntimeFile(repository, branch, pathname);
if (prior.snapshot) validateRuntimeSnapshot(prior.snapshot, 0, { allowIncomplete: true }); if (prior.snapshot) validateRuntimeSnapshot(prior.snapshot, 0, { allowIncomplete: true });
+2 -2
View File
@@ -9,7 +9,7 @@ const runner = fs.readFileSync(new URL("./run-autonomous-cycle.mjs", import.meta
const resolutionAudit = JSON.parse(fs.readFileSync(new URL("../research/resolution-week-no-audit.json", import.meta.url), "utf8")); const resolutionAudit = JSON.parse(fs.readFileSync(new URL("../research/resolution-week-no-audit.json", 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, 103); assert.equal(build, 104);
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\]\)/);
@@ -26,7 +26,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: "103"/); assert.match(workflow, /EXPECTED_BUILD: "104"/);
assert.match(index, /saveSuggestions\(sugs,markets\.length,analysisMarkets\.length,bundleAudit\)/); assert.match(index, /saveSuggestions\(sugs,markets\.length,analysisMarkets\.length,bundleAudit\)/);
assert.match(index, /const NEG_RISK_EVENT_SCAN_LIMIT=1000;/); assert.match(index, /const NEG_RISK_EVENT_SCAN_LIMIT=1000;/);
assert.match(index, /bundleOpportunityTelemetry:true/); assert.match(index, /bundleOpportunityTelemetry:true/);
+1 -1
View File
@@ -1,4 +1,4 @@
const CACHE_NAME = "polymarket-arena-build-103"; const CACHE_NAME = "polymarket-arena-build-104";
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 => {