Verify negative-risk conversions on chain

This commit is contained in:
Theodore Song
2026-08-22 19:55:15 -04:00
parent c15dc12323
commit 6853821dc9
5 changed files with 201 additions and 59 deletions
+8 -5
View File
@@ -71,11 +71,14 @@ YES and NO amounts directly back into collateral, so a verified binary complemen
is merged and realized in the same paper cycle instead of waiting for resolution. is merged and realized in the same paper cycle instead of waiting for resolution.
The official negative-risk adapter also converts a complete set of NO tokens into The official negative-risk adapter also converts a complete set of NO tokens into
`n - 1` units of collateral, less the event's `negRiskFeeBips`. Strategy 65 treats `n - 1` units of collateral, less the event's `negRiskFeeBips`. Strategy 65 treats
that as a separate immediate path: every leg must expose one consistent that as a separate immediate path. The scanner reserves 20 of its 80 depth checks
`negRiskMarketID` and conversion fee, all asks and CLOB fee schedules must verify, for complete-NO candidates, then reads `getFeeBips` and `getQuestionCount` from the
and the post-conversion proceeds must remain profitable. Missing or inconsistent official Polygon adapter for only those candidates. Every leg must expose one
adapter metadata cannot produce paper P&L. Complete YES sets and logical dominance consistent `negRiskMarketID`, the event leg count must equal the on-chain question
pairs are not convertible and continue to use settlement or verified live-bid exits. count, all asks and CLOB fee schedules must verify, and the post-conversion proceeds
must remain profitable. Missing or inconsistent adapter data cannot produce paper
P&L. Complete YES sets and logical dominance pairs are not convertible and continue
to use settlement or verified live-bid exits.
Gasless CTF operations include merge transactions; see Gasless CTF operations include merge transactions; see
[Positions & Tokens](https://docs.polymarket.com/concepts/positions-tokens) and [Positions & Tokens](https://docs.polymarket.com/concepts/positions-tokens) and
[Gasless Transactions](https://docs.polymarket.com/trading/gasless). [Gasless Transactions](https://docs.polymarket.com/trading/gasless).
+5 -2
View File
@@ -289,8 +289,11 @@ export function compactSuggestion(s) {
promoted_for_agents: s.promoted_for_agents, promoted_for_agents: s.promoted_for_agents,
watch_only: s.watch_only, jump_risk: s.jump_risk, requires_live: s.requires_live, watch_only: s.watch_only, jump_risk: s.jump_risk, requires_live: s.requires_live,
bundle_id: s.bundle_id, bundle_event_id: s.bundle_event_id, bundle_side: s.bundle_side, bundle_logic: s.bundle_logic, bundle_id: s.bundle_id, bundle_event_id: s.bundle_event_id, bundle_side: s.bundle_side, bundle_logic: s.bundle_logic,
bundle_immediate_merge: s.bundle_immediate_merge, bundle_immediate_convert: s.bundle_immediate_convert, bundle_immediate_merge: s.bundle_immediate_merge, bundle_conversion_candidate: s.bundle_conversion_candidate,
neg_risk_market_id: s.neg_risk_market_id, neg_risk_fee_bips: s.neg_risk_fee_bips, bundle_conversion_terms_verified: s.bundle_conversion_terms_verified, bundle_immediate_convert: s.bundle_immediate_convert,
neg_risk_market_id: s.neg_risk_market_id, neg_risk_fee_bips: s.neg_risk_fee_bips, neg_risk_metadata_fee_bips: s.neg_risk_metadata_fee_bips,
neg_risk_question_count: s.neg_risk_question_count,
conversion_verification_status: s.conversion_verification_status,
bundle_cost_per_unit: s.bundle_cost_per_unit, bundle_payout_per_unit: s.bundle_payout_per_unit, bundle_cost_per_unit: s.bundle_cost_per_unit, bundle_payout_per_unit: s.bundle_payout_per_unit,
bundle_settlement_payout_per_unit: s.bundle_settlement_payout_per_unit, bundle_settlement_payout_per_unit: s.bundle_settlement_payout_per_unit,
bundle_net_profit_per_unit: s.bundle_net_profit_per_unit, bundle_net_profit_per_unit: s.bundle_net_profit_per_unit,
+146 -33
View File
@@ -1210,10 +1210,10 @@ function dominanceBundleSuggestions(event,{includeUnprofitable=false}={}){
} }
return candidates.sort(compareBundleOpportunities); return candidates.sort(compareBundleOpportunities);
} }
function negativeRiskBundleSuggestion(event,{includeUnprofitable=false}={}){ function negativeRiskBundleSuggestions(event,{includeUnprofitable=false,conversionTerms=null}={}){
if(!event||!event.negRisk||event.enableNegRisk===false)return null; if(!event||!event.negRisk||event.enableNegRisk===false)return [];
const rawLegs=Array.isArray(event.markets)?event.markets:[]; const rawLegs=Array.isArray(event.markets)?event.markets:[];
if(rawLegs.length<2||rawLegs.some(m=>m.closed||m.active===false||m.acceptingOrders===false))return null; if(rawLegs.length<2||rawLegs.some(m=>m.closed||m.active===false||m.acceptingOrders===false))return [];
const eventTags=Array.isArray(event.tags)?event.tags:[],category=classifyCategory(eventTags); const eventTags=Array.isArray(event.tags)?event.tags:[],category=classifyCategory(eventTags);
const quotes=rawLegs.map(raw=>{ const quotes=rawLegs.map(raw=>{
const outcomes=parseJsonField(raw.outcomes).map(outcome=>String(outcome||"").trim().toLowerCase()); const outcomes=parseJsonField(raw.outcomes).map(outcome=>String(outcome||"").trim().toLowerCase());
@@ -1225,16 +1225,22 @@ function negativeRiskBundleSuggestion(event,{includeUnprofitable=false}={}){
}); });
if(quotes.some(leg=>!leg.binary_labels||!leg.market_id||!leg.yes_token||!leg.no_token||!Number.isFinite(leg.yes_bid)||!Number.isFinite(leg.yes_ask) if(quotes.some(leg=>!leg.binary_labels||!leg.market_id||!leg.yes_token||!leg.no_token||!Number.isFinite(leg.yes_bid)||!Number.isFinite(leg.yes_ask)
||leg.yes_bid<0||leg.yes_ask>1||leg.yes_ask<leg.yes_bid||!Number.isFinite(leg.yes_mid)||!Number.isFinite(leg.no_mid) ||leg.yes_bid<0||leg.yes_ask>1||leg.yes_ask<leg.yes_bid||!Number.isFinite(leg.yes_mid)||!Number.isFinite(leg.no_mid)
||leg.liquidity<NEG_RISK_MIN_LIQUIDITY))return null; ||leg.liquidity<NEG_RISK_MIN_LIQUIDITY))return [];
const conversionIds=[event.negRiskMarketID,...rawLegs.map(raw=>raw.negRiskMarketID)].filter(value=>String(value||"").trim()).map(String); const conversionIds=[event.negRiskMarketID,...rawLegs.map(raw=>raw.negRiskMarketID)].filter(value=>String(value||"").trim()).map(String);
const conversionFees=[event.negRiskFeeBips,...rawLegs.map(raw=>raw.negRiskFeeBips)].filter(value=>value!==null&&value!==undefined&&value!=="").map(Number); const conversionFees=[event.negRiskFeeBips,...rawLegs.map(raw=>raw.negRiskFeeBips)].filter(value=>value!==null&&value!==undefined&&value!=="").map(Number);
const conversionMarketId=conversionIds.length&&new Set(conversionIds).size===1?conversionIds[0]:null; const conversionMarketId=conversionIds.length&&new Set(conversionIds).size===1?conversionIds[0]:null;
const conversionFeeBips=conversionFees.length&&conversionFees.every(value=>Number.isFinite(value)&&value>=0&&value<=10000) const metadataFeeBips=conversionFees.length&&conversionFees.every(value=>Number.isFinite(value)&&value>=0&&value<=10000)
&&new Set(conversionFees.map(value=>value.toFixed(8))).size===1?conversionFees[0]:null; &&new Set(conversionFees.map(value=>value.toFixed(8))).size===1?conversionFees[0]:null;
const conversionTermsVerified=Boolean(conversionMarketId&&conversionFeeBips!==null); const onchainTerms=conversionMarketId&&conversionTerms&&typeof conversionTerms.get==="function"?conversionTerms.get(conversionMarketId):null;
const onchainFeeBips=Number(onchainTerms&&onchainTerms.fee_bips),onchainQuestionCount=Number(onchainTerms&&onchainTerms.question_count);
const conversionTermsVerified=Boolean(conversionMarketId&&onchainTerms&&onchainTerms.status==="verified-onchain"
&&Number.isInteger(onchainQuestionCount)&&onchainQuestionCount===quotes.length
&&Number.isFinite(onchainFeeBips)&&onchainFeeBips>=0&&onchainFeeBips<=10000
&&(metadataFeeBips===null||Math.abs(metadataFeeBips-onchainFeeBips)<=1e-9));
const conversionFeeBips=conversionTermsVerified?onchainFeeBips:null;
const makeCandidate=(side)=>{ const makeCandidate=(side)=>{
const yesSide=side==="YES",settlementPayout=yesSide?1:quotes.length-1; const yesSide=side==="YES",settlementPayout=yesSide?1:quotes.length-1;
const immediateConvert=!yesSide&&conversionTermsVerified; const conversionCandidate=!yesSide&&Boolean(conversionMarketId),immediateConvert=conversionCandidate&&conversionTermsVerified;
const payout=immediateConvert?settlementPayout*(1-conversionFeeBips/10000):settlementPayout; const payout=immediateConvert?settlementPayout*(1-conversionFeeBips/10000):settlementPayout;
const legs=quotes.map(leg=>{ const legs=quotes.map(leg=>{
const topAsk=yesSide?leg.yes_ask:1-leg.yes_bid,feeReserve=bundleFeeReserve(leg.raw_market,topAsk),entry=topAsk+feeReserve,current=yesSide?leg.yes_mid:leg.no_mid; const topAsk=yesSide?leg.yes_ask:1-leg.yes_bid,feeReserve=bundleFeeReserve(leg.raw_market,topAsk),entry=topAsk+feeReserve,current=yesSide?leg.yes_mid:leg.no_mid;
@@ -1244,16 +1250,16 @@ function negativeRiskBundleSuggestion(event,{includeUnprofitable=false}={}){
}); });
if(legs.some(leg=>!Number.isFinite(leg.entry_price)||!Number.isFinite(leg.current_price)||leg.entry_price<=0||leg.entry_price>=1))return null; if(legs.some(leg=>!Number.isFinite(leg.entry_price)||!Number.isFinite(leg.current_price)||leg.entry_price<=0||leg.entry_price>=1))return null;
const cost=legs.reduce((sum,leg)=>sum+leg.entry_price,0),profit=payout-cost,netReturn=cost>0?profit/cost:0; const cost=legs.reduce((sum,leg)=>sum+leg.entry_price,0),profit=payout-cost,netReturn=cost>0?profit/cost:0;
return {side,legs,cost,payout,settlementPayout,profit,netReturn,immediateConvert}; return {side,legs,cost,payout,settlementPayout,profit,netReturn,conversionCandidate,immediateConvert};
}; };
const candidate=[makeCandidate("YES"),makeCandidate("NO")].filter(Boolean) const candidates=[makeCandidate("YES"),makeCandidate("NO")].filter(Boolean)
.filter(x=>includeUnprofitable||(x.profit>=NEG_RISK_MIN_NET_PROFIT&&x.netReturn>=NEG_RISK_MIN_NET_RETURN)) .filter(x=>includeUnprofitable||(x.profit>=NEG_RISK_MIN_NET_PROFIT&&x.netReturn>=NEG_RISK_MIN_NET_RETURN))
.sort((a,b)=>{ .sort((a,b)=>{
const days=Math.max(1,Number(daysUntil(event.endDate))||365); const days=Math.max(1,Number(daysUntil(event.endDate))||365);
return (b.netReturn/(b.immediateConvert?1:days))-(a.netReturn/(a.immediateConvert?1:days))||b.netReturn-a.netReturn; return (b.netReturn/(b.immediateConvert?1:days))-(a.netReturn/(a.immediateConvert?1:days))||b.netReturn-a.netReturn;
})[0]; });
if(!candidate)return null; return candidates.map(candidate=>{
const {side,legs,cost,payout,settlementPayout,profit,netReturn,immediateConvert}=candidate,minLiquidity=Math.min(...legs.map(leg=>leg.liquidity)); const {side,legs,cost,payout,settlementPayout,profit,netReturn,conversionCandidate,immediateConvert}=candidate,minLiquidity=Math.min(...legs.map(leg=>leg.liquidity));
const actionable=profit>=NEG_RISK_MIN_NET_PROFIT&&netReturn>=NEG_RISK_MIN_NET_RETURN; const actionable=profit>=NEG_RISK_MIN_NET_PROFIT&&netReturn>=NEG_RISK_MIN_NET_RETURN;
return {market_id:`bundle:${event.id}:${side.toLowerCase()}`,bundle_id:`bundle:${event.id}:${side.toLowerCase()}`,bundle_event_id:String(event.id||""),bundle_side:side, return {market_id:`bundle:${event.id}:${side.toLowerCase()}`,bundle_id:`bundle:${event.id}:${side.toLowerCase()}`,bundle_event_id:String(event.id||""),bundle_side:side,
question:`Complete ${side} bundle: ${event.title||"multi-outcome event"}`,event:event.title||"", question:`Complete ${side} bundle: ${event.title||"multi-outcome event"}`,event:event.title||"",
@@ -1266,16 +1272,21 @@ function negativeRiskBundleSuggestion(event,{includeUnprofitable=false}={}){
spread:Math.max(...rawLegs.map(m=>toNum(m.spread))),price_change_1h:0,price_change_1d:0,price_change_1w:0,momentum_strength:0, spread:Math.max(...rawLegs.map(m=>toNum(m.spread))),price_change_1h:0,price_change_1d:0,price_change_1w:0,momentum_strength:0,
signal_strength:1,signal_confidence:1,signal_type:"bundle-arb",trade_ready:actionable,entry_candidate:actionable,audited_observation_only:!actionable, signal_strength:1,signal_confidence:1,signal_type:"bundle-arb",trade_ready:actionable,entry_candidate:actionable,audited_observation_only:!actionable,
adaptive_promotion:false,watch_only:!actionable,jump_risk:false,requires_live:true,opportunity_actionable:actionable,days_to_resolution:daysUntil(event.endDate), adaptive_promotion:false,watch_only:!actionable,jump_risk:false,requires_live:true,opportunity_actionable:actionable,days_to_resolution:daysUntil(event.endDate),
bundle_logic:`neg-risk-complete-${side.toLowerCase()}`,bundle_immediate_convert:immediateConvert, bundle_logic:`neg-risk-complete-${side.toLowerCase()}`,bundle_conversion_candidate:conversionCandidate,
neg_risk_market_id:immediateConvert?conversionMarketId:null,neg_risk_fee_bips:immediateConvert?conversionFeeBips:null, bundle_conversion_terms_verified:immediateConvert,bundle_immediate_convert:immediateConvert,
neg_risk_market_id:conversionCandidate?conversionMarketId:null,neg_risk_fee_bips:immediateConvert?conversionFeeBips:null,
neg_risk_metadata_fee_bips:conversionCandidate?metadataFeeBips:null,neg_risk_question_count:immediateConvert?onchainQuestionCount:null,
conversion_verification_status:immediateConvert?"verified-onchain":(conversionCandidate?"onchain-terms-pending":null),
bundle_cost_per_unit:+cost.toFixed(4),bundle_payout_per_unit:+payout.toFixed(8),bundle_settlement_payout_per_unit:settlementPayout, bundle_cost_per_unit:+cost.toFixed(4),bundle_payout_per_unit:+payout.toFixed(8),bundle_settlement_payout_per_unit:settlementPayout,
bundle_net_profit_per_unit:+profit.toFixed(4),bundle_legs:legs, bundle_net_profit_per_unit:+profit.toFixed(4),bundle_legs:legs,
depth_verified:false,fees_verified:false,execution_model:"top-of-book-estimate", depth_verified:false,fees_verified:false,execution_model:"top-of-book-estimate",
drivers:["complete negative-risk event",immediateConvert?"exact adapter conversion payout":"guaranteed settlement payout","executable bid/ask gap","positive margin after estimated costs"], drivers:["complete negative-risk event",immediateConvert?"exact adapter conversion payout":(conversionCandidate?"on-chain conversion terms pending":"guaranteed settlement payout"),"executable bid/ask gap","positive margin after estimated costs"],
rationale:immediateConvert rationale:immediateConvert
?`Complete NO conversion: buy every NO leg together for ${cost.toFixed(3)} per bundle unit, then atomically convert them through Polymarket's negative-risk adapter for ${payout.toFixed(4)} collateral after the exact ${conversionFeeBips.toFixed(2)} bps event conversion fee. The preliminary immediate margin is ${profit.toFixed(3)} (${(netReturn*100).toFixed(2)}%); every live ask, CLOB fee schedule, event market ID, and conversion fee must still verify before entry.` ?`Complete NO conversion: buy every NO leg together for ${cost.toFixed(3)} per bundle unit, then atomically convert them through Polymarket's negative-risk adapter for ${payout.toFixed(4)} collateral after the exact ${conversionFeeBips.toFixed(2)} bps event conversion fee. The preliminary immediate margin is ${profit.toFixed(3)} (${(netReturn*100).toFixed(2)}%); every live ask, CLOB fee schedule, event market ID, and conversion fee must still verify before entry.`
:`Complete bundle: buy every ${side} leg together for ${cost.toFixed(3)} per bundle unit against a ${payout.toFixed(2)} worst-case settlement payout. The preliminary margin is ${profit.toFixed(3)} (${(netReturn*100).toFixed(2)}%); a live depth and market-specific fee check is required before entry. This must stay intact until settlement.`}; :`Complete bundle: buy every ${side} leg together for ${cost.toFixed(3)} per bundle unit against a ${payout.toFixed(2)} worst-case settlement payout. The preliminary margin is ${profit.toFixed(3)} (${(netReturn*100).toFixed(2)}%). ${conversionCandidate?"The adapter fee and full on-chain question count must verify before this can be treated as an immediate conversion.":"A live depth and market-specific fee check is required before entry; this must stay intact until settlement."}`};
});
} }
function negativeRiskBundleSuggestion(event,options={}){return negativeRiskBundleSuggestions(event,options)[0]||null;}
function binaryComplementBundleSuggestions(event,{includeUnprofitable=false}={}){ function binaryComplementBundleSuggestions(event,{includeUnprofitable=false}={}){
if(!event)return []; if(!event)return [];
const eventTags=Array.isArray(event.tags)?event.tags:[],category=classifyCategory(eventTags),eventId=String(event.id||event.slug||""); const eventTags=Array.isArray(event.tags)?event.tags:[],category=classifyCategory(eventTags),eventId=String(event.id||event.slug||"");
@@ -1426,10 +1437,11 @@ function prioritizeIndependentBundles(candidates,limit=Infinity){
} }
function bundleVerificationShortlist(candidates){ function bundleVerificationShortlist(candidates){
const ranked=(candidates||[]).slice().sort(compareBundleOpportunities); const ranked=(candidates||[]).slice().sort(compareBundleOpportunities);
const general=prioritizeIndependentBundles(ranked.filter(candidate=>candidate.bundle_logic!=="binary-complement"), const conversion=prioritizeIndependentBundles(ranked.filter(candidate=>candidate.bundle_conversion_candidate),NEG_RISK_CONVERSION_DEPTH_RESERVE);
BUNDLE_DEPTH_CANDIDATE_LIMIT-BINARY_COMPLEMENT_DEPTH_RESERVE);
const binary=prioritizeIndependentBundles(ranked.filter(candidate=>candidate.bundle_logic==="binary-complement"),BINARY_COMPLEMENT_DEPTH_RESERVE); const binary=prioritizeIndependentBundles(ranked.filter(candidate=>candidate.bundle_logic==="binary-complement"),BINARY_COMPLEMENT_DEPTH_RESERVE);
const selected=[...general,...binary],selectedIds=new Set(selected.map(candidate=>String(candidate.bundle_id||candidate.market_id||""))); const general=prioritizeIndependentBundles(ranked.filter(candidate=>candidate.bundle_logic!=="binary-complement"&&!candidate.bundle_conversion_candidate),
BUNDLE_DEPTH_CANDIDATE_LIMIT-BINARY_COMPLEMENT_DEPTH_RESERVE-NEG_RISK_CONVERSION_DEPTH_RESERVE);
const selected=[...conversion,...general,...binary],selectedIds=new Set(selected.map(candidate=>String(candidate.bundle_id||candidate.market_id||"")));
const remaining=prioritizeIndependentBundles(ranked.filter(candidate=>!selectedIds.has(String(candidate.bundle_id||candidate.market_id||""))), const remaining=prioritizeIndependentBundles(ranked.filter(candidate=>!selectedIds.has(String(candidate.bundle_id||candidate.market_id||""))),
BUNDLE_DEPTH_CANDIDATE_LIMIT-selected.length); BUNDLE_DEPTH_CANDIDATE_LIMIT-selected.length);
return [...selected,...remaining]; return [...selected,...remaining];
@@ -1491,8 +1503,65 @@ async function fetchBundleFeeSchedules(conditionIds){
}); });
await Promise.all(workers);return results; await Promise.all(workers);return results;
} }
function validNegativeRiskMarketId(value){return /^0x[0-9a-f]{64}$/i.test(String(value||""));}
async function fetchNegativeRiskConversionTerms(marketIds){
const unique=[...new Set((marketIds||[]).map(String).filter(validNegativeRiskMarketId))],terms=new Map();
if(!unique.length)return terms;
const requests=[],requestMeta=new Map();let requestId=1;
unique.forEach(marketId=>{
[[NEG_RISK_FEE_BIPS_SELECTOR,"fee_bips"],[NEG_RISK_QUESTION_COUNT_SELECTOR,"question_count"]].forEach(([selector,field])=>{
const id=requestId++;requestMeta.set(id,{marketId,field});requests.push({jsonrpc:"2.0",id,method:"eth_call",
params:[{to:NEG_RISK_ADAPTER_ADDRESS,data:`${selector}${marketId.slice(2)}`},"latest"]});
});
});
try{
const partial=new Map();
for(let offset=0;offset<requests.length;offset+=NEG_RISK_RPC_BATCH_CALL_LIMIT){
const batch=requests.slice(offset,offset+NEG_RISK_RPC_BATCH_CALL_LIMIT);
const response=await fetchWithTimeout(NEG_RISK_POLYGON_RPC,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(batch)});
if(!response.ok)continue;
const payload=await response.json();
(Array.isArray(payload)?payload:[payload]).forEach(row=>{
const meta=requestMeta.get(Number(row&&row.id));if(!meta||typeof row.result!=="string"||!/^0x[0-9a-f]+$/i.test(row.result))return;
let value;try{value=Number(BigInt(row.result));}catch(e){return;}
if(!Number.isSafeInteger(value)||value<0)return;
const current=partial.get(meta.marketId)||{};current[meta.field]=value;partial.set(meta.marketId,current);
});
}
unique.forEach(marketId=>{
const current=partial.get(marketId);if(!current)return;
const fee=Number(current.fee_bips),count=Number(current.question_count);
if(Number.isInteger(fee)&&fee>=0&&fee<=10000&&Number.isInteger(count)&&count>=2&&count<=255){
terms.set(marketId,{status:"verified-onchain",fee_bips:fee,question_count:count});
}
});
}catch(e){}
return terms;
}
function applyNegativeRiskConversionTerms(candidate,terms){
if(!candidate||!candidate.bundle_conversion_candidate)return candidate;
const marketId=String(candidate.neg_risk_market_id||""),term=terms&&terms.get(marketId),legCount=(candidate.bundle_legs||[]).length;
const hasMetadataFee=candidate.neg_risk_metadata_fee_bips!==null&&candidate.neg_risk_metadata_fee_bips!==undefined;
const metadataFee=Number(candidate.neg_risk_metadata_fee_bips),metadataMatches=!hasMetadataFee
||(Number.isFinite(metadataFee)&&Math.abs(metadataFee-Number(term&&term.fee_bips))<=1e-9);
const verified=Boolean(term&&term.status==="verified-onchain"&&Number(term.question_count)===legCount
&&Number.isFinite(Number(term.fee_bips))&&Number(term.fee_bips)>=0&&Number(term.fee_bips)<=10000&&metadataMatches);
if(!verified)return Object.assign({},candidate,{bundle_conversion_terms_verified:false,bundle_immediate_convert:false,
neg_risk_fee_bips:null,neg_risk_question_count:term?Number(term.question_count):null,
conversion_verification_status:!term?"onchain-terms-unavailable":(!metadataMatches?"metadata-fee-mismatch":"question-count-mismatch")});
const feeBips=Number(term.fee_bips),settlementPayout=Number(candidate.bundle_settlement_payout_per_unit),cost=Number(candidate.bundle_cost_per_unit);
const payout=settlementPayout*(1-feeBips/10000),profit=payout-cost,netReturn=cost>0?profit/cost:0;
return Object.assign({},candidate,{bundle_conversion_terms_verified:true,bundle_immediate_convert:true,neg_risk_fee_bips:feeBips,
neg_risk_question_count:Number(term.question_count),conversion_verification_status:"verified-onchain",
bundle_payout_per_unit:+payout.toFixed(8),bundle_net_profit_per_unit:+profit.toFixed(6),edge:+netReturn.toFixed(6),net_edge:+netReturn.toFixed(6),
drivers:[...(candidate.drivers||[]).filter(driver=>driver!=="on-chain conversion terms pending"&&driver!=="guaranteed settlement payout"),"exact adapter conversion payout"],
rationale:`Complete NO conversion: buy every NO leg together, then atomically convert the full ${legCount}-question set through Polymarket's negative-risk adapter for ${payout.toFixed(4)} collateral per unit after the on-chain ${feeBips.toFixed(2)} bps conversion fee. Live order-book depth and every market-specific CLOB fee must still verify before entry.`});
}
async function verifyExecutableBundles(candidates){ async function verifyExecutableBundles(candidates){
const shortlist=bundleVerificationShortlist(candidates); const initialShortlist=bundleVerificationShortlist(candidates);
const conversionTerms=await fetchNegativeRiskConversionTerms(initialShortlist.filter(candidate=>candidate.bundle_conversion_candidate)
.map(candidate=>candidate.neg_risk_market_id));
const shortlist=initialShortlist.map(candidate=>applyNegativeRiskConversionTerms(candidate,conversionTerms));
const tokenIds=shortlist.flatMap(candidate=>(candidate.bundle_legs||[]).map(leg=>leg.token_id)); const tokenIds=shortlist.flatMap(candidate=>(candidate.bundle_legs||[]).map(leg=>leg.token_id));
const books=await fetchBundleBooks(tokenIds),depthChecked=shortlist.map(candidate=>{ const books=await fetchBundleBooks(tokenIds),depthChecked=shortlist.map(candidate=>{
const estimatedCost=Number(candidate.bundle_cost_per_unit),requiredUnits=bundleMinimumExecutionUnits(Math.max(estimatedCost,0.01)); const estimatedCost=Number(candidate.bundle_cost_per_unit),requiredUnits=bundleMinimumExecutionUnits(Math.max(estimatedCost,0.01));
@@ -1539,8 +1608,8 @@ async function fetchNegativeRiskBundles(limit=NEG_RISK_EVENT_SCAN_LIMIT){
events.push(...page);if(page.length<size)break; events.push(...page);if(page.length<size)break;
} }
const audited=events.flatMap(event=>{ const audited=events.flatMap(event=>{
const complete=negativeRiskBundleSuggestion(event,{includeUnprofitable:true}); const complete=negativeRiskBundleSuggestions(event,{includeUnprofitable:true});
return [...(complete?[complete]:[]),...dominanceBundleSuggestions(event,{includeUnprofitable:true}), return [...complete,...dominanceBundleSuggestions(event,{includeUnprofitable:true}),
...binaryComplementBundleSuggestions(event,{includeUnprofitable:true})]; ...binaryComplementBundleSuggestions(event,{includeUnprofitable:true})];
}).sort(compareBundleOpportunities); }).sort(compareBundleOpportunities);
const executableAudit=await verifyExecutableBundles(audited); const executableAudit=await verifyExecutableBundles(audited);
@@ -1549,9 +1618,19 @@ async function fetchNegativeRiskBundles(limit=NEG_RISK_EVENT_SCAN_LIMIT){
const unique=candidates.filter(candidate=>{const id=String(candidate.bundle_id||candidate.market_id);if(!id||seen.has(id))return false;seen.add(id);return true;}); const unique=candidates.filter(candidate=>{const id=String(candidate.bundle_id||candidate.market_id);if(!id||seen.has(id))return false;seen.add(id);return true;});
const prioritized=prioritizeIndependentBundles(unique,20); const prioritized=prioritizeIndependentBundles(unique,20);
const closest=executableAudit.find(candidate=>candidate.depth_verified)||executableAudit[0]||null; const closest=executableAudit.find(candidate=>candidate.depth_verified)||executableAudit[0]||null;
const conversions=executableAudit.filter(candidate=>candidate.bundle_conversion_candidate);
const closestConversion=conversions.find(candidate=>candidate.depth_verified)||conversions[0]||null;
return {candidates:prioritized,audit:{status:"ok",scanned_at:nowIso(),event_scan_limit:limit,events_scanned:events.length, return {candidates:prioritized,audit:{status:"ok",scanned_at:nowIso(),event_scan_limit:limit,events_scanned:events.length,
evaluated_structures:audited.length,depth_checked_structures:executableAudit.length,depth_verified_structures:executableAudit.filter(candidate=>candidate.depth_verified).length, evaluated_structures:audited.length,depth_checked_structures:executableAudit.length,depth_verified_structures:executableAudit.filter(candidate=>candidate.depth_verified).length,
fee_verified_structures:executableAudit.filter(candidate=>candidate.fees_verified).length,actionable_bundles:unique.length, fee_verified_structures:executableAudit.filter(candidate=>candidate.fees_verified).length,actionable_bundles:unique.length,
conversion_candidates_scanned:audited.filter(candidate=>candidate.bundle_conversion_candidate).length,
conversion_structures:conversions.length,conversion_depth_verified:conversions.filter(candidate=>candidate.depth_verified).length,
conversion_terms_verified:conversions.filter(candidate=>candidate.bundle_conversion_terms_verified).length,
conversion_fee_verified:conversions.filter(candidate=>candidate.fees_verified).length,
actionable_conversions:unique.filter(candidate=>candidate.bundle_immediate_convert).length,
closest_conversion_margin_cents:closestConversion?+(Number(closestConversion.bundle_net_profit_per_unit)*100).toFixed(2):null,
closest_conversion_return_pct:closestConversion?+(Number(closestConversion.net_edge)*100).toFixed(3):null,
closest_conversion_title:closestConversion?closestConversion.question:null,
actionable_events:new Set(unique.map(bundleEventKey).filter(Boolean)).size,returned_events:new Set(prioritized.map(bundleEventKey).filter(Boolean)).size, actionable_events:new Set(unique.map(bundleEventKey).filter(Boolean)).size,returned_events:new Set(prioritized.map(bundleEventKey).filter(Boolean)).size,
closest_margin_cents:closest?+(Number(closest.bundle_net_profit_per_unit)*100).toFixed(2):null, closest_margin_cents:closest?+(Number(closest.bundle_net_profit_per_unit)*100).toFixed(2):null,
closest_return_pct:closest?+(Number(closest.net_edge)*100).toFixed(3):null, closest_return_pct:closest?+(Number(closest.net_edge)*100).toFixed(3):null,
@@ -1609,6 +1688,12 @@ const NEG_RISK_MIN_NET_RETURN=0.0015;
const BUNDLE_BOOK_BATCH_SIZE=200; const BUNDLE_BOOK_BATCH_SIZE=200;
const BUNDLE_DEPTH_CANDIDATE_LIMIT=80; const BUNDLE_DEPTH_CANDIDATE_LIMIT=80;
const BINARY_COMPLEMENT_DEPTH_RESERVE=20; const BINARY_COMPLEMENT_DEPTH_RESERVE=20;
const NEG_RISK_CONVERSION_DEPTH_RESERVE=20;
const NEG_RISK_POLYGON_RPC="https://polygon.drpc.org";
const NEG_RISK_ADAPTER_ADDRESS="0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296";
const NEG_RISK_FEE_BIPS_SELECTOR="0x2582cb5e";
const NEG_RISK_QUESTION_COUNT_SELECTOR="0xb7f75d2c";
const NEG_RISK_RPC_BATCH_CALL_LIMIT=10;
const BUNDLE_FEE_CONCURRENCY=8; const BUNDLE_FEE_CONCURRENCY=8;
const BUNDLE_MIN_NOTIONAL=50; const BUNDLE_MIN_NOTIONAL=50;
const BUNDLE_MIN_UNITS=5; const BUNDLE_MIN_UNITS=5;
@@ -2158,8 +2243,11 @@ function compactSuggestionForSync(s){
adaptive_promotion:s.adaptive_promotion,adaptive_probation:s.adaptive_probation, adaptive_promotion:s.adaptive_promotion,adaptive_probation:s.adaptive_probation,
probation_exit_hours:s.probation_exit_hours,promoted_for_agents:s.promoted_for_agents,watch_only:s.watch_only,jump_risk:s.jump_risk, probation_exit_hours:s.probation_exit_hours,promoted_for_agents:s.promoted_for_agents,watch_only:s.watch_only,jump_risk:s.jump_risk,
requires_live:s.requires_live,bundle_id:s.bundle_id,bundle_event_id:s.bundle_event_id,bundle_side:s.bundle_side,bundle_logic:s.bundle_logic, requires_live:s.requires_live,bundle_id:s.bundle_id,bundle_event_id:s.bundle_event_id,bundle_side:s.bundle_side,bundle_logic:s.bundle_logic,
bundle_immediate_merge:s.bundle_immediate_merge,bundle_immediate_convert:s.bundle_immediate_convert, bundle_immediate_merge:s.bundle_immediate_merge,bundle_conversion_candidate:s.bundle_conversion_candidate,
neg_risk_market_id:s.neg_risk_market_id,neg_risk_fee_bips:s.neg_risk_fee_bips, bundle_conversion_terms_verified:s.bundle_conversion_terms_verified,bundle_immediate_convert:s.bundle_immediate_convert,
neg_risk_market_id:s.neg_risk_market_id,neg_risk_fee_bips:s.neg_risk_fee_bips,neg_risk_metadata_fee_bips:s.neg_risk_metadata_fee_bips,
neg_risk_question_count:s.neg_risk_question_count,
conversion_verification_status:s.conversion_verification_status,
bundle_cost_per_unit:s.bundle_cost_per_unit,bundle_payout_per_unit:s.bundle_payout_per_unit, bundle_cost_per_unit:s.bundle_cost_per_unit,bundle_payout_per_unit:s.bundle_payout_per_unit,
bundle_settlement_payout_per_unit:s.bundle_settlement_payout_per_unit,bundle_net_profit_per_unit:s.bundle_net_profit_per_unit,bundle_legs:s.bundle_legs, bundle_settlement_payout_per_unit:s.bundle_settlement_payout_per_unit,bundle_net_profit_per_unit:s.bundle_net_profit_per_unit,bundle_legs:s.bundle_legs,
bundle_capital_efficiency:s.bundle_capital_efficiency, bundle_capital_efficiency:s.bundle_capital_efficiency,
@@ -2624,10 +2712,12 @@ function convertibleNegativeRiskNoBundleGroup(group){
if(!Array.isArray(group)||group.length<2)return false; if(!Array.isArray(group)||group.length<2)return false;
const expected=Math.max(...group.map(pos=>Number(pos.bundle_leg_count||0))); const expected=Math.max(...group.map(pos=>Number(pos.bundle_leg_count||0)));
const marketIds=new Set(group.map(pos=>String(pos.market_id||""))),adapterIds=new Set(group.map(pos=>String(pos.neg_risk_market_id||""))); const marketIds=new Set(group.map(pos=>String(pos.market_id||""))),adapterIds=new Set(group.map(pos=>String(pos.neg_risk_market_id||"")));
const feeBips=group.map(pos=>Number(pos.neg_risk_fee_bips)); const feeBips=group.map(pos=>Number(pos.neg_risk_fee_bips)),questionCounts=group.map(pos=>Number(pos.neg_risk_question_count));
return group.length===expected&&marketIds.size===expected&&adapterIds.size===1&&Boolean([...adapterIds][0]) return group.length===expected&&marketIds.size===expected&&adapterIds.size===1&&Boolean([...adapterIds][0])
&&group.every(pos=>pos.side==="NO"&&pos.bundle_immediate_convert&&pos.bundle_logic==="neg-risk-complete-no"&&Number(pos.shares)>0) &&group.every(pos=>pos.side==="NO"&&pos.bundle_conversion_terms_verified&&pos.bundle_immediate_convert
&&feeBips.every(value=>Number.isFinite(value)&&value>=0&&value<=10000&&Math.abs(value-feeBips[0])<=1e-9); &&pos.bundle_logic==="neg-risk-complete-no"&&Number(pos.shares)>0)
&&feeBips.every(value=>Number.isFinite(value)&&value>=0&&value<=10000&&Math.abs(value-feeBips[0])<=1e-9)
&&questionCounts.every(value=>Number.isInteger(value)&&value===expected);
} }
function convertCompleteNegativeRiskNoBundle(p,bundleId){ function convertCompleteNegativeRiskNoBundle(p,bundleId){
const group=completeBundleGroups(p).find(rows=>String(rows[0]&&rows[0].bundle_id||"")===String(bundleId||"")); const group=completeBundleGroups(p).find(rows=>String(rows[0]&&rows[0].bundle_id||"")===String(bundleId||""));
@@ -4350,6 +4440,7 @@ function rankSuggestionsForAgent(cfg,suggestions){
function openNegativeRiskBundle(p,cfg,s,stake,decision){ function openNegativeRiskBundle(p,cfg,s,stake,decision){
const legs=Array.isArray(s.bundle_legs)?s.bundle_legs:[],unitCost=Number(s.bundle_cost_per_unit),verifiedUnits=Number(s.execution_units); const legs=Array.isArray(s.bundle_legs)?s.bundle_legs:[],unitCost=Number(s.bundle_cost_per_unit),verifiedUnits=Number(s.execution_units);
if(legs.length<2||!s.depth_verified||!s.fees_verified||s.verification_status!=="executable" if(legs.length<2||!s.depth_verified||!s.fees_verified||s.verification_status!=="executable"
||(s.bundle_immediate_convert&&!s.bundle_conversion_terms_verified)
||!(verifiedUnits>0)||!(unitCost>0)||!(Number(s.bundle_net_profit_per_unit)>0))return null; ||!(verifiedUnits>0)||!(unitCost>0)||!(Number(s.bundle_net_profit_per_unit)>0))return null;
const units=+Math.min(verifiedUnits,Math.max(0,stake)/unitCost).toFixed(2);if(units<=0)return null; const units=+Math.min(verifiedUnits,Math.max(0,stake)/unitCost).toFixed(2);if(units<=0)return null;
const bundleSide=s.bundle_side||s.side||"NO"; const bundleSide=s.bundle_side||s.side||"NO";
@@ -4363,8 +4454,11 @@ function openNegativeRiskBundle(p,cfg,s,stake,decision){
momentum_strength:0,signal_strength:1,signal_confidence:1,signal_type:"bundle-arb",price_change_1d:0,price_change_1w:0, momentum_strength:0,signal_strength:1,signal_confidence:1,signal_type:"bundle-arb",price_change_1d:0,price_change_1w:0,
days_to_resolution:s.days_to_resolution,jump_risk:false,bundle_id:s.bundle_id,bundle_event_id:bundleEventKey(s),bundle_name:s.event||s.question,bundle_leg_count:legs.length, days_to_resolution:s.days_to_resolution,jump_risk:false,bundle_id:s.bundle_id,bundle_event_id:bundleEventKey(s),bundle_name:s.event||s.question,bundle_leg_count:legs.length,
bundle_payout_per_unit:s.bundle_payout_per_unit,bundle_net_profit_per_unit:s.bundle_net_profit_per_unit,requires_complete_bundle:true, bundle_payout_per_unit:s.bundle_payout_per_unit,bundle_net_profit_per_unit:s.bundle_net_profit_per_unit,requires_complete_bundle:true,
bundle_logic:s.bundle_logic||null,bundle_immediate_merge:Boolean(s.bundle_immediate_merge),bundle_immediate_convert:Boolean(s.bundle_immediate_convert), bundle_logic:s.bundle_logic||null,bundle_immediate_merge:Boolean(s.bundle_immediate_merge),bundle_conversion_candidate:Boolean(s.bundle_conversion_candidate),
neg_risk_market_id:s.neg_risk_market_id||null,neg_risk_fee_bips:s.neg_risk_fee_bips==null?null:Number(s.neg_risk_fee_bips),fee_schedule:leg.fee_schedule||null, bundle_conversion_terms_verified:Boolean(s.bundle_conversion_terms_verified),bundle_immediate_convert:Boolean(s.bundle_immediate_convert),
neg_risk_market_id:s.neg_risk_market_id||null,neg_risk_fee_bips:s.neg_risk_fee_bips==null?null:Number(s.neg_risk_fee_bips),
neg_risk_metadata_fee_bips:s.neg_risk_metadata_fee_bips==null?null:Number(s.neg_risk_metadata_fee_bips),
neg_risk_question_count:s.neg_risk_question_count==null?null:Number(s.neg_risk_question_count),fee_schedule:leg.fee_schedule||null,
learning_score:0,learning_confidence:0,market_learning_score:0,market_learning_confidence:0,learning_state:"priced-bundle",market_learning_state:"priced-bundle", learning_score:0,learning_confidence:0,market_learning_score:0,market_learning_confidence:0,learning_state:"priced-bundle",market_learning_state:"priced-bundle",
historical_prior_score:0,historical_prior_confidence:0,historical_prior_features:[],historical_requires_promotion:false, historical_prior_score:0,historical_prior_confidence:0,historical_prior_features:[],historical_requires_promotion:false,
learning_multiplier:1,learning_exploration:false,risk_budget_pct:+(tradeLossBudgetPct(cfg,s)*100).toFixed(2), learning_multiplier:1,learning_exploration:false,risk_budget_pct:+(tradeLossBudgetPct(cfg,s)*100).toFixed(2),
@@ -4736,7 +4830,9 @@ async function runDailyCycle(){
setStatus(`analyzing ${analysisMarkets.length.toLocaleString()} most-active markets…`,true); setStatus(`analyzing ${analysisMarkets.length.toLocaleString()} most-active markets…`,true);
setStatus("checking complete live-priced event bundles…",true); setStatus("checking complete live-priced event bundles…",true);
try{const bundleScan=await fetchNegativeRiskBundles();bundleSugs=bundleScan.candidates;bundleAudit=bundleScan.audit;} try{const bundleScan=await fetchNegativeRiskBundles();bundleSugs=bundleScan.candidates;bundleAudit=bundleScan.audit;}
catch(e){bundleSugs=[];bundleAudit={status:"unavailable",scanned_at:nowIso(),event_scan_limit:NEG_RISK_EVENT_SCAN_LIMIT,events_scanned:0,evaluated_structures:0,actionable_bundles:0,error:String(e&&e.message||e)};} catch(e){bundleSugs=[];bundleAudit={status:"unavailable",scanned_at:nowIso(),event_scan_limit:NEG_RISK_EVENT_SCAN_LIMIT,events_scanned:0,evaluated_structures:0,
conversion_candidates_scanned:0,conversion_structures:0,conversion_terms_verified:0,conversion_depth_verified:0,conversion_fee_verified:0,actionable_conversions:0,
actionable_bundles:0,error:String(e&&e.message||e)};}
setStatus("measuring reward-book competition…",true); setStatus("measuring reward-book competition…",true);
try{makerAuditCandidates=await fetchRewardMakerCandidates();}catch(e){makerAuditCandidates=[];} try{makerAuditCandidates=await fetchRewardMakerCandidates();}catch(e){makerAuditCandidates=[];}
setStatus("checking real-world context…",true); setStatus("checking real-world context…",true);
@@ -5327,7 +5423,7 @@ function renderSuggestions(){
const analyzed=Number(data.analyzed_count||data.market_count||0).toLocaleString(); const analyzed=Number(data.analyzed_count||data.market_count||0).toLocaleString();
const audit=data.opportunity_audit||null; const audit=data.opportunity_audit||null;
const auditText=audit&&audit.status==="ok" const auditText=audit&&audit.status==="ok"
?` Bundle scanner checked ${Number(audit.events_scanned||0).toLocaleString()} events and ${Number(audit.evaluated_structures||0).toLocaleString()} complete, dominance, and binary-complement structures, depth-tested ${Number(audit.depth_checked_structures||0)}, and found ${Number(audit.depth_verified_structures||0)} with $50 depth; ${Number(audit.actionable_bundles||0)} also cleared the market-specific fee and profit gates.${audit.closest_margin_cents!=null?` Closest depth-tested margin: ${Number(audit.closest_margin_cents)>=0?"+":""}${Number(audit.closest_margin_cents).toFixed(2)}c per bundle.`:""}` ?` Bundle scanner checked ${Number(audit.events_scanned||0).toLocaleString()} events and ${Number(audit.evaluated_structures||0).toLocaleString()} complete, dominance, and binary-complement structures, depth-tested ${Number(audit.depth_checked_structures||0)}, and found ${Number(audit.depth_verified_structures||0)} with $50 depth; ${Number(audit.actionable_bundles||0)} also cleared the market-specific fee and profit gates. Exact complete-NO conversion: ${Number(audit.conversion_candidates_scanned||0)} discovered, ${Number(audit.conversion_structures||0)} depth-tested in its reserved lane, ${Number(audit.conversion_terms_verified||0)} adapter-verified, ${Number(audit.conversion_depth_verified||0)} depth-verified, ${Number(audit.conversion_fee_verified||0)} CLOB-fee-verified, ${Number(audit.actionable_conversions||0)} actionable.${audit.closest_conversion_margin_cents!=null?` Closest conversion margin: ${Number(audit.closest_conversion_margin_cents)>=0?"+":""}${Number(audit.closest_conversion_margin_cents).toFixed(2)}c (${Number(audit.closest_conversion_return_pct)>=0?"+":""}${Number(audit.closest_conversion_return_pct).toFixed(2)}%).`:""}${audit.closest_margin_cents!=null?` Closest overall depth-tested margin: ${Number(audit.closest_margin_cents)>=0?"+":""}${Number(audit.closest_margin_cents).toFixed(2)}c per bundle.`:""}`
:(audit?" Bundle scanner was unavailable during this cycle; the site did not treat cached bundle prices as executable.":""); :(audit?" Bundle scanner was unavailable during this cycle; the site did not treat cached bundle prices as executable.":"");
$("focusNote").textContent=focus==="All" $("focusNote").textContent=focus==="All"
? `Loaded the ${scanned} most active markets, analyzed ${analyzed}, and kept ${all.length} ideas (${buyCount} TRADE READY, ${watchCount} WATCH). Showing ${filtered.length}; directional signals remain WATCH until their own event-clustered cohorts earn positive promotion. Complete bundles are trade ready only after every leg clears a live $50 order-book depth check and the CLOB fee state agrees with the market-specific taker curve while preserving a positive worst-case payout margin. Cash is retained when neither condition is met. Avg evidence ${evAvg}.${auditText}` ? `Loaded the ${scanned} most active markets, analyzed ${analyzed}, and kept ${all.length} ideas (${buyCount} TRADE READY, ${watchCount} WATCH). Showing ${filtered.length}; directional signals remain WATCH until their own event-clustered cohorts earn positive promotion. Complete bundles are trade ready only after every leg clears a live $50 order-book depth check and the CLOB fee state agrees with the market-specific taker curve while preserving a positive worst-case payout margin. Cash is retained when neither condition is met. Avg evidence ${evAvg}.${auditText}`
@@ -7441,12 +7537,21 @@ function runEngineSelfTest(){
{id:"yes-bundle-b",question:"B wins",outcomes:'["Yes","No"]',outcomePrices:'["0.305","0.695"]',clobTokenIds:'["yb-yes","yb-no"]',bestBid:0.30,bestAsk:0.31,liquidityNum:28000,volumeNum:100000,volume24hr:10000,acceptingOrders:true}, {id:"yes-bundle-b",question:"B wins",outcomes:'["Yes","No"]',outcomePrices:'["0.305","0.695"]',clobTokenIds:'["yb-yes","yb-no"]',bestBid:0.30,bestAsk:0.31,liquidityNum:28000,volumeNum:100000,volume24hr:10000,acceptingOrders:true},
{id:"yes-bundle-draw",question:"Draw",outcomes:'["Yes","No"]',outcomePrices:'["0.335","0.665"]',clobTokenIds:'["yd-yes","yd-no"]',bestBid:0.33,bestAsk:0.34,liquidityNum:20000,volumeNum:100000,volume24hr:10000,acceptingOrders:true}, {id:"yes-bundle-draw",question:"Draw",outcomes:'["Yes","No"]',outcomePrices:'["0.335","0.665"]',clobTokenIds:'["yd-yes","yd-no"]',bestBid:0.33,bestAsk:0.34,liquidityNum:20000,volumeNum:100000,volume24hr:10000,acceptingOrders:true},
]}); ]});
const convertibleNoBundleSuggestion=negativeRiskBundleSuggestion({id:"bundle-no-convert",title:"Three-way exact conversion",slug:"bundle-no-convert", const convertibleNoBundleEvent={id:"bundle-no-convert",title:"Three-way exact conversion",slug:"bundle-no-convert",
negRisk:true,enableNegRisk:true,negRiskMarketID:"0xneg-risk-market",negRiskFeeBips:25,markets:[ negRisk:true,enableNegRisk:true,negRiskMarketID:"0xneg-risk-market",negRiskFeeBips:25,markets:[
{id:"convert-a",conditionId:"condition-a",question:"A wins",outcomes:'["Yes","No"]',outcomePrices:'["0.455","0.545"]',clobTokenIds:'["ca-yes","ca-no"]',bestBid:0.45,bestAsk:0.46,negRiskMarketID:"0xneg-risk-market",negRiskFeeBips:25,feesEnabled:false,liquidityNum:30000,acceptingOrders:true}, {id:"convert-a",conditionId:"condition-a",question:"A wins",outcomes:'["Yes","No"]',outcomePrices:'["0.455","0.545"]',clobTokenIds:'["ca-yes","ca-no"]',bestBid:0.45,bestAsk:0.46,negRiskMarketID:"0xneg-risk-market",negRiskFeeBips:25,feesEnabled:false,liquidityNum:30000,acceptingOrders:true},
{id:"convert-b",conditionId:"condition-b",question:"B wins",outcomes:'["Yes","No"]',outcomePrices:'["0.355","0.645"]',clobTokenIds:'["cb-yes","cb-no"]',bestBid:0.35,bestAsk:0.36,negRiskMarketID:"0xneg-risk-market",negRiskFeeBips:25,feesEnabled:false,liquidityNum:30000,acceptingOrders:true}, {id:"convert-b",conditionId:"condition-b",question:"B wins",outcomes:'["Yes","No"]',outcomePrices:'["0.355","0.645"]',clobTokenIds:'["cb-yes","cb-no"]',bestBid:0.35,bestAsk:0.36,negRiskMarketID:"0xneg-risk-market",negRiskFeeBips:25,feesEnabled:false,liquidityNum:30000,acceptingOrders:true},
{id:"convert-c",conditionId:"condition-c",question:"C wins",outcomes:'["Yes","No"]',outcomePrices:'["0.255","0.745"]',clobTokenIds:'["cc-yes","cc-no"]',bestBid:0.25,bestAsk:0.26,negRiskMarketID:"0xneg-risk-market",negRiskFeeBips:25,feesEnabled:false,liquidityNum:30000,acceptingOrders:true}, {id:"convert-c",conditionId:"condition-c",question:"C wins",outcomes:'["Yes","No"]',outcomePrices:'["0.255","0.745"]',clobTokenIds:'["cc-yes","cc-no"]',bestBid:0.25,bestAsk:0.26,negRiskMarketID:"0xneg-risk-market",negRiskFeeBips:25,feesEnabled:false,liquidityNum:30000,acceptingOrders:true},
]}); ]};
const conversionFixtureTerms=new Map([["0xneg-risk-market",{status:"verified-onchain",fee_bips:25,question_count:3}]]);
const convertibleCompleteSides=negativeRiskBundleSuggestions(convertibleNoBundleEvent,{includeUnprofitable:true,conversionTerms:conversionFixtureTerms});
const convertibleNoBundleSuggestion=convertibleCompleteSides.find(candidate=>candidate.bundle_side==="NO");
const questionCountMismatchSides=negativeRiskBundleSuggestions(convertibleNoBundleEvent,{includeUnprofitable:true,
conversionTerms:new Map([["0xneg-risk-market",{status:"verified-onchain",fee_bips:25,question_count:4}]])});
const pendingConversionCandidate=negativeRiskBundleSuggestions(convertibleNoBundleEvent,{includeUnprofitable:true})
.find(candidate=>candidate.bundle_side==="NO");
const mismatchedOnchainFeeCandidate=applyNegativeRiskConversionTerms(pendingConversionCandidate,
new Map([["0xneg-risk-market",{status:"verified-onchain",fee_bips:30,question_count:3}]]));
const convertibleNoBooks=new Map((convertibleNoBundleSuggestion.bundle_legs||[]).map(leg=>[String(leg.token_id), const convertibleNoBooks=new Map((convertibleNoBundleSuggestion.bundle_legs||[]).map(leg=>[String(leg.token_id),
{min_order_size:"5",asks:[{price:String(leg.top_ask_price),size:"100"}]}])); {min_order_size:"5",asks:[{price:String(leg.top_ask_price),size:"100"}]}]));
const convertibleNoQuote=bundleQuoteAtUnits(convertibleNoBundleSuggestion,convertibleNoBooks,100); const convertibleNoQuote=bundleQuoteAtUnits(convertibleNoBundleSuggestion,convertibleNoBooks,100);
@@ -7558,6 +7663,7 @@ function runEngineSelfTest(){
const binaryReserveOrder=bundleVerificationShortlist([ const binaryReserveOrder=bundleVerificationShortlist([
...Array.from({length:90},(_,index)=>Object.assign({},dominanceSuggestion,{bundle_id:`dominance:general-${index}:a:b`,bundle_event_id:`general-${index}`,net_edge:0.10-index/1000,days_to_resolution:5})), ...Array.from({length:90},(_,index)=>Object.assign({},dominanceSuggestion,{bundle_id:`dominance:general-${index}:a:b`,bundle_event_id:`general-${index}`,net_edge:0.10-index/1000,days_to_resolution:5})),
...Array.from({length:30},(_,index)=>Object.assign({},binaryComplementSuggestion,{bundle_id:`binary:reserved-${index}:market`,bundle_event_id:`reserved-${index}`,net_edge:-0.01-index/1000})), ...Array.from({length:30},(_,index)=>Object.assign({},binaryComplementSuggestion,{bundle_id:`binary:reserved-${index}:market`,bundle_event_id:`reserved-${index}`,net_edge:-0.01-index/1000})),
...Array.from({length:30},(_,index)=>Object.assign({},convertibleNoBundleSuggestion,{bundle_id:`bundle:conversion-${index}:no`,bundle_event_id:`conversion-${index}`,net_edge:-0.02-index/1000})),
]); ]);
const eventCapBook=defaultPortfolio(); const eventCapBook=defaultPortfolio();
eventCapBook.cash=8800; eventCapBook.cash=8800;
@@ -8083,12 +8189,17 @@ function runEngineSelfTest(){
bundleArbitrage:{ bundleArbitrage:{
discoversExactCompleteNoConversion:Boolean(convertibleNoBundleSuggestion&&convertibleNoBundleSuggestion.bundle_immediate_convert discoversExactCompleteNoConversion:Boolean(convertibleNoBundleSuggestion&&convertibleNoBundleSuggestion.bundle_immediate_convert
&&convertibleNoBundleSuggestion.bundle_logic==="neg-risk-complete-no"&&convertibleNoBundleSuggestion.neg_risk_market_id==="0xneg-risk-market"), &&convertibleNoBundleSuggestion.bundle_logic==="neg-risk-complete-no"&&convertibleNoBundleSuggestion.neg_risk_market_id==="0xneg-risk-market"),
preservesBothCompleteSidesThroughAudit:convertibleCompleteSides.length===2
&&convertibleCompleteSides.some(candidate=>candidate.bundle_side==="YES")&&convertibleCompleteSides.some(candidate=>candidate.bundle_side==="NO"),
deductsAdapterFeeFromConversionPayout:Boolean(convertibleNoBundleSuggestion deductsAdapterFeeFromConversionPayout:Boolean(convertibleNoBundleSuggestion
&&Math.abs(convertibleNoBundleSuggestion.bundle_payout_per_unit-1.995)<0.0000001 &&Math.abs(convertibleNoBundleSuggestion.bundle_payout_per_unit-1.995)<0.0000001
&&convertibleNoBundleSuggestion.neg_risk_fee_bips===25), &&convertibleNoBundleSuggestion.neg_risk_fee_bips===25),
atomicallyConvertsCompleteNoSet:Boolean(conversionOpen&&conversionOpen.conversion&&conversionBook.positions.length===0 atomicallyConvertsCompleteNoSet:Boolean(conversionOpen&&conversionOpen.conversion&&conversionBook.positions.length===0
&&conversionBook.closed.length===3&&conversionBook.cash===10004.5&&conversionOpen.conversion.realized===4.5), &&conversionBook.closed.length===3&&conversionBook.cash===10004.5&&conversionOpen.conversion.realized===4.5),
blocksImmediateConversionOnMismatchedMetadata:Boolean(mismatchedConversionMetadata&&!mismatchedConversionMetadata.bundle_immediate_convert), blocksImmediateConversionOnMismatchedMetadata:Boolean(mismatchedConversionMetadata&&!mismatchedConversionMetadata.bundle_immediate_convert),
blocksImmediateConversionOnQuestionCountMismatch:questionCountMismatchSides.every(candidate=>!candidate.bundle_immediate_convert),
blocksImmediateConversionOnMetadataFeeMismatch:Boolean(mismatchedOnchainFeeCandidate
&&!mismatchedOnchainFeeCandidate.bundle_immediate_convert&&mismatchedOnchainFeeCandidate.conversion_verification_status==="metadata-fee-mismatch"),
doesNotInventConversionWithoutAdapterMetadata:Boolean(bundleSuggestion&&!bundleSuggestion.bundle_immediate_convert), doesNotInventConversionWithoutAdapterMetadata:Boolean(bundleSuggestion&&!bundleSuggestion.bundle_immediate_convert),
discoversExecutableBinaryComplements:Boolean(binaryComplementSuggestion&&binaryComplementSuggestion.bundle_logic==="binary-complement" discoversExecutableBinaryComplements:Boolean(binaryComplementSuggestion&&binaryComplementSuggestion.bundle_logic==="binary-complement"
&&binaryComplementQuote.depth_verified&&bundleQuoteIsActionable(binaryComplementQuote)&&Math.abs(binaryComplementQuote.profit-0.02)<0.000001), &&binaryComplementQuote.depth_verified&&bundleQuoteIsActionable(binaryComplementQuote)&&Math.abs(binaryComplementQuote.profit-0.02)<0.000001),
@@ -8101,6 +8212,8 @@ function runEngineSelfTest(){
immediateMergeMetadataSurvivesSync:compactedBinarySuggestion.bundle_immediate_merge===true, immediateMergeMetadataSurvivesSync:compactedBinarySuggestion.bundle_immediate_merge===true,
reservesBinaryComplementDepthChecks:binaryReserveOrder.length===BUNDLE_DEPTH_CANDIDATE_LIMIT reservesBinaryComplementDepthChecks:binaryReserveOrder.length===BUNDLE_DEPTH_CANDIDATE_LIMIT
&&binaryReserveOrder.filter(row=>row.bundle_logic==="binary-complement").length===BINARY_COMPLEMENT_DEPTH_RESERVE, &&binaryReserveOrder.filter(row=>row.bundle_logic==="binary-complement").length===BINARY_COMPLEMENT_DEPTH_RESERVE,
reservesExactConversionDepthChecks:binaryReserveOrder.length===BUNDLE_DEPTH_CANDIDATE_LIMIT
&&binaryReserveOrder.filter(row=>row.bundle_conversion_candidate).length===NEG_RISK_CONVERSION_DEPTH_RESERVE,
prioritizesReturnPerLockedDay:capitalEfficiencyOrder[0].bundle_event_id==="fast-event", prioritizesReturnPerLockedDay:capitalEfficiencyOrder[0].bundle_event_id==="fast-event",
prioritizesIndependentEventsBeforeAlternates:independentBundleOrder.map(row=>row.bundle_event_id).join(",")==="event-a,event-b,event-a", prioritizesIndependentEventsBeforeAlternates:independentBundleOrder.map(row=>row.bundle_event_id).join(",")==="event-a,event-b,event-a",
derivesLegacyBundleEventKey:bundleEventKey({bundle_id:"dominance:legacy-event:market-a:market-b"})==="legacy-event", derivesLegacyBundleEventKey:bundleEventKey({bundle_id:"dominance:legacy-event:market-a:market-b"})==="legacy-event",
+16
View File
@@ -81,12 +81,19 @@ assert.match(index, /const NEG_RISK_EVENT_SCAN_LIMIT=1000;/);
assert.match(index, /bundleOpportunityTelemetry:true/); assert.match(index, /bundleOpportunityTelemetry:true/);
assert.match(index, /const BUNDLE_DEPTH_CANDIDATE_LIMIT=80;/); assert.match(index, /const BUNDLE_DEPTH_CANDIDATE_LIMIT=80;/);
assert.match(index, /const BINARY_COMPLEMENT_DEPTH_RESERVE=20;/); assert.match(index, /const BINARY_COMPLEMENT_DEPTH_RESERVE=20;/);
assert.match(index, /const NEG_RISK_CONVERSION_DEPTH_RESERVE=20;/);
assert.match(index, /bundleRequiresDepthVerification:true/); assert.match(index, /bundleRequiresDepthVerification:true/);
assert.match(index, /bundleRequiresClobFeeVerification:true/); assert.match(index, /bundleRequiresClobFeeVerification:true/);
assert.match(index, /function bundleExecutableLeg\(book,units,feeSchedule\)/); assert.match(index, /function bundleExecutableLeg\(book,units,feeSchedule\)/);
assert.match(index, /function generalAdaptiveLearningExclusion\(trade\)/); assert.match(index, /function generalAdaptiveLearningExclusion\(trade\)/);
assert.match(index, /specializedUnsafeTradesCannotBiasDirectionalLearning:/); assert.match(index, /specializedUnsafeTradesCannotBiasDirectionalLearning:/);
assert.match(index, /function fetchBundleFeeSchedules\(conditionIds\)/); assert.match(index, /function fetchBundleFeeSchedules\(conditionIds\)/);
assert.match(index, /function fetchNegativeRiskConversionTerms\(marketIds\)/);
assert.match(index, /const NEG_RISK_ADAPTER_ADDRESS="0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296";/);
assert.match(index, /const NEG_RISK_FEE_BIPS_SELECTOR="0x2582cb5e";/);
assert.match(index, /const NEG_RISK_QUESTION_COUNT_SELECTOR="0xb7f75d2c";/);
assert.match(index, /const NEG_RISK_RPC_BATCH_CALL_LIMIT=10;/);
assert.match(index, /function applyNegativeRiskConversionTerms\(candidate,terms\)/);
assert.match(index, /function bundleFeeSchedulesMatch\(expected,reported\)/); assert.match(index, /function bundleFeeSchedulesMatch\(expected,reported\)/);
assert.match(index, /rejectsMismatchedClobFeeCurve:/); assert.match(index, /rejectsMismatchedClobFeeCurve:/);
assert.doesNotMatch(index, /\/fee-rate\?token_id=/); assert.doesNotMatch(index, /\/fee-rate\?token_id=/);
@@ -102,14 +109,23 @@ assert.match(index, /rejectsCrossMarketBinaryMerge:/);
assert.match(index, /immediateMergeMetadataSurvivesSync:/); assert.match(index, /immediateMergeMetadataSurvivesSync:/);
assert.match(api, /bundle_immediate_merge: s\.bundle_immediate_merge/); assert.match(api, /bundle_immediate_merge: s\.bundle_immediate_merge/);
assert.match(index, /function convertCompleteNegativeRiskNoBundle\(p,bundleId\)/); assert.match(index, /function convertCompleteNegativeRiskNoBundle\(p,bundleId\)/);
assert.match(index, /function negativeRiskBundleSuggestions\(event,\{includeUnprofitable=false,conversionTerms=null\}=\{\}\)/);
assert.match(index, /preservesBothCompleteSidesThroughAudit:/);
assert.match(index, /discoversExactCompleteNoConversion:/); assert.match(index, /discoversExactCompleteNoConversion:/);
assert.match(index, /deductsAdapterFeeFromConversionPayout:/); assert.match(index, /deductsAdapterFeeFromConversionPayout:/);
assert.match(index, /atomicallyConvertsCompleteNoSet:/); assert.match(index, /atomicallyConvertsCompleteNoSet:/);
assert.match(index, /blocksImmediateConversionOnMismatchedMetadata:/); assert.match(index, /blocksImmediateConversionOnMismatchedMetadata:/);
assert.match(index, /blocksImmediateConversionOnQuestionCountMismatch:/);
assert.match(index, /blocksImmediateConversionOnMetadataFeeMismatch:/);
assert.match(index, /doesNotInventConversionWithoutAdapterMetadata:/); assert.match(index, /doesNotInventConversionWithoutAdapterMetadata:/);
assert.match(index, /conversion_structures:conversions\.length/);
assert.match(index, /conversion_candidates_scanned:audited\.filter\(candidate=>candidate\.bundle_conversion_candidate\)\.length/);
assert.match(index, /actionable_conversions:unique\.filter\(candidate=>candidate\.bundle_immediate_convert\)\.length/);
assert.match(index, /Exact complete-NO conversion:/);
assert.match(api, /bundle_immediate_convert: s\.bundle_immediate_convert/); assert.match(api, /bundle_immediate_convert: s\.bundle_immediate_convert/);
assert.match(api, /neg_risk_market_id: s\.neg_risk_market_id, neg_risk_fee_bips: s\.neg_risk_fee_bips/); assert.match(api, /neg_risk_market_id: s\.neg_risk_market_id, neg_risk_fee_bips: s\.neg_risk_fee_bips/);
assert.match(index, /reservesBinaryComplementDepthChecks:/); assert.match(index, /reservesBinaryComplementDepthChecks:/);
assert.match(index, /reservesExactConversionDepthChecks:/);
assert.match(index, /function bundleVerificationShortlist\(candidates\)/); assert.match(index, /function bundleVerificationShortlist\(candidates\)/);
assert.match(index, /function prioritizeIndependentBundles\(candidates,limit=Infinity\)/); assert.match(index, /function prioritizeIndependentBundles\(candidates,limit=Infinity\)/);
assert.match(index, /prioritizesIndependentEventsBeforeAlternates:/); assert.match(index, /prioritizesIndependentEventsBeforeAlternates:/);
+9 -2
View File
@@ -34,8 +34,10 @@ else process.env.NEON_DATABASE_URL = originalNeonUrl;
const compacted = compactSuggestion({ const compacted = compactSuggestion({
market_id: "bundle:1:yes", side: "YES", signal_type: "bundle-arb", signal_confidence: 1, market_id: "bundle:1:yes", side: "YES", signal_type: "bundle-arb", signal_confidence: 1,
entry_candidate: true, adaptive_promotion: false, requires_live: true, bundle_id: "bundle:1:yes", bundle_event_id: "1", entry_candidate: true, adaptive_promotion: false, requires_live: true, bundle_id: "bundle:1:yes", bundle_event_id: "1",
bundle_side: "NO", bundle_logic: "neg-risk-complete-no", bundle_immediate_convert: true, bundle_side: "NO", bundle_logic: "neg-risk-complete-no", bundle_conversion_candidate: true,
neg_risk_market_id: "0xmarket", neg_risk_fee_bips: 25, bundle_cost_per_unit: 1.95, bundle_conversion_terms_verified: true, bundle_immediate_convert: true,
neg_risk_market_id: "0xmarket", neg_risk_fee_bips: 25, neg_risk_metadata_fee_bips: 25,
neg_risk_question_count: 3, conversion_verification_status: "verified-onchain", bundle_cost_per_unit: 1.95,
bundle_payout_per_unit: 1.995, bundle_settlement_payout_per_unit: 2, bundle_payout_per_unit: 1.995, bundle_settlement_payout_per_unit: 2,
bundle_net_profit_per_unit: 0.05, bundle_capital_efficiency: 0.0025, bundle_legs: [{ market_id: "1", side: "YES" }], bundle_net_profit_per_unit: 0.05, bundle_capital_efficiency: 0.0025, bundle_legs: [{ market_id: "1", side: "YES" }],
fees_enabled: false, fee_schedule: { rate: 0, exponent: 1, takerOnly: true }, fees_enabled: false, fee_schedule: { rate: 0, exponent: 1, takerOnly: true },
@@ -48,9 +50,14 @@ assert.equal(compacted.requires_live, true);
assert.equal(compacted.bundle_side, "NO"); assert.equal(compacted.bundle_side, "NO");
assert.equal(compacted.bundle_event_id, "1"); assert.equal(compacted.bundle_event_id, "1");
assert.equal(compacted.bundle_logic, "neg-risk-complete-no"); assert.equal(compacted.bundle_logic, "neg-risk-complete-no");
assert.equal(compacted.bundle_conversion_candidate, true);
assert.equal(compacted.bundle_conversion_terms_verified, true);
assert.equal(compacted.bundle_immediate_convert, true); assert.equal(compacted.bundle_immediate_convert, true);
assert.equal(compacted.neg_risk_market_id, "0xmarket"); assert.equal(compacted.neg_risk_market_id, "0xmarket");
assert.equal(compacted.neg_risk_fee_bips, 25); assert.equal(compacted.neg_risk_fee_bips, 25);
assert.equal(compacted.neg_risk_metadata_fee_bips, 25);
assert.equal(compacted.neg_risk_question_count, 3);
assert.equal(compacted.conversion_verification_status, "verified-onchain");
assert.equal(compacted.bundle_settlement_payout_per_unit, 2); assert.equal(compacted.bundle_settlement_payout_per_unit, 2);
assert.equal(compacted.bundle_capital_efficiency, 0.0025); assert.equal(compacted.bundle_capital_efficiency, 0.0025);
assert.equal(compacted.bundle_legs.length, 1); assert.equal(compacted.bundle_legs.length, 1);