mirror of
https://github.com/theodore-song/polymarket-analyst.git
synced 2026-08-19 18:48:10 +00:00
Preserve strategy evidence across builds
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. Engine v41 also installs an offline app shell and caches timestamped
|
Vercel Blob. Build 42 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.
|
||||||
|
|
||||||
Engine v41 treats each binary stake as capable of falling to zero even when the
|
Strategy 40 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
|
||||||
@@ -42,7 +42,7 @@ without backfilling future information into old decisions.
|
|||||||
The initial seven-day chart seed is an approximate replay, not a live return.
|
The initial seven-day chart seed is an approximate replay, not a live return.
|
||||||
It uses only prices available on each simulated date, computes daily and weekly
|
It uses only prices available on each simulated date, computes daily and weekly
|
||||||
changes from those historical prices, disables unavailable hourly reversal data,
|
changes from those historical prices, disables unavailable hourly reversal data,
|
||||||
and labels the combined number as legacy/replay. Engine-version returns are the
|
and labels the combined number as legacy/replay. Adaptive-strategy returns are the
|
||||||
clean live comparison.
|
clean live comparison.
|
||||||
|
|
||||||
Run `npm run evaluate:signals` to test the price-signal rules against one month
|
Run `npm run evaluate:signals` to test the price-signal rules against one month
|
||||||
@@ -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. Engine v41 therefore blocks reversal and sports-trend entries outside the fixed
|
negative overall. Strategy 40 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,29 +66,35 @@ 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.
|
||||||
Engine v41 gives Politics trend positions that 72-hour observation window before
|
Strategy 40 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.
|
||||||
|
|
||||||
Engine v41 also subtracts a half-cent round-trip cost when grading each live
|
Strategy 40 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.
|
||||||
|
|
||||||
Engine v41 adds uncertainty-aware promotion and demotion. A matching setup must
|
Strategy 40 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.
|
||||||
|
|
||||||
Engine v41 enforces the documented offline boundary end to end. Cached snapshots
|
Build 42 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
|
||||||
requests have bounded timeouts so a weak connection falls back to cache instead
|
requests have bounded timeouts so a weak connection falls back to cache instead
|
||||||
of leaving a cycle hanging indefinitely.
|
of leaving a cycle hanging indefinitely.
|
||||||
|
|
||||||
|
Build identity is separate from strategy lineage starting with build 42. The
|
||||||
|
service worker and deployment metadata advance with each code release, but
|
||||||
|
adaptive baselines, pending signal grades, and trade evidence remain in strategy
|
||||||
|
40 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.
|
||||||
|
|
||||||
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,
|
||||||
|
|||||||
+70
-36
@@ -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 offline engine · v41</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 40 · build 42</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 v41 active:</b> adaptive sizing requires repeatable evidence, and offline execution now has a hard freshness boundary. Snapshots under 90 minutes may trade; older snapshots are mark-only and cannot open, stop, scale out, rebalance, settle, or close positions. This remains paper trading; profits are not guaranteed.</div>
|
<div class="live-build-banner"><b>Build 42 active:</b> code releases and strategy lineage are now separate. Operational fixes no longer reset adaptive returns or down-weight same-strategy evidence. Strategy 40 keeps its uncertainty gates and offline freshness boundary. This remains paper trading; profits are not guaranteed.</div>
|
||||||
|
|
||||||
<!-- ============ OVERVIEW ============ -->
|
<!-- ============ OVERVIEW ============ -->
|
||||||
<section class="tabpanel" data-tab="overview">
|
<section class="tabpanel" data-tab="overview">
|
||||||
@@ -425,7 +425,7 @@ footer{margin-top:34px;padding-top:22px;border-top:1px solid var(--border);color
|
|||||||
<div class="card-h"><h3>Returns — all agents</h3><div><span class="small muted">$10,000 start each</span><div class="rangebar" data-chart-ranges></div></div></div>
|
<div class="card-h"><h3>Returns — all agents</h3><div><span class="small muted">$10,000 start each</span><div class="rangebar" data-chart-ranges></div></div></div>
|
||||||
<div class="chart-wrap"><svg id="chart2" viewBox="0 0 960 320" preserveAspectRatio="xMidYMid meet"></svg></div>
|
<div class="chart-wrap"><svg id="chart2" viewBox="0 0 960 320" preserveAspectRatio="xMidYMid meet"></svg></div>
|
||||||
<div class="legend" id="comboLegend2"></div>
|
<div class="legend" id="comboLegend2"></div>
|
||||||
<div class="small muted" style="margin-top:10px">The initial week is an approximate historical replay using prices available on each day and current liquidity as a proxy. The v41 return starts from live cycles only.</div>
|
<div class="small muted" style="margin-top:10px">The initial week is an approximate historical replay using prices available on each day and current liquidity as a proxy. Adaptive return continues across builds until the trading strategy itself changes.</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -745,7 +745,7 @@ footer{margin-top:34px;padding-top:22px;border-top:1px solid var(--border);color
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Build adaptive-offline-v41 · Paper trading only · Live prices from Polymarket's public Gamma API · Not financial advice ·
|
Build 42 · Adaptive strategy 40 · 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,7 +774,13 @@ 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 SUGGESTION_ENGINE_VERSION = 41;
|
const BUILD_VERSION = 42;
|
||||||
|
const SUGGESTION_ENGINE_VERSION = 40;
|
||||||
|
const LEGACY_BUILD_STRATEGY_LINEAGE = Object.freeze({40:40,41:40});
|
||||||
|
function normalizedStrategyVersion(value){
|
||||||
|
const version=Number(value||0);
|
||||||
|
return Number(LEGACY_BUILD_STRATEGY_LINEAGE[version]||version);
|
||||||
|
}
|
||||||
const FOCUS_KEY = "pma_focus_v1";
|
const FOCUS_KEY = "pma_focus_v1";
|
||||||
const VIEW_KEY = "pma_view_v1";
|
const VIEW_KEY = "pma_view_v1";
|
||||||
const PF_SORT_KEY = "pma_portfolio_sort_v1";
|
const PF_SORT_KEY = "pma_portfolio_sort_v1";
|
||||||
@@ -917,11 +923,11 @@ const PRICE_REQUEST_TIMEOUT_MS = 4000;
|
|||||||
const SIGNAL_EVAL_HOURS = 12;
|
const SIGNAL_EVAL_HOURS = 12;
|
||||||
const SIGNAL_LEDGER_PENDING_LIMIT = 300;
|
const SIGNAL_LEDGER_PENDING_LIMIT = 300;
|
||||||
const SIGNAL_LEDGER_OUTCOME_LIMIT = 500;
|
const SIGNAL_LEDGER_OUTCOME_LIMIT = 500;
|
||||||
const currentCycleHour = () => {const p=partsInLocalTime();return `${p.year}-${p.month}-${p.day}T${p.hour}:${p.minute}|v${SUGGESTION_ENGINE_VERSION}`;};
|
const currentCycleHour = () => {const p=partsInLocalTime();return `${p.year}-${p.month}-${p.day}T${p.hour}:${p.minute}|s${SUGGESTION_ENGINE_VERSION}`;};
|
||||||
function cycleHourFromIso(iso){
|
function cycleHourFromIso(iso){
|
||||||
const d=new Date(iso);
|
const d=new Date(iso);
|
||||||
if(isNaN(d))return null;
|
if(isNaN(d))return null;
|
||||||
const p=partsInLocalTime(d);return `${p.year}-${p.month}-${p.day}T${p.hour}:${p.minute}|v${SUGGESTION_ENGINE_VERSION}`;
|
const p=partsInLocalTime(d);return `${p.year}-${p.month}-${p.day}T${p.hour}:${p.minute}|s${SUGGESTION_ENGINE_VERSION}`;
|
||||||
}
|
}
|
||||||
const nowIso = () => new Date().toISOString();
|
const nowIso = () => new Date().toISOString();
|
||||||
const cycleIso = () => SIM_DAY ? new Date(SIM_DAY+"T12:00:00Z").toISOString() : nowIso();
|
const cycleIso = () => SIM_DAY ? new Date(SIM_DAY+"T12:00:00Z").toISOString() : nowIso();
|
||||||
@@ -1298,7 +1304,33 @@ function generateSuggestions(markets,total=SUGGESTION_TOTAL,perCategory=SUGGESTI
|
|||||||
|
|
||||||
/* ---------- Multi-agent store ---------- */
|
/* ---------- Multi-agent store ---------- */
|
||||||
function defaultPortfolio(){return {cash:STARTING_BALANCE,starting_balance:STARTING_BALANCE,positions:[],closed:[],history:[],snapshots:[],stopped:{},lastDecision:null};}
|
function defaultPortfolio(){return {cash:STARTING_BALANCE,starting_balance:STARTING_BALANCE,positions:[],closed:[],history:[],snapshots:[],stopped:{},lastDecision:null};}
|
||||||
function defaultState(){const agents={};AGENTS.forEach(a=>agents[a.id]=defaultPortfolio());return {date:null,last_run:null,last_cycle_hour:null,engine_version:SUGGESTION_ENGINE_VERSION,engine_started_at:nowIso(),agents,signal_ledger:defaultSignalLedger(),seeded:false};}
|
function defaultState(){const agents={};AGENTS.forEach(a=>agents[a.id]=defaultPortfolio());return {date:null,last_run:null,last_cycle_hour:null,
|
||||||
|
engine_version:BUILD_VERSION,strategy_version:SUGGESTION_ENGINE_VERSION,engine_started_at:nowIso(),build_started_at:nowIso(),agents,signal_ledger:defaultSignalLedger(),seeded:false};}
|
||||||
|
function reconcileStateVersions(st){
|
||||||
|
let migrated=false;
|
||||||
|
const storedBuild=Number(st.engine_version||0);
|
||||||
|
const storedStrategy=normalizedStrategyVersion(st.strategy_version!=null?st.strategy_version:storedBuild);
|
||||||
|
const strategyChanged=storedStrategy!==SUGGESTION_ENGINE_VERSION;
|
||||||
|
const started=strategyChanged?nowIso():(st.strategy_started_at||st.engine_started_at||nowIso());
|
||||||
|
AGENTS.forEach(a=>{
|
||||||
|
const p=st.agents[a.id],eq=Number(p.cash||0)+(p.positions||[]).reduce((sum,pos)=>sum+Number(pos.value||Number(pos.shares||0)*Number(pos.current_price||0)),0);
|
||||||
|
const baselineStrategy=normalizedStrategyVersion(p.engine_baseline&&p.engine_baseline.version);
|
||||||
|
if(strategyChanged||!p.engine_baseline||baselineStrategy!==SUGGESTION_ENGINE_VERSION){
|
||||||
|
p.engine_baseline={version:SUGGESTION_ENGINE_VERSION,started_at:started,equity:+eq.toFixed(2)};
|
||||||
|
migrated=true;
|
||||||
|
}else if(p.engine_baseline.version!==SUGGESTION_ENGINE_VERSION){p.engine_baseline.version=SUGGESTION_ENGINE_VERSION;migrated=true;}
|
||||||
|
});
|
||||||
|
if(strategyChanged||st.strategy_version!==SUGGESTION_ENGINE_VERSION||storedBuild!==BUILD_VERSION){
|
||||||
|
st.previous_engine_version=storedBuild||null;
|
||||||
|
st.engine_version=BUILD_VERSION;
|
||||||
|
st.strategy_version=SUGGESTION_ENGINE_VERSION;
|
||||||
|
st.engine_started_at=started;
|
||||||
|
st.strategy_started_at=started;
|
||||||
|
st.build_started_at=nowIso();
|
||||||
|
migrated=true;
|
||||||
|
}
|
||||||
|
return migrated;
|
||||||
|
}
|
||||||
function loadState(){
|
function loadState(){
|
||||||
let st; try{st=JSON.parse(localStorage.getItem(AGENTS_KEY));}catch(e){st=null;}
|
let st; try{st=JSON.parse(localStorage.getItem(AGENTS_KEY));}catch(e){st=null;}
|
||||||
if(!st||!st.agents)st=defaultState();
|
if(!st||!st.agents)st=defaultState();
|
||||||
@@ -1313,17 +1345,7 @@ function loadState(){
|
|||||||
if(!st.agents[a.id].stopped)st.agents[a.id].stopped={};
|
if(!st.agents[a.id].stopped)st.agents[a.id].stopped={};
|
||||||
if(!("lastDecision" in st.agents[a.id]))st.agents[a.id].lastDecision=null;
|
if(!("lastDecision" in st.agents[a.id]))st.agents[a.id].lastDecision=null;
|
||||||
});
|
});
|
||||||
if(st.engine_version!==SUGGESTION_ENGINE_VERSION){
|
migrated=reconcileStateVersions(st)||migrated;
|
||||||
const started=nowIso();
|
|
||||||
st.previous_engine_version=st.engine_version||null;
|
|
||||||
st.engine_version=SUGGESTION_ENGINE_VERSION;
|
|
||||||
st.engine_started_at=started;
|
|
||||||
AGENTS.forEach(a=>{
|
|
||||||
const p=st.agents[a.id],eq=Number(p.cash||0)+(p.positions||[]).reduce((sum,pos)=>sum+Number(pos.value||Number(pos.shares||0)*Number(pos.current_price||0)),0);
|
|
||||||
p.engine_baseline={version:SUGGESTION_ENGINE_VERSION,started_at:started,equity:+eq.toFixed(2)};
|
|
||||||
});
|
|
||||||
migrated=true;
|
|
||||||
}
|
|
||||||
if(!st.last_cycle_hour&&st.last_run)st.last_cycle_hour=cycleHourFromIso(st.last_run);
|
if(!st.last_cycle_hour&&st.last_run)st.last_cycle_hour=cycleHourFromIso(st.last_run);
|
||||||
if(migrated)localStorage.setItem(AGENTS_KEY,JSON.stringify(compactAgentStateForSync(st)));
|
if(migrated)localStorage.setItem(AGENTS_KEY,JSON.stringify(compactAgentStateForSync(st)));
|
||||||
return st;
|
return st;
|
||||||
@@ -1391,7 +1413,7 @@ function compactSyncItems(items,limits=SYNC_LIMITS){
|
|||||||
}
|
}
|
||||||
function saveState(st){localStorage.setItem(AGENTS_KEY,JSON.stringify(compactAgentStateForSync(st)));}
|
function saveState(st){localStorage.setItem(AGENTS_KEY,JSON.stringify(compactAgentStateForSync(st)));}
|
||||||
function loadSuggestions(){try{const s=localStorage.getItem(SUG_KEY);return s?JSON.parse(s):{date:null,suggestions:[]};}catch(e){return {date:null,suggestions:[]};}}
|
function loadSuggestions(){try{const s=localStorage.getItem(SUG_KEY);return s?JSON.parse(s):{date:null,suggestions:[]};}catch(e){return {date:null,suggestions:[]};}}
|
||||||
function saveSuggestions(sugs,marketCount=0,analyzedCount=null){const p={date:todayStr(),generated_at:nowIso(),engine_version:SUGGESTION_ENGINE_VERSION,market_count:marketCount,analyzed_count:analyzedCount==null?marketCount:analyzedCount,analysis_limit:MARKET_ANALYSIS_LIMIT,suggestion_cap:SUGGESTION_TOTAL,suggestions:sugs};const compact=compactSuggestionsForSync(p);localStorage.setItem(SUG_KEY,JSON.stringify(compact));return compact;}
|
function saveSuggestions(sugs,marketCount=0,analyzedCount=null){const p={date:todayStr(),generated_at:nowIso(),engine_version:BUILD_VERSION,strategy_version:SUGGESTION_ENGINE_VERSION,market_count:marketCount,analyzed_count:analyzedCount==null?marketCount:analyzedCount,analysis_limit:MARKET_ANALYSIS_LIMIT,suggestion_cap:SUGGESTION_TOTAL,suggestions:sugs};const compact=compactSuggestionsForSync(p);localStorage.setItem(SUG_KEY,JSON.stringify(compact));return compact;}
|
||||||
function compactCachedMarket(m){
|
function compactCachedMarket(m){
|
||||||
return {id:m.id,question:m.question,event:m.event,url:m.url,category:m.category,tags:m.tags,
|
return {id:m.id,question:m.question,event:m.event,url:m.url,category:m.category,tags:m.tags,
|
||||||
clob_token_ids:m.clob_token_ids,yes_price:m.yes_price,no_price:m.no_price,volume:m.volume,
|
clob_token_ids:m.clob_token_ids,yes_price:m.yes_price,no_price:m.no_price,volume:m.volume,
|
||||||
@@ -1401,7 +1423,7 @@ function compactCachedMarket(m){
|
|||||||
days_to_resolution:m.days_to_resolution,end_date:m.end_date,closed:m.closed,accepting_orders:m.accepting_orders};
|
days_to_resolution:m.days_to_resolution,end_date:m.end_date,closed:m.closed,accepting_orders:m.accepting_orders};
|
||||||
}
|
}
|
||||||
function saveMarketCache(markets,suggestions,priceMap={}){
|
function saveMarketCache(markets,suggestions,priceMap={}){
|
||||||
const payload={version:SUGGESTION_ENGINE_VERSION,captured_at:nowIso(),markets:(markets||[]).slice(0,MARKET_ANALYSIS_LIMIT).map(compactCachedMarket),
|
const payload={version:BUILD_VERSION,strategy_version:SUGGESTION_ENGINE_VERSION,captured_at:nowIso(),markets:(markets||[]).slice(0,MARKET_ANALYSIS_LIMIT).map(compactCachedMarket),
|
||||||
suggestions:compactSuggestionsForSync({suggestions:suggestions||[]}).suggestions,price_map:{}};
|
suggestions:compactSuggestionsForSync({suggestions:suggestions||[]}).suggestions,price_map:{}};
|
||||||
Object.entries(priceMap||{}).forEach(([id,m])=>{if(m)payload.price_map[id]=compactCachedMarket(m);});
|
Object.entries(priceMap||{}).forEach(([id,m])=>{if(m)payload.price_map[id]=compactCachedMarket(m);});
|
||||||
try{localStorage.setItem(MARKET_CACHE_KEY,JSON.stringify(payload));return payload;}catch(e){return null;}
|
try{localStorage.setItem(MARKET_CACHE_KEY,JSON.stringify(payload));return payload;}catch(e){return null;}
|
||||||
@@ -1622,7 +1644,7 @@ function updateSignalLedger(st,markets,suggestions){
|
|||||||
const key=`${s.market_id}:${s.side}:${bucket}`;if(existing.has(key))continue;
|
const key=`${s.market_id}:${s.side}:${bucket}`;if(existing.has(key))continue;
|
||||||
existing.add(key);stillPending.push({key,market_id:String(s.market_id),observed_at:nowIso(),side:s.side,entry_price:Number(s.entry_price),
|
existing.add(key);stillPending.push({key,market_id:String(s.market_id),observed_at:nowIso(),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),
|
||||||
strategy_version:SUGGESTION_ENGINE_VERSION});
|
strategy_version:SUGGESTION_ENGINE_VERSION,build_version:BUILD_VERSION});
|
||||||
}
|
}
|
||||||
ledger.pending=stillPending.slice(-SIGNAL_LEDGER_PENDING_LIMIT);
|
ledger.pending=stillPending.slice(-SIGNAL_LEDGER_PENDING_LIMIT);
|
||||||
ledger.outcomes=ledger.outcomes.slice(-SIGNAL_LEDGER_OUTCOME_LIMIT);
|
ledger.outcomes=ledger.outcomes.slice(-SIGNAL_LEDGER_OUTCOME_LIMIT);
|
||||||
@@ -1631,7 +1653,7 @@ function updateSignalLedger(st,markets,suggestions){
|
|||||||
function buildSignalCalibration(ledger){
|
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=Number(outcome.strategy_version||0);
|
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===SUGGESTION_ENGINE_VERSION-1?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;
|
||||||
@@ -1641,7 +1663,7 @@ function buildSignalCalibration(ledger){
|
|||||||
const learned=Object.fromEntries(Object.entries(buckets).map(([key,b])=>[key,summarizeLearningBucket(b,12)]));
|
const learned=Object.fromEntries(Object.entries(buckets).map(([key,b])=>[key,summarizeLearningBucket(b,12)]));
|
||||||
const learnedRows=Object.values(learned);
|
const learnedRows=Object.values(learned);
|
||||||
return {version:SUGGESTION_ENGINE_VERSION,samples:((ledger&&ledger.outcomes)||[]).length,
|
return {version:SUGGESTION_ENGINE_VERSION,samples:((ledger&&ledger.outcomes)||[]).length,
|
||||||
current_samples:((ledger&&ledger.outcomes)||[]).filter(x=>Number(x.strategy_version||0)===SUGGESTION_ENGINE_VERSION).length,buckets:learned,
|
current_samples:((ledger&&ledger.outcomes)||[]).filter(x=>normalizedStrategyVersion(x.strategy_version)===SUGGESTION_ENGINE_VERSION).length,buckets:learned,
|
||||||
promoted_buckets:learnedRows.filter(r=>r.weight>=8&&r.lower_bound>0.003).length,
|
promoted_buckets:learnedRows.filter(r=>r.weight>=8&&r.lower_bound>0.003).length,
|
||||||
demoted_buckets:learnedRows.filter(r=>r.weight>=8&&r.upper_bound<-0.003).length,
|
demoted_buckets:learnedRows.filter(r=>r.weight>=8&&r.upper_bound<-0.003).length,
|
||||||
pending:((ledger&&ledger.pending)||[]).length};
|
pending:((ledger&&ledger.pending)||[]).length};
|
||||||
@@ -1669,7 +1691,7 @@ function tradeReturnForLearning(trade,closed){
|
|||||||
function buildAdaptiveProfile(p){
|
function buildAdaptiveProfile(p){
|
||||||
const buckets={},observations=[],currentClosedObservations=[],currentClosedReturns=[];
|
const buckets={},observations=[],currentClosedObservations=[],currentClosedReturns=[];
|
||||||
const add=(trade,closed)=>{
|
const add=(trade,closed)=>{
|
||||||
const version=Number(trade.strategy_version||0);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===SUGGESTION_ENGINE_VERSION-1?0.45:0.20);
|
||||||
@@ -1692,7 +1714,7 @@ function buildAdaptiveProfile(p){
|
|||||||
const currentClosedSum=currentClosedObservations.reduce((s,x)=>s+x.ret*x.weight,0);
|
const currentClosedSum=currentClosedObservations.reduce((s,x)=>s+x.ret*x.weight,0);
|
||||||
const ranked=Object.entries(learned).filter(([k,v])=>!k.startsWith("side:")&&v.weight>=1)
|
const ranked=Object.entries(learned).filter(([k,v])=>!k.startsWith("side:")&&v.weight>=1)
|
||||||
.sort((a,b)=>b[1].score-a[1].score);
|
.sort((a,b)=>b[1].score-a[1].score);
|
||||||
return {version:SUGGESTION_ENGINE_VERSION,samples:(p.closed||[]).filter(t=>Number(t.strategy_version||0)>=34).length,
|
return {version:SUGGESTION_ENGINE_VERSION,samples:(p.closed||[]).filter(t=>normalizedStrategyVersion(t.strategy_version)>=34).length,
|
||||||
effective_samples:+totalWeight.toFixed(2),global_score:+globalScore.toFixed(4),buckets:learned,
|
effective_samples:+totalWeight.toFixed(2),global_score:+globalScore.toFixed(4),buckets:learned,
|
||||||
current_samples:currentClosedReturns.length,current_effective_samples:+currentClosedWeight.toFixed(2),
|
current_samples:currentClosedReturns.length,current_effective_samples:+currentClosedWeight.toFixed(2),
|
||||||
current_global_score:+(currentClosedSum/(currentClosedWeight+4)).toFixed(4),
|
current_global_score:+(currentClosedSum/(currentClosedWeight+4)).toFixed(4),
|
||||||
@@ -1946,7 +1968,7 @@ function takeProfitPosition(p,pos,tier){
|
|||||||
detail:`${tier.label} sold 25% of '${pos.question.slice(0,40)}' at ${pct(pos.current_price)} for ${fmtUSD(proceeds)} (realized ${fmtUSD(realizedPnl)})`});
|
detail:`${tier.label} sold 25% of '${pos.question.slice(0,40)}' at ${pct(pos.current_price)} for ${fmtUSD(proceeds)} (realized ${fmtUSD(realizedPnl)})`});
|
||||||
}
|
}
|
||||||
function normalizeLegacyPositionRisk(p,pos,cfg,fresh){
|
function normalizeLegacyPositionRisk(p,pos,cfg,fresh){
|
||||||
if(!cfg||Number(pos.strategy_version||0)>=SUGGESTION_ENGINE_VERSION||!(pos.shares>0)||!(pos.current_price>0))return 0;
|
if(!cfg||normalizedStrategyVersion(pos.strategy_version)>=SUGGESTION_ENGINE_VERSION||!(pos.shares>0)||!(pos.current_price>0))return 0;
|
||||||
const eq=equity(p),riskContext=Object.assign({},fresh||{},pos,{entry_price:pos.entry_price});
|
const eq=equity(p),riskContext=Object.assign({},fresh||{},pos,{entry_price:pos.entry_price});
|
||||||
const riskCap=tradeLossBudgetPct(cfg,riskContext),allowedValue=eq*riskCap,currentValue=Number(pos.shares)*Number(pos.current_price);
|
const riskCap=tradeLossBudgetPct(cfg,riskContext),allowedValue=eq*riskCap,currentValue=Number(pos.shares)*Number(pos.current_price);
|
||||||
if(!(eq>0)||currentValue<=allowedValue*1.10)return 0;
|
if(!(eq>0)||currentValue<=allowedValue*1.10)return 0;
|
||||||
@@ -2229,6 +2251,7 @@ function openPositions(p,cfg,rankedSugs,focus,decision,avoidMarketIds,peerStats=
|
|||||||
original_shares:shares,original_cost:cost,unrealized_pnl:0,conviction:s.conviction,peer_conviction:s.peer_conviction,category:s.category,opened_at:cycleIso(),url:s.url||"",
|
original_shares:shares,original_cost:cost,unrealized_pnl:0,conviction:s.conviction,peer_conviction:s.peer_conviction,category:s.category,opened_at:cycleIso(),url:s.url||"",
|
||||||
peer_note:s.peer_note||"",entry_reason:s.rationale||"",net_edge:s.net_edge,evidence_score:s.evidence_score,evidence_source_count:s.evidence_source_count||0,friction:s.friction,chase_penalty:s.chase_penalty,quality:s.quality,
|
peer_note:s.peer_note||"",entry_reason:s.rationale||"",net_edge:s.net_edge,evidence_score:s.evidence_score,evidence_source_count:s.evidence_source_count||0,friction:s.friction,chase_penalty:s.chase_penalty,quality:s.quality,
|
||||||
strategy_version:SUGGESTION_ENGINE_VERSION,
|
strategy_version:SUGGESTION_ENGINE_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,
|
||||||
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,
|
||||||
@@ -2470,7 +2493,7 @@ function format24h(change){
|
|||||||
function board(){
|
function board(){
|
||||||
const st=loadState();
|
const st=loadState();
|
||||||
return AGENTS.map(c=>{const p=st.agents[c.id]||defaultPortfolio();const eq=equity(p);
|
return AGENTS.map(c=>{const p=st.agents[c.id]||defaultPortfolio();const eq=equity(p);
|
||||||
const baseline=Number(p.engine_baseline&&p.engine_baseline.version===SUGGESTION_ENGINE_VERSION?p.engine_baseline.equity:eq);
|
const baseline=Number(p.engine_baseline&&normalizedStrategyVersion(p.engine_baseline.version)===SUGGESTION_ENGINE_VERSION?p.engine_baseline.equity:eq);
|
||||||
return {c,p,eq,pnl:eq-STARTING_BALANCE,ret:(eq/STARTING_BALANCE-1)*100,enginePnl:eq-baseline,engineRet:baseline>0?(eq/baseline-1)*100:0,change24h:portfolioChange24h(p,eq)};})
|
return {c,p,eq,pnl:eq-STARTING_BALANCE,ret:(eq/STARTING_BALANCE-1)*100,enginePnl:eq-baseline,engineRet:baseline>0?(eq/baseline-1)*100:0,change24h:portfolioChange24h(p,eq)};})
|
||||||
.sort((a,b)=>b.eq-a.eq);
|
.sort((a,b)=>b.eq-a.eq);
|
||||||
}
|
}
|
||||||
@@ -2490,7 +2513,7 @@ function renderOverview(){
|
|||||||
{ic:lead.c.emoji,label:"Leader",value:lead.c.name.split(" ")[0]},
|
{ic:lead.c.emoji,label:"Leader",value:lead.c.name.split(" ")[0]},
|
||||||
{ic:"📈",label:"Leader return",value:fmtPct(lead.ret),cls:signClass(lead.pnl)},
|
{ic:"📈",label:"Leader return",value:fmtPct(lead.ret),cls:signClass(lead.pnl)},
|
||||||
{ic:"⚖️",label:"Legacy / replay avg",value:fmtPct(avgRet),cls:signClass(avgRet)},
|
{ic:"⚖️",label:"Legacy / replay avg",value:fmtPct(avgRet),cls:signClass(avgRet)},
|
||||||
{ic:"🧪",label:`v${SUGGESTION_ENGINE_VERSION} avg`,value:fmtPct(engineAvg),cls:signClass(engineAvg)},
|
{ic:"🧪",label:"Adaptive avg",value:fmtPct(engineAvg),cls:signClass(engineAvg)},
|
||||||
{ic:"🧠",label:"Core strategy avg",value:fmtPct(coreAvg),cls:signClass(coreAvg)},
|
{ic:"🧠",label:"Core strategy avg",value:fmtPct(coreAvg),cls:signClass(coreAvg)},
|
||||||
{ic:"⚡",label:"Aggressive avg",value:fmtPct(aggressiveAvg),cls:signClass(aggressiveAvg)},
|
{ic:"⚡",label:"Aggressive avg",value:fmtPct(aggressiveAvg),cls:signClass(aggressiveAvg)},
|
||||||
{ic:"💡",label:"Scored ideas",value:sugCount},
|
{ic:"💡",label:"Scored ideas",value:sugCount},
|
||||||
@@ -2609,8 +2632,8 @@ function decisionSummary(p){
|
|||||||
const blockerLabels={historical_prior:"history-tested losing setup",learning:"live learned losing regime",confidence:"confidence",overlap:"material overlap",already_held:"already held",cooldown:"stop cooldown",focus:"category focus",price:"entry price",edge:"edge",timing:"timing",liquidity:"liquidity",activity:"activity",evidence:"evidence",direction:"direction",portfolio_limit:"portfolio limit"};
|
const blockerLabels={historical_prior:"history-tested losing setup",learning:"live learned losing regime",confidence:"confidence",overlap:"material overlap",already_held:"already held",cooldown:"stop cooldown",focus:"category focus",price:"entry price",edge:"edge",timing:"timing",liquidity:"liquidity",activity:"activity",evidence:"evidence",direction:"direction",portfolio_limit:"portfolio limit"};
|
||||||
const blockerRows=Object.entries(d.rejectionCounts||{}).filter(([,count])=>count>0).sort((a,b)=>b[1]-a[1]);
|
const blockerRows=Object.entries(d.rejectionCounts||{}).filter(([,count])=>count>0).sort((a,b)=>b[1]-a[1]);
|
||||||
const blockers=blockerRows.length?` Blocks: ${blockerRows.slice(0,4).map(([key,count])=>`${blockerLabels[key]||key} ${count}`).join(", ")}.`:"";
|
const blockers=blockerRows.length?` Blocks: ${blockerRows.slice(0,4).map(([key,count])=>`${blockerLabels[key]||key} ${count}`).join(", ")}.`:"";
|
||||||
const learning=d.learning?` Learning: ${d.learning.samples} completed trades retained with older engines down-weighted, ${(d.learning.global_score*100).toFixed(2)}% shrunk expectancy; ${d.learning.current_samples||0} completed under v${SUGGESTION_ENGINE_VERSION}${d.learning.best?`; strongest ${d.learning.best.feature.replace(":"," ")}`:""}${d.learning.worst?`; weakest ${d.learning.worst.feature.replace(":"," ")}`:""}.`:"";
|
const learning=d.learning?` Learning: ${d.learning.samples} completed trades retained with older strategies down-weighted, ${(d.learning.global_score*100).toFixed(2)}% shrunk expectancy; ${d.learning.current_samples||0} completed under adaptive strategy ${SUGGESTION_ENGINE_VERSION}${d.learning.best?`; strongest ${d.learning.best.feature.replace(":"," ")}`:""}${d.learning.worst?`; weakest ${d.learning.worst.feature.replace(":"," ")}`:""}.`:"";
|
||||||
const calibration=d.marketLearning?` Walk-forward calibration: ${d.marketLearning.samples||0} net-of-cost graded signals (${d.marketLearning.current_samples||0} under v${SUGGESTION_ENGINE_VERSION}), ${d.marketLearning.pending||0} awaiting a future price; ${d.marketLearning.promoted_buckets||0} feature cohorts promoted and ${d.marketLearning.demoted_buckets||0} demoted. Confidence counts independent outcomes once and uncertainty gates sizing. Historical prior: reversal and sports-trend entries require the fixed 15% exploration lane; crypto, longshots, and YES entries are sized down, not forbidden. Politics trends receive 72 hours before ordinary signal exits.`:"";
|
const calibration=d.marketLearning?` Walk-forward calibration: ${d.marketLearning.samples||0} net-of-cost graded signals (${d.marketLearning.current_samples||0} under adaptive strategy ${SUGGESTION_ENGINE_VERSION}), ${d.marketLearning.pending||0} awaiting a future price; ${d.marketLearning.promoted_buckets||0} feature cohorts promoted and ${d.marketLearning.demoted_buckets||0} demoted. Confidence counts independent outcomes once and uncertainty gates sizing. Historical prior: reversal and sports-trend entries require the fixed 15% exploration lane; crypto, longshots, and YES entries are sized down, not forbidden. Politics trends receive 72 hours before ordinary signal exits.`:"";
|
||||||
return `${d.mode} mode: ${d.reason}${emotion} Limits now: ${d.maxNew} new trade${d.maxNew===1?"":"s"}, max ${(d.maxFrac*100).toFixed(1)}% per position${d.minConv?`, conviction ${d.minConv}+`:""}.${learning}${calibration}${exposure}${allocation}${candidates}${blockers}`;
|
return `${d.mode} mode: ${d.reason}${emotion} Limits now: ${d.maxNew} new trade${d.maxNew===1?"":"s"}, max ${(d.maxFrac*100).toFixed(1)}% per position${d.minConv?`, conviction ${d.minConv}+`:""}.${learning}${calibration}${exposure}${allocation}${candidates}${blockers}`;
|
||||||
}
|
}
|
||||||
function renderAgentBrief(cfg,p,st){
|
function renderAgentBrief(cfg,p,st){
|
||||||
@@ -2641,7 +2664,7 @@ function renderLeaderboard(){
|
|||||||
<span class="rankpill">#${i+1}</span>
|
<span class="rankpill">#${i+1}</span>
|
||||||
<div class="lb-top"><span class="medal">${MEDALS[i]||""}</span><span class="lb-emoji">${r.c.emoji}</span>
|
<div class="lb-top"><span class="medal">${MEDALS[i]||""}</span><span class="lb-emoji">${r.c.emoji}</span>
|
||||||
<div><div class="lb-name">${r.c.name}</div><div class="lb-blurb">${agentBlurb(r.c,st)}</div></div></div>
|
<div><div class="lb-name">${r.c.name}</div><div class="lb-blurb">${agentBlurb(r.c,st)}</div></div></div>
|
||||||
<div class="lb-mid"><div class="lb-eq">${fmtUSD(r.eq)}</div><div><div class="lb-ret ${signClass(r.pnl)}">${fmtPct(r.ret)}</div><div class="small ${signClass(r.enginePnl)}">v${SUGGESTION_ENGINE_VERSION} ${fmtPct(r.engineRet)}</div><div class="small ${signClass(r.change24h.pct)}">24h ${format24h(r.change24h)}</div></div></div>
|
<div class="lb-mid"><div class="lb-eq">${fmtUSD(r.eq)}</div><div><div class="lb-ret ${signClass(r.pnl)}">${fmtPct(r.ret)}</div><div class="small ${signClass(r.enginePnl)}">adaptive ${fmtPct(r.engineRet)}</div><div class="small ${signClass(r.change24h.pct)}">24h ${format24h(r.change24h)}</div></div></div>
|
||||||
<div class="lb-foot"><span class="muted small">${r.p.positions.length} open · ${r.p.closed.length} closed</span>${miniSpark(r.p.snapshots,r.c.color)}</div>
|
<div class="lb-foot"><span class="muted small">${r.p.positions.length} open · ${r.p.closed.length} closed</span>${miniSpark(r.p.snapshots,r.c.color)}</div>
|
||||||
</div>`).join("");
|
</div>`).join("");
|
||||||
document.querySelectorAll("#leaderboard .lb-card").forEach(el=>{
|
document.querySelectorAll("#leaderboard .lb-card").forEach(el=>{
|
||||||
@@ -2854,7 +2877,7 @@ function renderPortfolioTab(){
|
|||||||
document.querySelectorAll("#agentSel .segbtn").forEach(el=>el.addEventListener("click",()=>{localStorage.setItem(VIEW_KEY,el.dataset.agent);renderPortfolioTab();}));
|
document.querySelectorAll("#agentSel .segbtn").forEach(el=>el.addEventListener("click",()=>{localStorage.setItem(VIEW_KEY,el.dataset.agent);renderPortfolioTab();}));
|
||||||
const p=st.agents[viewId]||defaultPortfolio();const eq=equity(p),pnl=eq-p.starting_balance;
|
const p=st.agents[viewId]||defaultPortfolio();const eq=equity(p),pnl=eq-p.starting_balance;
|
||||||
const change24h=portfolioChange24h(p,eq);
|
const change24h=portfolioChange24h(p,eq);
|
||||||
const engineBase=Number(p.engine_baseline&&p.engine_baseline.version===SUGGESTION_ENGINE_VERSION?p.engine_baseline.equity:eq),enginePnl=eq-engineBase;
|
const engineBase=Number(p.engine_baseline&&normalizedStrategyVersion(p.engine_baseline.version)===SUGGESTION_ENGINE_VERSION?p.engine_baseline.equity:eq),enginePnl=eq-engineBase;
|
||||||
renderAgentBrief(cfg,p,st);
|
renderAgentBrief(cfg,p,st);
|
||||||
const stats=[
|
const stats=[
|
||||||
{ic:"💰",label:"Equity",value:fmtUSD(eq)},
|
{ic:"💰",label:"Equity",value:fmtUSD(eq)},
|
||||||
@@ -2862,7 +2885,7 @@ function renderPortfolioTab(){
|
|||||||
{ic:"📈",label:"P&L",value:fmtUSD(pnl),cls:signClass(pnl)},
|
{ic:"📈",label:"P&L",value:fmtUSD(pnl),cls:signClass(pnl)},
|
||||||
{ic:"🎯",label:"Return",value:fmtPct((eq/p.starting_balance-1)*100),cls:signClass(pnl)},
|
{ic:"🎯",label:"Return",value:fmtPct((eq/p.starting_balance-1)*100),cls:signClass(pnl)},
|
||||||
{ic:"🕒",label:"24h change",value:format24h(change24h),cls:signClass(change24h.pct)},
|
{ic:"🕒",label:"24h change",value:format24h(change24h),cls:signClass(change24h.pct)},
|
||||||
{ic:"🧪",label:`v${SUGGESTION_ENGINE_VERSION}`,value:fmtPct(engineBase>0?(eq/engineBase-1)*100:0),cls:signClass(enginePnl)},
|
{ic:"🧪",label:"Adaptive",value:fmtPct(engineBase>0?(eq/engineBase-1)*100:0),cls:signClass(enginePnl)},
|
||||||
{ic:"📂",label:"Open",value:p.positions.length},
|
{ic:"📂",label:"Open",value:p.positions.length},
|
||||||
];
|
];
|
||||||
$("statsPf").innerHTML=stats.map(s=>`<div class="stat"><div class="ic">${s.ic}</div><div class="label">${s.label}</div><div class="value ${s.cls||""}">${s.value}</div></div>`).join("");
|
$("statsPf").innerHTML=stats.map(s=>`<div class="stat"><div class="ic">${s.ic}</div><div class="label">${s.label}</div><div class="value ${s.cls||""}">${s.value}</div></div>`).join("");
|
||||||
@@ -4167,6 +4190,7 @@ document.querySelectorAll(".tab").forEach(t=>t.addEventListener("click",()=>show
|
|||||||
window.addEventListener("hashchange",()=>showTab(location.hash.slice(1)));
|
window.addEventListener("hashchange",()=>showTab(location.hash.slice(1)));
|
||||||
|
|
||||||
window.PMA_ENGINE_DIAGNOSTICS=Object.freeze({
|
window.PMA_ENGINE_DIAGNOSTICS=Object.freeze({
|
||||||
|
build_version:BUILD_VERSION,
|
||||||
version:SUGGESTION_ENGINE_VERSION,
|
version:SUGGESTION_ENGINE_VERSION,
|
||||||
analyzeMarket,
|
analyzeMarket,
|
||||||
buildAdaptiveProfile,
|
buildAdaptiveProfile,
|
||||||
@@ -4182,7 +4206,7 @@ window.PMA_ENGINE_DIAGNOSTICS=Object.freeze({
|
|||||||
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,
|
||||||
networkTimeoutSeconds:NETWORK_REQUEST_TIMEOUT_MS/1000,priceTimeoutSeconds:PRICE_REQUEST_TIMEOUT_MS/1000,
|
networkTimeoutSeconds:NETWORK_REQUEST_TIMEOUT_MS/1000,priceTimeoutSeconds:PRICE_REQUEST_TIMEOUT_MS/1000,
|
||||||
staleCacheIsMarkOnly:true,signalRoundTripCostCents:SIGNAL_ROUND_TRIP_COST*100,independentConfidence:true,uncertaintyGatedCalibration:true,
|
staleCacheIsMarkOnly:true,strategyEvidenceSurvivesBuilds:true,signalRoundTripCostCents:SIGNAL_ROUND_TRIP_COST*100,independentConfidence:true,uncertaintyGatedCalibration:true,
|
||||||
historicalPrior:"reversal and sports trends blocked outside exploration; crypto, longshots, and YES sized down"}),
|
historicalPrior:"reversal and sports trends blocked outside exploration; crypto, longshots, and YES sized down"}),
|
||||||
});
|
});
|
||||||
function runEngineSelfTest(){
|
function runEngineSelfTest(){
|
||||||
@@ -4235,6 +4259,8 @@ function runEngineSelfTest(){
|
|||||||
const stablePositiveCalibration=calibratedOpportunity(calibrationCandidate,calibrationFromReturns(Array(24).fill(0.12)));
|
const stablePositiveCalibration=calibratedOpportunity(calibrationCandidate,calibrationFromReturns(Array(24).fill(0.12)));
|
||||||
const stableNegativeCalibration=calibratedOpportunity(calibrationCandidate,calibrationFromReturns(Array(24).fill(-0.12)));
|
const stableNegativeCalibration=calibratedOpportunity(calibrationCandidate,calibrationFromReturns(Array(24).fill(-0.12)));
|
||||||
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,
|
||||||
|
{strategy_version:41,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});
|
||||||
@@ -4277,7 +4303,11 @@ 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});
|
||||||
return {version:SUGGESTION_ENGINE_VERSION,
|
const lineageMigrationState=defaultState();
|
||||||
|
lineageMigrationState.engine_version=41;delete lineageMigrationState.strategy_version;
|
||||||
|
lineageMigrationState.agents.value.engine_baseline={version:41,started_at:hoursAgo(2),equity:9876.54};
|
||||||
|
reconcileStateVersions(lineageMigrationState);
|
||||||
|
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},
|
||||||
reversal:{ready:reversal.trade_ready,quality:reversal.quality,side:reversal.side,margin:reversal.net_edge},
|
reversal:{ready:reversal.trade_ready,quality:reversal.quality,side:reversal.side,margin:reversal.net_edge},
|
||||||
@@ -4291,6 +4321,10 @@ function runEngineSelfTest(){
|
|||||||
ledgerMaturesWithoutLookahead:ledgerState.signal_ledger.pending.length===0&&ledgerState.signal_ledger.outcomes.length===1&&ledgerState.signal_ledger.outcomes[0].return===0.2375,
|
ledgerMaturesWithoutLookahead:ledgerState.signal_ledger.pending.length===0&&ledgerState.signal_ledger.outcomes.length===1&&ledgerState.signal_ledger.outcomes[0].return===0.2375,
|
||||||
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,
|
||||||
|
sameStrategyBuildKeepsFullWeight:legacyBuildCalibration.current_samples===1&&legacyBuildCalibration.buckets["signal:trend"].weight===1,
|
||||||
|
baselineSurvivesBuildMigration:lineageMigrationState.agents.value.engine_baseline.equity===9876.54&&lineageMigrationState.agents.value.engine_baseline.version===SUGGESTION_ENGINE_VERSION,
|
||||||
|
buildMetadataAdvancesWithoutStrategyReset:lineageMigrationState.engine_version===BUILD_VERSION&&lineageMigrationState.strategy_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,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const CACHE_NAME = "polymarket-arena-v41";
|
const CACHE_NAME = "polymarket-arena-build-42";
|
||||||
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