feat: dealer flow, mirror portfolio (M21), options convexity, FINRA short interest, alert producers, vendor gate
CI / Test & Type-Check (push) Canceled after 0s

Snapshot of in-progress module work across multiple slices:

- Dealer Flow: dealerExposureEngine, dealerMapService, dealerMapExplain,
  dealerMapIntegrity, dealerMapReplay, dealerStudyEngine, hanStyleLevels
- Mirror Portfolio (M21): fundRepository, captureIngest, mirrorAlertProducers,
  fund holdings strip, live book, position capture ingest
- Options: BSM, NormalizedOptionSurface types, OptionsChainRouter,
  ConvexityGate, option legs panel
- Alert producers: vixLevel, rotation, thesis, unlock, portfolioRisk,
  mirror (fund_capture, fund_13f, mirror_diff)
- FINRA short interest adapter + queue integration
- SEC company tickers adapter + ingest (symbol search index seed)
- Vendor gate (rate-limit-first data plane, ADR-0009)
- CUSIP registry, reverse 13F refresh, stock float service
- LRU cache, portfolio backtest engine
- Frontend: dealer-flow, funds, journal, lab, monitor, plan, portfolio,
  reports, screener, strategies, theses, guided-start, exits, more pages
- Volume profile, workspace profile, visibility-aware poll
- ADRs 0010 (mirror math not advice), 0011 (symbol search index)
- VENDOR_INTEGRATIONS.md, END_USER_TEST.md
- .gitignore: exclude DBs, .DS_Store, local config, agent scratch
This commit is contained in:
Investor Flow Build
2026-08-10 13:36:26 -04:00
parent 04fc11b2fd
commit ac94acf9e3
229 changed files with 32617 additions and 3934 deletions
@@ -0,0 +1,141 @@
import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
import {
gradeStudySetup,
proposeStudySetups,
type CandleBar,
} from '../dealerStudyEngine.ts';
import type { DealerMap } from '../dealerExposureEngine.ts';
function baseMap(over: Partial<DealerMap> = {}): DealerMap {
return {
symbol: 'TEST',
spot: 100,
asOf: '2026-08-01T00:00:00.000Z',
delayNote: 'delayed',
delaySeconds: 900,
oiFreshness: 'prior_session',
providerId: 'yfinance',
convention: 'classic_retail',
unit: 'usd',
computation: 'settled_oi',
expiries: ['2026-08-15'],
cells: [],
byStrike: [],
netVexByStrike: [],
levels: {
king: { strike: 105, expiry: '2026-08-15', gex: 1e6 },
gatekeepers: [],
flip: 98,
callWall: 108,
putWall: 95,
airPockets: [],
clusters: [],
},
regimeAtSpot: 'positive',
scenario: 'gex_dominates',
patterns: [],
opexHints: { isNearOpex: false, note: '' },
provenance: { source: 'test' } as DealerMap['provenance'],
coveragePct: 90,
bsmFillPct: 80,
...over,
};
}
describe('proposeStudySetups', () => {
it('proposes cushion pin when positive regime and king away from spot', () => {
const props = proposeStudySetups(baseMap());
assert.ok(props.some((p) => p.hypothesisId === 'cushion_pin_toward_king'));
assert.ok(props.every((p) => p.disclaimer === 'Educational observation only.'));
});
it('proposes spring setup when negative regime', () => {
const props = proposeStudySetups(baseMap({ regimeAtSpot: 'negative' }));
assert.ok(props.some((p) => p.hypothesisId === 'spring_accelerate_from_spot'));
});
});
describe('gradeStudySetup', () => {
const loggedAt = '2026-08-01T00:00:00.000Z';
it('grades long win when target before invalidation', () => {
const bars: CandleBar[] = [
{ ts: '2026-08-02', o: 100, h: 101, l: 99, c: 100.5 },
{ ts: '2026-08-03', o: 100.5, h: 106, l: 100, c: 105 },
];
const r = gradeStudySetup(
{
bias: 'educational_long',
entry: 100,
invalidation: 95,
target: 105,
horizonDays: 5,
loggedAt,
},
bars,
new Date('2026-08-10'),
);
assert.equal(r.grade, 'win');
assert.ok(r.score >= 55);
});
it('grades long loss when invalidation first', () => {
const bars: CandleBar[] = [
{ ts: '2026-08-02', o: 100, h: 100.5, l: 94, c: 95 },
{ ts: '2026-08-03', o: 95, h: 110, l: 94, c: 108 },
];
const r = gradeStudySetup(
{
bias: 'educational_long',
entry: 100,
invalidation: 95,
target: 105,
horizonDays: 5,
loggedAt,
},
bars,
new Date('2026-08-10'),
);
assert.equal(r.grade, 'loss');
});
it('grades range win if held inside edges', () => {
const bars: CandleBar[] = [
{ ts: '2026-08-02', o: 100, h: 102, l: 98, c: 100 },
{ ts: '2026-08-03', o: 100, h: 103, l: 97, c: 101 },
{ ts: '2026-08-04', o: 101, h: 102, l: 99, c: 100 },
{ ts: '2026-08-05', o: 100, h: 101, l: 99, c: 100 },
{ ts: '2026-08-06', o: 100, h: 102, l: 98, c: 100 },
];
const r = gradeStudySetup(
{
bias: 'educational_range',
entry: 100,
invalidation: 95,
target: 105,
horizonDays: 5,
loggedAt,
},
bars,
new Date('2026-08-10'),
);
assert.equal(r.grade, 'win');
});
it('returns incomplete when no bars', () => {
const r = gradeStudySetup(
{
bias: 'educational_long',
entry: 100,
invalidation: 95,
target: 105,
horizonDays: 5,
loggedAt,
},
[],
new Date('2026-08-10'),
);
assert.equal(r.grade, 'incomplete');
});
});