import type { ExchangeRateSnapshot } from "./exchange-rate"; import type { AnalystResearchData, CorporateActionsData, Quote, QuoteMetadata, TickerFinancials, PricePoint, OptionsChain, HolderData, } from "./financials"; import type { TimeRange } from "../time-series/range"; import type { ChartResolutionSupport, ManualChartResolution } from "../time-series/resolution"; import type { BrokerContractRef, InstrumentSearchResult } from "./instrument"; import type { CachePolicyMap } from "./persistence"; import type { CachedQueryHandle } from "../data/cached-query"; export type CachedAssetMethod = "getExchangeRate" | "getHolders" | "getAnalystResearch" | "getCorporateActions" | "getOptionsChain" | "getSecFilings" | "getSecFilingDocuments" | "getSecFilingContent" | "getArticleSummary"; export type CachedAssetArgs = Parameters>; export type CachedAssetValue = Awaited>>; export interface NewsItem { title: string; url: string; source: string; publishedAt: Date; summary?: string; } export interface SecFilingItem { accessionNumber: string; form: string; filingDate: Date; acceptedAt?: Date; /** Unmodified SEC acceptanceDateTime; a missing timezone is not inferred. */ acceptedAtRaw?: string; primaryDocument?: string; primaryDocDescription?: string; items?: string; cik: string; companyName?: string; filingUrl: string; primaryDocumentUrl?: string; } export interface SecFilingDocument { sequence?: string; type: string; description?: string; document: string; url: string; size?: string; isPrimary: boolean; } export type EarningsEstimateField = | "epsEstimate" | "epsLow" | "epsHigh" | "epsYearAgo" | "epsGrowth" | "epsAnalysts" | "epsTrend7dAgo" | "epsTrend30dAgo" | "epsRevisionUp7d" | "epsRevisionUp30d" | "epsRevisionDown7d" | "epsRevisionDown30d" | "revenueEstimate" | "revenueLow" | "revenueHigh" | "revenueYearAgo" | "revenueGrowth" | "revenueAnalysts"; export interface EarningsEstimateBasis { source: "earningsTrend" | "calendarEvents"; /** Selected provider number before any explicit minor-unit normalization. */ sourceValue: number; /** Provider forecast label, not a derived fiscal quarter or announcement date. */ period: string | null; periodEndDate: string | null; /** Explicit currency for monetary values only; ratios/counts have none. */ currency?: string | null; sourceCurrency?: string | null; } export interface EarningsEvent { symbol: string; name: string; earningsDate: Date; earningsCallDate?: Date | null; isDateEstimate?: boolean | null; estimateBasis?: Partial>; epsEstimate: number | null; epsLow?: number | null; epsHigh?: number | null; epsYearAgo?: number | null; epsGrowth?: number | null; epsAnalysts?: number | null; epsTrend7dAgo?: number | null; epsTrend30dAgo?: number | null; epsRevisionUp7d?: number | null; epsRevisionUp30d?: number | null; epsRevisionDown7d?: number | null; epsRevisionDown30d?: number | null; epsActual: number | null; revenueEstimate: number | null; revenueLow?: number | null; revenueHigh?: number | null; revenueYearAgo?: number | null; revenueGrowth?: number | null; revenueAnalysts?: number | null; revenueActual: number | null; surprise: number | null; timing: "BMO" | "AMC" | "TNS" | ""; } export interface MarketDataRequestContext { brokerId?: string; brokerInstanceId?: string; instrument?: BrokerContractRef | null; cacheMode?: "default" | "refresh"; statementHistory?: "extended"; /** A validated, same-target detailed retry constrained to one exhausted source. */ historyRecovery?: import("../sources/history-retention").HistoryRecoveryCandidate; /** Stable acquisition identity for capture/replay of opaque history responses. */ historyRequestKey?: string; } export interface CachedFinancialsTarget { statementHistory?: "extended"; symbol: string; exchange?: string; brokerId?: string; brokerInstanceId?: string; instrument?: BrokerContractRef | null; } export interface SearchRequestContext { preferBroker?: boolean; brokerId?: string; brokerInstanceId?: string; /** * A person is waiting on this result, so a slow source should be abandoned in * well under a second rather than given the batch budget. */ interactive?: boolean; /** * Called when a later source improves the result the search already returned, * typically a broker adding contract detail to a symbol the cloud found * first. Receives the full merged list, not a delta. */ onPartial?: (results: InstrumentSearchResult[]) => void; } export interface QuoteSubscriptionTarget { symbol: string; exchange?: string; context?: MarketDataRequestContext; route?: "auto" | "provider" | "broker"; surface?: "portfolio" | "watchlist" | "detail" | "monitor" | "inline" | "options" | "screener" | "unknown"; visible?: boolean; selected?: boolean; weight?: number; } export interface QuoteBatchResult { target: QuoteSubscriptionTarget; quote: Quote | null; error?: unknown; } export interface TickerFinancialsBatchResult { target: CachedFinancialsTarget; financials: TickerFinancials | null; error?: unknown; } export interface AssetDataProvider { readonly id: string; readonly name: string; readonly priority?: number; readonly cachePolicy?: CachePolicyMap; /** Optional shared query owner. Consumers observe its age and refreshes instead of caching its values again. */ getCachedQuery?(method: K, args: CachedAssetArgs): CachedQueryHandle>; /** False in a short-lived process, where callers of getCachedQuery must await a stale entry's refresh. */ readonly revalidatesInBackground?: boolean; canProvide?(ticker: string, exchange?: string, context?: MarketDataRequestContext): Promise | boolean; /** * Name of the source a plain market request reaches first. A router answers * for its highest-priority member; a remote transport asks the process that * owns the router. Absent on a plain provider, whose own name is the answer. */ primaryMarketSourceName?(): string | null | Promise; getCachedFinancialsForTargets?(targets: CachedFinancialsTarget[], options?: { allowExpired?: boolean; includeStaleQuotes?: boolean }): Map | Promise>; getQuotesBatch?(targets: QuoteSubscriptionTarget[], options?: { forceRefresh?: boolean }): Promise; getTickerFinancialsBatch?(targets: CachedFinancialsTarget[], options?: { forceRefresh?: boolean }): Promise; getTickerFinancials(ticker: string, exchange?: string, context?: MarketDataRequestContext): Promise; getQuote(ticker: string, exchange?: string, context?: MarketDataRequestContext): Promise; /** Listing facts may outlive the quote price; this method never returns price/session values. */ getQuoteMetadata?(ticker: string, exchange?: string, context?: MarketDataRequestContext): Promise; getExchangeRate(fromCurrency: string): Promise; getExchangeRateSnapshot?(fromCurrency: string): Promise; search(query: string, context?: SearchRequestContext): Promise; getSecFilings?(ticker: string, count?: number, exchange?: string, context?: MarketDataRequestContext): Promise; getHolders?(ticker: string, exchange?: string, context?: MarketDataRequestContext): Promise; getAnalystResearch?(ticker: string, exchange?: string, context?: MarketDataRequestContext): Promise; getCorporateActions?(ticker: string, exchange?: string, context?: MarketDataRequestContext): Promise; getEarningsCalendar?(symbols: string[], context?: MarketDataRequestContext): Promise; getSecFilingDocuments?(filing: SecFilingItem): Promise; getSecFilingContent?(filing: SecFilingItem): Promise; /** Fetch article summary/description by URL (lazy-loaded on selection) */ getArticleSummary(url: string): Promise; getPriceHistory(ticker: string, exchange: string, range: TimeRange, context?: MarketDataRequestContext): Promise; /** Default history with source-declared cadence, when the provider can retain it. */ getPriceHistoryWithMetadata?( ticker: string, exchange: string, range: TimeRange, context?: MarketDataRequestContext, ): Promise; getPriceHistoryForResolutionWithMetadata?( ticker: string, exchange: string, bufferRange: TimeRange, resolution: ManualChartResolution, context?: MarketDataRequestContext, ): Promise; getDetailedPriceHistoryWithMetadata?( ticker: string, exchange: string, startDate: Date, endDate: Date, barSize: string, context?: MarketDataRequestContext, ): Promise; getPriceHistoryForResolution?( ticker: string, exchange: string, bufferRange: TimeRange, resolution: ManualChartResolution, context?: MarketDataRequestContext, ): Promise; /** Fetch higher-resolution price data for a specific date window (e.g. when zoomed in). */ getDetailedPriceHistory?(ticker: string, exchange: string, startDate: Date, endDate: Date, barSize: string, context?: MarketDataRequestContext): Promise; getChartResolutionSupport?( ticker: string, exchange?: string, context?: MarketDataRequestContext, ): Promise | ChartResolutionSupport[]; getChartResolutionCapabilities?( ticker: string, exchange?: string, context?: MarketDataRequestContext, ): Promise | ManualChartResolution[]; getOptionsChain?(ticker: string, exchange?: string, expirationDate?: number, context?: MarketDataRequestContext): Promise; subscribeQuotes?( targets: QuoteSubscriptionTarget[], onQuote: (target: QuoteSubscriptionTarget, quote: Quote) => void, ): () => void; } export type DataProvider = AssetDataProvider;