mirror of
https://github.com/theodore-song/polymarket-analyst.git
synced 2026-08-19 18:48:10 +00:00
Coordinate high-risk agent exposure
This commit is contained in:
@@ -15,7 +15,7 @@ https://polymarket-site-eta.vercel.app/personal.html
|
|||||||
|
|
||||||
The site fetches live Polymarket markets, generates agent suggestions, lets you
|
The site fetches live Polymarket markets, generates agent suggestions, lets you
|
||||||
run frequent paper cycles, and syncs the shared arena state through Neon or
|
run frequent paper cycles, and syncs the shared arena state through Neon or
|
||||||
Vercel Blob. Build 43 also installs an offline app shell and caches timestamped
|
Vercel Blob. Build 44 also installs an offline app shell and caches timestamped
|
||||||
market snapshots. During an outage, cycles continue locally; cached entries are
|
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.
|
||||||
@@ -26,7 +26,7 @@ small samples toward neutral, caps sizing changes to 0.68x-1.30x, and reserves
|
|||||||
15% of candidates for deterministic exploration so a stale regime cannot become
|
15% of candidates for deterministic exploration so a stale regime cannot become
|
||||||
permanent.
|
permanent.
|
||||||
|
|
||||||
Strategy 40 treats each binary stake as capable of falling to zero even when the
|
Strategy 42 treats each binary stake as capable of falling to zero even when the
|
||||||
18% stop cannot fill. New core positions are capped at 2.5%-4% of equity and
|
18% stop cannot fill. New core positions are capped at 2.5%-4% of equity and
|
||||||
aggressive positions at 3%-5%, with lower limits for near-term, extreme-price,
|
aggressive positions at 3%-5%, with lower limits for near-term, extreme-price,
|
||||||
reversal, and fast-moving setups. Oversized positions inherited from older
|
reversal, and fast-moving setups. Oversized positions inherited from older
|
||||||
@@ -55,7 +55,7 @@ evidence. Set `EVAL_MARKETS`, `EVAL_CONCURRENCY`, `EVAL_HORIZONS`, or
|
|||||||
`EVAL_COST_CENTS` to change the audit.
|
`EVAL_COST_CENTS` to change the audit.
|
||||||
The first 80-market audit found that reversal signals lost 4.34% on average in
|
The first 80-market audit found that reversal signals lost 4.34% on average in
|
||||||
both chronological partitions, while crypto and longshot samples were also
|
both chronological partitions, while crypto and longshot samples were also
|
||||||
negative overall. Strategy 40 therefore blocks reversal and sports-trend entries outside the fixed
|
negative overall. Strategy 42 therefore blocks reversal and sports-trend entries outside the fixed
|
||||||
15% exploration lane and applies modest sizing penalties to crypto and longshots.
|
15% exploration lane and applies modest sizing penalties to crypto and longshots.
|
||||||
It does not boost any rule from this audit because no positive rule was robust
|
It does not boost any rule from this audit because no positive rule was robust
|
||||||
across the chronological split.
|
across the chronological split.
|
||||||
@@ -66,23 +66,23 @@ segment and averaged -4.13%. Sports trends were negative in train and test and
|
|||||||
averaged -3.53% at 72 hours. Politics trends were the sole cohort with positive
|
averaged -3.53% at 72 hours. Politics trends were the sole cohort with positive
|
||||||
row-level returns in all three 72-hour segments, but its market-cluster interval
|
row-level returns in all three 72-hour segments, but its market-cluster interval
|
||||||
still crossed zero; that supports a longer hold test, not a larger entry bet.
|
still crossed zero; that supports a longer hold test, not a larger entry bet.
|
||||||
Strategy 40 gives Politics trend positions that 72-hour observation window before
|
Strategy 42 gives Politics trend positions that 72-hour observation window before
|
||||||
ordinary signal exits. Stops, profit locks, settlement handling, and risk-budget
|
ordinary signal exits. Stops, profit locks, settlement handling, and risk-budget
|
||||||
reductions remain immediate.
|
reductions remain immediate.
|
||||||
|
|
||||||
Strategy 40 also subtracts a half-cent round-trip cost when grading each live
|
Strategy 42 also subtracts a half-cent round-trip cost when grading each live
|
||||||
walk-forward signal. Confidence uses the largest independent matching bucket,
|
walk-forward signal. Confidence uses the largest independent matching bucket,
|
||||||
not the sum of five overlapping feature buckets, and evidence from older engine
|
not the sum of five overlapping feature buckets, and evidence from older engine
|
||||||
versions is down-weighted. This prevents a handful of duplicated observations
|
versions is down-weighted. This prevents a handful of duplicated observations
|
||||||
from authorizing larger positions or hiding a modest negative regime.
|
from authorizing larger positions or hiding a modest negative regime.
|
||||||
|
|
||||||
Strategy 40 adds uncertainty-aware promotion and demotion. A matching setup must
|
Strategy 42 adds uncertainty-aware promotion and demotion. A matching setup must
|
||||||
accumulate at least eight effective observations and agree across at least two
|
accumulate at least eight effective observations and agree across at least two
|
||||||
feature views before repeatable positive evidence can increase size or repeatable
|
feature views before repeatable positive evidence can increase size or repeatable
|
||||||
negative evidence can block a new entry. Mixed evidence stays close to neutral
|
negative evidence can block a new entry. Mixed evidence stays close to neutral
|
||||||
instead of being mistaken for an edge.
|
instead of being mistaken for an edge.
|
||||||
|
|
||||||
Build 43 enforces the documented offline boundary end to end. Cached snapshots
|
Build 44 enforces the documented offline boundary end to end. Cached snapshots
|
||||||
under 90 minutes old may continue paper execution. Older snapshots remain usable
|
under 90 minutes old may continue paper execution. Older snapshots remain usable
|
||||||
for valuation and chart snapshots for up to 24 hours, but cannot trigger entries,
|
for valuation and chart snapshots for up to 24 hours, but cannot trigger entries,
|
||||||
stop-losses, gain-stops, risk rebalances, settlements, or policy exits. Network
|
stop-losses, gain-stops, risk rebalances, settlements, or policy exits. Network
|
||||||
@@ -91,15 +91,21 @@ of leaving a cycle hanging indefinitely.
|
|||||||
|
|
||||||
Build identity is separate from strategy lineage starting with build 42. The
|
Build identity is separate from strategy lineage starting with build 42. The
|
||||||
service worker and deployment metadata advance with each code release, but
|
service worker and deployment metadata advance with each code release, but
|
||||||
adaptive baselines, pending signal grades, and trade evidence remain in strategy
|
adaptive baselines, pending signal grades, and trade evidence remain in one strategy
|
||||||
40 until the actual entry, sizing, or exit logic changes. Legacy build 40 and 41
|
lineage until the actual entry, sizing, or exit logic changes. Legacy build 40 and 41
|
||||||
records are migrated into the same strategy lineage without losing evidence.
|
records are migrated into the same strategy lineage without losing evidence.
|
||||||
|
|
||||||
Build 43 independently refreshes markets for matured pending signals that have
|
Build 44 independently refreshes markets for matured pending signals that have
|
||||||
left the current top-500 activity scan. Unavailable markets remain queued for a
|
left the current top-500 activity scan. Unavailable markets remain queued for a
|
||||||
bounded retry window. This prevents activity-rank survivorship from deciding
|
bounded retry window. This prevents activity-rank survivorship from deciding
|
||||||
which wins and losses reach the adaptive calibration ledger.
|
which wins and losses reach the adaptive calibration ledger.
|
||||||
|
|
||||||
|
Strategy 42 coordinates high-risk exploration globally. Crypto, reversal,
|
||||||
|
near-term, extreme-price, and other gap-prone positions may be held materially by
|
||||||
|
only one agent, while ordinary independently confirmed markets retain the
|
||||||
|
two-agent cap. A historically blocked setup can enter the exploration lane for
|
||||||
|
only one designated agent, preventing duplicated speculative losses.
|
||||||
|
|
||||||
Run `npm run evaluate:settlements` to evaluate fixed decisions made 1, 3, 7,
|
Run `npm run evaluate:settlements` to evaluate fixed decisions made 1, 3, 7,
|
||||||
14, 30, and 90 days before known binary settlements. The audit uses one
|
14, 30, and 90 days before known binary settlements. The audit uses one
|
||||||
observation per resolved market and horizon, includes losing contracts at zero,
|
observation per resolved market and horizon, includes losing contracts at zero,
|
||||||
|
|||||||
+60
-26
@@ -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 40 · build 43</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 42 · build 44</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 43 active:</b> matured signals are repriced even after their markets leave the top-500 activity scan, removing a survivorship bias from adaptive learning. Strategy lineage 40 and its return baseline continue unchanged. This remains paper trading; profits are not guaranteed.</div>
|
<div class="live-build-banner"><b>Build 44 active:</b> gap-prone and crypto positions are limited to one agent, and each historically blocked exploration market has one designated explorer. This prevents agents from duplicating the same high-risk loss. Strategy 42 starts a clean return baseline. This remains paper trading; 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 43 · Adaptive strategy 40 · Paper trading only · Live prices from Polymarket's public Gamma API · Not financial advice ·
|
Build 44 · Adaptive strategy 42 · Paper trading only · Live prices from Polymarket's public Gamma API · 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,8 +774,9 @@ 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 = 43;
|
const BUILD_VERSION = 44;
|
||||||
const SUGGESTION_ENGINE_VERSION = 40;
|
const SUGGESTION_ENGINE_VERSION = 42;
|
||||||
|
const PREVIOUS_STRATEGY_VERSION = 40;
|
||||||
const LEGACY_BUILD_STRATEGY_LINEAGE = Object.freeze({40:40,41:40});
|
const LEGACY_BUILD_STRATEGY_LINEAGE = Object.freeze({40:40,41:40});
|
||||||
function normalizedStrategyVersion(value){
|
function normalizedStrategyVersion(value){
|
||||||
const version=Number(value||0);
|
const version=Number(value||0);
|
||||||
@@ -1187,12 +1188,16 @@ function effectiveEntryEdge(s){
|
|||||||
const net=Math.abs(Number(s&&s.net_edge));
|
const net=Math.abs(Number(s&&s.net_edge));
|
||||||
return Number.isFinite(net)?net:0;
|
return Number.isFinite(net)?net:0;
|
||||||
}
|
}
|
||||||
|
function isGapProneTrade(s={}){
|
||||||
|
const days=Number(s.days_to_resolution),entry=Number(s.entry_price),dayMove=Math.abs(Number(s.price_change_1d||0));
|
||||||
|
return (Number.isFinite(days)&&days<=14)||(Number.isFinite(entry)&&(entry<=0.22||entry>=0.80))
|
||||||
|
||dayMove>=0.045||s.signal_type==="reversal"||Boolean(s.jump_risk);
|
||||||
|
}
|
||||||
|
function maxAgentOverlapForTrade(s={}){return (isGapProneTrade(s)||(s.category||"Other")==="Crypto")?1:2;}
|
||||||
function tradeLossBudgetPct(cfg,s={}){
|
function tradeLossBudgetPct(cfg,s={}){
|
||||||
const aggressive=Boolean(cfg&&cfg.aggressive);
|
const aggressive=Boolean(cfg&&cfg.aggressive);
|
||||||
let cap=aggressive?MAX_AGGRESSIVE_TRADE_LOSS_PCT:MAX_CORE_TRADE_LOSS_PCT;
|
let cap=aggressive?MAX_AGGRESSIVE_TRADE_LOSS_PCT:MAX_CORE_TRADE_LOSS_PCT;
|
||||||
const days=Number(s.days_to_resolution),entry=Number(s.entry_price),dayMove=Math.abs(Number(s.price_change_1d||0));
|
const gapProne=isGapProneTrade(s);
|
||||||
const gapProne=(Number.isFinite(days)&&days<=14)||(Number.isFinite(entry)&&(entry<=0.22||entry>=0.80))
|
|
||||||
||dayMove>=0.045||s.signal_type==="reversal"||Boolean(s.jump_risk);
|
|
||||||
if(gapProne)cap=Math.min(cap,aggressive?MAX_AGGRESSIVE_GAP_TRADE_LOSS_PCT:MAX_CORE_GAP_TRADE_LOSS_PCT);
|
if(gapProne)cap=Math.min(cap,aggressive?MAX_AGGRESSIVE_GAP_TRADE_LOSS_PCT:MAX_CORE_GAP_TRADE_LOSS_PCT);
|
||||||
return +cap.toFixed(4);
|
return +cap.toFixed(4);
|
||||||
}
|
}
|
||||||
@@ -1672,7 +1677,7 @@ function buildSignalCalibration(ledger){
|
|||||||
const buckets={};
|
const buckets={};
|
||||||
for(const outcome of (ledger&&ledger.outcomes)||[]){
|
for(const outcome of (ledger&&ledger.outcomes)||[]){
|
||||||
const age=Math.max(0,Date.now()-new Date(outcome.evaluated_at||0).getTime()),version=normalizedStrategyVersion(outcome.strategy_version);
|
const age=Math.max(0,Date.now()-new Date(outcome.evaluated_at||0).getTime()),version=normalizedStrategyVersion(outcome.strategy_version);
|
||||||
const versionWeight=version===SUGGESTION_ENGINE_VERSION?1:(version===SUGGESTION_ENGINE_VERSION-1?0.55:0.25);
|
const versionWeight=version===SUGGESTION_ENGINE_VERSION?1:(version===PREVIOUS_STRATEGY_VERSION?0.55:0.25);
|
||||||
const weight=Math.exp(-age/(30*86400000))*versionWeight;
|
const weight=Math.exp(-age/(30*86400000))*versionWeight;
|
||||||
const ret=clamp(Number(outcome.return||0),-1,2);if(!Number.isFinite(ret))continue;
|
const ret=clamp(Number(outcome.return||0),-1,2);if(!Number.isFinite(ret))continue;
|
||||||
learningFeatures(outcome).forEach(key=>{const b=buckets[key]||(buckets[key]={weight:0,sum:0,sumSq:0,wins:0,count:0});
|
learningFeatures(outcome).forEach(key=>{const b=buckets[key]||(buckets[key]={weight:0,sum:0,sumSq:0,wins:0,count:0});
|
||||||
@@ -1713,7 +1718,7 @@ function buildAdaptiveProfile(p){
|
|||||||
const version=normalizedStrategyVersion(trade.strategy_version);if(version<34)return;
|
const version=normalizedStrategyVersion(trade.strategy_version);if(version<34)return;
|
||||||
const age=Math.max(0,Date.now()-new Date(trade.closed_at||trade.opened_at||0).getTime());
|
const age=Math.max(0,Date.now()-new Date(trade.closed_at||trade.opened_at||0).getTime());
|
||||||
const recency=Number.isFinite(age)?Math.exp(-age/(45*86400000)):0.4;
|
const recency=Number.isFinite(age)?Math.exp(-age/(45*86400000)):0.4;
|
||||||
const versionWeight=version===SUGGESTION_ENGINE_VERSION?1:(version===SUGGESTION_ENGINE_VERSION-1?0.45:0.20);
|
const versionWeight=version===SUGGESTION_ENGINE_VERSION?1:(version===PREVIOUS_STRATEGY_VERSION?0.45:0.20);
|
||||||
const weight=recency*versionWeight*(closed?1:Math.min(0.30,Math.max(0.08,daysHeld(trade)/20)));
|
const weight=recency*versionWeight*(closed?1:Math.min(0.30,Math.max(0.08,daysHeld(trade)/20)));
|
||||||
const ret=tradeReturnForLearning(trade,closed);
|
const ret=tradeReturnForLearning(trade,closed);
|
||||||
if(!Number.isFinite(ret)||weight<=0)return;
|
if(!Number.isFinite(ret)||weight<=0)return;
|
||||||
@@ -1742,10 +1747,16 @@ function buildAdaptiveProfile(p){
|
|||||||
best:ranked[0]?{feature:ranked[0][0],score:ranked[0][1].score}:null,
|
best:ranked[0]?{feature:ranked[0][0],score:ranked[0][1].score}:null,
|
||||||
worst:ranked.length?{feature:ranked[ranked.length-1][0],score:ranked[ranked.length-1][1].score}:null};
|
worst:ranked.length?{feature:ranked[ranked.length-1][0],score:ranked[ranked.length-1][1].score}:null};
|
||||||
}
|
}
|
||||||
function stableExploration(agentId,marketId){
|
function stableHash(text){
|
||||||
const text=`${agentId}:${marketId}`;let h=2166136261;
|
let h=2166136261;
|
||||||
for(let i=0;i<text.length;i++){h^=text.charCodeAt(i);h=Math.imul(h,16777619);}
|
for(let i=0;i<text.length;i++){h^=text.charCodeAt(i);h=Math.imul(h,16777619);}
|
||||||
return (h>>>0)%100<15;
|
return h>>>0;
|
||||||
|
}
|
||||||
|
function stableExploration(agentId,marketId){
|
||||||
|
const id=String(marketId||"");
|
||||||
|
if(stableHash(`lane:${id}`)%100>=15)return false;
|
||||||
|
const owner=AGENTS[stableHash(`owner:${id}`)%AGENTS.length];
|
||||||
|
return Boolean(owner&&owner.id===agentId);
|
||||||
}
|
}
|
||||||
function historicalOpportunityPrior(s){
|
function historicalOpportunityPrior(s){
|
||||||
const rows=[];
|
const rows=[];
|
||||||
@@ -2157,7 +2168,8 @@ function reduceStrategyOverlap(st){
|
|||||||
});
|
});
|
||||||
Object.values(groups).filter(g=>g.length>1).forEach(group=>{
|
Object.values(groups).filter(g=>g.length>1).forEach(group=>{
|
||||||
group.sort((a,b)=>(b.score-a.score)||((b.pos.value||0)-(a.pos.value||0)));
|
group.sort((a,b)=>(b.score-a.score)||((b.pos.value||0)-(a.pos.value||0)));
|
||||||
group.slice(2).forEach(({p,pos})=>closePosition(p,pos,"Strict overlap guard limited this market to two agents","EXIT"));
|
const cap=Math.min(...group.map(({pos})=>maxAgentOverlapForTrade(pos)));
|
||||||
|
group.slice(cap).forEach(({p,pos})=>closePosition(p,pos,`Overlap guard limited this ${cap===1?"high-risk ":""}market to ${cap===1?"one agent":"two agents"}`,"EXIT"));
|
||||||
});
|
});
|
||||||
AGENTS.filter(a=>a.kind==="strategy").forEach(cfg=>{
|
AGENTS.filter(a=>a.kind==="strategy").forEach(cfg=>{
|
||||||
const p=st.agents&&st.agents[cfg.id]; if(p)p.positions=(p.positions||[]).filter(pos=>!pos.closed_at);
|
const p=st.agents&&st.agents[cfg.id]; if(p)p.positions=(p.positions||[]).filter(pos=>!pos.closed_at);
|
||||||
@@ -2229,7 +2241,8 @@ function openPositions(p,cfg,rankedSugs,focus,decision,avoidMarketIds,peerStats=
|
|||||||
if(s.volume_24hr<500&&s.conviction<62)return reject("activity");
|
if(s.volume_24hr<500&&s.conviction<62)return reject("activity");
|
||||||
if(s.evidence_score!=null&&s.evidence_score<0.46)return reject("evidence");
|
if(s.evidence_score!=null&&s.evidence_score<0.46)return reject("evidence");
|
||||||
const peer=(peerStats&&peerStats[`${s.market_id}:${s.side}`])||{};
|
const peer=(peerStats&&peerStats[`${s.market_id}:${s.side}`])||{};
|
||||||
if(avoid.has(String(s.market_id))&&!(Number(peer.same||0)<2&&Number(peer.opposite||0)===0))return reject("overlap");
|
const overlapCap=maxAgentOverlapForTrade(s);
|
||||||
|
if(avoid.has(String(s.market_id))&&!(Number(peer.same||0)<overlapCap&&Number(peer.opposite||0)===0))return reject("overlap");
|
||||||
if(hasPosition(p,s.market_id))return reject("already_held");
|
if(hasPosition(p,s.market_id))return reject("already_held");
|
||||||
if(hasRecentStop(p,s.market_id))return reject("cooldown");
|
if(hasRecentStop(p,s.market_id))return reject("cooldown");
|
||||||
if(focus!=="All"&&focus&&s.category!==focus)return reject("focus");
|
if(focus!=="All"&&focus&&s.category!==focus)return reject("focus");
|
||||||
@@ -2272,6 +2285,7 @@ function openPositions(p,cfg,rankedSugs,focus,decision,avoidMarketIds,peerStats=
|
|||||||
strategy_version:SUGGESTION_ENGINE_VERSION,
|
strategy_version:SUGGESTION_ENGINE_VERSION,
|
||||||
build_version:BUILD_VERSION,
|
build_version:BUILD_VERSION,
|
||||||
momentum_strength:s.momentum_strength,signal_strength:s.signal_strength,signal_confidence:s.signal_confidence,signal_type:s.signal_type,price_change_1d:s.price_change_1d,price_change_1w:s.price_change_1w,
|
momentum_strength:s.momentum_strength,signal_strength:s.signal_strength,signal_confidence:s.signal_confidence,signal_type:s.signal_type,price_change_1d:s.price_change_1d,price_change_1w:s.price_change_1w,
|
||||||
|
days_to_resolution:s.days_to_resolution,jump_risk:Boolean(s.jump_risk),
|
||||||
learning_score:s.learning_score,learning_confidence:s.learning_confidence,market_learning_score:s.market_learning_score,market_learning_confidence:s.market_learning_confidence,
|
learning_score:s.learning_score,learning_confidence:s.learning_confidence,market_learning_score:s.market_learning_score,market_learning_confidence:s.market_learning_confidence,
|
||||||
learning_state:s.learning_state,market_learning_state:s.market_learning_state,
|
learning_state:s.learning_state,market_learning_state:s.market_learning_state,
|
||||||
historical_prior_score:s.historical_prior_score,historical_prior_confidence:s.historical_prior_confidence,historical_prior_features:s.historical_prior_features,
|
historical_prior_score:s.historical_prior_score,historical_prior_confidence:s.historical_prior_confidence,historical_prior_features:s.historical_prior_features,
|
||||||
@@ -4229,7 +4243,7 @@ window.PMA_ENGINE_DIAGNOSTICS=Object.freeze({
|
|||||||
historicalPriceFeatures,
|
historicalPriceFeatures,
|
||||||
offlineCachePolicy,
|
offlineCachePolicy,
|
||||||
gainStopTargets:(entry)=>GAIN_STOP_TIERS.map(t=>gainStopTarget({entry_price:Number(entry),cost:1,shares:1,gain_stops:{}},t)),
|
gainStopTargets:(entry)=>GAIN_STOP_TIERS.map(t=>gainStopTarget({entry_price:Number(entry),cost:1,shares:1,gain_stops:{}},t)),
|
||||||
rules:Object.freeze({minimumPolicyHoldHours:MIN_POLICY_HOLD_HOURS,politicsTrendHoldHours:POLITICS_TREND_MIN_HOLD_HOURS,exitConfirmationHours:EXIT_CONFIRM_HOURS,maxAgentOverlap:2,materialOverlapPct:1.25,stopLossPct:18,
|
rules:Object.freeze({minimumPolicyHoldHours:MIN_POLICY_HOLD_HOURS,politicsTrendHoldHours:POLITICS_TREND_MIN_HOLD_HOURS,exitConfirmationHours:EXIT_CONFIRM_HOURS,maxAgentOverlap:2,gapProneMaxAgentOverlap:1,globalExplorationOwner:true,materialOverlapPct:1.25,stopLossPct:18,
|
||||||
coreTradeLossPct:MAX_CORE_TRADE_LOSS_PCT*100,aggressiveTradeLossPct:MAX_AGGRESSIVE_TRADE_LOSS_PCT*100,
|
coreTradeLossPct:MAX_CORE_TRADE_LOSS_PCT*100,aggressiveTradeLossPct:MAX_AGGRESSIVE_TRADE_LOSS_PCT*100,
|
||||||
coreGapTradeLossPct:MAX_CORE_GAP_TRADE_LOSS_PCT*100,aggressiveGapTradeLossPct:MAX_AGGRESSIVE_GAP_TRADE_LOSS_PCT*100,
|
coreGapTradeLossPct:MAX_CORE_GAP_TRADE_LOSS_PCT*100,aggressiveGapTradeLossPct:MAX_AGGRESSIVE_GAP_TRADE_LOSS_PCT*100,
|
||||||
offlineEntryMaxAgeMinutes:OFFLINE_ENTRY_MAX_AGE_MS/60000,offlineCacheMaxAgeHours:OFFLINE_CACHE_MAX_AGE_MS/3600000,explorationPct:15,
|
offlineEntryMaxAgeMinutes:OFFLINE_ENTRY_MAX_AGE_MS/60000,offlineCacheMaxAgeHours:OFFLINE_CACHE_MAX_AGE_MS/3600000,explorationPct:15,
|
||||||
@@ -4301,6 +4315,8 @@ function runEngineSelfTest(){
|
|||||||
const noisyCalibration=calibratedOpportunity(calibrationCandidate,calibrationFromReturns(Array.from({length:24},(_,i)=>i%2?0.12:-0.12)));
|
const noisyCalibration=calibratedOpportunity(calibrationCandidate,calibrationFromReturns(Array.from({length:24},(_,i)=>i%2?0.12:-0.12)));
|
||||||
const legacyBuildCalibration=buildSignalCalibration({pending:[],outcomes:[Object.assign({},calibrationCandidate,
|
const legacyBuildCalibration=buildSignalCalibration({pending:[],outcomes:[Object.assign({},calibrationCandidate,
|
||||||
{strategy_version:41,return:0.10,evaluated_at:closedAt})]});
|
{strategy_version:41,return:0.10,evaluated_at:closedAt})]});
|
||||||
|
const currentStrategyCalibration=buildSignalCalibration({pending:[],outcomes:[Object.assign({},calibrationCandidate,
|
||||||
|
{strategy_version:SUGGESTION_ENGINE_VERSION,return:0.10,evaluated_at:closedAt})]});
|
||||||
const lossLearner=defaultPortfolio();
|
const lossLearner=defaultPortfolio();
|
||||||
for(let i=0;i<6;i++)lossLearner.closed.push({strategy_version:SUGGESTION_ENGINE_VERSION,signal_type:"trend",quality:"confirmed",category:"Politics",side:"YES",entry_price:0.42,original_cost:100,
|
for(let i=0;i<6;i++)lossLearner.closed.push({strategy_version:SUGGESTION_ENGINE_VERSION,signal_type:"trend",quality:"confirmed",category:"Politics",side:"YES",entry_price:0.42,original_cost:100,
|
||||||
realized_pnl:-50,opened_at:hoursAgo(72+i),closed_at:closedAt});
|
realized_pnl:-50,opened_at:hoursAgo(72+i),closed_at:closedAt});
|
||||||
@@ -4310,7 +4326,7 @@ function runEngineSelfTest(){
|
|||||||
const lossOpportunity=learnedOpportunity(AGENTS[0],lossLearner,{market_id:lossMarketId,signal_type:"trend",quality:"confirmed",category:"Politics",side:"YES",entry_price:0.42},lossProfile);
|
const lossOpportunity=learnedOpportunity(AGENTS[0],lossLearner,{market_id:lossMarketId,signal_type:"trend",quality:"confirmed",category:"Politics",side:"YES",entry_price:0.42},lossProfile);
|
||||||
const lossDecision=adaptiveDecision(AGENTS[0],lossLearner,5,10,STARTING_BALANCE);
|
const lossDecision=adaptiveDecision(AGENTS[0],lossLearner,5,10,STARTING_BALANCE);
|
||||||
const legacyLossLearner=defaultPortfolio();
|
const legacyLossLearner=defaultPortfolio();
|
||||||
for(let i=0;i<4;i++)legacyLossLearner.closed.push({strategy_version:SUGGESTION_ENGINE_VERSION-1,signal_type:"trend",quality:"confirmed",category:"Politics",side:"YES",entry_price:0.42,original_cost:100,
|
for(let i=0;i<4;i++)legacyLossLearner.closed.push({strategy_version:PREVIOUS_STRATEGY_VERSION,signal_type:"trend",quality:"confirmed",category:"Politics",side:"YES",entry_price:0.42,original_cost:100,
|
||||||
realized_pnl:-50,opened_at:hoursAgo(72+i),closed_at:closedAt});
|
realized_pnl:-50,opened_at:hoursAgo(72+i),closed_at:closedAt});
|
||||||
const legacyLossDecision=adaptiveDecision(AGENTS[0],legacyLossLearner,5,10,STARTING_BALANCE);
|
const legacyLossDecision=adaptiveDecision(AGENTS[0],legacyLossLearner,5,10,STARTING_BALANCE);
|
||||||
const coreRiskBudget=tradeLossBudgetPct(AGENTS[0],{entry_price:0.50,days_to_resolution:40,price_change_1d:0.01,signal_type:"trend"});
|
const coreRiskBudget=tradeLossBudgetPct(AGENTS[0],{entry_price:0.50,days_to_resolution:40,price_change_1d:0.01,signal_type:"trend"});
|
||||||
@@ -4325,6 +4341,16 @@ function runEngineSelfTest(){
|
|||||||
["value","momentum","favorite"].forEach((id,i)=>mock.agents[id].positions.push({market_id:"overlap-test",question:"Overlap test",side:"YES",shares:1000,current_price:0.5,entry_price:0.5,cost:500,value:500,unrealized_pnl:0,conviction:70-i,opened_at:hoursAgo(24)}));
|
["value","momentum","favorite"].forEach((id,i)=>mock.agents[id].positions.push({market_id:"overlap-test",question:"Overlap test",side:"YES",shares:1000,current_price:0.5,entry_price:0.5,cost:500,value:500,unrealized_pnl:0,conviction:70-i,opened_at:hoursAgo(24)}));
|
||||||
reduceStrategyOverlap(mock);
|
reduceStrategyOverlap(mock);
|
||||||
const overlapRemaining=AGENTS.reduce((sum,a)=>sum+mock.agents[a.id].positions.filter(p=>p.market_id==="overlap-test").length,0);
|
const overlapRemaining=AGENTS.reduce((sum,a)=>sum+mock.agents[a.id].positions.filter(p=>p.market_id==="overlap-test").length,0);
|
||||||
|
const gapMock={agents:{}};AGENTS.forEach(a=>gapMock.agents[a.id]=defaultPortfolio());
|
||||||
|
["reversal","conviction"].forEach((id,i)=>gapMock.agents[id].positions.push({market_id:"gap-overlap-test",question:"Gap overlap test",side:"NO",category:"Crypto",signal_type:"reversal",
|
||||||
|
shares:2000,current_price:0.21,entry_price:0.21,cost:420,value:420,original_shares:2000,original_cost:420,unrealized_pnl:0,conviction:75-i,opened_at:hoursAgo(24)}));
|
||||||
|
reduceStrategyOverlap(gapMock);
|
||||||
|
const gapOverlapRemaining=AGENTS.reduce((sum,a)=>sum+gapMock.agents[a.id].positions.filter(p=>p.market_id==="gap-overlap-test").length,0);
|
||||||
|
let explorationMarketId="single-explorer-0",explorationIndex=0,explorationOwners=[];
|
||||||
|
while(!explorationOwners.length){
|
||||||
|
explorationOwners=AGENTS.filter(a=>stableExploration(a.id,explorationMarketId));
|
||||||
|
if(!explorationOwners.length)explorationMarketId=`single-explorer-${++explorationIndex}`;
|
||||||
|
}
|
||||||
mock.agents.tailalpha.positions.push({market_id:"runner-test",question:"Runner test",side:"YES",shares:100,current_price:0.5,entry_price:0.5,cost:50,value:50,unrealized_pnl:0,conviction:70,opened_at:hoursAgo(24)});
|
mock.agents.tailalpha.positions.push({market_id:"runner-test",question:"Runner test",side:"YES",shares:100,current_price:0.5,entry_price:0.5,cost:50,value:50,unrealized_pnl:0,conviction:70,opened_at:hoursAgo(24)});
|
||||||
const immaterialRunnerDoesNotBlock=!occupiedStrategyMarkets(mock).has("runner-test");
|
const immaterialRunnerDoesNotBlock=!occupiedStrategyMarkets(mock).has("runner-test");
|
||||||
const rejectBook=defaultPortfolio();rejectBook.cash=9900;
|
const rejectBook=defaultPortfolio();rejectBook.cash=9900;
|
||||||
@@ -4343,10 +4369,15 @@ function runEngineSelfTest(){
|
|||||||
const executableBook=JSON.parse(JSON.stringify(markOnlyBook));
|
const executableBook=JSON.parse(JSON.stringify(markOnlyBook));
|
||||||
delete executableBook.positions[0].price_status;
|
delete executableBook.positions[0].price_status;
|
||||||
markToMarket(executableBook,{"offline-mark":market({id:"offline-mark",yes_price:0.8,no_price:0.2})},AGENTS[0],{policyExits:true,executeTrades:true});
|
markToMarket(executableBook,{"offline-mark":market({id:"offline-mark",yes_price:0.8,no_price:0.2})},AGENTS[0],{policyExits:true,executeTrades:true});
|
||||||
const lineageMigrationState=defaultState();
|
const buildMigrationState=defaultState();
|
||||||
lineageMigrationState.engine_version=41;delete lineageMigrationState.strategy_version;
|
buildMigrationState.engine_version=43;buildMigrationState.strategy_version=SUGGESTION_ENGINE_VERSION;
|
||||||
lineageMigrationState.agents.value.engine_baseline={version:41,started_at:hoursAgo(2),equity:9876.54};
|
buildMigrationState.agents.value.engine_baseline={version:SUGGESTION_ENGINE_VERSION,started_at:hoursAgo(2),equity:9876.54};
|
||||||
reconcileStateVersions(lineageMigrationState);
|
reconcileStateVersions(buildMigrationState);
|
||||||
|
const strategyMigrationState=defaultState();
|
||||||
|
strategyMigrationState.engine_version=43;strategyMigrationState.strategy_version=PREVIOUS_STRATEGY_VERSION;
|
||||||
|
strategyMigrationState.agents.value.cash=9876.54;
|
||||||
|
strategyMigrationState.agents.value.engine_baseline={version:PREVIOUS_STRATEGY_VERSION,started_at:hoursAgo(2),equity:10000};
|
||||||
|
reconcileStateVersions(strategyMigrationState);
|
||||||
return {buildVersion:BUILD_VERSION,version:SUGGESTION_ENGINE_VERSION,
|
return {buildVersion:BUILD_VERSION,version:SUGGESTION_ENGINE_VERSION,
|
||||||
trend:{ready:trend.trade_ready,quality:trend.quality,side:trend.side,margin:trend.net_edge},
|
trend:{ready:trend.trade_ready,quality:trend.quality,side:trend.side,margin:trend.net_edge},
|
||||||
noSignal:{ready:noSignal.trade_ready,quality:noSignal.quality,signal:noSignal.signal_type,margin:noSignal.net_edge},
|
noSignal:{ready:noSignal.trade_ready,quality:noSignal.quality,signal:noSignal.signal_type,margin:noSignal.net_edge},
|
||||||
@@ -4364,10 +4395,12 @@ function runEngineSelfTest(){
|
|||||||
expiresOnlyAfterRetryWindow:expiredLedgerState.signal_ledger.pending.length===0&&expiredLedgerState.signal_ledger.expired_ungraded===1,
|
expiresOnlyAfterRetryWindow:expiredLedgerState.signal_ledger.pending.length===0&&expiredLedgerState.signal_ledger.expired_ungraded===1,
|
||||||
ledgerIsNetOfCosts:ledgerState.signal_ledger.outcomes[0].gross_return===0.25&&ledgerState.signal_ledger.outcomes[0].estimated_cost_return===0.0125,
|
ledgerIsNetOfCosts:ledgerState.signal_ledger.outcomes[0].gross_return===0.25&&ledgerState.signal_ledger.outcomes[0].estimated_cost_return===0.0125,
|
||||||
independentCalibrationConfidence:singleCalibration.confidence<0.06,
|
independentCalibrationConfidence:singleCalibration.confidence<0.06,
|
||||||
legacyBuildSharesStrategyLineage:normalizedStrategyVersion(41)===SUGGESTION_ENGINE_VERSION,
|
legacyBuildMapsToPreviousStrategy:normalizedStrategyVersion(41)===PREVIOUS_STRATEGY_VERSION,
|
||||||
sameStrategyBuildKeepsFullWeight:legacyBuildCalibration.current_samples===1&&legacyBuildCalibration.buckets["signal:trend"].weight===1,
|
previousStrategyIsDownWeighted:legacyBuildCalibration.current_samples===0&&legacyBuildCalibration.buckets["signal:trend"].weight>0.54&&legacyBuildCalibration.buckets["signal:trend"].weight<=0.55,
|
||||||
baselineSurvivesBuildMigration:lineageMigrationState.agents.value.engine_baseline.equity===9876.54&&lineageMigrationState.agents.value.engine_baseline.version===SUGGESTION_ENGINE_VERSION,
|
currentStrategyKeepsFullWeight:currentStrategyCalibration.current_samples===1&¤tStrategyCalibration.buckets["signal:trend"].weight>0.99,
|
||||||
buildMetadataAdvancesWithoutStrategyReset:lineageMigrationState.engine_version===BUILD_VERSION&&lineageMigrationState.strategy_version===SUGGESTION_ENGINE_VERSION,
|
baselineSurvivesBuildMigration:buildMigrationState.agents.value.engine_baseline.equity===9876.54&&buildMigrationState.agents.value.engine_baseline.version===SUGGESTION_ENGINE_VERSION,
|
||||||
|
buildMetadataAdvancesWithoutStrategyReset:buildMigrationState.engine_version===BUILD_VERSION&&buildMigrationState.strategy_version===SUGGESTION_ENGINE_VERSION,
|
||||||
|
strategyChangeStartsCleanBaseline:strategyMigrationState.agents.value.engine_baseline.equity===9876.54&&strategyMigrationState.agents.value.engine_baseline.version===SUGGESTION_ENGINE_VERSION,
|
||||||
singleOutcomeStaysObserving:singleCalibration.state==="observing"&&singleCalibration.multiplier<=1.01,
|
singleOutcomeStaysObserving:singleCalibration.state==="observing"&&singleCalibration.multiplier<=1.01,
|
||||||
stablePositiveIsPromoted:stablePositiveCalibration.state==="promoted"&&stablePositiveCalibration.multiplier>1.02&&stablePositiveCalibration.allowed,
|
stablePositiveIsPromoted:stablePositiveCalibration.state==="promoted"&&stablePositiveCalibration.multiplier>1.02&&stablePositiveCalibration.allowed,
|
||||||
stableNegativeIsBlocked:stableNegativeCalibration.state==="demoted"&&!stableNegativeCalibration.allowed,
|
stableNegativeIsBlocked:stableNegativeCalibration.state==="demoted"&&!stableNegativeCalibration.allowed,
|
||||||
@@ -4383,7 +4416,8 @@ function runEngineSelfTest(){
|
|||||||
exits:{youngConflict:exitReason(young,fresh,conflict,AGENTS[0]),matureConflict:exitReason(mature,fresh,conflict,AGENTS[0]),
|
exits:{youngConflict:exitReason(young,fresh,conflict,AGENTS[0]),matureConflict:exitReason(mature,fresh,conflict,AGENTS[0]),
|
||||||
politicsEarlyConflict:exitReason(politicsEarly,fresh,conflict,AGENTS[0]),politicsMatureConflict:exitReason(politicsMature,fresh,conflict,AGENTS[0]),trailing:trailingProfitReason(trailing)},
|
politicsEarlyConflict:exitReason(politicsEarly,fresh,conflict,AGENTS[0]),politicsMatureConflict:exitReason(politicsMature,fresh,conflict,AGENTS[0]),trailing:trailingProfitReason(trailing)},
|
||||||
backtest:{noLookahead:backtestNoLookahead,features:historicalFeatures},
|
backtest:{noLookahead:backtestNoLookahead,features:historicalFeatures},
|
||||||
overlapRemaining,immaterialRunnerDoesNotBlock,rejectionAccounting,convictionCapacityCoversTarget,rules:window.PMA_ENGINE_DIAGNOSTICS.rules};
|
overlapRemaining,gapOverlapRemaining,singleGlobalExplorer:explorationOwners.length===1,
|
||||||
|
immaterialRunnerDoesNotBlock,rejectionAccounting,convictionCapacityCoversTarget,rules:window.PMA_ENGINE_DIAGNOSTICS.rules};
|
||||||
}
|
}
|
||||||
if(new URLSearchParams(location.search).get("engine_test")==="1"){
|
if(new URLSearchParams(location.search).get("engine_test")==="1"){
|
||||||
const output=document.createElement("output");output.id="engineSelfTest";output.hidden=true;output.textContent=JSON.stringify(runEngineSelfTest());document.body.appendChild(output);
|
const output=document.createElement("output");output.id="engineSelfTest";output.hidden=true;output.textContent=JSON.stringify(runEngineSelfTest());document.body.appendChild(output);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const CACHE_NAME = "polymarket-arena-build-43";
|
const CACHE_NAME = "polymarket-arena-build-44";
|
||||||
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