Fix stuck adapter_queue jobs (ASTS/IRE/IREN stuck pending forever): 1. fetchSpec early-return paths (cooldown checks) now update job status to 'backoff' with last_attempt set and 30s backoff_until, instead of returning without any status change. Prevents jobs from being re-processed every drain cycle indefinitely. 2. Wrap adapter.fetchOne() in 30s Promise.race timeout. A hung HTTP request no longer blocks the entire per-source promise chain forever, preventing all subsequent jobs for that source. Also includes corridor/confluence feature, tiered quote schedules, cache improvements, and HoldingsBookView refinements.
124 lines
12 KiB
TypeScript
124 lines
12 KiB
TypeScript
// Investor Flow — Confluence Slot Catalog (M22, slice 2)
|
|
//
|
|
// The 40-slot confluence inventory for the Confluence Signal Engine. Each slot is
|
|
// a named, independently-evaluable check whose *firing* state contributes bullish
|
|
// or bearish evidence about a symbol's entry/exit quality.
|
|
//
|
|
// Pure data + retrieval helpers: NO I/O. ADR-0007: slots describe "quality of the
|
|
// picture" — never a buy/sell recommendation. Each slot has an ADR-safe explain
|
|
// note phrased as evidence ("relative strength is in the upper decile") rather
|
|
// than a directive ("buy").
|
|
|
|
/** Slot body: which side of the picture a firing slot supports. */
|
|
export type SlotBody = 'bull' | 'bear' | 'exit';
|
|
|
|
/**
|
|
* "exit" is a subclass of bear evidence: it indicates weakening conditions for an
|
|
* existing position rather than a fresh short thesis. Exit slots are still counted
|
|
* as bear evidence (risk-off side of the picture).
|
|
*/
|
|
export const isBearEvidence = (body: SlotBody): boolean => body === 'bear' || body === 'exit';
|
|
|
|
/** The seven confluence families (independent evidence axes). */
|
|
export type SlotFamily =
|
|
| 'technical'
|
|
| 'institutional'
|
|
| 'macro'
|
|
| 'seasonal'
|
|
| 'flows'
|
|
| 'sentiment';
|
|
|
|
/** Candle granularity a slot consumes (daily is the engine default). */
|
|
export type SlotGranularity = '1d' | '1wk';
|
|
|
|
/**
|
|
* A confluence slot definition. `id` is the stable machine key; `name` plain
|
|
* English; `explain` is the ADR-0007-safe evidence sentence surfaced to users.
|
|
*/
|
|
export interface ConfluenceSlot {
|
|
id: string;
|
|
name: string;
|
|
family: SlotFamily;
|
|
body: SlotBody;
|
|
/** Default candle granularity the slot evaluates on. */
|
|
granularity: SlotGranularity;
|
|
/** Short evidence sentence shown in UI / explain notes. */
|
|
explain: string;
|
|
}
|
|
|
|
/** Complete confluence catalog in evaluation order. */
|
|
export const CONFLUENCE_SLOTS: ConfluenceSlot[] = [
|
|
// ---------------------------------------------------------------- technical
|
|
{ id: 'goldenCross', name: 'Golden Cross', family: 'technical', body: 'bull', granularity: '1wk', explain: 'The 50-window average has crossed above the 200-window average, a widely-watched trend-quality marker.' },
|
|
{ id: 'deathCross', name: 'Death Cross', family: 'technical', body: 'exit', granularity: '1wk', explain: 'The 50-window average has crossed below the 200-window average, a commonly-cited trend-weakening marker.' },
|
|
{ id: 'trendAlignment', name: 'Trend Alignment', family: 'technical', body: 'bull', granularity: '1wk', explain: 'Price sits above both the 50- and 200-window averages, indicating an aligned long-term trend.' },
|
|
{ id: 'timeSeriesMomentum12_1', name: '12-1 Momentum', family: 'technical', body: 'bull', granularity: '1d', explain: 'The 12-month-return-minus-1-month gauge is positive, a period-validated trend-following signal.' },
|
|
{ id: 'relativeStrengthVsSpy', name: 'Relative Strength vs SPY', family: 'technical', body: 'bull', granularity: '1d', explain: 'The symbol is outperforming the S&P 500 over the 12-1 momentum window.' },
|
|
{ id: 'rsiOversold', name: 'RSI Oversold', family: 'technical', body: 'bull', granularity: '1d', explain: 'Momentum gauge oversold, a bounce-prone condition after sustained weakness.' },
|
|
{ id: 'rsiOverbought', name: 'RSI Overbought', family: 'technical', body: 'exit', granularity: '1d', explain: 'Momentum gauge overbought, a stretched condition after sustained strength.' },
|
|
{ id: 'macdBullish', name: 'MACD Bullish', family: 'technical', body: 'bull', granularity: '1d', explain: 'The MACD line sits above its signal line, indicating positive short-term momentum.' },
|
|
{ id: 'macdBearish', name: 'MACD Bearish', family: 'technical', body: 'exit', granularity: '1d', explain: 'The MACD line sits below its signal line, indicating negative short-term momentum.' },
|
|
{ id: 'relVolume', name: 'Relative Volume', family: 'technical', body: 'bull', granularity: '1d', explain: 'Current volume is notably above its recent average, increasing the confidence contribution of concurrent signals.' },
|
|
{ id: 'volumeProfileShelf', name: 'Volume-Profile Shelf', family: 'technical', body: 'bull', granularity: '1d', explain: 'Price is trading near a high-volume shelf of the volume profile, historically a supported level.' },
|
|
{ id: 'fibLevelCluster', name: 'Fib Level Cluster', family: 'technical', body: 'bull', granularity: '1d', explain: 'Price is near a Fibonacci level that confluences with other technical levels, a commonly-watched confluence.' },
|
|
{ id: 'volatilityRegimeLow', name: 'Low-Volatility Regime', family: 'technical', body: 'bull', granularity: '1d', explain: 'Realized volatility is in a low percentile versus its own history, historically favorable to trend continuation.' },
|
|
{ id: 'pullbackToEMA21', name: 'Pullback to EMA-21', family: 'technical', body: 'bull', granularity: '1d', explain: 'Price has pulled back toward a rising short-term average within a broader uptrend.' },
|
|
{ id: 'momentumForward', name: 'Forward Momentum', family: 'technical', body: 'bull', granularity: '1d', explain: 'Short-horizon rate of change is positive on a daily basis.' },
|
|
|
|
// ------------------------------------------------------------- institutional
|
|
{ id: 'instNetActivePositive', name: 'Active Funds Net Positive', family: 'institutional', body: 'bull', granularity: '1d', explain: 'Net institutional flows from active managers are positive in the latest observable quarter.' },
|
|
{ id: 'insiderInformedBuy30d', name: 'Informed Insider Buys (30d)', family: 'institutional', body: 'bull', granularity: '1d', explain: 'Informed insiders have been net buyers over the trailing 30 days, the strongest insider-feedback class.' },
|
|
{ id: 'insiderInformedSell', name: 'Informed Insider Selling', family: 'institutional', body: 'exit', granularity: '1d', explain: 'Informed insiders have been net sellers over the trailing window, a caution signal.' },
|
|
{ id: 'new13da', name: 'New 13D/A Disclosure', family: 'institutional', body: 'bull', granularity: '1d', explain: 'A fresh Schedule 13D/A was disclosed, signaling an activist or concentrated position just formed.' },
|
|
{ id: 'instBuyZoneProximity', name: 'Institutional Buy-Zone Proximity', family: 'institutional', body: 'bull', granularity: '1d', explain: 'Price is near the estimated institutional accumulation zone from the flow engine estimation model.' },
|
|
|
|
// -------------------------------------------------------------------- macro
|
|
{ id: 'consumerSentimentLow', name: 'Consumer Sentiment Low', family: 'macro', body: 'bull', granularity: '1wk', explain: 'The consumer-sentiment gauge is in its low historical band, a contrarian backdrop historically followed by higher forward returns.' },
|
|
{ id: 'consumerSentimentHigh', name: 'Consumer Sentiment High', family: 'macro', body: 'exit', granularity: '1wk', explain: 'The consumer-sentiment gauge is in its high historical band, a backdrop historically followed by lower forward returns.' },
|
|
{ id: 'ratesRegime', name: 'Falling-Rates Regime', family: 'macro', body: 'bull', granularity: '1wk', explain: 'Interest-rate expectations are on a falling trajectory, historically supportive of equities.' },
|
|
{ id: 'macroRegimeUp', name: 'Macro Regime Up', family: 'macro', body: 'bull', granularity: '1wk', explain: 'Leading macroeconomic indicators are on a rising trajectory.' },
|
|
{ id: 'breadthThrust', name: 'Breadth Thrust', family: 'macro', body: 'bull', granularity: '1wk', explain: 'Market breadth has surged from oversold, a historically constructive regime marker.' },
|
|
|
|
// -------------------------------------------------------------- seasonal
|
|
{ id: 'seasonalFavorableMonth', name: 'Seasonally Favorable Month', family: 'seasonal', body: 'bull', granularity: '1d', explain: 'The calendar month is historically favorable for the symbol, a mild cyclical tailwind.' },
|
|
{ id: 'winterHalfOn', name: 'Winter Half Indicator', family: 'seasonal', body: 'bull', granularity: '1d', explain: 'The November-April half of the year is historically favorable, a mild cyclical tailwind.' },
|
|
{ id: 'electionCycleFavorableYear', name: 'Election-Cycle Favorable Year', family: 'seasonal', body: 'bull', granularity: '1d', explain: 'The current year of the presidential cycle is historically above-average for equities.' },
|
|
{ id: 'nearTurnOfMonth', name: 'Turn-of-Month', family: 'seasonal', body: 'bull', granularity: '1d', explain: 'The calendar is near the turn of the month, historically a benign pocket of liquidity.' },
|
|
{ id: 'nearQuarterEnd', name: 'Near Quarter-End', family: 'seasonal', body: 'bull', granularity: '1d', explain: 'The calendar is near quarter-end, historically associated with institutional window dressing.' },
|
|
|
|
// -------------------------------------------------------------------- flows
|
|
{ id: 'etfFlowPositive', name: 'ETF Inflows', family: 'flows', body: 'bull', granularity: '1d', explain: 'The symbol is seeing net positive ETF inflows, evidence of systematic buying pressure.' },
|
|
{ id: 'cotPositioning', name: 'COT Positioning', family: 'flows', body: 'bull', granularity: '1wk', explain: 'CFTC futures positioning is in a supportive band, evidence of aligned speculative flows.' },
|
|
{ id: 'rotationIncipient', name: 'Incipient Sector Rotation', family: 'flows', body: 'bull', granularity: '1d', explain: 'Cross-sectional relative-strength analysis flags the symbol as an emerging rotation target.' },
|
|
|
|
// ---------------------------------------------------------------- sentiment
|
|
{ id: 'commentatorSentiment', name: 'Informed Commentator Sentiment', family: 'sentiment', body: 'bull', granularity: '1d', explain: 'Informed commentators tracked via the configured sentiment source are net-positive on the symbol in the measurement window.' },
|
|
|
|
// ----------------------------------------------------------------- corridor
|
|
{ id: 'corridorEntryCheap', name: 'Corridor: Entry Cheap', family: 'macro', body: 'bull', granularity: '1d', explain: 'The current P/E sits in the lower third of the 1-year observable valuation corridor, indicating a relatively attractive entry point versus the symbol\'s own history.' },
|
|
{ id: 'corridorEntryStretched', name: 'Corridor: Entry Stretched', family: 'macro', body: 'exit', granularity: '1d', explain: 'The current P/E sits in the upper third of the 1-year observable valuation corridor, indicating a stretched valuation versus the symbol\'s own history.' },
|
|
{ id: 'corridorUpsideHigh', name: 'Corridor: Upside High', family: 'macro', body: 'bull', granularity: '1d', explain: 'Applying the 1-year median observable multiple to forward earnings implies meaningful upside from the current price.' },
|
|
{ id: 'corridorUpsideLow', name: 'Corridor: Upside Low', family: 'macro', body: 'exit', granularity: '1d', explain: 'Applying the 1-year median observable multiple to forward earnings implies meaningful downside from the current price.' },
|
|
{ id: 'spyCorridorCheap', name: 'SPY Corridor: Cheap', family: 'macro', body: 'bull', granularity: '1wk', explain: 'The S&P 500 forward P/E sits below its 3-year median, a market-level valuation tailwind that improves the odds for broad equity exposure.' },
|
|
{ id: 'spyCorridorStretched', name: 'SPY Corridor: Stretched', family: 'macro', body: 'exit', granularity: '1wk', explain: 'The S&P 500 forward P/E sits at or above its 3-year median, a market-level valuation headwind that tempers the broad-equity picture.' },
|
|
];
|
|
|
|
/** Indexed by slot id for O(1) lookup. */
|
|
export const confluenceslotById: ReadonlyMap<string, ConfluenceSlot> = new Map(
|
|
CONFLUENCE_SLOTS.map((s) => [s.id, s]),
|
|
);
|
|
|
|
/** All slot ids, stable evaluation order. */
|
|
export const CONFLUENCE_SLOT_IDS: readonly string[] = CONFLUENCE_SLOTS.map((s) => s.id);
|
|
|
|
/** Type guard: is `id` a known confluence slot? */
|
|
export function isConfluenceSlot(id: string): id is string {
|
|
return confluenceslotById.has(id);
|
|
}
|
|
|
|
/** Slots grouped by family. */
|
|
export function slotsByFamily(family: SlotFamily): ConfluenceSlot[] {
|
|
return CONFLUENCE_SLOTS.filter((s) => s.family === family);
|
|
}
|
|
|
|
/** DSL helper removed — catalog written literally above for full control. */ |