64 lines
2.5 KiB
TypeScript
64 lines
2.5 KiB
TypeScript
import { test } from 'node:test';
|
|||
|
|
import { strict as assert } from 'node:assert';
|
||
|
|
import { readFileSync } from 'node:fs';
|
||
|
|
import { dirname, join } from 'node:path';
|
||
|
|
import { fileURLToPath } from 'node:url';
|
||
|
|
import { buildDealerMap } from '../dealerExposureEngine.ts';
|
||
|
|
import { auditDealerMap } from '../dealerMapIntegrity.ts';
|
||
|
|
import type { NormalizedOptionSurface } from '../../options/types.ts';
|
||
|
|
|
||
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||
|
|
const fixturePath = join(__dirname, '../__fixtures__/dealer-surface-synthetic.json');
|
||
|
|
|
||
|
|
function loadFixture(): NormalizedOptionSurface {
|
||
|
|
return JSON.parse(readFileSync(fixturePath, 'utf8')) as NormalizedOptionSurface;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Small fixture uses looser strike-count thresholds; production defaults stay strict. */
|
||
|
|
const FIXTURE_THRESHOLDS = {
|
||
|
|
minOiStrikesPerExpiry: 3,
|
||
|
|
minNearSpotOiStrikes: 3,
|
||
|
|
minCells: 6,
|
||
|
|
minByStrike: 3,
|
||
|
|
};
|
||
|
|
|
||
|
|
test('golden fixture: map is complete and king is max |gex| call cluster', () => {
|
||
|
|
const surface = loadFixture();
|
||
|
|
const map = buildDealerMap(surface, { maxExpiries: 3 });
|
||
|
|
const integrity = auditDealerMap(map, surface, { thresholds: FIXTURE_THRESHOLDS });
|
||
|
|
|
||
|
|
assert.equal(integrity.status, 'complete', JSON.stringify(integrity.hardFailed));
|
||
|
|
assert.ok(map.levels.king);
|
||
|
|
// Heaviest call OI + gamma at 105 08-08
|
||
|
|
assert.equal(map.levels.king!.strike, 105);
|
||
|
|
assert.equal(map.levels.king!.expiry, '2026-08-08');
|
||
|
|
assert.ok(map.cells.length >= 6);
|
||
|
|
assert.ok(map.quality.greekQuality === 'ok' || map.quality.greekQuality === 'degraded');
|
||
|
|
|
||
|
|
// Determinism
|
||
|
|
const map2 = buildDealerMap(surface, { maxExpiries: 3 });
|
||
|
|
assert.equal(map2.levels.king!.gex, map.levels.king!.gex);
|
||
|
|
assert.equal(map2.cells.length, map.cells.length);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('golden fixture: zero IV across surface → incomplete integrity', () => {
|
||
|
|
const surface = loadFixture();
|
||
|
|
surface.rows = surface.rows.map((r) => ({
|
||
|
|
...r,
|
||
|
|
iv: 1e-5,
|
||
|
|
greeks: null,
|
||
|
|
}));
|
||
|
|
const map = buildDealerMap(surface, { maxExpiries: 3 });
|
||
|
|
const integrity = auditDealerMap(map, surface, { thresholds: FIXTURE_THRESHOLDS });
|
||
|
|
assert.equal(integrity.status, 'incomplete');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('golden fixture: drop to one expiry → incomplete', () => {
|
||
|
|
const surface = loadFixture();
|
||
|
|
surface.rows = surface.rows.filter((r) => r.expiry === '2026-08-08');
|
||
|
|
const map = buildDealerMap(surface, { maxExpiries: 3 });
|
||
|
|
const integrity = auditDealerMap(map, surface, { thresholds: FIXTURE_THRESHOLDS });
|
||
|
|
assert.equal(integrity.status, 'incomplete');
|
||
|
|
assert.ok(integrity.hardFailed.includes('expiries'));
|
||
|
|
});
|