bot / test / bursa-rl.test.mjs
  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,
    );
  }
});

static mirror of HEAD · about · clone: git clone https://git.ardegazu.ro/bot.git