@general-liquidity/sharpebench 0.0.6 → 0.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { AgentSubmission, AllocationPolicy, AllocationReport, AllocationTrajectory, Briefing, BriefingAudit, BriefingPolicy, Canary, CompositeScore, GreeksParams, GreeksResult, ScoreConfig, SelfAuditReport } from "./types.js";
1
+ import type { AgentSubmission, AllocationPolicy, AllocationReport, AllocationTrajectory, Briefing, BriefingAudit, BriefingPolicy, Canary, CompositeScore, FullVerdict, GreeksParams, GreeksResult, HonestyOpts, HonestyVerdict, ScoreConfig, SelfAuditReport } from "./types.js";
2
2
  export * from "./types.js";
3
3
  /**
4
4
  * Score and rank a field of submissions on the luck-robust composite. Returns the
@@ -21,3 +21,19 @@ export declare function scoreAllocation(trajectory: AllocationTrajectory, policy
21
21
  export declare function greeks(params: GreeksParams): GreeksResult;
22
22
  /** Derive a deterministic do-not-train contamination tripwire from seed material. */
23
23
  export declare function canary(seed: string): Canary;
24
+ /**
25
+ * "Is my Sharpe real, or an artifact of luck and multiple testing?" — the LITE
26
+ * backtest-honesty verdict over one per-period return series. Deflates the observed
27
+ * Sharpe for `nTrials` (the search footprint), then renders Pass / Borderline / Fail
28
+ * with PSR, expected-max-Sharpe, haircut, and MinTRL.
29
+ */
30
+ export declare function isMySharpeReal(returns: number[], opts: HonestyOpts): HonestyVerdict;
31
+ /**
32
+ * The FULL verdict: the winner's LITE verdict plus the multiple-testing family
33
+ * (White's Reality Check, Hansen's SPA + consistent variant, Romano-Wolf step-down)
34
+ * and the CSCV Probability of Backtest Overfitting over the whole field.
35
+ *
36
+ * `field` is N rows (candidate strategies) × T cols (time); `winnerIdx` is the row
37
+ * whose LITE verdict is reported.
38
+ */
39
+ export declare function isMySharpeRealFull(field: number[][], winnerIdx: number, opts: HonestyOpts): FullVerdict;
package/dist/index.js CHANGED
@@ -43,6 +43,8 @@ exports.auditBriefing = auditBriefing;
43
43
  exports.scoreAllocation = scoreAllocation;
44
44
  exports.greeks = greeks;
45
45
  exports.canary = canary;
46
+ exports.isMySharpeReal = isMySharpeReal;
47
+ exports.isMySharpeRealFull = isMySharpeRealFull;
46
48
  /**
47
49
  * `@general-liquidity/sharpebench` — the luck-robust scoring kernel for AI trading
48
50
  * agents, as a typed JS API over the *identical* Rust kernel that powers the
@@ -103,3 +105,64 @@ function greeks(params) {
103
105
  function canary(seed) {
104
106
  return parse(kernel.canary(seed));
105
107
  }
108
+ /** Map camelCase {@link HonestyOpts} → the snake_case `HonestyConfig` JSON the kernel reads. */
109
+ function honestyConfigJson(opts) {
110
+ const cfg = { n_trials: opts.nTrials };
111
+ if (opts.trialsSrStd !== undefined)
112
+ cfg.trials_sr_std = opts.trialsSrStd;
113
+ if (opts.confidence !== undefined)
114
+ cfg.confidence = opts.confidence;
115
+ if (opts.borderline !== undefined)
116
+ cfg.borderline = opts.borderline;
117
+ if (opts.srBenchmark !== undefined)
118
+ cfg.sr_benchmark = opts.srBenchmark;
119
+ return JSON.stringify(cfg);
120
+ }
121
+ /** Map the kernel's snake_case HonestyVerdict JSON → the camelCase {@link HonestyVerdict}. */
122
+ function toHonestyVerdict(raw) {
123
+ return {
124
+ sharpe: raw.sharpe,
125
+ nObs: raw.n_obs,
126
+ skew: raw.skew,
127
+ kurtosis: raw.kurtosis,
128
+ nTrials: raw.n_trials,
129
+ expectedMaxSharpe: raw.expected_max_sharpe,
130
+ deflatedSharpe: raw.deflated_sharpe,
131
+ probabilisticSharpe: raw.probabilistic_sharpe,
132
+ haircut: raw.haircut,
133
+ haircutSharpe: raw.haircut_sharpe,
134
+ minTrackRecordLen: raw.min_track_record_len,
135
+ verdict: raw.verdict,
136
+ explanation: raw.explanation,
137
+ methodologyVersion: raw.methodology_version,
138
+ };
139
+ }
140
+ /**
141
+ * "Is my Sharpe real, or an artifact of luck and multiple testing?" — the LITE
142
+ * backtest-honesty verdict over one per-period return series. Deflates the observed
143
+ * Sharpe for `nTrials` (the search footprint), then renders Pass / Borderline / Fail
144
+ * with PSR, expected-max-Sharpe, haircut, and MinTRL.
145
+ */
146
+ function isMySharpeReal(returns, opts) {
147
+ const raw = parse(kernel.is_my_sharpe_real(JSON.stringify(returns), honestyConfigJson(opts)));
148
+ return toHonestyVerdict(raw);
149
+ }
150
+ /**
151
+ * The FULL verdict: the winner's LITE verdict plus the multiple-testing family
152
+ * (White's Reality Check, Hansen's SPA + consistent variant, Romano-Wolf step-down)
153
+ * and the CSCV Probability of Backtest Overfitting over the whole field.
154
+ *
155
+ * `field` is N rows (candidate strategies) × T cols (time); `winnerIdx` is the row
156
+ * whose LITE verdict is reported.
157
+ */
158
+ function isMySharpeRealFull(field, winnerIdx, opts) {
159
+ const raw = parse(kernel.is_my_sharpe_real_full(JSON.stringify(field), winnerIdx, honestyConfigJson(opts)));
160
+ return {
161
+ honesty: toHonestyVerdict(raw.honesty),
162
+ realityCheckP: raw.reality_check_p,
163
+ spaP: raw.spa_p,
164
+ spaConsistentP: raw.spa_consistent_p,
165
+ stepDown: raw.step_down,
166
+ pbo: raw.pbo,
167
+ };
168
+ }
package/dist/types.d.ts CHANGED
@@ -126,3 +126,57 @@ export interface Canary {
126
126
  id: string;
127
127
  token: string;
128
128
  }
129
+ /** The headline call: does the edge survive deflation for the search? */
130
+ export type Verdict = "Pass" | "Borderline" | "Fail";
131
+ /**
132
+ * Options for {@link isMySharpeReal}. `nTrials` is the multiple-testing footprint
133
+ * (how many strategies/configs were tried before this one was kept) and is the one
134
+ * the caller must think about — `nTrials = 1` is almost always a lie.
135
+ */
136
+ export interface HonestyOpts {
137
+ /** Number of strategy trials behind this result. REQUIRED. */
138
+ nTrials: number;
139
+ /** Cross-trial Sharpe dispersion. Omit → estimated at 0.5 and flagged. */
140
+ trialsSrStd?: number;
141
+ /** Deflated-Sharpe threshold for a Pass. Default 0.95. */
142
+ confidence?: number;
143
+ /** Deflated-Sharpe threshold for Borderline. Default 0.90. */
144
+ borderline?: number;
145
+ /** PSR / MinTRL benchmark Sharpe to beat. Default 0.0. */
146
+ srBenchmark?: number;
147
+ }
148
+ /** The LITE verdict: everything derivable from one return series. */
149
+ export interface HonestyVerdict {
150
+ sharpe: number;
151
+ nObs: number;
152
+ skew: number;
153
+ kurtosis: number;
154
+ nTrials: number;
155
+ expectedMaxSharpe: number;
156
+ deflatedSharpe: number;
157
+ probabilisticSharpe: number;
158
+ /** `1 - deflatedSharpe`: probability the edge is a search artifact. */
159
+ haircut: number;
160
+ /** `sharpe * deflatedSharpe`: Sharpe discounted by survival probability. */
161
+ haircutSharpe: number;
162
+ minTrackRecordLen: number;
163
+ verdict: Verdict;
164
+ explanation: string;
165
+ methodologyVersion: string;
166
+ [k: string]: unknown;
167
+ }
168
+ /** The FULL verdict: LITE on the winner plus the multiple-testing family + PBO. */
169
+ export interface FullVerdict {
170
+ honesty: HonestyVerdict;
171
+ /** White's Reality Check p-value over the field. */
172
+ realityCheckP: number;
173
+ /** Hansen's SPA p-value (liberal/lower studentized variant). */
174
+ spaP: number;
175
+ /** Hansen's consistent SPA p-value. */
176
+ spaConsistentP: number;
177
+ /** Romano-Wolf step-down: which field members are significant at α. */
178
+ stepDown: boolean[];
179
+ /** CSCV Probability of Backtest Overfitting over the field. */
180
+ pbo: number;
181
+ [k: string]: unknown;
182
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@general-liquidity/sharpebench",
3
- "version": "0.0.6",
3
+ "version": "0.0.12",
4
4
  "description": "The luck-robust scoring kernel for AI trading agents — deflated Sharpe, pass^k reliability, and process-discipline gates. The identical Rust kernel as the SharpeBench benchmark, compiled to WASM.",
5
5
  "keywords": [
6
6
  "trading",
package/pkg/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sharpebench-wasm",
3
3
  "description": "WASM bindings for the SharpeBench scoring kernel (consumed by Gordon/Bun via the identical kernel).",
4
- "version": "0.0.6",
4
+ "version": "0.0.12",
5
5
  "license": "MIT OR Apache-2.0",
6
6
  "repository": {
7
7
  "type": "git",
@@ -7,6 +7,10 @@ export function canary(seed: string): string;
7
7
 
8
8
  export function greeks(params_json: string): string;
9
9
 
10
+ export function is_my_sharpe_real(returns_json: string, config_json: string): string;
11
+
12
+ export function is_my_sharpe_real_full(field_json: string, winner_idx: number, config_json: string): string;
13
+
10
14
  export function score(submissions_json: string, config_json: string): string;
11
15
 
12
16
  export function score_agent(submission_json: string, config_json: string): string;
@@ -63,6 +63,53 @@ function greeks(params_json) {
63
63
  }
64
64
  exports.greeks = greeks;
65
65
 
66
+ /**
67
+ * @param {string} returns_json
68
+ * @param {string} config_json
69
+ * @returns {string}
70
+ */
71
+ function is_my_sharpe_real(returns_json, config_json) {
72
+ let deferred3_0;
73
+ let deferred3_1;
74
+ try {
75
+ const ptr0 = passStringToWasm0(returns_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
76
+ const len0 = WASM_VECTOR_LEN;
77
+ const ptr1 = passStringToWasm0(config_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
78
+ const len1 = WASM_VECTOR_LEN;
79
+ const ret = wasm.is_my_sharpe_real(ptr0, len0, ptr1, len1);
80
+ deferred3_0 = ret[0];
81
+ deferred3_1 = ret[1];
82
+ return getStringFromWasm0(ret[0], ret[1]);
83
+ } finally {
84
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
85
+ }
86
+ }
87
+ exports.is_my_sharpe_real = is_my_sharpe_real;
88
+
89
+ /**
90
+ * @param {string} field_json
91
+ * @param {number} winner_idx
92
+ * @param {string} config_json
93
+ * @returns {string}
94
+ */
95
+ function is_my_sharpe_real_full(field_json, winner_idx, config_json) {
96
+ let deferred3_0;
97
+ let deferred3_1;
98
+ try {
99
+ const ptr0 = passStringToWasm0(field_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
100
+ const len0 = WASM_VECTOR_LEN;
101
+ const ptr1 = passStringToWasm0(config_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
102
+ const len1 = WASM_VECTOR_LEN;
103
+ const ret = wasm.is_my_sharpe_real_full(ptr0, len0, winner_idx, ptr1, len1);
104
+ deferred3_0 = ret[0];
105
+ deferred3_1 = ret[1];
106
+ return getStringFromWasm0(ret[0], ret[1]);
107
+ } finally {
108
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
109
+ }
110
+ }
111
+ exports.is_my_sharpe_real_full = is_my_sharpe_real_full;
112
+
66
113
  /**
67
114
  * @param {string} submissions_json
68
115
  * @param {string} config_json
Binary file
@@ -4,6 +4,8 @@ export const memory: WebAssembly.Memory;
4
4
  export const audit_briefing: (a: number, b: number, c: number, d: number) => [number, number];
5
5
  export const canary: (a: number, b: number) => [number, number];
6
6
  export const greeks: (a: number, b: number) => [number, number];
7
+ export const is_my_sharpe_real: (a: number, b: number, c: number, d: number) => [number, number];
8
+ export const is_my_sharpe_real_full: (a: number, b: number, c: number, d: number, e: number) => [number, number];
7
9
  export const score: (a: number, b: number, c: number, d: number) => [number, number];
8
10
  export const score_agent: (a: number, b: number, c: number, d: number) => [number, number];
9
11
  export const score_allocation: (a: number, b: number, c: number, d: number) => [number, number];