1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112 | // Golden vectors for the bursa RL core (bot.rl.bursa-policy), exported off
// the :worker build — the SAME compiled namespace the gym (dist/rl/train.js)
// and the live arm (dist/worker.js) load, which is the point: pinning these
// bytes pins what the net sees in both places. Expectations in
// test/vectors/bursa-rl.json are hand-computed from the documented formulas.
// Runs against the committed dist/ — never src/.
//
// What each family proves:
// pxOff — the lattice prices are the bootstrap's exact reduced
// rationals (one price grammar for both policies).
// candidates — the fixed 22-action lattice in its trained order; the
// index IS the action, so this list is wire-frozen.
// stats — vol/flow/sinceFill derive from the SNAPSHOT alone (never a
// step counter or a clock), so gym and live compute them
// identically; other pairs filtered.
// view — one decision's whole world: my best per side, others'
// depth and queue mass per lattice offset, and the best-take
// deltas priced through quote-leg-amt's exact rounding.
// features — 13-wide per-candidate afterstates, trailing 1 bias; takes
// shift inventory, quotes own their queue position.
// decide — features → netQs → pickAction, ties to the FIRST max, so
// ε = 0 is fully deterministic.
// gate — the promotion arithmetic: champion AND the random floor
// AND enough decided evidence; no champion ⇒ floor alone.
// The bootstrap quoter appears nowhere — it is the live
// fallback, not the baseline.
// plan — plan-actions' 8th argument: a model swaps the QUOTING
// decision only (solvency clamps intact), a nil model is the
// bootstrap byte-for-byte, skip leaves the book alone.
import { test } from "node:test";
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
const {
bursaPxOff, bursaCandidates, bursaStats, bursaView,
bursaFeatures, bursaDecide, bursaGate, bursaPlanActions,
} = await import(new URL("../stack-b/dist/worker.js", import.meta.url).href);
const vec = JSON.parse(
readFileSync(new URL("./vectors/bursa-rl.json", import.meta.url), "utf8"),
);
const plain = (v) => JSON.parse(JSON.stringify(v));
test("bursa lattice prices", () => {
for (const c of vec.pxOff) {
assert.deepEqual(plain(bursaPxOff(c.side, c.pct)), c.px, `${c.side} ${c.pct}`);
}
});
test("bursa candidate lattice", () => {
for (const c of vec.candidates) {
assert.deepEqual(plain(bursaCandidates(c.quoteSize)), c.out, c.name);
}
});
test("bursa snapshot stats", () => {
for (const c of vec.stats) {
assert.deepEqual(plain(bursaStats(c.snapshot, c.me, c.pair)), c.out, c.name);
}
});
test("bursa view builder", () => {
for (const c of vec.view) {
assert.deepEqual(
plain(bursaView(c.snapshot, c.me, c.pair, c.quoteSize, c.wB, c.wQ, c.rb, c.rq)),
c.out,
c.name,
);
}
});
test("bursa candidate features", () => {
for (const c of vec.features) {
assert.deepEqual(
bursaFeatures(c.view, c.candidates).map((f) => [...f]),
c.out,
c.name,
);
}
});
test("bursa greedy decision", () => {
const f = vec.features[0];
for (const c of vec.decide) {
assert.equal(bursaDecide(c.model, f.view, f.candidates, c.epsilon), c.a, c.name);
}
});
test("bursa promotion gate arithmetic", () => {
for (const c of vec.gate) {
assert.deepEqual(
plain(bursaGate(c.cvc, c.champ, c.cvr, c.rnd, c.decided, c.nMin)),
c.out,
c.name,
);
}
});
test("bursa plan-actions learned-quoter seam", () => {
for (const c of vec.plan) {
assert.deepEqual(
plain(
bursaPlanActions(
c.market, c.banks, c.me, c.myBank, c.secrets, c.cfg, c.now, c.policy,
),
),
c.ops,
c.name,
);
}
});
|