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
+15 -4
View File
@@ -4,6 +4,8 @@
// Cache with weekly staleness (macro data is slow-moving).
import type { CacheEntry } from '../cache/CacheRepository.ts';
import type { FetchResult } from '../adapters/SourceAdapter.ts';
import { vendorFetch } from '../services/vendorGate.ts';
export interface FredSeries {
seriesId: string;
@@ -14,7 +16,7 @@ export interface FredSeries {
export interface FredAdapter {
sourceKind: 'fred';
fetchOne(key: string): Promise<CacheEntry<FredSeries | unknown>>;
fetchOne(key: string): Promise<FetchResult>;
series(seriesId: string): Promise<CacheEntry<FredSeries>>;
}
@@ -30,12 +32,17 @@ export class FredAdapterImpl implements FredAdapter {
this.apiKey = apiKey ?? process.env.FRED_API_KEY ?? '';
}
async fetchOne(key: string): Promise<CacheEntry<FredSeries | unknown>> {
async fetchOne(key: string): Promise<FetchResult> {
// key format: "fred:series:{seriesId}"
const parts = key.split(':');
if (parts.length >= 3 && parts[0] === 'fred' && parts[1] === 'series') {
const seriesId = parts[2];
return this.series(seriesId);
const entry = await this.series(seriesId);
return {
value: entry.value as FredSeries,
ttlClass: 'fred_macro',
provenance: entry.provenance ?? { fetchedAt: new Date().toISOString(), sourceKind: 'fred' },
};
}
throw new Error(`Unknown FRED cache key: ${key}`);
}
@@ -46,7 +53,10 @@ export class FredAdapterImpl implements FredAdapter {
}
const url = `${FRED_BASE}/series/observations?series_id=${seriesId}&api_key=${this.apiKey}&file_type=json&limit=100&sort_order=desc`;
const resp = await fetch(url);
const resp = await vendorFetch('fred', url, {
accept: 'application/json',
hostAllowlist: /api\.stlouisfed\.org/i,
});
if (!resp.ok) {
let detail = '';
try {
@@ -93,4 +103,5 @@ export const FRED_SERIES = {
FED_FUNDS: 'FEDFUNDS',
HEAVY_TRUCK_SALES: 'HTRUCKSSAAR',
MANUFACTURING_ACTIVITY: 'IPMAN',
CONSUMER_SENTIMENT: 'UMCSENT',
} as const;
+1 -1
View File
@@ -185,7 +185,7 @@ export function generateMacroCommentary(
? shortTermWithEvents(upcomingEvents.join(', '))
: SHORT_TERM_NO_EVENTS,
longTerm: LONG_TERM_MAP[classification.regime],
disclaimer: 'This commentary is for educational purposes only and is not investment advice. '
disclaimer: 'Educational observation only. '
+ 'Past performance does not guarantee future results. Always do your own research '
+ 'before making investment decisions.',
};