Broaden audited adaptive settlement windows

This commit is contained in:
Theodore Song
2026-08-21 19:19:40 -04:00
parent c0ce373833
commit a01571d5ee
8 changed files with 156 additions and 87 deletions
+36 -2
View File
@@ -31,6 +31,16 @@ function categoryOf(raw) {
return "Other";
}
function hardSettlementJumpRisk(raw) {
const text = `${raw?.question || ""} ${raw?.events?.[0]?.title || ""}`.toLowerCase();
const numericRange = /\b\d+(?:\.\d+)?\s*(?:%|percent)?\s*(?:-||—|to)\s*\d+(?:\.\d+)?\s*(?:%|percent|votes?|points?|seats?|bps|basis points?|tweets?|posts?|goals?)(?![a-z])/;
const currencyRange = /[$€£]\d+(?:\.\d+)?\s*(?:-||—|to)\s*[$€£]?\d+(?:\.\d+)?/;
const betweenRange = /\bbetween\s+[$€£]?\d+(?:\.\d+)?\s*(?:%|percent)?\s+(?:and|to)\s+[$€£]?\d+(?:\.\d+)?/;
const pathDependentBarrier = /\b(?:reach|hit|touch|dip(?:\s+(?:to|below))?|rise\s+(?:to|above)|fall\s+(?:to|below))\b[^?]{0,45}(?:[$€£]\s*)?\d[\d,]*(?:\.\d+)?\s*(?:%|percent|k|m|b|points?|bps|basis points?)?/;
return numericRange.test(text) || currencyRange.test(text) || betweenRange.test(text) || pathDependentBarrier.test(text)
|| /\bexact score\b|\bscore:\s*\d|\bposts? \d+-\d+|\bnumber of (tweets|posts)\b/.test(text);
}
async function fetchJson(url, options = {}, attempts = 3) {
let lastError;
for (let attempt = 0; attempt < attempts; attempt++) {
@@ -109,7 +119,7 @@ async function fetchResolvedMarkets(limit) {
seen.add(id); raw.push({ id, question: market.question || "", category: categoryOf(market),
eventId: String(market.events?.[0]?.id || id),
tokenId: String(tokens[0]), finalYes: outcomes[0] >= 0.99 ? 1 : 0, closedAt,
volume: Number(market.volumeNum || market.volume || 0) });
safeContract: !hardSettlementJumpRisk(market), volume: Number(market.volumeNum || market.volume || 0) });
if (raw.length >= limit) break;
}
if (page.length < pageSize || !payload.next_cursor || payload.next_cursor === cursor) break;
@@ -129,7 +139,8 @@ function evaluateMarket(market, points) {
for (const side of ["YES", "NO"]) {
const entry = side === "YES" ? yesEntry : noEntry, final = side === winningSide ? 1 : 0;
const netReturn = final / entry - 1 - (COST_CENTS / 100) / entry;
rows.push({ marketId: market.id, eventId: market.eventId, question: market.question, category: market.category, closedAt: market.closedAt,
rows.push({ marketId: market.id, eventId: market.eventId, question: market.question, category: market.category,
safeContract: market.safeContract, closedAt: market.closedAt,
horizonDays, side, favorite: side === favoriteSide, winner: side === winningSide,
trend: Boolean(trend && trend.side === side), trendSide: trend?.side || null,
dayMove: trend?.dayMove || 0, weekMove: trend?.weekMove || 0,
@@ -167,6 +178,16 @@ function summarize(rows) {
worst: Math.min(...values), best: Math.max(...values) };
}
const SAFE_PRICE_BANDS = Object.freeze([
{ label: "50_55", min: 0.50, max: 0.55 },
{ label: "55_60", min: 0.55, max: 0.60 },
{ label: "60_70", min: 0.60, max: 0.70 },
{ label: "70_80", min: 0.70, max: 0.80 },
{ label: "80_90", min: 0.80, max: 0.90 },
{ label: "90_95", min: 0.90, max: 0.95 },
{ label: "95_97", min: 0.95, max: 0.97 },
]);
const RULES = [
{ name: "buy_favorite", test: (row) => row.favorite },
{ name: "buy_heavy_favorite", test: (row) => row.favorite && row.entry >= 0.78 },
@@ -176,8 +197,13 @@ const RULES = [
{ name: "buy_yes", test: (row) => row.side === "YES" },
{ name: "buy_no", test: (row) => row.side === "NO" },
{ name: "buy_no_favorite", test: (row) => row.side === "NO" && row.favorite },
{ name: "buy_no_45_50", test: (row) => row.side === "NO" && row.entry >= 0.45 && row.entry < 0.50 },
{ name: "buy_no_55_90", test: (row) => row.side === "NO" && row.entry >= 0.55 && row.entry < 0.90 },
{ name: "buy_no_50_55", test: (row) => row.side === "NO" && row.entry >= 0.50 && row.entry < 0.55 },
{ name: "buy_no_50_55_non_sports", test: (row) => row.side === "NO" && row.entry >= 0.50 && row.entry < 0.55 && row.category !== "Sports" },
{ name: "buy_no_50_55_safe_non_sports", test: (row) => row.side === "NO" && row.entry >= 0.50 && row.entry < 0.55
&& row.category !== "Sports" && row.safeContract },
{ name: "buy_no_55_60", test: (row) => row.side === "NO" && row.entry >= 0.55 && row.entry < 0.60 },
{ name: "buy_no_60_90", test: (row) => row.side === "NO" && row.entry >= 0.60 && row.entry < 0.90 },
{ name: "buy_no_90_95", test: (row) => row.side === "NO" && row.entry >= 0.90 && row.entry < 0.95 },
{ name: "buy_no_95_99", test: (row) => row.side === "NO" && row.entry >= 0.95 && row.entry < 0.99 },
@@ -189,9 +215,17 @@ const RULES = [
{ name: "follow_trend_underdog", test: (row) => row.trend && !row.favorite },
{ name: "follow_strong_trend", test: (row) => row.trend && row.strongTrend },
{ name: "follow_moderate_trend", test: (row) => row.trend && row.moderateTrend },
...SAFE_PRICE_BANDS.flatMap((band) => [
{ name: `buy_safe_favorite_${band.label}`, test: (row) => row.favorite && row.entry >= band.min && row.entry < band.max
&& row.category !== "Sports" && row.safeContract },
{ name: `buy_safe_no_${band.label}`, test: (row) => row.side === "NO" && row.entry >= band.min && row.entry < band.max
&& row.category !== "Sports" && row.safeContract },
]),
...["Politics", "Sports", "Crypto", "Economy", "Pop Culture", "Other"].flatMap((category) => [
{ name: `buy_favorite_${category.toLowerCase().replace(/\s+/g, "_")}`, test: (row) => row.favorite && row.category === category },
{ name: `buy_underdog_${category.toLowerCase().replace(/\s+/g, "_")}`, test: (row) => !row.favorite && row.category === category },
{ name: `buy_no_50_55_${category.toLowerCase().replace(/\s+/g, "_")}`,
test: (row) => row.side === "NO" && row.entry >= 0.50 && row.entry < 0.55 && row.category === category },
{ name: `follow_trend_${category.toLowerCase().replace(/\s+/g, "_")}`, test: (row) => row.trend && row.category === category },
]),
];
+1 -1
View File
@@ -128,7 +128,7 @@ async function main() {
const branch = process.env.RUNTIME_BRANCH || "runtime-state";
const pathname = process.env.RUNTIME_STATE_PATH || "runtime/state.json";
const arenaUrl = (process.env.ARENA_URL || "https://polymarket-site-eta.vercel.app").replace(/\/$/, "");
const expectedBuild = Number(required("EXPECTED_BUILD", "96"));
const expectedBuild = Number(required("EXPECTED_BUILD", "97"));
await ensureRuntimeBranch(repository, branch);
const prior = await readRuntimeFile(repository, branch, pathname);
if (prior.snapshot) validateRuntimeSnapshot(prior.snapshot, 0, { allowIncomplete: true });
+12 -11
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 build = Number(index.match(/const BUILD_VERSION = (\d+);/)?.[1]);
assert.equal(build, 96);
assert.equal(build, 97);
assert.deepEqual([...ALLOWED_RUNTIME_KEYS].sort(), ["pma_agents_v2", "pma_suggestions_v5"]);
assert.match(index, /function collectPublicRuntimeItems\(\)/);
assert.match(index, /const PUBLIC_RUNTIME_KEYS=Object\.freeze\(\[AGENTS_KEY,SUG_KEY\]\)/);
@@ -26,17 +26,18 @@ assert.match(api, /Buffer\.from\(file\.content/);
assert.match(api, /searchParams\.set\("runtime", `\$\{Date\.now\(\)\}/);
assert.match(workflow, /cron: "7,22,37,52 \* \* \* \*"/);
assert.match(workflow, /contents: write/);
assert.match(workflow, /EXPECTED_BUILD: "96"/);
assert.match(workflow, /EXPECTED_BUILD: "97"/);
assert.match(runner, /MAX_STATE_BYTES = 900_000/);
assert.equal(resolutionAudit.strategy, "resolution-window-no-50-55");
assert.deepEqual(resolutionAudit.selection.horizon_days_enabled, [3, 7]);
assert.ok(resolutionAudit.rules["3_day"].train_event_lower_90 > 0);
assert.ok(resolutionAudit.rules["3_day"].holdout_event_lower_90 > 0);
assert.ok(resolutionAudit.rules["3_day"].chronological_thirds_event_lower_90.every((value) => value > 0));
assert.ok(resolutionAudit.rules["7_day"].train_event_lower_90 > 0);
assert.ok(resolutionAudit.rules["7_day"].holdout_event_lower_90 > 0);
assert.ok(resolutionAudit.rules["7_day"].chronological_thirds_event_lower_90.every((value) => value > 0));
assert.ok(resolutionAudit.rejected_neighboring_rule.event_lower_90 < 0);
assert.equal(resolutionAudit.strategy, "resolution-window-no-50-55-safe-non-sports-v2");
assert.deepEqual(resolutionAudit.selection.horizon_days_enabled, [3, 4, 5, 6]);
for (const days of resolutionAudit.selection.horizon_days_enabled) {
const rule = resolutionAudit.rules[`${days}_day`];
assert.ok(rule.train_event_lower_90 > 0);
assert.ok(rule.holdout_event_lower_90 > 0);
assert.ok(rule.chronological_thirds_event_lower_90.every((value) => value > 0));
}
assert.match(resolutionAudit.rejected_windows["2_day"], /holdout/i);
assert.match(resolutionAudit.rejected_windows["7_day"], /negative/i);
const agentIds = ["value", "momentum", "favorite", "longshot", "diversifier", "catalyst", "reversal", "breakout", "tailalpha", "conviction"];
const agents = Object.fromEntries(agentIds.map(id => [id, { cash: 10000, positions: [], lastDecision: { mode: "test" } }]));