9612560479
Nuova harness condivisa xslib.py (panel HL certificato, score per-asset causale, book long-k/short-k vol-targeted leak-free) + 43 script in runs/ su 11 famiglie (MOM/REV/VOL/ DIST/LIQ/VAL/STRUCT/UNIV). Scoring = earns_slot (full>0 AND hold-out>0 AND marginal ADDS al portafoglio live AND corr XS01<0.6, con jackknife drop-one-month). Find: 42/257 config earns_slot=True, ma TUTTE con corr TP01 -0.2..-0.4 e PnL ~solo 2025. Verify (verify_survivors.py, 3 scettici deterministici): - S1 redundancy: cluster low-vol = UNA scommessa (XV01=XU02=1.00, XV02/XV03 r 0.44-0.67); XM09/XL02/XS06b/XR02 distinti (corr media off-diag +0.20). - S2 short-beta: cluster low-vol carica 0.44-0.70 su short-market -> NON market-neutral, e' un tilt short-alt-beta di regime. XM09(0.08)/XR02(-0.21) NON short-beta. - S3 per-anno: cluster low-vol decade (XV01/XU02 2026 -0.09); XL02 morto (2025 -0.14, 2026 -0.43); XM09 (0.82/0.50/0.74) e XR02 (0.84/0.40/2.68) positivi in tutti e 3 gli anni. Esito: nessuna sleeve nuova. Cluster low-vol RIGETTATO (regime-bet), XL02 RIGETTATO (overfit). 2 LEAD genuini (XM09 trend-gated x-sec momentum, XR02 reversal vol-gated) -> forward-monitor, non deployabili (panel 2.5y regime unico + STAT-MODE esecuzione). Portafoglio live invariato. Incluso anche options_vrp_managed.py (A/B VRP01 hold-to-expiry vs gestione attiva del doc credit-spread): la gestione attiva DISTRUGGE l'edge (combo FULL managed Sh -1.29 vs HtE +0.96, il delta-exit taglia i vincenti) -> scartata, VRP01 resta hold-to-expiry. Diari: 2026-06-20-xsec-strategies-sweep.md, 2026-06-20-vrp-active-management.md. gitignore: data/paper_portfolio/ (stato runtime paper) + scripts/research/xsec/runs/out/ (output rigenerabile). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
238 lines
20 KiB
JavaScript
238 lines
20 KiB
JavaScript
export const meta = {
|
||
name: 'xsec-strategies-hyperliquid',
|
||
description: 'Search NEW cross-sectional / multi-asset strategies on the 51 certified Hyperliquid alts, distinct from XS01: honest backtest each, verify, score marginal vs the live TP01+XS01+VRP01 stack',
|
||
phases: [
|
||
{ title: 'Find', detail: 'one agent per cross-sectional mechanism via shared xslib' },
|
||
{ title: 'Verify', detail: '3 adversarial skeptics per promising finding (overfit/distinctness/short-history)' },
|
||
{ title: 'Synthesize', detail: 'rank survivors, marginal contribution to the live portfolio' },
|
||
],
|
||
}
|
||
|
||
// fam | id | name | kind hint | idea
|
||
const CATALOG = [
|
||
// --- MOM: cross-sectional momentum variants ---
|
||
['MOM','XM01','Single-L momentum sweep','Score = past_return(close,L); long top-k/short bottom-k. Grid L in {20,30,60,90,120}. Try universe "all","majors",top20. (Known: momentum on full 49-universe is NEGATIVE — confirm; majors is XS01 turf.)'],
|
||
['MOM','XM02','Multi-L z-blend momentum','Score = mean of xs_zscore(past_return(close,L)) over L in {30,90} (and try {20,60,120}). Like XS01 blend. Compare "all" vs "majors".'],
|
||
['MOM','XM03','Vol-scaled (risk-adj) momentum','Score = past_return(close,L) / roll_std(ret,L). Risk-adjusted momentum (Sharpe-like). Grid L in {30,60,90}.'],
|
||
['MOM','XM04','Residual / idiosyncratic momentum','Score = cumulative residual_return(ret, win) over last L (beta-removed momentum). Cleaner than raw momentum? win=60, L in {30,60}.'],
|
||
['MOM','XM05','Momentum acceleration','Score = past_return(close,L_short) - past_return(close,L_long) (is momentum accelerating). L_short=20,L_long=60.'],
|
||
['MOM','XM06','52-day-high proximity','Score = close / rolling_max(high,W) (closeness to recent high). W in {60,90}.'],
|
||
['MOM','XM07','Sharpe-rank momentum','Score = roll_mean(ret,L) / roll_std(ret,L). Rank by realized Sharpe. L in {30,60,90}.'],
|
||
['MOM','XM08','Momentum consistency (frog-in-pan)','Score = past_return(close,L) * fraction_of_up_days(ret,L) (smooth momentum beats jumpy). L=60.'],
|
||
['MOM','XM09','Market-trend-gated momentum','XS momentum but only ACTIVE when the equal-weight market (market_ret) is in an uptrend (trailing sum>0); else flat. L=60.'],
|
||
['MOM','XM10','Rank-weighted continuous momentum','Instead of top-k/bottom-k, weight ALL assets by demeaned xs_rank(past_return) (continuous book). Implement weights yourself via a fine score + large k≈A/2, or note xslib top-k is the proxy. L=60.'],
|
||
// --- REV: reversal ---
|
||
['REV','XR01','Short-term reversal','Score = -past_return(close,L) (long losers/short winners). Grid L in {1,3,5,7}. (Known smoke: REV5 negative — confirm/diagnose.)'],
|
||
['REV','XR02','Reversal gated by high-vol regime','Short-term reversal active only when market vol is high (panic) else flat. L=3.'],
|
||
['REV','XR03','Residual short-term reversal','Score = -(sum of residual_return over last L). Idiosyncratic reversal (beta-removed). L in {3,5}.'],
|
||
['REV','XR04','Volume-shock reversal','Long recent losers that ALSO had a volume spike (volume_z high): score = -past_return*(volume_z>1). L=3.'],
|
||
['REV','XR05','Overreaction reversal (mid-horizon)','Score = -past_return(close,L) for L in {20,30} (mean-reversion of multi-week moves).'],
|
||
// --- VOL/RISK anomalies (the frontier) ---
|
||
['VOL','XV01','Low realized-vol anomaly','Score = -roll_std(ret,W) (long low-vol / short high-vol alts). Grid W in {20,30,60}, universe all/majors/top20, long-short AND long-only. (Smoke: ADDS — verify hard.)'],
|
||
['VOL','XV02','Low idiosyncratic-vol anomaly','Score = -roll_std(residual_return(ret,60), 30) (low idio vol). Distinct from total vol?'],
|
||
['VOL','XV03','Low-beta anomaly (BAB)','Score = -roll_beta(ret,60) (long low-beta / short high-beta). Betting-against-beta.'],
|
||
['VOL','XV04','Low downside-vol / semivariance','Score = -roll_std(min(ret,0), W) (only downside dispersion). W=30.'],
|
||
['VOL','XV05','Low max-drawdown anomaly','Score = -rolling_maxdrawdown(close,W) (prefer smooth equity). W=60.'],
|
||
['VOL','XV06','Low vol-of-vol','Score = -roll_std(roll_std(ret,10), 30). Stability of volatility.'],
|
||
// --- DIST: distribution shape ---
|
||
['DIST','XD01','Low-skew / anti-lottery','Score = -roll_skew(ret,60) (short high-skew lottery alts, long low-skew). Lottery-preference premium.'],
|
||
['DIST','XD02','High-skew momentum (opposite)','Score = +roll_skew(ret,60). Test the OTHER sign (does positive skew pay in crypto?).'],
|
||
['DIST','XD03','Coskewness with market','Rank by rolling coskewness of asset returns with market; long low-coskew. win=60.'],
|
||
// --- LIQ: volume / liquidity ---
|
||
['LIQ','XL01','Amihud illiquidity premium','Score = mean(|ret| / (close*volume)) over W (illiquidity). Long illiquid? Test both signs. W=30.'],
|
||
['LIQ','XL02','Volume-trend momentum','Score = volume_z(vol,30) combined with positive return (rising-volume winners). '],
|
||
['LIQ','XL03','Low-turnover anomaly','Score = -roll_mean(close*volume, 30) (long low dollar-volume names). Test sign.'],
|
||
['LIQ','XL04','Dollar-volume momentum','Score = past_return of dollar-volume (assets gaining liquidity/attention). W=30.'],
|
||
// --- VAL: value / mean-reversion to anchor ---
|
||
['VAL','XVa1','Distance-from-MA value','Score = -(close/roll_mean(close,W) - 1) (long the ones furthest BELOW their MA = cheap). W in {60,100}.'],
|
||
['VAL','XVa2','Cross-sectional RSI reversal','Compute RSI(14) per asset (use al.rsi per column); score = -RSI (long oversold). '],
|
||
['VAL','XVa3','Price-to-high value','Score = -(close / rolling_max(close,W)) (long the most beaten-down vs their high). W=90.'],
|
||
// --- STRUCT: structure / combos / construction ---
|
||
['STRUCT','XS01b','Double-sort momentum × low-vol','Score = xs_zscore(past_return(close,60)) + xs_zscore(-roll_std(ret,30)). Combine momentum and low-vol.'],
|
||
['STRUCT','XS02b','Long-mom + short-rev multi-horizon','Score = xs_zscore(past_return(close,90)) + xs_zscore(-past_return(close,5)). Long-term winners that dipped short-term.'],
|
||
['STRUCT','XS03b','Beta-hedged momentum','XS momentum book but subtract market beta exposure (score=residual momentum; or note xslib book is already ~dollar-neutral). Compare net vs market-hedged.'],
|
||
['STRUCT','XS04b','Ensemble z-vote','Score = mean of xs_zscore over {momentum90, -vol30, -skew60, -beta60}. Diversified cross-sectional signal.'],
|
||
['STRUCT','XS05b','Risk-parity legs (inverse-vol)','Momentum selection but weight legs by inverse own-vol (approximate via score = past_return and rely on xslib; document the limitation). L=60.'],
|
||
['STRUCT','XS06b','Correlation-to-market diversifier','Score = -rolling_corr(asset_ret, market_ret, 60) (long alts least correlated to the pack). win=60.'],
|
||
['STRUCT','XS07b','Trend-quality (R^2) ranking','Score = R^2 of a linear fit of log price over last W (smooth trenders). Long high-R2-up. W=60.'],
|
||
['STRUCT','XS08b','Lead-lag vs BTC','Score = past_return(close,L) of alts conditional on BTC having risen (alts that lag BTC catch up). L=10.'],
|
||
// --- UNIV: universe / rebalance sensitivity (same core signal, vary the frame) ---
|
||
['UNIV','XU01','Momentum universe sweep','Best momentum z-blend, run on universe in {majors, top20, top30, all}. Where does x-sec momentum live? (Maps the small-cap dilution.)'],
|
||
['UNIV','XU02','Rebalance/holding sweep','Low-vol or momentum with H in {5,10,20,30} and k in {3,5,8}. Turnover vs signal decay.'],
|
||
['UNIV','XU03','Long-only top-k (alt selection)','Low-vol / momentum LONG-ONLY top-k (captures alt-beta + selection, executable at small capital unlike the 38-leg book). Note: NOT market-neutral.'],
|
||
['UNIV','XU04','Liquidity-filtered momentum','Momentum but only on the top-20 by median dollar-volume (avoid illiquid noise). Compare to "all".'],
|
||
]
|
||
|
||
const ROOT = '/opt/docker/PythagorasGoal'
|
||
const CHEAT = `SHARED LIB (built & validated): ${ROOT}/scripts/research/xsec/xslib.py
|
||
Top of your script: import sys; sys.path.insert(0, "${ROOT}/scripts/research/xsec"); import xslib as xs; import numpy as np
|
||
PANEL: xs.load_panel(universe) -> Panel(.syms, .index, .close, .open, .high, .low, .vol, .ret) all numpy (n_days x n_assets).
|
||
universe: "all" (49 alts, >=700d), "majors" (19 XS01 majors), a list of syms, or an int N (top-N by $-volume).
|
||
Certified Hyperliquid 1d, 2024-2026 (~900 days). DVOL not here (that's BTC/ETH only).
|
||
CAUSAL HELPERS (value at row i uses data <= i): xs.past_return(close,L), xs.roll_std/roll_mean/roll_skew/ewm_mean(mat,win),
|
||
xs.xs_zscore(mat) (cross-sectional z per row), xs.xs_rank(mat), xs.market_ret(ret), xs.roll_beta(ret,win),
|
||
xs.residual_return(ret,win) (idiosyncratic), xs.volume_z(vol,win). For per-asset TA (RSI etc.) loop columns with altlib (sys.path has it: import altlib as al; al.rsi(col)).
|
||
BACKTEST/EVAL (no look-ahead: weight at bar i earns return of bar i+1 — built in):
|
||
xs.study_xs("NAME", lambda P: score_matrix(P), universe="all", H=10, k=5, long_short=True, target_vol=0.20)
|
||
score_matrix(P) -> np.ndarray (n_days x n_assets), HIGHER = long. Ranked cross-sectionally each H days;
|
||
long top-k / short bottom-k (long_short) or long-only top-k. Vol-targeted, fee 0.10% RT on turnover.
|
||
Returns {name,universe,H,k,long_short,n_assets,n_days, full:{sharpe,maxdd,ret,cagr}, holdout:{sharpe,...} (2025+),
|
||
yearly, corr_tp01, corr_xs01, corr_active, marginal:{verdict(ADDS/REDUNDANT/DILUTES/NEUTRAL),corr,
|
||
holdout_uplift_w20, jackknife_min_uplift, robust_oos}, earns_slot}.
|
||
PRINT xs.fmt(rep) and print("JSON:", xs.as_json(rep)).
|
||
THE BAR: a finding matters only if it is (1) positive FULL & hold-out 2025+, (2) DISTINCT from XS01 (corr_xs01 < 0.6 —
|
||
else it is just XS01), (3) marginal verdict ADDS to the live portfolio with robust_oos=True (survives the OOS jackknife).
|
||
earns_slot encodes exactly this. HONESTY: the panel is ~2.5 YEARS -> every result is SUGGESTIVE, not robust; a single
|
||
good config or one lucky quarter is NOT an edge. Report negatives plainly (most cross-sectional signals will fail here).`
|
||
|
||
function finderPrompt([fam, id, name, idea]) {
|
||
return `You are studying ONE cross-sectional / multi-asset trading mechanism on the certified Hyperliquid alt panel for PythagorasGoal. Goal of the wave: find something DISTINCT from the existing XS01 (plain cross-sectional momentum) that ADDS to the live TP01+XS01+VRP01 portfolio. Implement honestly with the shared library, backtest, report STRUCTURED results.
|
||
|
||
MECHANISM ${id} [${fam}] — ${name}
|
||
IDEA: ${idea}
|
||
|
||
CHEATSHEET
|
||
${CHEAT}
|
||
|
||
STEPS
|
||
1. Write ${ROOT}/scripts/research/xsec/runs/${id}.py: import xslib as xs, implement the score_matrix CAUSALLY, try a SMALL grid (<=5 study_xs calls total: vary universe / H / k / long_short / a param), pick the BEST config by marginal robustness (prefer earns_slot, then hold-out, then distinctness from XS01). Print xs.fmt(rep)+"JSON:"+xs.as_json(rep) for the best.
|
||
2. Run: cd ${ROOT} && uv run python scripts/research/xsec/runs/${id}.py (fix NaN/shape errors and re-run until it produces numbers).
|
||
3. Fill the schema from your BEST config, HONESTLY. promising=true ONLY if earns_slot is true OR (full>0 AND hold-out>0 AND corr_xs01<0.6 AND marginal verdict is ADDS). Remember the ~2.5y caveat — be skeptical.
|
||
|
||
CONSTRAINTS: keep <=5 backtests (each scans ~49 assets x 900 days). Score matrices must be (n_days x n_assets), higher=long, causal. Don't fabricate — every number from a real run.
|
||
Your final message IS the schema (data row), not prose.`
|
||
}
|
||
|
||
const FIND_SCHEMA = {
|
||
type: 'object',
|
||
required: ['id','name','family','implemented','best_universe','best_H','best_k','long_short','full_sharpe','holdout_sharpe','worst_maxdd','corr_xs01','corr_tp01','marginal_verdict','robust_oos','earns_slot','promising','summary'],
|
||
properties: {
|
||
id: { type: 'string' }, name: { type: 'string' }, family: { type: 'string' },
|
||
implemented: { type: 'boolean' },
|
||
best_universe: { type: 'string' }, best_H: { type: 'number' }, best_k: { type: 'number' },
|
||
long_short: { type: 'boolean' },
|
||
full_sharpe: { type: 'number' }, holdout_sharpe: { type: 'number' },
|
||
worst_maxdd: { type: 'number' },
|
||
corr_xs01: { type: 'number', description: 'correlation to existing XS01 (must be <0.6 to be distinct)' },
|
||
corr_tp01: { type: 'number' },
|
||
marginal_verdict: { type: 'string', enum: ['ADDS','REDUNDANT','DILUTES','NEUTRAL','N/A'] },
|
||
holdout_uplift_w20: { type: 'number' },
|
||
robust_oos: { type: 'boolean', description: 'survives the OOS drop-best-month jackknife' },
|
||
earns_slot: { type: 'boolean' },
|
||
promising: { type: 'boolean' },
|
||
summary: { type: 'string' },
|
||
caveats: { type: 'string' },
|
||
script_path: { type: 'string' },
|
||
},
|
||
}
|
||
|
||
function verifyPrompt(spec, find, kk) {
|
||
const [fam, id, name] = spec
|
||
const angles = [
|
||
'OVERFIT TO 2.5y / SHORT-HISTORY: the panel is only 2024-2026 with a ~1.5y hold-out. Re-run the best config and its neighbors (other universe/H/k). Is the edge a plateau or one lucky cell? Split the hold-out: is it carried by ONE quarter or the partial-2026 stub? Re-check jackknife (drop-best-month). Default real=false if it leans on a short window or single config.',
|
||
'DISTINCTNESS FROM XS01 & LEAK: is corr_xs01 really < 0.6, or is this XS01 in disguise (same momentum signal re-skinned)? Read xslib to confirm the score is causal (no future bar in rolling/beta/residual; weight at i applies to i+1). Confirm the mechanism is economically DIFFERENT from cross-sectional momentum. Default real=false if redundant with XS01 or leaky.',
|
||
'MARGINAL & EXECUTABILITY: re-verify it ADDS to the LIVE active portfolio (marginal uplift hold-out positive AND robust_oos) — not just standalone-positive. Is the book executable (a 10-leg market-neutral alt book needs ~20k capital; a long-only top-k is lighter)? Is turnover/fee realistic? For volume/illiquidity signals, are they an artifact of thin alts? Default real=false if it does not robustly improve the live stack.',
|
||
]
|
||
return `You are an ADVERSARIAL SKEPTIC (#${kk + 1}) for PythagorasGoal. A finder claims cross-sectional mechanism ${id} [${fam}] "${name}" is promising on the Hyperliquid alt panel. REFUTE it — this project was wrecked once by fake edges, and here the history is only ~2.5 years so the overfit risk is HIGH. Assume false-positive until proven otherwise.
|
||
|
||
FINDER'S CLAIM:
|
||
${JSON.stringify(find)}
|
||
Run script: ${find.script_path || ROOT + '/scripts/research/xsec/runs/' + id + '.py'}
|
||
Trusted leak-free lib: ${ROOT}/scripts/research/xsec/xslib.py
|
||
|
||
YOUR ANGLE: ${angles[kk % 3]}
|
||
|
||
Read the script, run your own checks (cd ${ROOT} && uv run python ...), quote the numbers you produce, and decide. Default to real=false when uncertain. Return ONLY the schema.`
|
||
}
|
||
|
||
const VERIFY_SCHEMA = {
|
||
type: 'object',
|
||
required: ['id','real','confidence','reason'],
|
||
properties: {
|
||
id: { type: 'string' },
|
||
real: { type: 'boolean', description: 'true only if the edge survives your adversarial check AND robustly adds to the live stack' },
|
||
confidence: { type: 'number' },
|
||
overfit_short_history: { type: 'boolean' },
|
||
redundant_with_xs01: { type: 'boolean' },
|
||
leak_suspected: { type: 'boolean' },
|
||
corrected_full_sharpe: { type: 'number' },
|
||
corrected_holdout_sharpe: { type: 'number' },
|
||
reason: { type: 'string', description: 'specific, with numbers you produced' },
|
||
},
|
||
}
|
||
|
||
// ===========================================================================
|
||
phase('Find')
|
||
log(`Searching ${CATALOG.length} cross-sectional mechanisms on the 51-alt Hyperliquid panel, one agent each. Frontier: distinct from XS01, additive to the live stack.`)
|
||
|
||
const results = await pipeline(
|
||
CATALOG,
|
||
(spec) => agent(finderPrompt(spec), { label: `find:${spec[1]}`, phase: 'Find', schema: FIND_SCHEMA, model: 'sonnet', effort: 'medium' }),
|
||
(find, spec) => {
|
||
if (!find) return { id: spec[1], name: spec[2], family: spec[0], promising: false, verify: [] }
|
||
if (!find.promising) return { ...find, verify: [] }
|
||
return parallel([0, 1, 2].map((kk) => () =>
|
||
agent(verifyPrompt(spec, find, kk), { label: `verify:${spec[1]}.${kk}`, phase: 'Verify', schema: VERIFY_SCHEMA, effort: 'high' })
|
||
)).then((votes) => ({ ...find, verify: votes.filter(Boolean) }))
|
||
}
|
||
)
|
||
|
||
phase('Synthesize')
|
||
const clean = results.filter(Boolean)
|
||
const enriched = clean.map((r) => {
|
||
const v = r.verify || []
|
||
const realVotes = v.filter((x) => x && x.real).length
|
||
const survived = r.promising && v.length >= 2 && realVotes >= Math.ceil(v.length / 2)
|
||
return { ...r, real_votes: realVotes, n_verify: v.length, survived }
|
||
})
|
||
const survivors = enriched.filter((r) => r.survived)
|
||
const killed = enriched.filter((r) => r.promising && !r.survived)
|
||
log(`Find done: ${clean.length} studied. Promising: ${enriched.filter(r => r.promising).length}. Survived adversarial verify: ${survivors.length}.`)
|
||
|
||
const compact = enriched.map((r) => ({
|
||
id: r.id, name: r.name, family: r.family, universe: r.best_universe, H: r.best_H, k: r.best_k, ls: r.long_short,
|
||
full: r.full_sharpe, hold: r.holdout_sharpe, dd: r.worst_maxdd, corr_xs01: r.corr_xs01, corr_tp01: r.corr_tp01,
|
||
marginal: r.marginal_verdict, robust: r.robust_oos, earns_slot: r.earns_slot, promising: r.promising,
|
||
survived: r.survived, real_votes: r.real_votes, summary: r.summary,
|
||
verify: (r.verify || []).map((x) => x ? `[real=${x.real} conf=${x.confidence}] ${x.reason}` : '').filter(Boolean),
|
||
}))
|
||
|
||
const SYNTH_SCHEMA = {
|
||
type: 'object',
|
||
required: ['headline', 'survivors', 'ranking', 'recommendations', 'dead_families'],
|
||
properties: {
|
||
headline: { type: 'string', description: '2-4 sentences: did a NEW cross-sectional mechanism, distinct from XS01 and additive to the live stack, emerge — net of the ~2.5y caveat?' },
|
||
survivors: { type: 'array', items: { type: 'object', required: ['id', 'name', 'why', 'suggested_role'], properties: {
|
||
id: { type: 'string' }, name: { type: 'string' }, why: { type: 'string' },
|
||
suggested_role: { type: 'string', description: 'new sleeve candidate / lead to forward-monitor / needs longer history' },
|
||
distinct_from_xs01: { type: 'string' } } } },
|
||
ranking: { type: 'array', items: { type: 'string' } },
|
||
recommendations: { type: 'string', description: 'concrete: what (if anything) to deep-validate or add, weight, and how to handle the short history' },
|
||
dead_families: { type: 'array', items: { type: 'string' } },
|
||
},
|
||
}
|
||
|
||
const synthPrompt = `You are the SYNTHESIZER for a PythagorasGoal wave that searched ${CATALOG.length} CROSS-SECTIONAL / multi-asset mechanisms on the 51 certified Hyperliquid alts (1d, 2024-2026), then adversarially verified every promising one. This is the frontier the previous BTC/ETH sweep pointed to (single-asset directional is exhausted at the ~1.3 ceiling).
|
||
|
||
LIVE stack (do not re-derive): TP01 (TSMOM trend BTC/ETH, defensive), XS01 (cross-sectional MOMENTUM on 19 HL majors, top5/bottom5, blend+dispersion-gate, vol-target — corr ~-0.12 to TP01), VRP01 (modeled options short-vol). A NEW cross-sectional sleeve is only valuable if it is (1) robust despite the SHORT ~2.5y history, (2) DISTINCT from XS01 (corr < 0.6 — not momentum re-skinned), and (3) ADDS to the live active portfolio out-of-sample (marginal uplift + robust_oos jackknife). Honesty is prime: on 2.5 years, be very skeptical; a clean set of negatives is an acceptable outcome.
|
||
|
||
Full result table (verify = the skeptics' findings):
|
||
${JSON.stringify(compact)}
|
||
|
||
Survivors (passed adversarial verify): ${JSON.stringify(survivors.map((s) => ({ id: s.id, name: s.name, full: s.full_sharpe, hold: s.holdout_sharpe, corr_xs01: s.corr_xs01, corr_tp01: s.corr_tp01, marginal: s.marginal_verdict, real_votes: s.real_votes })))}
|
||
Promising-but-killed: ${JSON.stringify(killed.map((s) => ({ id: s.id, name: s.name, why: (s.verify || []).map((v) => v && v.reason).filter(Boolean) })))}
|
||
|
||
Produce the synthesis. Be concrete and skeptical about the short history. If a genuinely distinct, additive mechanism survived (e.g. a risk/low-vol anomaly orthogonal to momentum), say what it is, whether it is a sleeve candidate or a lead needing more history, and its correlation profile. If nothing robust survived, say so plainly.`
|
||
|
||
const synthesis = await agent(synthPrompt, { schema: SYNTH_SCHEMA, effort: 'high', label: 'synthesize' })
|
||
|
||
return {
|
||
n_studied: clean.length,
|
||
n_promising: enriched.filter((r) => r.promising).length,
|
||
n_survived: survivors.length,
|
||
survivors: survivors.map((s) => ({ id: s.id, name: s.name, family: s.family, full: s.full_sharpe, hold: s.holdout_sharpe, corr_xs01: s.corr_xs01, corr_tp01: s.corr_tp01, marginal: s.marginal_verdict, real_votes: s.real_votes, summary: s.summary })),
|
||
promising_killed: killed.map((s) => ({ id: s.id, name: s.name })),
|
||
all_grades: clean.map((r) => ({ id: r.id, name: r.name, full: r.full_sharpe, hold: r.holdout_sharpe, corr_xs01: r.corr_xs01, marginal: r.marginal_verdict, earns_slot: r.earns_slot, promising: r.promising })),
|
||
synthesis,
|
||
}
|