mirror of
https://github.com/theodore-song/polymarket-analyst.git
synced 2026-08-24 04:58:08 +00:00
Retire failed maker capital path
This commit is contained in:
@@ -151,19 +151,24 @@ passed the chronological path screen at 25% of the present reward estimate, but
|
|||||||
both did so without an adverse historical touch; this prioritizes shadow
|
both did so without an adverse historical touch; this prioritizes shadow
|
||||||
research and does not authorize capital.
|
research and does not authorize capital.
|
||||||
|
|
||||||
Maker research version 2 lets all ten agents split distinct zero-capital shadow
|
Maker research version 3 lets all ten agents split distinct zero-capital shadow
|
||||||
quote pairs selected by the shared reward-book audit. Token histories are fetched
|
quote pairs selected by the shared reward-book audit. Token histories are fetched
|
||||||
in batches, so the learner no longer silently ignores quotes after the first ten
|
in batches, so the learner no longer silently ignores quotes after the first ten
|
||||||
markets. A later live
|
markets. A live cycle must still verify each touch from public CLOB price history
|
||||||
cycle must still verify each touch from public CLOB price history or a current
|
or a current book cross. After the first one-sided touch, the shadow engine now
|
||||||
book cross. A one-hour executable exit grades one-sided touches after a
|
buys the complement only when the current executable ask locks a positive margin
|
||||||
conservative half-cent cost, while paired touches and unfilled attempts are also
|
after modeled cost; otherwise it grades an immediate executable exit. It no
|
||||||
retained in one shared cross-agent ledger and clustered by Polymarket event. Capital exposure can only
|
longer waits with adverse one-sided shadow inventory.
|
||||||
resume after at least 20 current-strategy event clusters in the matching
|
|
||||||
category, spread, and estimated reward-yield cohorts have positive 90% confidence
|
The August 21 expanded audit loaded both token histories for all 500 requested
|
||||||
bounds and at least three distinct-event completed pairs, with any mature losing cohort acting as a veto. There is
|
markets, formed 7,335 observations, and tested 6,048 wait and immediate-hedge
|
||||||
no capital-backed exploration lane. Existing paper inventory from prior builds
|
rules. Zero passed training, validation, or untouched holdout. The separate
|
||||||
is still reconciled honestly. The engine does not credit hypothetical rewards.
|
reward-assisted stress test also found zero passing candidates. Maker capital is
|
||||||
|
therefore disabled even if a small live cohort appears positive; those outcomes
|
||||||
|
remain research evidence and cannot override the failed independent backtest.
|
||||||
|
Existing paper inventory from prior maker versions is still reconciled honestly.
|
||||||
|
There is no capital-backed exploration lane, and the engine does not credit
|
||||||
|
hypothetical rewards.
|
||||||
See Polymarket's official [fees](https://docs.polymarket.com/trading/fees),
|
See Polymarket's official [fees](https://docs.polymarket.com/trading/fees),
|
||||||
[maker rebates](https://docs.polymarket.com/market-makers/maker-rebates), and
|
[maker rebates](https://docs.polymarket.com/market-makers/maker-rebates), and
|
||||||
[liquidity rewards](https://docs.polymarket.com/market-makers/liquidity-rewards)
|
[liquidity rewards](https://docs.polymarket.com/market-makers/liquidity-rewards)
|
||||||
@@ -364,6 +369,13 @@ personal cohort or increase current risk. Forward directional evidence from
|
|||||||
Strategies 51-59 remains compatible because the signal and checkpoint policy
|
Strategies 51-59 remains compatible because the signal and checkpoint policy
|
||||||
did not change.
|
did not change.
|
||||||
|
|
||||||
|
Build 84 retires maker capital after the expanded 500-market audit found zero
|
||||||
|
validated winners among 6,048 wait and immediate-hedge rules. New maker work is
|
||||||
|
zero-capital lock-or-exit research: after one resting bid touches, the engine
|
||||||
|
records a complementary hedge only when the current executable ask locks a net
|
||||||
|
profit; otherwise it grades an immediate exit. A positive in-app cohort cannot
|
||||||
|
reactivate capital without a separately approved chronological backtest.
|
||||||
|
|
||||||
Build 77 separates the directional learner's evidence lineage from the global
|
Build 77 separates the directional learner's evidence lineage from the global
|
||||||
strategy release. Code-history verification found the same trend/reversal
|
strategy release. Code-history verification found the same trend/reversal
|
||||||
generator and 24-hour/72-hour grading policy in Strategy 51 through Strategy
|
generator and 24-hour/72-hour grading policy in Strategy 51 through Strategy
|
||||||
|
|||||||
+49
-21
@@ -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 59 · agent learning 3 · build 83</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 59 · maker research 3 · agent learning 3 · build 84</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 83 active:</b> Strategy 59 removes two verified return leaks. The current 300-market replay hard-blocks favorite-priced directional trends after they remained net-negative across 6h, 12h, 24h, and 72h windows, and only Strategy 59 closed trades can now alter Strategy 59 position sizing. Older trades remain historical context, not permission to increase risk. Forward observations, agent-specific calibration, and offline reconstruction continue unchanged. This remains paper trading; profits are not guaranteed.</div>
|
<div class="live-build-banner"><b>Build 84 active:</b> Maker capital is retired after 6,048 wait and immediate-hedge rules produced no validated winner. New maker work is zero-capital lock-or-exit research: a one-sided touch is hedged only when the executable complement locks a net profit, otherwise it is graded as an immediate exit. Strategy 59 directional adaptation still uses only current-strategy closed trades. 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 83 · Adaptive strategy 59 · Agent learning 3 · Paper trading only · Live prices from Polymarket's public Gamma and CLOB APIs · Not financial advice ·
|
Build 84 · Adaptive strategy 59 · Maker research 3 · Agent learning 3 · Paper trading only · Live prices from Polymarket's public Gamma and CLOB APIs · Not financial advice ·
|
||||||
<a class="market-link" href="https://github.com/theodore-song/polymarket-analyst" target="_blank" rel="noopener">Source on GitHub</a>
|
<a class="market-link" href="https://github.com/theodore-song/polymarket-analyst" target="_blank" rel="noopener">Source on GitHub</a>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
@@ -774,10 +774,10 @@ 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 = 83;
|
const BUILD_VERSION = 84;
|
||||||
const AGENT_LEARNING_VERSION = 3;
|
const AGENT_LEARNING_VERSION = 3;
|
||||||
const SUGGESTION_ENGINE_VERSION = 59;
|
const SUGGESTION_ENGINE_VERSION = 59;
|
||||||
const MAKER_STRATEGY_VERSION = 2;
|
const MAKER_STRATEGY_VERSION = 3;
|
||||||
const PREVIOUS_STRATEGY_VERSION = 58;
|
const PREVIOUS_STRATEGY_VERSION = 58;
|
||||||
const DIRECTIONAL_SIGNAL_POLICY_VERSION = 1;
|
const DIRECTIONAL_SIGNAL_POLICY_VERSION = 1;
|
||||||
const DIRECTIONAL_SIGNAL_COMPATIBLE_STRATEGY_MIN = 51;
|
const DIRECTIONAL_SIGNAL_COMPATIBLE_STRATEGY_MIN = 51;
|
||||||
@@ -1288,6 +1288,7 @@ const MAKER_OUTCOME_LIMIT=240;
|
|||||||
const MAKER_MIN_COHORT_ATTEMPTS=20;
|
const MAKER_MIN_COHORT_ATTEMPTS=20;
|
||||||
const MAKER_MIN_PROMOTION_LOCKS=3;
|
const MAKER_MIN_PROMOTION_LOCKS=3;
|
||||||
const MAKER_TOUCH_FIDELITY_MINUTES=1;
|
const MAKER_TOUCH_FIDELITY_MINUTES=1;
|
||||||
|
const MAKER_CAPITAL_BACKTEST_APPROVED=false;
|
||||||
const clamp=(x,a,b)=>Math.max(a,Math.min(b,x));
|
const clamp=(x,a,b)=>Math.max(a,Math.min(b,x));
|
||||||
function liquiditySignal(m){const vol=Math.min(1,Math.log10(m.volume+1)/6.0);const liq=Math.min(1,Math.log10(m.liquidity+1)/5.3);return 0.6*vol+0.4*liq;}
|
function liquiditySignal(m){const vol=Math.min(1,Math.log10(m.volume+1)/6.0);const liq=Math.min(1,Math.log10(m.liquidity+1)/5.3);return 0.6*vol+0.4*liq;}
|
||||||
function momentumSignal(m){const da=m.volume_1wk?m.volume_1wk/7:0;if(da<=0)return m.volume_24hr>0?0.3:0;return clamp((m.volume_24hr/da-0.5)/2.0,0,1);}
|
function momentumSignal(m){const da=m.volume_1wk?m.volume_1wk/7:0;if(da<=0)return m.volume_24hr>0?0.3:0;return clamp((m.volume_24hr/da-0.5)/2.0,0,1);}
|
||||||
@@ -2718,8 +2719,9 @@ function summarizeMakerOutcomes(rows){
|
|||||||
const clusters=new Map();
|
const clusters=new Map();
|
||||||
weighted.forEach(row=>{const cluster=clusters.get(row.eventKey)||{weighted:0,weight:0,evidenceWeight:0,current:false,locked:false,currentLocked:false};
|
weighted.forEach(row=>{const cluster=clusters.get(row.eventKey)||{weighted:0,weight:0,evidenceWeight:0,current:false,locked:false,currentLocked:false};
|
||||||
cluster.weighted+=row.value*row.weight;cluster.weight+=row.weight;cluster.evidenceWeight=Math.max(cluster.evidenceWeight,row.weight);
|
cluster.weighted+=row.value*row.weight;cluster.weight+=row.weight;cluster.evidenceWeight=Math.max(cluster.evidenceWeight,row.weight);
|
||||||
cluster.current=cluster.current||row.current;cluster.locked=cluster.locked||row.status==="locked";
|
const locked=row.status==="locked"||row.status==="hedged-lock";
|
||||||
cluster.currentLocked=cluster.currentLocked||(row.current&&row.status==="locked");clusters.set(row.eventKey,cluster);});
|
cluster.current=cluster.current||row.current;cluster.locked=cluster.locked||locked;
|
||||||
|
cluster.currentLocked=cluster.currentLocked||(row.current&&locked);clusters.set(row.eventKey,cluster);});
|
||||||
const evidence=[...clusters.values()].map(cluster=>({value:cluster.weighted/Math.max(0.01,cluster.weight),weight:cluster.evidenceWeight,
|
const evidence=[...clusters.values()].map(cluster=>({value:cluster.weighted/Math.max(0.01,cluster.weight),weight:cluster.evidenceWeight,
|
||||||
current:cluster.current,locked:cluster.locked,currentLocked:cluster.currentLocked}));
|
current:cluster.current,locked:cluster.locked,currentLocked:cluster.currentLocked}));
|
||||||
const totalWeight=evidence.reduce((sum,row)=>sum+row.weight,0),attempts=weighted.length;
|
const totalWeight=evidence.reduce((sum,row)=>sum+row.weight,0),attempts=weighted.length;
|
||||||
@@ -2727,9 +2729,10 @@ function summarizeMakerOutcomes(rows){
|
|||||||
const variance=totalWeight?evidence.reduce((sum,row)=>sum+row.weight*(row.value-mean)**2,0)/totalWeight:0;
|
const variance=totalWeight?evidence.reduce((sum,row)=>sum+row.weight*(row.value-mean)**2,0)/totalWeight:0;
|
||||||
const margin=evidence.length>1?1.645*Math.sqrt(variance/Math.max(1,totalWeight)):1;
|
const margin=evidence.length>1?1.645*Math.sqrt(variance/Math.max(1,totalWeight)):1;
|
||||||
return {attempts,events:evidence.length,current_events:evidence.filter(row=>row.current).length,effective_attempts:+totalWeight.toFixed(2),
|
return {attempts,events:evidence.length,current_events:evidence.filter(row=>row.current).length,effective_attempts:+totalWeight.toFixed(2),
|
||||||
locked:weighted.filter(row=>row.status==="locked").length,current_locked:weighted.filter(row=>row.current&&row.status==="locked").length,
|
locked:weighted.filter(row=>row.status==="locked"||row.status==="hedged-lock").length,
|
||||||
|
current_locked:weighted.filter(row=>row.current&&(row.status==="locked"||row.status==="hedged-lock")).length,
|
||||||
locked_events:evidence.filter(row=>row.locked).length,current_locked_events:evidence.filter(row=>row.currentLocked).length,
|
locked_events:evidence.filter(row=>row.locked).length,current_locked_events:evidence.filter(row=>row.currentLocked).length,
|
||||||
adverse:weighted.filter(row=>row.status==="single-exit").length,unfilled:weighted.filter(row=>row.status==="unfilled").length,
|
adverse:weighted.filter(row=>row.status==="single-exit"||row.status==="immediate-exit").length,unfilled:weighted.filter(row=>row.status==="unfilled").length,
|
||||||
pnl:+(rows||[]).filter(row=>!row.shadow_only).reduce((sum,row)=>sum+Number(row.pnl||0),0).toFixed(2),
|
pnl:+(rows||[]).filter(row=>!row.shadow_only).reduce((sum,row)=>sum+Number(row.pnl||0),0).toFixed(2),
|
||||||
shadow_pnl:+(rows||[]).filter(row=>row.shadow_only).reduce((sum,row)=>sum+Number(row.pnl||0),0).toFixed(2),mean:+mean.toFixed(5),
|
shadow_pnl:+(rows||[]).filter(row=>row.shadow_only).reduce((sum,row)=>sum+Number(row.pnl||0),0).toFixed(2),mean:+mean.toFixed(5),
|
||||||
lower:+(mean-margin).toFixed(5),upper:+(mean+margin).toFixed(5),confidence:+(totalWeight/(totalWeight+8)).toFixed(4)};
|
lower:+(mean-margin).toFixed(5),upper:+(mean+margin).toFixed(5),confidence:+(totalWeight/(totalWeight+8)).toFixed(4)};
|
||||||
@@ -2750,15 +2753,16 @@ function makerCandidateLearning(candidate,profile){
|
|||||||
const category=profile.buckets[`category:${candidate.category}`],spread=profile.buckets[`spread:${makerSpreadBand(candidate.spread)}`];
|
const category=profile.buckets[`category:${candidate.category}`],spread=profile.buckets[`spread:${makerSpreadBand(candidate.spread)}`];
|
||||||
const rewardBand=candidate.reward_yield_band||makerRewardBand(candidate),reward=profile.buckets[`reward:${rewardBand}`];
|
const rewardBand=candidate.reward_yield_band||makerRewardBand(candidate),reward=profile.buckets[`reward:${rewardBand}`];
|
||||||
const matching=[profile.global,category,spread,reward].filter(Boolean),mature=matching.filter(stats=>stats.current_events>=MAKER_MIN_COHORT_ATTEMPTS);
|
const matching=[profile.global,category,spread,reward].filter(Boolean),mature=matching.filter(stats=>stats.current_events>=MAKER_MIN_COHORT_ATTEMPTS);
|
||||||
const losing=mature.some(stats=>stats.upper<0),promoted=!losing&&category&&spread&&[category,spread].every(stats=>
|
const losing=mature.some(stats=>stats.upper<0),evidencePromoted=!losing&&category&&spread&&[category,spread].every(stats=>
|
||||||
stats.current_events>=MAKER_MIN_COHORT_ATTEMPTS&&stats.current_locked_events>=MAKER_MIN_PROMOTION_LOCKS&&stats.lower>0)
|
stats.current_events>=MAKER_MIN_COHORT_ATTEMPTS&&stats.current_locked_events>=MAKER_MIN_PROMOTION_LOCKS&&stats.lower>0)
|
||||||
&&reward&&reward.current_events>=MAKER_MIN_COHORT_ATTEMPTS&&reward.current_locked_events>=MAKER_MIN_PROMOTION_LOCKS&&reward.lower>0;
|
&&reward&&reward.current_events>=MAKER_MIN_COHORT_ATTEMPTS&&reward.current_locked_events>=MAKER_MIN_PROMOTION_LOCKS&&reward.lower>0;
|
||||||
|
const promoted=MAKER_CAPITAL_BACKTEST_APPROVED&&evidencePromoted;
|
||||||
const positive=[category,spread,reward].filter(Boolean).sort((a,b)=>b.lower-a.lower)[0];
|
const positive=[category,spread,reward].filter(Boolean).sort((a,b)=>b.lower-a.lower)[0];
|
||||||
const multiplier=promoted?clamp(1+Math.max(0,positive.lower)*6*positive.confidence,1,1.25):1;
|
const multiplier=promoted?clamp(1+Math.max(0,positive.lower)*6*positive.confidence,1,1.25):1;
|
||||||
const units=+(candidate.units*multiplier).toFixed(2),requiredCapital=+(units*candidate.paired_cost).toFixed(2),lockedProfit=+(units*(1-candidate.paired_cost)).toFixed(2);
|
const units=+(candidate.units*multiplier).toFixed(2),requiredCapital=+(units*candidate.paired_cost).toFixed(2),lockedProfit=+(units*(1-candidate.paired_cost)).toFixed(2);
|
||||||
const learned=mature.length?mature.reduce((sum,stats)=>sum+stats.mean,0)/mature.length:0;
|
const learned=mature.length?mature.reduce((sum,stats)=>sum+stats.mean,0)/mature.length:0;
|
||||||
return Object.assign({},candidate,{units,required_capital:requiredCapital,locked_profit:lockedProfit,reward_yield_band:rewardBand,
|
return Object.assign({},candidate,{units,required_capital:requiredCapital,locked_profit:lockedProfit,reward_yield_band:rewardBand,
|
||||||
maker_learning_multiplier:+multiplier.toFixed(3),maker_learning_state:promoted?"promoted":losing?"shadow-rejected":"shadow-observing",
|
maker_learning_multiplier:+multiplier.toFixed(3),maker_learning_state:promoted?"promoted":losing?"shadow-rejected":evidencePromoted?"shadow-backtest-blocked":"shadow-observing",
|
||||||
maker_capital_enabled:promoted,maker_expected_return:+learned.toFixed(5),score:+(candidate.score+learned*60+(promoted?positive.lower*100:0)).toFixed(4)});
|
maker_capital_enabled:promoted,maker_expected_return:+learned.toFixed(5),score:+(candidate.score+learned*60+(promoted?positive.lower*100:0)).toFixed(4)});
|
||||||
}
|
}
|
||||||
function recordMakerOutcome(p,quote,status,pnl,deployedCapital){
|
function recordMakerOutcome(p,quote,status,pnl,deployedCapital){
|
||||||
@@ -2920,11 +2924,23 @@ function finishShadowMakerQuote(p,quote,fresh){
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const entry=Number(side==="YES"?quote.yes_fill_price:quote.no_fill_price),executable=side==="YES"?Number(fresh.best_bid):1-Number(fresh.best_ask);
|
const entry=Number(side==="YES"?quote.yes_fill_price:quote.no_fill_price),executable=side==="YES"?Number(fresh.best_bid):1-Number(fresh.best_ask);
|
||||||
|
const complementSide=side==="YES"?"NO":"YES",complementAsk=side==="YES"?1-Number(fresh.best_bid):Number(fresh.best_ask);
|
||||||
|
const hedgedCost=entry+complementAsk+SIGNAL_ROUND_TRIP_COST;
|
||||||
|
if(complementAsk>0&&complementAsk<1&&hedgedCost<=1-MAKER_MIN_LOCK_MARGIN){
|
||||||
|
const deployed=Number(quote.units)*(entry+complementAsk),pnl=Number(quote.units)*(1-hedgedCost);
|
||||||
|
quote[`${complementSide.toLowerCase()}_filled_at`]=cycleIso();
|
||||||
|
quote[`${complementSide.toLowerCase()}_fill_price`]=+complementAsk.toFixed(4);
|
||||||
|
quote[`${complementSide.toLowerCase()}_fill_evidence`]="executable-complement-ask";
|
||||||
|
recordMakerOutcome(p,quote,"hedged-lock",pnl,deployed);
|
||||||
|
p.history.push({date:logDay(),action:"SHADOW_HEDGE",question:quote.question,side:"PAIR",
|
||||||
|
detail:`Only the shadow ${side} resting bid touched; buying ${complementSide} at the executable ${pct(complementAsk)} ask would lock ${fmtUSD(pnl)} after modeled cost · portfolio cash unchanged`});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if(!(executable>0&&executable<1))return false;
|
if(!(executable>0&&executable<1))return false;
|
||||||
const deployed=Number(quote.units)*entry,pnl=Number(quote.units)*(executable-entry-SIGNAL_ROUND_TRIP_COST);
|
const deployed=Number(quote.units)*entry,pnl=Number(quote.units)*(executable-entry-SIGNAL_ROUND_TRIP_COST);
|
||||||
recordMakerOutcome(p,quote,"single-exit",pnl,deployed);
|
recordMakerOutcome(p,quote,"immediate-exit",pnl,deployed);
|
||||||
p.history.push({date:logDay(),action:"SHADOW_EXIT",question:quote.question,side,
|
p.history.push({date:logDay(),action:"SHADOW_EXIT",question:quote.question,side,
|
||||||
detail:`Only the shadow ${side} bid touched; ${quote.shadow_horizon_hours||MAKER_SHADOW_HORIZON_HOURS}h executable exit grades ${fmtUSD(pnl)} after modeled cost · portfolio cash unchanged`});
|
detail:`Only the shadow ${side} resting bid touched and the complementary ask could not lock a profit; immediate executable exit grades ${fmtUSD(pnl)} after modeled cost · portfolio cash unchanged`});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
function unwindMakerInventory(p,quote,fresh){
|
function unwindMakerInventory(p,quote,fresh){
|
||||||
@@ -2981,6 +2997,10 @@ function manageMakerQuotes(p,marketMap,{executeTrades=false,touchHistory={}}={})
|
|||||||
}
|
}
|
||||||
if(quote.shadow_only){
|
if(quote.shadow_only){
|
||||||
if(quote.yes_filled_at&"e.no_filled_at){completeShadowMakerPair(p,quote);locked++;shadowCompleted++;continue;}
|
if(quote.yes_filled_at&"e.no_filled_at){completeShadowMakerPair(p,quote);locked++;shadowCompleted++;continue;}
|
||||||
|
if(Boolean(quote.yes_filled_at)!==Boolean(quote.no_filled_at)&&finishShadowMakerQuote(p,quote,fresh)){
|
||||||
|
if((p.maker_outcomes||[]).at(-1)?.status==="hedged-lock")locked++;
|
||||||
|
expired++;shadowCompleted++;continue;
|
||||||
|
}
|
||||||
if(age>=Number(quote.shadow_horizon_hours||MAKER_SHADOW_HORIZON_HOURS)&&finishShadowMakerQuote(p,quote,fresh)){expired++;shadowCompleted++;continue;}
|
if(age>=Number(quote.shadow_horizon_hours||MAKER_SHADOW_HORIZON_HOURS)&&finishShadowMakerQuote(p,quote,fresh)){expired++;shadowCompleted++;continue;}
|
||||||
keep.push(quote);continue;
|
keep.push(quote);continue;
|
||||||
}
|
}
|
||||||
@@ -3538,7 +3558,7 @@ async function runDailyCycle(){
|
|||||||
makerShadowCompleted:makerActivity.shadowCompleted,
|
makerShadowCompleted:makerActivity.shadowCompleted,
|
||||||
makerReserved:staged.reserved,makerProfile:sharedMakerProfile});
|
makerReserved:staged.reserved,makerProfile:sharedMakerProfile});
|
||||||
if(staged.staged||makerActivity.fills||makerActivity.locked||makerActivity.expired){
|
if(staged.staged||makerActivity.fills||makerActivity.locked||makerActivity.expired){
|
||||||
p.lastDecision.allocationStatus=`${p.lastDecision.allocationStatus||""} Reward-book learner: ${staged.shadowActive} zero-capital shadow observation${staged.shadowActive===1?"":"s"}, ${staged.capitalActive} evidence-promoted capital quote${staged.capitalActive===1?"":"s"}, ${makerActivity.shadowCompleted||0} shadow outcome${makerActivity.shadowCompleted===1?"":"s"} graded this cycle; displayed reward estimates are never credited as P&L.`.trim();
|
p.lastDecision.allocationStatus=`${p.lastDecision.allocationStatus||""} Maker research: ${staged.shadowActive} zero-capital lock-or-exit observation${staged.shadowActive===1?"":"s"}, ${makerActivity.shadowCompleted||0} outcome${makerActivity.shadowCompleted===1?"":"s"} graded this cycle; capital remains disabled after the chronological holdout failure, and displayed reward estimates are never credited as P&L.`.trim();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
recordSnapshot(p);
|
recordSnapshot(p);
|
||||||
@@ -3738,7 +3758,7 @@ function decisionSummary(p){
|
|||||||
calibration=` Walk-forward calibration for ${learningScope}: ${ml.samples||0} net-of-cost checkpoint observations ${countText}, graded at ${SIGNAL_EARLY_RISK_HORIZONS.join("h, ")}h for early loss vetoes and ${SIGNAL_PROMOTION_HORIZONS.join("h and ")}h for promotion (${currentText} under directional signal policy ${ml.policy_version||DIRECTIONAL_SIGNAL_POLICY_VERSION}), ${ml.pending||0} awaiting a future checkpoint${ml.expired_ungraded?`, ${ml.expired_ungraded} expired checkpoints`:""}.${queueAudit} ${ml.promoted_buckets||0} horizon-specific feature cohorts promoted and ${ml.demoted_buckets||0} demoted. Promotion requires positive compatible-policy evidence at both promotion horizons across independent events; one mature negative cohort at any checkpoint can veto risk. Each agent studies a broader strategy-specific research universe before the stricter capital-entry gate is applied, while unlabeled legacy evidence remains readable. Sports pilots and priced bundles stay outside directional calibration. Missed windows expire rather than borrowing a later price. New observations prioritize under-sampled signal/side/category cohorts and independent events before repeats. Correlated outcome markets in one event count as one effective outcome. Historical prior: every directional trend and reversal remains observation-only until its exact recent cohorts independently promote; settlement-jump barriers stay excluded.`;
|
calibration=` Walk-forward calibration for ${learningScope}: ${ml.samples||0} net-of-cost checkpoint observations ${countText}, graded at ${SIGNAL_EARLY_RISK_HORIZONS.join("h, ")}h for early loss vetoes and ${SIGNAL_PROMOTION_HORIZONS.join("h and ")}h for promotion (${currentText} under directional signal policy ${ml.policy_version||DIRECTIONAL_SIGNAL_POLICY_VERSION}), ${ml.pending||0} awaiting a future checkpoint${ml.expired_ungraded?`, ${ml.expired_ungraded} expired checkpoints`:""}.${queueAudit} ${ml.promoted_buckets||0} horizon-specific feature cohorts promoted and ${ml.demoted_buckets||0} demoted. Promotion requires positive compatible-policy evidence at both promotion horizons across independent events; one mature negative cohort at any checkpoint can veto risk. Each agent studies a broader strategy-specific research universe before the stricter capital-entry gate is applied, while unlabeled legacy evidence remains readable. Sports pilots and priced bundles stay outside directional calibration. Missed windows expire rather than borrowing a later price. New observations prioritize under-sampled signal/side/category cohorts and independent events before repeats. Correlated outcome markets in one event count as one effective outcome. Historical prior: every directional trend and reversal remains observation-only until its exact recent cohorts independently promote; settlement-jump barriers stay excluded.`;
|
||||||
}
|
}
|
||||||
const makerStats=d.makerProfile&&d.makerProfile.global;
|
const makerStats=d.makerProfile&&d.makerProfile.global;
|
||||||
const maker=d.makerQuotes!=null?` Maker learner: ${d.makerShadowActive||0} zero-capital shadow observations and ${d.makerCapitalActive||0} evidence-promoted capital quotes active; ${d.makerFills||0} verified touches and ${d.makerShadowCompleted||0} shadow outcomes completed this cycle, ${fmtUSD(d.makerReserved||0)} capital reserved.${makerStats?` Event-clustered ledger: ${makerStats.attempts} attempts / ${makerStats.events} events, ${makerStats.locked} paired touches, ${makerStats.adverse} adverse single touches, ${makerStats.unfilled} unfilled, ${fmtUSD(makerStats.shadow_pnl)} simulated shadow net and ${fmtUSD(makerStats.pnl)} actual paper net.`:""} Capital promotion requires ${MAKER_MIN_COHORT_ATTEMPTS} current-strategy events with positive confidence bounds in both category and spread cohorts. Rewards remain excluded until externally verified.`:"";
|
const maker=d.makerQuotes!=null?` Maker research: ${d.makerShadowActive||0} zero-capital lock-or-exit observations active; ${d.makerFills||0} verified touches and ${d.makerShadowCompleted||0} outcomes completed this cycle.${makerStats?` Event-clustered ledger: ${makerStats.attempts} attempts / ${makerStats.events} events, ${makerStats.locked} locked pairs, ${makerStats.adverse} immediate adverse exits, ${makerStats.unfilled} unfilled, and ${fmtUSD(makerStats.shadow_pnl)} simulated shadow net.`:""} Capital is disabled because neither the 6,048-rule chronological maker audit nor the reward stress test produced a validated holdout winner. Hypothetical rewards are excluded.`:"";
|
||||||
const sportsPilot=d.sportsFavoritePilot?` Sports forward learner: ${d.sportsFavoritePilot.state}, ${d.sportsFavoritePilot.active_shadows||0} zero-capital observations active and ${d.sportsFavoritePilot.events} independent closed events, ${d.sportsFavoritePilot.events?`${(d.sportsFavoritePilot.mean*100).toFixed(2)}% mean with ${d.sportsFavoritePilot.lower>=0?"+":""}${(d.sportsFavoritePilot.lower*100).toFixed(2)}% to ${d.sportsFavoritePilot.upper>=0?"+":""}${(d.sportsFavoritePilot.upper*100).toFixed(2)}% 90% interval; `:""}${fmtUSD(d.sportsFavoritePilot.shadow_pnl_per_100||0)} simulated per-$100 net and ${fmtUSD(d.sportsFavoritePilot.pnl)} realized capital P&L. Position cap ${(d.sportsFavoritePilot.position_pct*100).toFixed(2)}%; capital remains zero until ${SPORTS_FAVORITE_PROMOTION_EVENTS} new independent events establish a positive lower bound.`:"";
|
const sportsPilot=d.sportsFavoritePilot?` Sports forward learner: ${d.sportsFavoritePilot.state}, ${d.sportsFavoritePilot.active_shadows||0} zero-capital observations active and ${d.sportsFavoritePilot.events} independent closed events, ${d.sportsFavoritePilot.events?`${(d.sportsFavoritePilot.mean*100).toFixed(2)}% mean with ${d.sportsFavoritePilot.lower>=0?"+":""}${(d.sportsFavoritePilot.lower*100).toFixed(2)}% to ${d.sportsFavoritePilot.upper>=0?"+":""}${(d.sportsFavoritePilot.upper*100).toFixed(2)}% 90% interval; `:""}${fmtUSD(d.sportsFavoritePilot.shadow_pnl_per_100||0)} simulated per-$100 net and ${fmtUSD(d.sportsFavoritePilot.pnl)} realized capital P&L. Position cap ${(d.sportsFavoritePilot.position_pct*100).toFixed(2)}%; capital remains zero until ${SPORTS_FAVORITE_PROMOTION_EVENTS} new independent events establish a positive lower bound.`:"";
|
||||||
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}${maker}${sportsPilot}${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}${maker}${sportsPilot}${exposure}${allocation}${candidates}${blockers}`;
|
||||||
}
|
}
|
||||||
@@ -4464,7 +4484,7 @@ function renderPositions(positions){
|
|||||||
const positionRules=p.requires_complete_bundle
|
const positionRules=p.requires_complete_bundle
|
||||||
? `<div class="sub">Complete paired hedge: individual stops and gain sales are disabled; the two legs stay intact through settlement.</div>`
|
? `<div class="sub">Complete paired hedge: individual stops and gain sales are disabled; the two legs stay intact through settlement.</div>`
|
||||||
:p.maker_pair_pending
|
:p.maker_pair_pending
|
||||||
? `<div class="sub">Unmatched maker leg: the complementary resting bid remains live; unresolved inventory exits at an executable bid after ${MAKER_QUOTE_EXPIRY_HOURS}h.</div>`
|
? `<div class="sub">Legacy unmatched maker leg: capital maker research is retired, so the next live cycle unwinds it at an executable bid.</div>`
|
||||||
:`<div class="sub">${esc(stopLossLabel(p))}</div><div class="sub">${esc(gainStopLabel(p))}</div>`;
|
:`<div class="sub">${esc(stopLossLabel(p))}</div><div class="sub">${esc(gainStopLabel(p))}</div>`;
|
||||||
return `<div class="pos"><div>
|
return `<div class="pos"><div>
|
||||||
<div class="pq">${title}</div>
|
<div class="pq">${title}</div>
|
||||||
@@ -5385,10 +5405,11 @@ window.PMA_ENGINE_DIAGNOSTICS=Object.freeze({
|
|||||||
focusAndReconnectCatchup:true,liveOnlyCompleteBundles:true,negativeRiskBundleSides:["YES","NO"],negativeRiskEventScanLimit:NEG_RISK_EVENT_SCAN_LIMIT,
|
focusAndReconnectCatchup:true,liveOnlyCompleteBundles:true,negativeRiskBundleSides:["YES","NO"],negativeRiskEventScanLimit:NEG_RISK_EVENT_SCAN_LIMIT,
|
||||||
dominanceBundleLogic:"same-event nested threshold or calendar-deadline YES/NO pairs with identical normalized terms",
|
dominanceBundleLogic:"same-event nested threshold or calendar-deadline YES/NO pairs with identical normalized terms",
|
||||||
negativeRiskMinimumNetReturnPct:NEG_RISK_MIN_NET_RETURN*100,
|
negativeRiskMinimumNetReturnPct:NEG_RISK_MIN_NET_RETURN*100,
|
||||||
pairedMakerQuotes:"reward-book-audited-shadow-until-promoted",makerStrategyVersion:MAKER_STRATEGY_VERSION,
|
pairedMakerQuotes:"research-only-immediate-lock-or-exit",makerStrategyVersion:MAKER_STRATEGY_VERSION,
|
||||||
makerShadowHorizonHours:MAKER_SHADOW_HORIZON_HOURS,makerLegacyQuoteExpiryHours:MAKER_QUOTE_EXPIRY_HOURS,makerMinimumLockMarginPct:MAKER_MIN_LOCK_MARGIN*100,
|
makerShadowHorizonHours:MAKER_SHADOW_HORIZON_HOURS,makerLegacyQuoteExpiryHours:MAKER_QUOTE_EXPIRY_HOURS,makerMinimumLockMarginPct:MAKER_MIN_LOCK_MARGIN*100,
|
||||||
makerTouchSource:"Polymarket CLOB batch price history",makerOutcomeLimit:MAKER_OUTCOME_LIMIT,makerMinimumCohortAttempts:MAKER_MIN_COHORT_ATTEMPTS,
|
makerTouchSource:"Polymarket CLOB batch price history",makerOutcomeLimit:MAKER_OUTCOME_LIMIT,makerMinimumCohortAttempts:MAKER_MIN_COHORT_ATTEMPTS,
|
||||||
makerMinimumPromotionLocks:MAKER_MIN_PROMOTION_LOCKS,makerMaximumLearningMultiplier:1.25,makerCapitalExplorationPct:0,hypotheticalRewardsCredited:false,
|
makerMinimumPromotionLocks:MAKER_MIN_PROMOTION_LOCKS,makerMaximumLearningMultiplier:1,makerCapitalExplorationPct:0,
|
||||||
|
makerCapitalBacktestApproved:MAKER_CAPITAL_BACKTEST_APPROVED,hypotheticalRewardsCredited:false,
|
||||||
makerCompetitionSource:"shared public CLOB order-book audit",makerResearchSharedAcrossAgents:true,makerMarketsPartitionedAcrossAgents:true,
|
makerCompetitionSource:"shared public CLOB order-book audit",makerResearchSharedAcrossAgents:true,makerMarketsPartitionedAcrossAgents:true,
|
||||||
makerHistoryRequestsBatched:true,makerPromotionCohorts:["category","spread","reward-yield"],makerRewardPayoutMinimum:1,
|
makerHistoryRequestsBatched:true,makerPromotionCohorts:["category","spread","reward-yield"],makerRewardPayoutMinimum:1,
|
||||||
emotionCanIncreaseSize:false,dualPromotionPeerBoostPct:5,currentStrategyOnlyCapitalAdaptation:true,
|
emotionCanIncreaseSize:false,dualPromotionPeerBoostPct:5,currentStrategyOnlyCapitalAdaptation:true,
|
||||||
@@ -5399,7 +5420,7 @@ window.PMA_ENGINE_DIAGNOSTICS=Object.freeze({
|
|||||||
verdictEvents:SPORTS_FAVORITE_VERDICT_EVENTS,promotionEvents:SPORTS_FAVORITE_PROMOTION_EVENTS,
|
verdictEvents:SPORTS_FAVORITE_VERDICT_EVENTS,promotionEvents:SPORTS_FAVORITE_PROMOTION_EVENTS,
|
||||||
slippageBufferCents:SPORTS_FAVORITE_SLIPPAGE_BUFFER*100,maximumExecutionCostCents:SPORTS_FAVORITE_MAX_EXECUTION_COST*100,
|
slippageBufferCents:SPORTS_FAVORITE_SLIPPAGE_BUFFER*100,maximumExecutionCostCents:SPORTS_FAVORITE_MAX_EXECUTION_COST*100,
|
||||||
capitalRequiresForwardPromotion:true,old24HourCapitalRuleRetired:true},
|
capitalRequiresForwardPromotion:true,old24HourCapitalRuleRetired:true},
|
||||||
historicalPrior:"No directional rule survived the current 300-market 60/20/20 adaptive holdout at both 24h and 72h, and no settlement rule survived validation across 5,000 resolved markets. Favorite-priced trend following was independently net-negative at 6h, 12h, 24h, and 72h and is hard-blocked. The prior sports-capital rule also remains retired. Live-priced complete negative-risk bundles may trade when positive after costs; paired maker quotes and sports favorites remain zero-capital observations until current cohorts independently promote"}),
|
historicalPrior:"No directional rule survived the current 300-market 60/20/20 adaptive holdout at both 24h and 72h, and no settlement rule survived validation across 5,000 resolved markets. Favorite-priced trend following was independently net-negative at 6h, 12h, 24h, and 72h and is hard-blocked. The prior sports-capital rule also remains retired. Live-priced complete negative-risk bundles may trade when positive after costs. Maker research remains zero-capital because 6,048 wait and immediate-hedge rules produced no train, validation, or holdout winner"}),
|
||||||
});
|
});
|
||||||
function runEngineSelfTest(){
|
function runEngineSelfTest(){
|
||||||
const market=(overrides={})=>Object.assign({
|
const market=(overrides={})=>Object.assign({
|
||||||
@@ -5741,6 +5762,10 @@ function runEngineSelfTest(){
|
|||||||
shadowQuote.created_at=hoursAgo(4);shadowQuote.yes_quote_updated_at=shadowQuote.created_at;shadowQuote.no_quote_updated_at=shadowQuote.created_at;
|
shadowQuote.created_at=hoursAgo(4);shadowQuote.yes_quote_updated_at=shadowQuote.created_at;shadowQuote.no_quote_updated_at=shadowQuote.created_at;
|
||||||
const shadowTouchTimestamp=Math.floor((Date.now()-30*60000)/1000),shadowCashBefore=shadowBook.cash;
|
const shadowTouchTimestamp=Math.floor((Date.now()-30*60000)/1000),shadowCashBefore=shadowBook.cash;
|
||||||
const shadowFinished=manageMakerQuotes(shadowBook,{"maker-test":touchMarket},{executeTrades:true,touchHistory:{yes:[{t:shadowTouchTimestamp,p:0.395}]}});
|
const shadowFinished=manageMakerQuotes(shadowBook,{"maker-test":touchMarket},{executeTrades:true,touchHistory:{yes:[{t:shadowTouchTimestamp,p:0.395}]}});
|
||||||
|
const shadowHedgeBook=defaultPortfolio();stageMakerQuotes(shadowHedgeBook,[makerMarket]);const shadowHedgeQuote=shadowHedgeBook.maker_quotes[0];
|
||||||
|
shadowHedgeQuote.created_at=hoursAgo(1);shadowHedgeQuote.yes_quote_updated_at=shadowHedgeQuote.created_at;shadowHedgeQuote.no_quote_updated_at=shadowHedgeQuote.created_at;
|
||||||
|
const shadowHedgeCashBefore=shadowHedgeBook.cash,shadowHedgeMarket=market(Object.assign({},makerMarket,{best_bid:0.43,best_ask:0.44,yes_price:0.435,no_price:0.565}));
|
||||||
|
const shadowHedged=manageMakerQuotes(shadowHedgeBook,{"maker-test":shadowHedgeMarket},{executeTrades:true,touchHistory:{yes:[{t:shadowTouchTimestamp,p:0.395}]}});
|
||||||
const makerDedupeBook=defaultPortfolio(),dedupeQuote=Object.assign({},makerQuote,{id:"dedupe-maker"});
|
const makerDedupeBook=defaultPortfolio(),dedupeQuote=Object.assign({},makerQuote,{id:"dedupe-maker"});
|
||||||
recordMakerOutcome(makerDedupeBook,dedupeQuote,"unfilled",0,0);recordMakerOutcome(makerDedupeBook,dedupeQuote,"unfilled",0,0);
|
recordMakerOutcome(makerDedupeBook,dedupeQuote,"unfilled",0,0);recordMakerOutcome(makerDedupeBook,dedupeQuote,"unfilled",0,0);
|
||||||
const makerCompactionBook=defaultPortfolio();makerCompactionBook.maker_quotes=[Object.assign({},makerQuote)];makerCompactionBook.maker_outcomes=[...profitableMakerBook.maker_outcomes];
|
const makerCompactionBook=defaultPortfolio();makerCompactionBook.maker_quotes=[Object.assign({},makerQuote)];makerCompactionBook.maker_outcomes=[...profitableMakerBook.maker_outcomes];
|
||||||
@@ -6117,12 +6142,15 @@ function runEngineSelfTest(){
|
|||||||
offlineHistoryCannotInventFill:offlineTouch.fills===0&&offlineTouchBook.positions.length===0&&offlineTouchBook.maker_quotes.length===1,
|
offlineHistoryCannotInventFill:offlineTouch.fills===0&&offlineTouchBook.positions.length===0&&offlineTouchBook.maker_quotes.length===1,
|
||||||
repricedQuoteRejectsEarlierTouch:preRepriceIgnored,
|
repricedQuoteRejectsEarlierTouch:preRepriceIgnored,
|
||||||
repricedQuoteAcceptsLaterTouch:postRepriceTouch.fills===1&&postRepriceTouch.locked===1&&repriceBook.maker_quotes.length===0,
|
repricedQuoteAcceptsLaterTouch:postRepriceTouch.fills===1&&postRepriceTouch.locked===1&&repriceBook.maker_quotes.length===0,
|
||||||
profitableCohortScalesWithinCap:profitableCandidate&&profitableCandidate.maker_learning_state==="promoted"&&profitableCandidate.maker_capital_enabled&&profitableCandidate.units>makerQuote.units&&profitableCandidate.units<=makerQuote.units*1.25,
|
positiveShadowCohortCannotOverrideFailedBacktest:profitableCandidate&&profitableCandidate.maker_learning_state==="shadow-backtest-blocked"
|
||||||
|
&&!profitableCandidate.maker_capital_enabled&&profitableCandidate.units===makerQuote.units,
|
||||||
promotionRequiresDistinctLockedEvents:buildMakerProfile(profitableMakerBook).global.current_locked_events===24,
|
promotionRequiresDistinctLockedEvents:buildMakerProfile(profitableMakerBook).global.current_locked_events===24,
|
||||||
losingCohortRemainsShadowOnly:blockedMakerCandidate&&blockedMakerCandidate.maker_learning_state==="shadow-rejected"&&!blockedMakerCandidate.maker_capital_enabled,
|
losingCohortRemainsShadowOnly:blockedMakerCandidate&&blockedMakerCandidate.maker_learning_state==="shadow-rejected"&&!blockedMakerCandidate.maker_capital_enabled,
|
||||||
noRealMoneyExplorationLane:explorationMakerCandidate&&explorationMakerCandidate.maker_learning_state==="shadow-rejected"&&!explorationMakerCandidate.maker_capital_enabled,
|
noRealMoneyExplorationLane:explorationMakerCandidate&&explorationMakerCandidate.maker_learning_state==="shadow-rejected"&&!explorationMakerCandidate.maker_capital_enabled,
|
||||||
shadowSingleTouchChangesNoCash:shadowFinished.shadowCompleted===1&&shadowBook.cash===shadowCashBefore&&shadowBook.positions.length===0&&shadowBook.maker_quotes.length===0,
|
shadowSingleTouchChangesNoCash:shadowFinished.shadowCompleted===1&&shadowBook.cash===shadowCashBefore&&shadowBook.positions.length===0&&shadowBook.maker_quotes.length===0,
|
||||||
shadowSingleTouchRecordsAdverseOutcome:shadowBook.maker_outcomes.length===1&&shadowBook.maker_outcomes[0].shadow_only&&shadowBook.maker_outcomes[0].status==="single-exit"&&shadowBook.maker_outcomes[0].pnl<0,
|
shadowSingleTouchExitsImmediately:shadowBook.maker_outcomes.length===1&&shadowBook.maker_outcomes[0].shadow_only&&shadowBook.maker_outcomes[0].status==="immediate-exit"&&shadowBook.maker_outcomes[0].pnl<0,
|
||||||
|
executableComplementCanLockShadowPair:shadowHedged.shadowCompleted===1&&shadowHedged.locked===1&&shadowHedgeBook.cash===shadowHedgeCashBefore
|
||||||
|
&&shadowHedgeBook.positions.length===0&&shadowHedgeBook.maker_quotes.length===0&&shadowHedgeBook.maker_outcomes[0].status==="hedged-lock"&&shadowHedgeBook.maker_outcomes[0].pnl>0,
|
||||||
outcomesAreDeduplicated:makerDedupeBook.maker_outcomes.length===1,
|
outcomesAreDeduplicated:makerDedupeBook.maker_outcomes.length===1,
|
||||||
makerLearningSurvivesCompaction:compactedMakerBook.maker_quotes.length===1&&compactedMakerBook.maker_outcomes.length===24,
|
makerLearningSurvivesCompaction:compactedMakerBook.maker_quotes.length===1&&compactedMakerBook.maker_outcomes.length===24,
|
||||||
sharedLedgerCombinesAgentEvidence:sharedMakerFixture.global.current_events===2&&sharedMakerFixture.global.current_locked_events===2,
|
sharedLedgerCombinesAgentEvidence:sharedMakerFixture.global.current_events===2&&sharedMakerFixture.global.current_locked_events===2,
|
||||||
|
|||||||
+43
-13
@@ -105,6 +105,10 @@ function atOrBefore(points, target) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function atOrAfter(points, target) {
|
||||||
|
return points.find((point) => point.t >= target) || null;
|
||||||
|
}
|
||||||
|
|
||||||
function observations(market, yesPoints, noPoints) {
|
function observations(market, yesPoints, noPoints) {
|
||||||
const rows = [], seen = new Set();
|
const rows = [], seen = new Set();
|
||||||
for (const yes of yesPoints) {
|
for (const yes of yesPoints) {
|
||||||
@@ -137,9 +141,31 @@ function simulate(row, rule) {
|
|||||||
const futureYes = row.futureYes.filter((point) => point.t <= horizonEnd), futureNo = row.futureNo.filter((point) => point.t <= horizonEnd);
|
const futureYes = row.futureYes.filter((point) => point.t <= horizonEnd), futureNo = row.futureNo.filter((point) => point.t <= horizonEnd);
|
||||||
const endYes = atOrBefore(futureYes, horizonEnd), endNo = atOrBefore(futureNo, horizonEnd);
|
const endYes = atOrBefore(futureYes, horizonEnd), endNo = atOrBefore(futureNo, horizonEnd);
|
||||||
if (!endYes || !endNo || horizonEnd - Math.min(endYes.t, endNo.t) > 2 * HOUR) return null;
|
if (!endYes || !endNo || horizonEnd - Math.min(endYes.t, endNo.t) > 2 * HOUR) return null;
|
||||||
const yesFill = futureYes.some((point) => point.p <= yesQuote), noFill = futureNo.some((point) => point.p <= noQuote);
|
const yesFillPoint = futureYes.find((point) => point.p <= yesQuote) || null;
|
||||||
|
const noFillPoint = futureNo.find((point) => point.p <= noQuote) || null;
|
||||||
|
const yesFill = Boolean(yesFillPoint), noFill = Boolean(noFillPoint);
|
||||||
let pnl = 0, status = "unfilled";
|
let pnl = 0, status = "unfilled";
|
||||||
if (yesFill && noFill) { pnl = 1 - reserved; status = "locked"; }
|
if (rule.mode === "immediate-hedge" && (yesFill || noFill)) {
|
||||||
|
const yesFirst = yesFillPoint && (!noFillPoint || yesFillPoint.t < noFillPoint.t);
|
||||||
|
const noFirst = noFillPoint && (!yesFillPoint || noFillPoint.t < yesFillPoint.t);
|
||||||
|
if (!yesFirst && !noFirst) {
|
||||||
|
pnl = 1 - reserved;
|
||||||
|
status = "locked";
|
||||||
|
} else {
|
||||||
|
const first = yesFirst ? yesFillPoint : noFillPoint;
|
||||||
|
const firstQuote = yesFirst ? yesQuote : noQuote;
|
||||||
|
const otherPoints = yesFirst ? futureNo : futureYes;
|
||||||
|
const other = atOrAfter(otherPoints, first.t);
|
||||||
|
const hedgeCost = other ? firstQuote + other.p + EXIT_COST : Infinity;
|
||||||
|
if (hedgeCost < 1) {
|
||||||
|
pnl = 1 - hedgeCost;
|
||||||
|
status = "hedged-lock";
|
||||||
|
} else {
|
||||||
|
pnl = first.p - firstQuote - EXIT_COST;
|
||||||
|
status = "immediate-exit";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (yesFill && noFill) { pnl = 1 - reserved; status = "locked"; }
|
||||||
else if (yesFill) { pnl = endYes.p - yesQuote - EXIT_COST; status = "single-exit"; }
|
else if (yesFill) { pnl = endYes.p - yesQuote - EXIT_COST; status = "single-exit"; }
|
||||||
else if (noFill) { pnl = endNo.p - noQuote - EXIT_COST; status = "single-exit"; }
|
else if (noFill) { pnl = endNo.p - noQuote - EXIT_COST; status = "single-exit"; }
|
||||||
return { marketId: row.marketId, eventKey: row.eventKey, observedAt: row.observedAt, pnl,
|
return { marketId: row.marketId, eventKey: row.eventKey, observedAt: row.observedAt, pnl,
|
||||||
@@ -160,17 +186,19 @@ function summary(rows) {
|
|||||||
return { attempts: rows.length, markets: new Set(rows.map((row) => row.marketId)).size, events: eventReturns.length,
|
return { attempts: rows.length, markets: new Set(rows.map((row) => row.marketId)).size, events: eventReturns.length,
|
||||||
pnl: rows.reduce((sum, row) => sum + row.pnl, 0), mean: rows.reduce((sum, row) => sum + row.netReturn, 0) / rows.length,
|
pnl: rows.reduce((sum, row) => sum + row.pnl, 0), mean: rows.reduce((sum, row) => sum + row.netReturn, 0) / rows.length,
|
||||||
eventMean, lower: eventMean - margin, upper: eventMean + margin,
|
eventMean, lower: eventMean - margin, upper: eventMean + margin,
|
||||||
lockedRate: rows.filter((row) => row.status === "locked").length / rows.length,
|
lockedRate: rows.filter((row) => row.status === "locked" || row.status === "hedged-lock").length / rows.length,
|
||||||
adverseRate: rows.filter((row) => row.status === "single-exit").length / rows.length };
|
adverseRate: rows.filter((row) => row.status === "single-exit" || row.status === "immediate-exit").length / rows.length };
|
||||||
}
|
}
|
||||||
|
|
||||||
const rules = [];
|
const rules = [];
|
||||||
for (const horizon of [3, 6, 12, 24]) {
|
for (const mode of ["wait", "immediate-hedge"]) {
|
||||||
for (const gap of [0.005, 0.01, 0.015, 0.02, 0.025, 0.03, 0.04]) {
|
for (const horizon of [3, 6, 12, 24]) {
|
||||||
for (const maxPriorRange of [0.02, 0.04, 0.06, 0.08, 0.12, 0.2]) {
|
for (const gap of [0.005, 0.01, 0.015, 0.02, 0.025, 0.03, 0.04]) {
|
||||||
for (const band of ["all", "mid", "tails"]) {
|
for (const maxPriorRange of [0.02, 0.04, 0.06, 0.08, 0.12, 0.2]) {
|
||||||
for (const category of ["All", "Politics", "Sports", "Crypto", "Economy", "Other"])
|
for (const band of ["all", "mid", "tails"]) {
|
||||||
rules.push({ id: `h${horizon}_gap${gap}_range${maxPriorRange}_${band}_${category}`, horizon, gap, maxPriorRange, band, category });
|
for (const category of ["All", "Politics", "Sports", "Crypto", "Economy", "Other"])
|
||||||
|
rules.push({ id: `${mode}_h${horizon}_gap${gap}_range${maxPriorRange}_${band}_${category}`, mode, horizon, gap, maxPriorRange, band, category });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -204,9 +232,11 @@ const broadByGap = evaluated.filter((candidate) => candidate.rule.maxPriorRange
|
|||||||
const report = { generatedAt: new Date().toISOString(), requestedMarkets: MARKET_LIMIT, rewardMarkets: markets.length,
|
const report = { generatedAt: new Date().toISOString(), requestedMarkets: MARKET_LIMIT, rewardMarkets: markets.length,
|
||||||
marketsWithBothHistories: markets.filter((market) => fetched.history[market.tokens[0]]?.length && fetched.history[market.tokens[1]]?.length).length,
|
marketsWithBothHistories: markets.filter((market) => fetched.history[market.tokens[0]]?.length && fetched.history[market.tokens[1]]?.length).length,
|
||||||
batchFailures: fetched.failures, batchFailureMessages: fetched.failureMessages, observations: rows.length, testedRules: rules.length,
|
batchFailures: fetched.failures, batchFailureMessages: fetched.failureMessages, observations: rows.length, testedRules: rules.length,
|
||||||
methodology: { historyDays: HISTORY_DAYS, quoteHorizonHours: [3, 6, 12, 24], observationSpacingHours: 24, exitCostCents: EXIT_COST * 100,
|
methodology: { historyDays: HISTORY_DAYS, quoteHorizonHours: [3, 6, 12, 24], modes: ["wait", "immediate-hedge"], observationSpacingHours: 24, exitCostCents: EXIT_COST * 100,
|
||||||
split: "60% train / 20% validation / 20% untouched holdout", clusterUnit: "Polymarket event",
|
split: "60% train / 20% validation / 20% untouched holdout", clusterUnit: "Polymarket event",
|
||||||
fillProxy: "public CLOB token price touched the resting bid after placement", noFillPnl: 0 },
|
fillProxy: "public CLOB token price touched the resting bid after placement",
|
||||||
|
hedgeProxy: "first complementary token history point plus exit cost; production must use a fresh executable ask",
|
||||||
|
noFillPnl: 0 },
|
||||||
partitionRows: Object.fromEntries(Object.entries(partitions).map(([key, value]) => [key, value.length])),
|
partitionRows: Object.fromEntries(Object.entries(partitions).map(([key, value]) => [key, value.length])),
|
||||||
trainPassed: evaluated.filter((candidate) => candidate.trainPassed).length, validationSelected: candidates.length,
|
trainPassed: evaluated.filter((candidate) => candidate.trainPassed).length, validationSelected: candidates.length,
|
||||||
holdoutPassed: candidates.filter((candidate) => candidate.passesHoldout).length,
|
holdoutPassed: candidates.filter((candidate) => candidate.passesHoldout).length,
|
||||||
@@ -224,7 +254,7 @@ if (SUMMARY_ONLY) {
|
|||||||
batchFailures: report.batchFailures, observations: report.observations, testedRules: report.testedRules,
|
batchFailures: report.batchFailures, observations: report.observations, testedRules: report.testedRules,
|
||||||
partitionRows: report.partitionRows, trainPassed: report.trainPassed, validationSelected: report.validationSelected,
|
partitionRows: report.partitionRows, trainPassed: report.trainPassed, validationSelected: report.validationSelected,
|
||||||
holdoutPassed: report.holdoutPassed,
|
holdoutPassed: report.holdoutPassed,
|
||||||
broadByGap: broadByGap.map((candidate) => ({ horizon: candidate.rule.horizon, gap: candidate.rule.gap,
|
broadByGap: broadByGap.map((candidate) => ({ mode: candidate.rule.mode, horizon: candidate.rule.horizon, gap: candidate.rule.gap,
|
||||||
trainLower: +candidate.train.lower.toFixed(5), validationLower: +candidate.validation.lower.toFixed(5),
|
trainLower: +candidate.train.lower.toFixed(5), validationLower: +candidate.validation.lower.toFixed(5),
|
||||||
holdoutMean: +candidate.holdout.eventMean.toFixed(5), holdoutLower: +candidate.holdout.lower.toFixed(5),
|
holdoutMean: +candidate.holdout.eventMean.toFixed(5), holdoutLower: +candidate.holdout.lower.toFixed(5),
|
||||||
holdoutLockedRate: +candidate.holdout.lockedRate.toFixed(4), holdoutAdverseRate: +candidate.holdout.adverseRate.toFixed(4) })),
|
holdoutLockedRate: +candidate.holdout.lockedRate.toFixed(4), holdoutAdverseRate: +candidate.holdout.adverseRate.toFixed(4) })),
|
||||||
|
|||||||
Reference in New Issue
Block a user