feat: Unraid deploy, dealer-flow heatmap, confluence zones, 13F capture
CI / Test (push) Canceled after 0s
CI / Build and push (push) Canceled after 0s

Ship Node production images, Unraid compose, and Gitea CI/CD (test then
push registry images; cron script if no runner). Rebuild dealer flow as a
heatmap-first map with integrity gates and chart helpers. Add confluence
zone rules, session clock, capture evidence, and tighter 13F/queue/options
paths, plus the matching UI and tests.
This commit is contained in:
Investor Flow Build
2026-08-18 14:10:02 -04:00
parent f7efea2178
commit 90e1829d39
113 changed files with 7606 additions and 1947 deletions
+96 -4
View File
@@ -58,7 +58,7 @@ export interface FundHoldersResult {
symbol: string;
tracked: Array<{
fundId: string; fundName: string; shares: number | null; valueUsd: number | null;
asOf: string; source: string; weightPct: number | null;
asOf: string; source: string; notes: string | null; weightPct: number | null;
}>;
institutionCount: number;
}
@@ -79,6 +79,22 @@ export interface XAccountRow {
handle: string;
label: string;
created_at: string;
pullStatus?: string | null;
pullAt?: string | null;
pullError?: string | null;
lastPostAt?: string | null;
}
export interface FundFreshness {
xHandle: string | null;
xPull: {
status: "pending" | "in_flight" | "done" | "backoff" | "failed" | "none";
lastAttempt: string | null;
error: string | null;
};
lastPostAt: string | null;
lastCaptureAt: string | null;
last13fAt: string | null;
}
// ─── Dealer Flow types ─────────────────────────────────────────────────────
@@ -119,6 +135,8 @@ export interface DealerMapPayload {
symbol: string;
spot: number;
asOf: string;
quoteAsOf?: string | null;
chainAsOf?: string | null;
delayNote: string;
delaySeconds: number | null;
oiFreshness: string;
@@ -659,6 +677,8 @@ export interface XFedFeed {
nextCursor: string | null;
configured: boolean;
health?: { healthy: 'healthy' | 'degraded'; lastError: string | null } | null;
lastPullAt?: string | null;
queuedHandles?: number;
}
export interface MacroCommentary {
shortTerm: string;
@@ -672,6 +692,7 @@ export interface Snapshot {
candles: PriceCandle[] | null;
sector: SymbolMeta | null;
stale: { quote: boolean; candles: boolean; sector: boolean };
observed?: { quote: string | null; candles: string | null; sector: string | null };
}
export interface AuthUser {
userId: string;
@@ -783,7 +804,7 @@ export interface IndicatorPeriods {
}
export interface IndicatorOptions {
periods?: IndicatorPeriods;
timeframe?: '1d' | '1wk' | '1mo';
timeframe?: '1m' | '5m' | '1d' | '1wk' | '1mo';
}
export interface IndicatorResult {
ema?: Record<number, (number | null)[]>;
@@ -848,7 +869,9 @@ export const api = {
/** Batched snapshot for multiple symbols — reduces N+1 API calls */
snapshots: (symbols: string[]) => trpcQuery<Array<{ symbol: string; quote: Snapshot['quote'] | null; candles: PriceCandle[] | null; sector: SymbolMeta | null; stale: { quote: boolean; candles: boolean; sector: boolean } }>>("market.snapshots", { symbols }),
tickerContext: (symbol: string) => trpcQuery<TickerContext>("market.tickerContext", { symbol }),
candles: async (symbol: string, timeframe = "1d") => trpcQuery<{ symbol: string; timeframe: string; candles: PriceCandle[]; isStale: boolean }>("market.candles", { symbol, timeframe }).then((r) => r?.candles ?? []),
candles: async (symbol: string, timeframe = "1d") => trpcQuery<{ symbol: string; timeframe: string; candles: PriceCandle[]; isStale: boolean; fetchedAt: string | null }>("market.candles", { symbol, timeframe }).then((r) => r?.candles ?? []),
candlesWithMeta: (symbol: string, timeframe = "1d") =>
trpcQuery<{ symbol: string; timeframe: string; candles: PriceCandle[]; isStale: boolean; fetchedAt: string | null }>("market.candles", { symbol, timeframe }),
indicators: (symbol: string, opts: IndicatorOptions) =>
trpcQuery<IndicatorResult>("market.indicators", { symbol, ...opts }),
truckSales: () => trpcQuery<TruckSalesData>("market.truckSales"),
@@ -890,16 +913,23 @@ export const api = {
list: () => trpcQuery<Array<{
id: string; ci_key: string; fund_name: string; manager_name: string;
x_handle: string | null; paywall_status: string; enabled: boolean;
freshness: FundFreshness | null;
}>>("funds.list", {}),
get: (input: { id: string }) => trpcQuery<{
id: string; ci_key: string; fund_name: string; manager_name: string;
x_handle: string | null; paywall_status: string; enabled: boolean;
freshness: FundFreshness | null;
} | null>("funds.get", input),
liveBook: (input: { fundId: string }) =>
trpcQuery<Array<{
symbol: string; shares: number | null; value_usd: number | null;
cost_basis: number | null; as_of: string; source: string; evidence_url: string | null;
notes: string | null; post_text: string | null;
status: "held" | "exited"; last_held_shares: number | null;
prior_shares: number | null; share_delta: number | null;
change: "add" | "cut" | "flat" | "new" | null;
x_only: boolean;
evidence_status?: "ok" | "deleted" | "unknown";
}>>("funds.liveBook", input),
adminCreate: (input: {
ci_key: string; fund_name: string; manager_name: string; x_handle?: string;
@@ -928,7 +958,7 @@ export const api = {
symbol: string;
tracked: Array<{
fundId: string; fundName: string; shares: number | null; valueUsd: number | null;
asOf: string; source: string; weightPct: number | null;
asOf: string; source: string; notes: string | null; weightPct: number | null;
}>;
institutionCount: number;
}>("symbols.holders", input),
@@ -1305,6 +1335,8 @@ export const api = {
queueLogs: (key: string, limit: number) => trpcQuery<ErrorLogEntry[]>("admin.queueLogs", { key, limit }),
queueRetryJob: (key: string) => trpcMutate<{ ok: boolean }>("admin.queueRetryJob", { key }),
queueRetrySource: (sourceKind: string) => trpcMutate<{ cleared: number }>("admin.queueRetrySource", { sourceKind }),
clearSourceCooldown: (sourceKind: string) =>
trpcMutate<{ ok: boolean; sourceKind: string }>("admin.clearSourceCooldown", { sourceKind }),
queueSourcePause: (source: string) => trpcMutate<{ ok: boolean; source: string }>("admin.queueSourcePause", { source }),
queueSourceResume: (source: string) => trpcMutate<{ ok: boolean; source: string }>("admin.queueSourceResume", { source }),
queueSourceStop: (source: string) => trpcMutate<{ ok: boolean; source: string; cleared: number }>("admin.queueSourceStop", { source }),
@@ -1485,8 +1517,64 @@ export const api = {
body: 'bull' | 'bear' | 'exit';
firedAt: string;
qualityAtFire: string;
verdict: 'real' | 'false_alarm' | null;
priceConfirmed: boolean;
}>;
}>("confluence.signalHistory", { symbol }),
recentZones: (symbol: string, opts?: { rackId?: string; entries?: number; exits?: number }) =>
trpcQuery<{
symbol: string;
rackId: string | null;
entries: Array<{
kind: 'entry' | 'exit';
startAsOf: string;
endAsOf: string;
open: boolean;
qualityAtStart: string;
netEvidenceAtStart: number;
firedSlotIds: string[];
forwardReturn: number | null;
verdict: 'confirmed' | 'false_alarm' | 'open';
}>;
exits: Array<{
kind: 'entry' | 'exit';
startAsOf: string;
endAsOf: string;
open: boolean;
qualityAtStart: string;
netEvidenceAtStart: number;
firedSlotIds: string[];
forwardReturn: number | null;
verdict: 'confirmed' | 'false_alarm' | 'open';
}>;
entryRule: {
label: string;
source: string;
derivedAt: string | null;
sampleCaveat: string;
train: { hitRate: number | null; resolved: number; baselineHitRate: number | null } | null;
validate: { hitRate: number | null; resolved: number; baselineHitRate: number | null } | null;
};
exitRule: {
label: string;
source: string;
derivedAt: string | null;
sampleCaveat: string;
train: { hitRate: number | null; resolved: number; baselineHitRate: number | null } | null;
validate: { hitRate: number | null; resolved: number; baselineHitRate: number | null } | null;
};
coverage: { evaluatedDays: number; lookbackDays: number; replayComplete: boolean };
symbolScore: {
entry: { zones: number; resolved: number; confirmed: number; hitRate: number | null };
exit: { zones: number; resolved: number; confirmed: number; hitRate: number | null };
};
learningLedger: { ready: boolean; filled: number; total: number };
}>("confluence.recentZones", {
symbol,
...(opts?.rackId ? { rackId: opts.rackId } : {}),
...(opts?.entries ? { entries: opts.entries } : {}),
...(opts?.exits ? { exits: opts.exits } : {}),
}),
saveRack: (input: { id?: string; name: string; description?: string; slotIds: string[] }) =>
trpcMutate<{ id: string; name: string; slotIds: string[]; isSystem: boolean; description: string | null }>("confluence.saveRack", input),
corridorSnapshot: (symbol: string) =>
@@ -1734,6 +1822,10 @@ export interface QueueStatus {
pausedSources?: string[];
/** Operator-stopped sources (drain frozen, jobs cleared, enqueue blocked). */
stoppedSources?: string[];
pendingByKind?: Record<string, number>;
demandSize?: number;
dataPlaneHealthy?: boolean;
dataPlaneNotes?: string[];
}
export interface ScheduleEntry {