mirror of
https://github.com/theodore-song/polymarket-analyst.git
synced 2026-08-24 04:58:08 +00:00
Hold complete bundles at cost until settlement
This commit is contained in:
@@ -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: "109"
|
EXPECTED_BUILD: "110"
|
||||||
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 }}
|
||||||
|
|||||||
@@ -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 109 runs the headless GitHub Actions runtime every five minutes, continues
|
Build 110 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 109 cycle also scans the 1,000 most-active Polymarket events for
|
Each Build 110 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 109 retains the directional learner's exact-fee policy, which replaced the blanket half-cent cost with
|
Build 110 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
|
||||||
@@ -73,7 +73,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 109 retains Build 100's retirement of the old 3-6 day resolution-window
|
Build 110 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
|
||||||
@@ -193,7 +193,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 109 no longer allocates capital to that rule.
|
reliable confidence bound, so Build 110 no longer allocates capital to that rule.
|
||||||
|
|
||||||
Strategy 62 instead uses the exact-fee settlement calibration's three-day Sports
|
Strategy 62 instead uses the exact-fee settlement calibration's three-day Sports
|
||||||
NO cohort as a bounded paper exploration lane. The corrected 5,000-market run
|
NO cohort as a bounded paper exploration lane. The corrected 5,000-market run
|
||||||
|
|||||||
+21
-19
@@ -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 62 · contest-level learning · build 109</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 62 · contest-level learning · build 110</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 109 active:</b> The public paper agents run autonomously every five minutes while every user device is closed. Each cycle scans the 500 most-active eligible markets and 1,000 most-active events, carries exact Gamma fee schedules through cloud and offline caches, and checks complete bundles against live depth. Strategy 62 adds a bounded sports-contest NO exploration lane: one highest-priced NO contract per real contest near the three-day checkpoint, exact entry fee plus slippage, 0.5% initial size, 3% total cap, and automatic forward promotion or suspension. Intact guaranteed bundles are conservatively marked at no less than their cost basis, while modeled profit remains unbooked until settlement. This point-positive historical pattern is not a proven edge. Phones and computers display the same read-only autonomous state. Profits are not guaranteed.</div>
|
<div class="live-build-banner"><b>Build 110 active:</b> The public paper agents run autonomously every five minutes while every user device is closed. Each cycle scans the 500 most-active eligible markets and 1,000 most-active events, carries exact Gamma fee schedules through cloud and offline caches, and checks complete bundles against live depth. Strategy 62 adds a bounded sports-contest NO exploration lane: one highest-priced NO contract per real contest near the three-day checkpoint, exact entry fee plus slippage, 0.5% initial size, 3% total cap, and automatic forward promotion or suspension. Intact guaranteed bundles are conservatively held at cost in portfolio accounting, while modeled profit remains unbooked until settlement. This point-positive historical pattern is not a proven 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 109 · Adaptive strategy 62 · Five-minute autonomous scans · Exact-fee directional learning · Conservative intact-bundle accounting · Contest-deduplicated sports exploration · Live depth, fee, and size-verified bundle audit · Corrected one-decision-per-event settlement audit · 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 110 · Adaptive strategy 62 · Five-minute autonomous scans · Exact-fee directional learning · Conservative intact-bundle accounting · Contest-deduplicated sports exploration · Live depth, fee, and size-verified bundle audit · Corrected one-decision-per-event settlement audit · 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 = 109;
|
const BUILD_VERSION = 110;
|
||||||
const AGENT_LEARNING_VERSION = 3;
|
const AGENT_LEARNING_VERSION = 3;
|
||||||
const SUGGESTION_ENGINE_VERSION = 62;
|
const SUGGESTION_ENGINE_VERSION = 62;
|
||||||
const MAKER_STRATEGY_VERSION = 3;
|
const MAKER_STRATEGY_VERSION = 3;
|
||||||
@@ -2271,26 +2271,19 @@ function portfolioPositionValue(p){
|
|||||||
let total=positions.reduce((sum,pos)=>sum+Number(pos.shares||0)*Number(pos.current_price||0),0);
|
let total=positions.reduce((sum,pos)=>sum+Number(pos.shares||0)*Number(pos.current_price||0),0);
|
||||||
completeBundleGroups(p).forEach(group=>{
|
completeBundleGroups(p).forEach(group=>{
|
||||||
const raw=group.reduce((sum,pos)=>sum+Number(pos.shares||0)*Number(pos.current_price||0),0);
|
const raw=group.reduce((sum,pos)=>sum+Number(pos.shares||0)*Number(pos.current_price||0),0);
|
||||||
total+=Math.max(0,completeBundleAccountingFloor(group)-raw);
|
const lockedValue=completeBundleAccountingFloor(group);
|
||||||
|
if(lockedValue>0)total+=lockedValue-raw;
|
||||||
});
|
});
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
function applyCompleteBundleAccountingMarks(p){
|
function applyCompleteBundleAccountingMarks(p){
|
||||||
completeBundleGroups(p).forEach(group=>{
|
completeBundleGroups(p).forEach(group=>{
|
||||||
const raw=group.reduce((sum,pos)=>sum+Number(pos.shares||0)*Number(pos.current_price||0),0);
|
const lockedValue=completeBundleAccountingFloor(group);
|
||||||
const floor=completeBundleAccountingFloor(group),adjustment=Math.max(0,floor-raw);
|
if(!(lockedValue>0))return;
|
||||||
const cost=group.reduce((sum,pos)=>sum+Number(pos.cost||0),0);
|
group.forEach(pos=>{
|
||||||
let distributed=0;
|
|
||||||
group.forEach((pos,index)=>{
|
|
||||||
const rawValue=Number(pos.shares||0)*Number(pos.current_price||0);
|
const rawValue=Number(pos.shares||0)*Number(pos.current_price||0);
|
||||||
const weight=cost>0?Number(pos.cost||0)/cost:1/group.length;
|
pos.raw_value=+rawValue.toFixed(2);pos.bundle_mark_adjustment=+(Number(pos.cost||0)-pos.raw_value).toFixed(2);
|
||||||
const allocated=index===group.length-1
|
pos.value=+Number(pos.cost||0).toFixed(2);pos.unrealized_pnl=0;
|
||||||
? adjustment-distributed
|
|
||||||
: Number((adjustment*weight).toFixed(2));
|
|
||||||
distributed+=allocated;
|
|
||||||
pos.raw_value=+rawValue.toFixed(2);pos.bundle_mark_adjustment=+allocated.toFixed(2);
|
|
||||||
pos.value=+(pos.raw_value+pos.bundle_mark_adjustment).toFixed(2);
|
|
||||||
pos.unrealized_pnl=+(pos.value-Number(pos.cost||0)).toFixed(2);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -6933,6 +6926,13 @@ function runEngineSelfTest(){
|
|||||||
applyCompleteBundleAccountingMarks(conservativeBundleMarkBook);
|
applyCompleteBundleAccountingMarks(conservativeBundleMarkBook);
|
||||||
const conservativeBundleAccountedValue=conservativeBundleMarkBook.positions.reduce((sum,pos)=>sum+Number(pos.value),0);
|
const conservativeBundleAccountedValue=conservativeBundleMarkBook.positions.reduce((sum,pos)=>sum+Number(pos.value),0);
|
||||||
const conservativeBundleCost=conservativeBundleMarkBook.positions.reduce((sum,pos)=>sum+Number(pos.cost),0);
|
const conservativeBundleCost=conservativeBundleMarkBook.positions.reduce((sum,pos)=>sum+Number(pos.cost),0);
|
||||||
|
const optimisticBundleMarkBook=JSON.parse(JSON.stringify(repricedBoundaryBook));
|
||||||
|
optimisticBundleMarkBook.positions.forEach(pos=>{
|
||||||
|
pos.current_price=+(Number(pos.current_price)*1.25).toFixed(6);
|
||||||
|
pos.value=+(Number(pos.shares)*Number(pos.current_price)).toFixed(2);
|
||||||
|
pos.unrealized_pnl=+(pos.value-Number(pos.cost)).toFixed(2);
|
||||||
|
});
|
||||||
|
applyCompleteBundleAccountingMarks(optimisticBundleMarkBook);
|
||||||
const undersizedBoundaryCandidate=Object.assign({},repricedBoundaryCandidate,{execution_units:50.04});
|
const undersizedBoundaryCandidate=Object.assign({},repricedBoundaryCandidate,{execution_units:50.04});
|
||||||
const undersizedBoundaryBook=defaultPortfolio();
|
const undersizedBoundaryBook=defaultPortfolio();
|
||||||
openPositions(undersizedBoundaryBook,AGENTS.find(a=>a.id==="value"),[undersizedBoundaryCandidate],"All",{
|
openPositions(undersizedBoundaryBook,AGENTS.find(a=>a.id==="value"),[undersizedBoundaryCandidate],"All",{
|
||||||
@@ -7392,7 +7392,9 @@ function runEngineSelfTest(){
|
|||||||
intactBundleDoesNotShowArtificialLoss:conservativeBundleRawValue<conservativeBundleCost
|
intactBundleDoesNotShowArtificialLoss:conservativeBundleRawValue<conservativeBundleCost
|
||||||
&&Math.abs(conservativeBundleAccountedValue-conservativeBundleCost)<=0.01
|
&&Math.abs(conservativeBundleAccountedValue-conservativeBundleCost)<=0.01
|
||||||
&&Math.abs(equity(conservativeBundleMarkBook)-STARTING_BALANCE)<=0.01,
|
&&Math.abs(equity(conservativeBundleMarkBook)-STARTING_BALANCE)<=0.01,
|
||||||
modeledSettlementProfitIsNotBookedEarly:Math.abs(equity(conservativeBundleMarkBook)-STARTING_BALANCE)<=0.01,
|
modeledSettlementProfitIsNotBookedEarly:Math.abs(equity(conservativeBundleMarkBook)-STARTING_BALANCE)<=0.01
|
||||||
|
&&Math.abs(equity(optimisticBundleMarkBook)-STARTING_BALANCE)<=0.01
|
||||||
|
&&optimisticBundleMarkBook.positions.every(pos=>pos.unrealized_pnl===0),
|
||||||
undersizedAtomicFailureIsReported:undersizedBoundaryBook.positions.length===0
|
undersizedAtomicFailureIsReported:undersizedBoundaryBook.positions.length===0
|
||||||
&&undersizedBoundaryBook.lastDecision.rejectionCounts.bundle_execution===1,
|
&&undersizedBoundaryBook.lastDecision.rejectionCounts.bundle_execution===1,
|
||||||
blocksUnverifiedBundleEntry:unverifiedBundleOpen===null&&unverifiedBundleBook.positions.length===0&&unverifiedBundleBook.cash===STARTING_BALANCE,
|
blocksUnverifiedBundleEntry:unverifiedBundleOpen===null&&unverifiedBundleBook.positions.length===0&&unverifiedBundleBook.cash===STARTING_BALANCE,
|
||||||
|
|||||||
@@ -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", "109"));
|
const expectedBuild = Number(required("EXPECTED_BUILD", "110"));
|
||||||
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 });
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ const resolutionAudit = JSON.parse(fs.readFileSync(new URL("../research/resoluti
|
|||||||
const sportsContestAudit = JSON.parse(fs.readFileSync(new URL("../research/sports-contest-no-exploration-audit.json", import.meta.url), "utf8"));
|
const sportsContestAudit = JSON.parse(fs.readFileSync(new URL("../research/sports-contest-no-exploration-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, 109);
|
assert.equal(build, 110);
|
||||||
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\]\)/);
|
||||||
@@ -27,7 +27,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: "109"/);
|
assert.match(workflow, /EXPECTED_BUILD: "110"/);
|
||||||
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,4 +1,4 @@
|
|||||||
const CACHE_NAME = "polymarket-arena-build-109";
|
const CACHE_NAME = "polymarket-arena-build-110";
|
||||||
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 => {
|
||||||
|
|||||||
Reference in New Issue
Block a user