From e2389eba31b8891c735edd330495e929748ba35f Mon Sep 17 00:00:00 2001 From: I Luk Kim Date: Tue, 12 May 2026 15:16:35 -0700 Subject: [PATCH] =?UTF-8?q?feat:=20GET=20/stocks/gainers/snapshots=20?= =?UTF-8?q?=E2=80=94=20=EA=B3=BC=EA=B1=B0=205=EB=B6=84=EB=B4=89=20gainer?= =?UTF-8?q?=20snapshot=20=EC=A1=B0=ED=9A=8C=20=EC=97=94=EB=93=9C=ED=8F=AC?= =?UTF-8?q?=EC=9D=B8=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gainer_snapshots 테이블을 읽는 엔드포인트가 없어 백테스팅이 불가능했던 문제 해결. ?at= 생략 시 최신 snapshot, as-of semantics로 장외 시각도 자연스럽게 처리. openapi.json 동기화. Co-Authored-By: Claude Sonnet 4.6 --- app/api/v1/endpoints/stocks.py | 84 +- docs/openapi.json | 13780 ++++++++++++++++++++++++++++++- 2 files changed, 13861 insertions(+), 3 deletions(-) diff --git a/app/api/v1/endpoints/stocks.py b/app/api/v1/endpoints/stocks.py index 7f940a0..847738f 100644 --- a/app/api/v1/endpoints/stocks.py +++ b/app/api/v1/endpoints/stocks.py @@ -4,11 +4,17 @@ Stock Market Data endpoints """ from typing import Optional -from fastapi import APIRouter, HTTPException, Query, Response +from fastapi import APIRouter, Depends, HTTPException, Query, Response import logging import asyncio -from datetime import datetime +from datetime import datetime, timezone +from sqlalchemy import select, func +from sqlalchemy.ext.asyncio import AsyncSession + +from app.core.database import get_db +from app.models.gainer_snapshot import GainerSnapshot +from app.services.gainers.collector import _floor_to_5min from app.services.yahoo_most_active_service import yahoo_most_active_service from app.services.yahoo_52week_gainers_service import yahoo_52week_gainers_service from app.services.index_constituents_service import index_constituents_service @@ -346,6 +352,80 @@ async def get_day_gainers( } +@router.get( + "/gainers/snapshots", + summary="Historical top gainers snapshot (5-min interval, DB)", +) +async def get_gainer_snapshot( + at: Optional[datetime] = Query( + None, + description="UTC timestamp to query (ISO 8601). Omit for the latest snapshot.", + ), + limit: int = Query(100, ge=1, le=200, description="Number of top gainers to return (max 200)"), + db: AsyncSession = Depends(get_db), +): + """ + Return top gainers stored in the DB at the requested point in time. + + - **at** omitted → most recent 5-min snapshot. + - **at** provided → as-of semantics: the latest snapshot whose `snapshot_at ≤ floor(at, 5min)`. + - Returns `404` when no snapshot exists before the requested time. + """ + if at is None: + target = ( + await db.execute(select(func.max(GainerSnapshot.snapshot_at))) + ).scalar() + else: + floored = _floor_to_5min( + at if at.tzinfo else at.replace(tzinfo=timezone.utc) + ) + target = ( + await db.execute( + select(func.max(GainerSnapshot.snapshot_at)).where( + GainerSnapshot.snapshot_at <= floored + ) + ) + ).scalar() + + if target is None: + raise HTTPException(status_code=404, detail="No gainer snapshots found for the requested time") + + rows = ( + await db.execute( + select(GainerSnapshot) + .where(GainerSnapshot.snapshot_at == target) + .order_by(GainerSnapshot.rank.asc()) + .limit(limit) + ) + ).scalars().all() + + return { + "snapshot_at": target.isoformat(), + "requested_at": at.isoformat() if at else None, + "count": len(rows), + "stocks": [ + { + "rank": r.rank, + "symbol": r.symbol, + "name": r.name, + "exchange": r.exchange, + "price": r.price, + "change_percent": r.change_percent, + "volume": r.volume, + "avg_volume_3m": r.avg_volume_3m, + "market_cap": r.market_cap, + "pe_ratio": r.pe_ratio, + "forward_pe": r.forward_pe, + "eps_ttm": r.eps_ttm, + "dividend_yield": r.dividend_yield, + "fifty_two_week_high": r.fifty_two_week_high, + "fifty_two_week_low": r.fifty_two_week_low, + } + for r in rows + ], + } + + @router.get( "/trending", summary="Trending stocks combining most active and 52-week gainers", diff --git a/docs/openapi.json b/docs/openapi.json index 2e6c93b..910338b 100644 --- a/docs/openapi.json +++ b/docs/openapi.json @@ -1 +1,13779 @@ -{"openapi":"3.1.0","info":{"title":"Stock Oracle","version":"1.0.0"},"paths":{"/api/v1/health":{"get":{"tags":["health"],"summary":"Health check","description":"Check the health status of the API and its dependencies","operationId":"health_check_api_v1_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthCheckResponse"}}}}}}},"/api/v1/financial/data":{"post":{"tags":["financial"],"summary":"Get SEC EDGAR financial data for a ticker","description":"Retrieve comprehensive financial data directly from SEC EDGAR filings for a specific ticker and time period.\n \n **🔥 Three Ways to Specify Time Period (choose one):**\n \n 1. **Period String** (NEW! Most convenient):\n - `period`: \"1d\", \"7d\", \"30d\", \"1m\", \"3m\", \"6m\", \"1y\", \"2y\", \"5y\", \"max\"\n - Examples: `{\"ticker\": \"AAPL\", \"period\": \"1y\"}` - Last 1 year of data\n - Example: `{\"ticker\": \"TSLA\", \"period\": \"max\"}` - All available data from listing date to SEC limits\n \n 2. **Date Range** (Traditional):\n - `start_date` + `end_date`: Specific date range\n - Example: `{\"ticker\": \"AAPL\", \"start_date\": \"2024-01-01\", \"end_date\": \"2024-12-31\"}`\n \n 3. **Quarters** (Quarter-based):\n - `quarters`: List of quarters like [\"2024Q1\", \"2024Q2\"]\n - Example: `{\"ticker\": \"AAPL\", \"quarters\": [\"2024Q1\", \"2024Q2\", \"2024Q3\"]}`\n \n **Data Sources:**\n - **Financial Data**: Direct SEC EDGAR API calls (revenue, income, assets, cash flow)\n - **Price Data**: Available via separate price data endpoints using yfinance-plus\n \n **This endpoint returns:**\n - Company information (name, CIK, sector, industry)\n - Financial statements data from SEC filings (income statement, balance sheet, cash flow)\n - Calculated financial metrics (ratios, margins, growth rates)\n - Period types: quarterly (10-Q) and annual (10-K) filings\n \n **Performance Features:**\n - Database caching to avoid repeated SEC API calls\n - Historical data available from 1994-present\n - 15+ years of data typically available for most companies\n - Use `force_refresh=true` to fetch fresh data from SEC EDGAR\n \n **Data Quality:**\n - All financial data sourced directly from official SEC filings\n - No estimated or synthetic data - only actual reported figures\n - Automatic validation and error handling for missing periods\n \n **Example Requests:**\n ```json\n // Using period (simplest)\n {\n \"ticker\": \"AAPL\",\n \"period\": \"1y\",\n \"include_metrics\": true\n }\n \n // Using date range\n {\n \"ticker\": \"MSFT\",\n \"start_date\": \"2024-01-01\",\n \"end_date\": \"2024-12-31\",\n \"period_type\": \"quarterly\"\n }\n \n // Using quarters\n {\n \"ticker\": \"GOOGL\",\n \"quarters\": [\"2024Q1\", \"2024Q2\"],\n \"include_metrics\": true\n }\n ```","operationId":"get_financial_data_api_v1_financial_data_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinancialDataRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinancialDataResponse"}}}},"400":{"description":"Invalid request parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Data not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/financial/data/{ticker}":{"get":{"tags":["financial"],"summary":"Get financial data by ticker (simplified)","description":"Simplified GET endpoint to retrieve financial data with query parameters.\n \n **Time Period Options:**\n - Use `period` for convenience: \"1d\", \"7d\", \"1m\", \"3m\", \"6m\", \"1y\", \"2y\", \"5y\", \"max\"\n - OR use `start_date` and `end_date` for specific date range\n - Cannot use both approaches simultaneously\n \n **Examples:**\n - `/api/v1/financial/data/AAPL?period=1y&include_metrics=true` - Last year of financial data\n - `/api/v1/financial/data/AAPL?start_date=2024-01-01&end_date=2024-12-31&period_type=quarterly` - Specific date range","operationId":"get_financial_data_simple_api_v1_financial_data__ticker__get","parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string","title":"Ticker"}},{"name":"period","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Period like '1d', '7d', '1m', '3m', '6m', '1y', '2y', '5y', 'max'","title":"Period"},"description":"Period like '1d', '7d', '1m', '3m', '6m', '1y', '2y', '5y', 'max'"},{"name":"start_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Start date for data retrieval (use with end_date, not with period)","title":"Start Date"},"description":"Start date for data retrieval (use with end_date, not with period)"},{"name":"end_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"End date for data retrieval (use with start_date, not with period)","title":"End Date"},"description":"End date for data retrieval (use with start_date, not with period)"},{"name":"period_type","in":"query","required":false,"schema":{"type":"string","description":"Period type: quarterly, annual, or all","default":"all","title":"Period Type"},"description":"Period type: quarterly, annual, or all"},{"name":"include_metrics","in":"query","required":false,"schema":{"type":"boolean","description":"Include calculated metrics","default":true,"title":"Include Metrics"},"description":"Include calculated metrics"},{"name":"force_refresh","in":"query","required":false,"schema":{"type":"boolean","description":"Force refresh from SEC","default":false,"title":"Force Refresh"},"description":"Force refresh from SEC"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinancialDataResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/financial/data/bulk":{"post":{"tags":["financial"],"summary":"Get SEC EDGAR financial data for multiple tickers","description":"Retrieve comprehensive financial data for multiple tickers in a single request directly from SEC EDGAR filings.\n \n **🔥 Three Ways to Specify Time Period (choose one):**\n \n 1. **Period String** (NEW! Most convenient):\n - `period`: \"1d\", \"7d\", \"30d\", \"1m\", \"3m\", \"6m\", \"1y\", \"2y\", \"5y\", \"max\"\n - Example: Last 1 year for multiple tickers, or \"max\" for all available data\n \n 2. **Date Range** (Traditional):\n - `start_date` + `end_date`: Specific date range\n - Example: Specific date range for all tickers\n \n 3. **Quarters** (Quarter-based):\n - `quarters`: List of quarters like [\"2024Q1\", \"2024Q2\"]\n - Example: Specific quarters for all tickers\n \n **Data Sources:**\n - **Financial Data**: Direct SEC EDGAR API calls (revenue, income, assets, cash flow)\n - **Price Data**: Available via separate price data endpoints using yfinance-plus\n \n **Bulk Processing Features:**\n - Processes up to 100 tickers in parallel for maximum efficiency\n - Returns individual success/failure results for each ticker\n - Handles partial failures gracefully (some tickers can fail while others succeed)\n - Uses the same robust SEC data retrieval logic as single ticker endpoint\n \n **SEC EDGAR Integration:**\n - Direct API calls to official SEC EDGAR database\n - All financial data sourced from actual SEC filings (10-K, 10-Q)\n - No estimated or synthetic data - only actual reported figures\n - Historical data available from 1994-present (15+ years for most companies)\n - Automatic validation and error handling for missing periods\n \n **Data Quality & Features:**\n - Company information (name, CIK, sector, industry, business description)\n - Comprehensive financial statements (income statement, balance sheet, cash flow)\n - Calculated financial metrics (ratios, margins, growth rates)\n - Period types: quarterly (10-Q) and annual (10-K) filings\n - Database caching to avoid repeated SEC API calls\n \n **Performance:**\n - Parallel processing for bulk requests\n - Intelligent caching and rate limiting\n - Use `force_refresh=true` to fetch fresh data from SEC EDGAR\n \n **Example Requests:**\n ```json\n // Using period (simplest)\n {\n \"tickers\": [\"AAPL\", \"MSFT\", \"GOOGL\"],\n \"period\": \"1y\",\n \"include_metrics\": true\n }\n \n // Using date range\n {\n \"tickers\": [\"NVDA\", \"AMD\", \"INTC\"],\n \"start_date\": \"2024-01-01\",\n \"end_date\": \"2024-12-31\",\n \"period_type\": \"quarterly\"\n }\n \n // Using quarters\n {\n \"tickers\": [\"TSLA\", \"F\", \"GM\"],\n \"quarters\": [\"2024Q1\", \"2024Q2\"],\n \"include_metrics\": true\n }\n ```\n \n Each ticker result includes the same comprehensive financial data structure as the single ticker endpoint.\n Failed tickers will have detailed error messages while successful ones will have complete SEC filing data.","operationId":"get_bulk_financial_data_api_v1_financial_data_bulk_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkFinancialDataRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkFinancialDataResponse"}}}},"400":{"description":"Invalid request parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/price/data":{"post":{"tags":["price"],"summary":"Get enhanced price data via yfinance-plus","description":"Retrieve historical price data for a specific ticker using enhanced yfinance-plus integration.\n \n **🔥 Three Ways to Specify Time Period (choose one):**\n \n 1. **Period String** (NEW! Most convenient):\n - `period`: \"1d\", \"7d\", \"30d\", \"1m\", \"3m\", \"6m\", \"1y\", \"2y\", \"5y\", \"max\"\n - Example: `{\"ticker\": \"AAPL\", \"period\": \"3m\", \"interval\": \"1d\"}` - Last 3 months, daily prices\n - Example: `{\"ticker\": \"TSLA\", \"period\": \"max\", \"interval\": \"1d\"}` - Maximum 20 years of data\n \n 2. **Date Range** (Traditional):\n - `start_date` + `end_date`: Specific date range\n - Example: `{\"ticker\": \"AAPL\", \"start_date\": \"2024-01-01\", \"end_date\": \"2024-12-31\", \"interval\": \"1d\"}`\n \n 3. **Quarters** (Quarter-based):\n - `quarters`: List of quarters like [\"2024Q1\", \"2024Q2\"]\n - Example: `{\"ticker\": \"AAPL\", \"quarters\": [\"2024Q1\", \"2024Q2\"], \"interval\": \"1d\"}`\n \n **Data Source:**\n - **Price Data**: Yahoo Finance via yfinance-plus with enhanced rate limiting and caching\n - **Financial Data**: Available via separate financial endpoints using SEC EDGAR\n \n **This endpoint returns:**\n - OHLCV data (Open, High, Low, Close, Volume)\n - Adjusted close prices with dividend/split adjustments\n - Multiple intervals: 1d, 1w, 1m, 1h (where available)\n - Extensive historical data (decades for most symbols)\n \n **Enhanced Features (yfinance-plus):**\n - Intelligent rate limiting to prevent API throttling\n - Multi-threaded bulk downloads for better performance\n - Advanced caching with cache management\n - Automatic retry with exponential backoff\n - Multiple user agents for improved reliability\n - Enhanced error handling and recovery\n \n **Performance:**\n - Database caching to minimize external API calls\n - Bulk mode capable of 59+ tickers/second throughput\n - 4.3x faster than individual ticker requests\n - Use `force_refresh=true` to fetch fresh data from Yahoo Finance\n \n **Example Requests:**\n ```json\n // Using period (simplest)\n {\n \"ticker\": \"AAPL\",\n \"period\": \"6m\",\n \"interval\": \"1d\"\n }\n \n // Using date range\n {\n \"ticker\": \"TSLA\",\n \"start_date\": \"2024-01-01\",\n \"end_date\": \"2024-12-31\",\n \"interval\": \"1w\"\n }\n \n // Using quarters\n {\n \"ticker\": \"NVDA\",\n \"quarters\": [\"2024Q1\", \"2024Q2\"],\n \"interval\": \"1d\",\n \"force_refresh\": true\n }\n ```","operationId":"get_price_data_api_v1_price_data_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceDataRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceDataResponse"}}}},"400":{"description":"Invalid request parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Data not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["price","price"],"summary":"Get daily bars for multiple tickers via yfinance (DB-backed)","description":"Fetch OHLCV daily bars for one or more tickers via Yahoo Finance (yfinance-plus). Results are stored in DB; subsequent calls for the same range skip the external API.\n\n- `tickers` or `ticker`: comma-separated list, e.g. `AAPL,MSFT` or single `QQQ`\n- `force_refresh=true`: re-fetch from Yahoo Finance even if DB has data\n- Up to 1000 tickers per request (auto-chunked internally)\n\n**경로 파라미터 대안**: 단일 종목은 `/data/{ticker}?start_date=...&end_date=...` 도 동일하게 동작합니다.","operationId":"get_multi_ticker_daily_bars_api_v1_price_data_get","parameters":[{"name":"tickers","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated tickers, e.g. AAPL,MSFT,QQQ","title":"Tickers"},"description":"Comma-separated tickers, e.g. AAPL,MSFT,QQQ"},{"name":"ticker","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Alias for tickers (single ticker shorthand)","title":"Ticker"},"description":"Alias for tickers (single ticker shorthand)"},{"name":"start_date","in":"query","required":true,"schema":{"type":"string","format":"date","description":"Start date (YYYY-MM-DD)","title":"Start Date"},"description":"Start date (YYYY-MM-DD)"},{"name":"end_date","in":"query","required":true,"schema":{"type":"string","format":"date","description":"End date (YYYY-MM-DD)","title":"End Date"},"description":"End date (YYYY-MM-DD)"},{"name":"interval","in":"query","required":false,"schema":{"type":"string","description":"Bar interval: 1d, 1w, 1m","default":"1d","title":"Interval"},"description":"Bar interval: 1d, 1w, 1m"},{"name":"force_refresh","in":"query","required":false,"schema":{"type":"boolean","description":"Re-fetch from Yahoo Finance even if DB has data","default":false,"title":"Force Refresh"},"description":"Re-fetch from Yahoo Finance even if DB has data"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlpacaMultiBarsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/price/data/{ticker}":{"get":{"tags":["price"],"summary":"Get price data by ticker (simplified)","description":"Simplified GET endpoint to retrieve price data with query parameters.\n \n **Time Period Options:**\n - Use `period` for convenience: \"1d\", \"7d\", \"1m\", \"3m\", \"6m\", \"1y\", \"2y\", \"5y\", \"max\"\n - OR use `start_date` and `end_date` for specific date range\n - Cannot use both approaches simultaneously\n \n **Examples:**\n - `/api/v1/price/data/AAPL?period=1y&interval=1d` - Last year of daily prices\n - `/api/v1/price/data/TSLA?period=max&interval=1d` - Maximum 20 years of data for Tesla\n - `/api/v1/price/data/AAPL?start_date=2024-01-01&end_date=2024-12-31&interval=1d` - Specific date range","operationId":"get_price_data_simple_api_v1_price_data__ticker__get","parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string","title":"Ticker"}},{"name":"period","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Period like '1d', '7d', '1m', '3m', '6m', '1y', '2y', '5y', 'max'","title":"Period"},"description":"Period like '1d', '7d', '1m', '3m', '6m', '1y', '2y', '5y', 'max'"},{"name":"start_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Start date for data retrieval (use with end_date, not with period)","title":"Start Date"},"description":"Start date for data retrieval (use with end_date, not with period)"},{"name":"end_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"End date for data retrieval (use with start_date, not with period)","title":"End Date"},"description":"End date for data retrieval (use with start_date, not with period)"},{"name":"start","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Alias for start_date","title":"Start"},"description":"Alias for start_date"},{"name":"end","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Alias for end_date","title":"End"},"description":"Alias for end_date"},{"name":"interval","in":"query","required":false,"schema":{"type":"string","description":"Data interval: 1d, 1w, 1m, 5d, 1h, etc.","default":"1d","title":"Interval"},"description":"Data interval: 1d, 1w, 1m, 5d, 1h, etc."},{"name":"force_refresh","in":"query","required":false,"schema":{"type":"boolean","description":"Force refresh from Yahoo Finance","default":false,"title":"Force Refresh"},"description":"Force refresh from Yahoo Finance"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceDataResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/price/data/bulk":{"post":{"tags":["price"],"summary":"Get enhanced price data for multiple tickers via yfinance-plus","description":"Retrieve historical price data for multiple tickers in a single request using enhanced yfinance-plus integration.\n \n **🔥 Three Ways to Specify Time Period (choose one):**\n \n 1. **Period String** (NEW! Most convenient):\n - `period`: \"1d\", \"7d\", \"30d\", \"1m\", \"3m\", \"6m\", \"1y\", \"2y\", \"5y\", \"max\"\n - Example: Last 3 months for multiple tickers, or \"max\" for maximum 20 years of data\n \n 2. **Date Range** (Traditional):\n - `start_date` + `end_date`: Specific date range\n - Example: Specific date range for all tickers\n \n 3. **Quarters** (Quarter-based):\n - `quarters`: List of quarters like [\"2024Q1\", \"2024Q2\"]\n - Example: Specific quarters for all tickers\n \n **Data Source:**\n - **Price Data**: Yahoo Finance via yfinance-plus with enhanced rate limiting and caching\n - **Financial Data**: Available via separate financial endpoints using SEC EDGAR\n \n **Bulk Processing Features:**\n - Processes up to 100 tickers in parallel for maximum throughput\n - Returns individual success/failure results for each ticker\n - Handles partial failures gracefully (some tickers can fail while others succeed)\n - Uses the same enhanced data retrieval logic as single ticker endpoint\n \n **Enhanced Performance (yfinance-plus):**\n - Multi-threaded bulk downloads with intelligent rate limiting\n - 4.3x faster than individual ticker requests\n - Bulk mode capable of 59+ tickers/second throughput\n - Advanced caching and automatic retry with exponential backoff\n - Enhanced error handling and recovery mechanisms\n \n **Data Quality:**\n - OHLCV data with dividend/split adjustments\n - Multiple intervals: 1d, 1w, 1m, 1h (where available)\n - Extensive historical data (decades for most symbols)\n - Database caching to minimize external API calls\n \n **Example Requests:**\n ```json\n // Using period (simplest)\n {\n \"tickers\": [\"AAPL\", \"MSFT\", \"GOOGL\"],\n \"period\": \"3m\",\n \"interval\": \"1d\"\n }\n \n // Using date range\n {\n \"tickers\": [\"NVDA\", \"AMD\", \"INTC\"],\n \"start_date\": \"2024-01-01\",\n \"end_date\": \"2024-12-31\",\n \"interval\": \"1w\"\n }\n \n // Using quarters\n {\n \"tickers\": [\"TSLA\", \"F\", \"GM\"],\n \"quarters\": [\"2024Q1\", \"2024Q2\"],\n \"interval\": \"1d\",\n \"force_refresh\": true\n }\n ```\n \n Each ticker result includes the same comprehensive price data structure as the single ticker endpoint.\n Failed tickers will have detailed error messages while successful ones will have complete OHLCV data.","operationId":"get_bulk_price_data_api_v1_price_data_bulk_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkPriceDataRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkPriceDataResponse"}}}},"400":{"description":"Invalid request parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/price/latest/{ticker}":{"get":{"tags":["price"],"summary":"Get latest price for a ticker","description":"Get the most recent price data point for a ticker","operationId":"get_latest_price_api_v1_price_latest__ticker__get","parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string","title":"Ticker"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceDataPoint"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/price/quote/{ticker}":{"get":{"tags":["price"],"summary":"Get latest quote (regular/pre/post)","description":"Return latest price with regular/pre/post market fields from yfinance-plus","operationId":"get_quote_api_v1_price_quote__ticker__get","parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string","title":"Ticker"}},{"name":"use_prepost","in":"query","required":false,"schema":{"type":"boolean","description":"Include pre/post market prices if available","default":true,"title":"Use Prepost"},"description":"Include pre/post market prices if available"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/price/intraday":{"get":{"tags":["price"],"summary":"Get intraday bars for multiple tickers via Yahoo Finance","description":"Fetch intraday OHLCV bars for up to ~500 tickers using Yahoo Finance.\n\n**⚠️ Yahoo Finance 분봉 데이터 한계**\n\n| 항목 | 내용 |\n|------|------|\n| 지연 | **15분 지연** (실시간 아님) |\n| `1m` 최대 조회 기간 | 최근 **7일** 이내 |\n| `2m`/`5m`/`15m`/`30m`/`90m` | 최근 **60일** 이내 |\n| `1h` | 최근 **730일** 이내 |\n| 실시간 거래 전략 | **부적합** — 15분 지연으로 ORB 등 당일 전략에 사용 불가 |\n| 데이터 품질 | Yahoo Finance 자체 집계, 간헐적 누락/오류 가능 |\n\n**권장 용도**: 백테스트, 과거 분봉 분석 (60일 이내)\n\n**실시간 당일 분봉이 필요하면** → `GET /api/v1/alpaca/intraday` 사용 (Alpaca IEX 피드, 실시간)\n\n- `tickers`: comma-separated, e.g. `AAPL,MSFT,BF-B`\n- `interval`: `1m`, `5m`, `15m`, `30m`, `1h`\n- Redis 5분 TTL 캐시 적용","operationId":"get_multi_ticker_intraday_api_v1_price_intraday_get","parameters":[{"name":"tickers","in":"query","required":true,"schema":{"type":"string","description":"Comma-separated tickers","title":"Tickers"},"description":"Comma-separated tickers"},{"name":"interval","in":"query","required":false,"schema":{"type":"string","description":"Interval: 1m, 5m, 15m, 30m, 1h","default":"5m","title":"Interval"},"description":"Interval: 1m, 5m, 15m, 30m, 1h"},{"name":"start_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Start date (YYYY-MM-DD)","title":"Start Date"},"description":"Start date (YYYY-MM-DD)"},{"name":"end_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"End date (YYYY-MM-DD)","title":"End Date"},"description":"End date (YYYY-MM-DD)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlpacaMultiBarsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/price/intraday/{ticker}":{"get":{"tags":["price"],"summary":"Get intraday candles","description":"Return intraday candles using yfinance-plus history(period,interval)","operationId":"get_intraday_api_v1_price_intraday__ticker__get","parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string","title":"Ticker"}},{"name":"interval","in":"query","required":false,"schema":{"type":"string","default":"1m","title":"Interval"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","default":"1d","title":"Period"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntradayResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/price/today/{ticker}":{"get":{"tags":["price"],"summary":"Get today's OHLC","description":"Return today's OHLC. If daily not finalized yet, aggregate from 1m intraday.","operationId":"get_today_ohlc_api_v1_price_today__ticker__get","parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string","title":"Ticker"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TodayOHLCResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/stocks/index/{index_name}":{"get":{"tags":["stocks"],"summary":"Get index constituents (S&P 500 / Nasdaq 100)","description":"Get current constituents of a major stock index from Wikipedia.\n\nReturns each stock's symbol, company name, GICS Sector, and GICS Sub-Industry.\n\n**Supported values for `index_name`**:\n- `sp500` — S&P 500 (~503 stocks)\n- `nasdaq100` — Nasdaq 100 (~101 stocks)\n\n**Data Source**: Wikipedia\n**Cache TTL**: 24 hours (`X-Cache: HIT/MISS`, `ETag` headers included)\n**Timeout**: 30 seconds (Wikipedia fetch)\n\n**Error codes**:\n- `400` — unsupported `index_name`\n- `504` — Wikipedia response timed out","operationId":"get_index_constituents_api_v1_stocks_index__index_name__get","parameters":[{"name":"index_name","in":"path","required":true,"schema":{"type":"string","title":"Index Name"}},{"name":"force_refresh","in":"query","required":false,"schema":{"type":"boolean","description":"If true, bypasses cache and fetches fresh data","default":false,"title":"Force Refresh"},"description":"If true, bypasses cache and fetches fresh data"}],"responses":{"200":{"description":"List of constituent stocks with symbol, name, sector, and industry","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/stocks/most-active":{"get":{"tags":["stocks"],"summary":"Most actively traded stocks by volume","description":"Get most actively traded stocks from Yahoo Finance.\n\n**⚠️ 실시간 전용**: DB에 저장되지 않음. 과거 데이터 조회 불가.\n캐시 TTL: 1시간 (`X-Cache: HIT/MISS` 헤더 포함).","operationId":"get_most_active_stocks_api_v1_stocks_most_active_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":500,"minimum":1},{"type":"null"}],"description":"Maximum number of stocks to return (1-500). If not specified, returns all available stocks.","title":"Limit"},"description":"Maximum number of stocks to return (1-500). If not specified, returns all available stocks."},{"name":"force_refresh","in":"query","required":false,"schema":{"type":"boolean","description":"If true, bypasses cache and fetches fresh data","default":false,"title":"Force Refresh"},"description":"If true, bypasses cache and fetches fresh data"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/stocks/52-week-gainers":{"get":{"tags":["stocks"],"summary":"Top 52-week gaining stocks","description":"Get 52-week top gaining stocks from Yahoo Finance.\n\n**⚠️ 실시간 전용**: DB에 저장되지 않음. 과거 데이터 조회 불가.\n캐시 TTL: 1시간. 첫 호출 시 15-30초 소요 (웹 스크래핑).","operationId":"get_52week_gainers_api_v1_stocks_52_week_gainers_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":1000,"minimum":1},{"type":"null"}],"description":"Maximum number of stocks to return (1-1000). If not specified, returns first 600 stocks (3 pages) for performance.","title":"Limit"},"description":"Maximum number of stocks to return (1-1000). If not specified, returns first 600 stocks (3 pages) for performance."},{"name":"max_pages","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":10,"minimum":1},{"type":"null"}],"description":"Maximum pages to fetch (1-10). Each page has ~200 stocks. Higher values may cause rate limiting.","default":3,"title":"Max Pages"},"description":"Maximum pages to fetch (1-10). Each page has ~200 stocks. Higher values may cause rate limiting."},{"name":"force_refresh","in":"query","required":false,"schema":{"type":"boolean","description":"Bypass cache","default":false,"title":"Force Refresh"},"description":"Bypass cache"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/stocks/trending":{"get":{"tags":["stocks"],"summary":"Trending stocks combining most active and 52-week gainers","description":"Get trending stocks by combining most-active + 52-week gainers.\n\n**⚠️ 실시간 전용**: DB에 저장되지 않음. 과거 데이터 조회 불가.\n캐시 TTL: 30분. 병렬 스크래핑으로 최적화.","operationId":"get_trending_stocks_api_v1_stocks_trending_get","parameters":[{"name":"n","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"description":"Total number of trending stocks to return after combining most active + gainers (default: 500)","default":500,"title":"N"},"description":"Total number of trending stocks to return after combining most active + gainers (default: 500)"},{"name":"most_active_limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"description":"Number of most active stocks to include. If not specified, returns all available stocks (~170).","title":"Most Active Limit"},"description":"Number of most active stocks to include. If not specified, returns all available stocks (~170)."},{"name":"gainers_limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"description":"Number of 52-week gainers to fetch. If not specified, fetches enough to reach target 'n' after combining with most active.","title":"Gainers Limit"},"description":"Number of 52-week gainers to fetch. If not specified, fetches enough to reach target 'n' after combining with most active."},{"name":"force_refresh","in":"query","required":false,"schema":{"type":"boolean","description":"Bypass cache","default":false,"title":"Force Refresh"},"description":"Bypass cache"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/fred/stats/usage":{"get":{"tags":["fred"],"summary":"FRED API usage statistics and cache performance","description":"Get FRED API usage statistics and cache performance\n\nReturns detailed statistics about API usage, cache performance, and daily limits.\nNow includes enhanced proxy service statistics.\n\n**Example Response**:\n```json\n{\n \"success\": true,\n \"data\": {\n \"daily_limit\": 1000,\n \"used_today\": 45,\n \"remaining_today\": 955,\n \"usage_percentage\": 4.5,\n \"can_make_requests\": true,\n \"daily_stats\": [\n {\n \"date\": \"2025-01-14\",\n \"total_calls\": 45,\n \"successful_calls\": 44,\n \"total_records\": 1250,\n \"success_rate\": 97.8\n }\n ],\n \"endpoint_stats\": [\n {\n \"endpoint\": \"series\",\n \"call_count\": 25\n }\n ],\n \"proxy_info\": {\n \"mode\": \"pass_through_proxy\",\n \"supported_endpoints\": \"all_fred_endpoints\"\n }\n }\n}\n```\n\n**Parameters**:\n- `days`: Number of days to include in historical statistics (1-30)\n- `use_proxy_stats`: Use enhanced proxy service statistics (recommended)\n\n**Metrics Included**:\n- Daily API usage and remaining quota\n- Historical usage patterns \n- Endpoint-specific usage statistics (NEW!)\n- Success rates and error tracking\n- Proxy service information (NEW!)","operationId":"get_fred_usage_stats_api_v1_fred_stats_usage_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":30,"minimum":1,"description":"Number of days to include in stats","default":7,"title":"Days"},"description":"Number of days to include in stats"},{"name":"use_proxy_stats","in":"query","required":false,"schema":{"type":"boolean","description":"Use enhanced proxy service statistics","default":true,"title":"Use Proxy Stats"},"description":"Use enhanced proxy service statistics"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/fred/proxy/{endpoint}":{"get":{"tags":["fred"],"summary":"Universal FRED API proxy","description":"FRED API Pass-through Proxy\n\nUniversal proxy endpoint that forwards requests to any FRED API endpoint while maintaining\nour caching and rate limiting logic.\n\n**Supported Endpoints**: All FRED API endpoints are supported\n\n**Examples**:\n```bash\n# Series information\nGET /api/v1/fred/proxy/series?series_id=GDP\n\n# Series observations \nGET /api/v1/fred/proxy/series/observations?series_id=UNRATE&limit=12\n\n# Category information\nGET /api/v1/fred/proxy/category?category_id=125\n\n# Category children\nGET /api/v1/fred/proxy/category/children?category_id=13\n\n# Release information\nGET /api/v1/fred/proxy/release?release_id=53\n\n# Search series\nGET /api/v1/fred/proxy/series/search?search_text=unemployment&limit=25\n\n# Sources\nGET /api/v1/fred/proxy/sources\n\n# Tags\nGET /api/v1/fred/proxy/tags?limit=100\n```\n\n**Key Features**:\n- **Universal Access**: Support for all FRED API endpoints\n- **Smart Caching**: 24-hour DB caching for series and observations (NEW!)\n- **Permanent Storage**: Historical data permanently stored in database (NEW!)\n- **Rate Limiting**: Respects 1,000/day limit with usage tracking \n- **Parameter Forwarding**: Automatically forwards all supported parameters\n- **Error Handling**: Comprehensive error handling and logging\n- **Usage Statistics**: Tracks endpoint usage and performance\n\n**Parameters**:\nAll standard FRED API parameters are supported including:\n- `series_id`, `category_id`, `release_id`, `source_id`\n- `realtime_start`, `realtime_end`, `observation_start`, `observation_end` \n- `limit`, `offset`, `order_by`, `sort_order`\n- `search_text`, `search_type`, `frequency`, `aggregation_method`\n- `force_refresh`: Bypass cache and fetch fresh data from FRED API\n- `bypass_limit_check`: Skip daily limit validation (admin only)\n- And many more...\n\n**Caching Strategy**:\n- **Cache Hit**: Returns instantly from database (no API call)\n- **Cache Miss**: Fetches from FRED API and stores for 24 hours \n- **Permanent Storage**: Historical observations stored permanently\n- **API Limit Reached**: Returns cached data even if expired\n\n**Response Format**: Returns original FRED API response with additional metadata","operationId":"fred_proxy_endpoint_api_v1_fred_proxy__endpoint__get","parameters":[{"name":"endpoint","in":"path","required":true,"schema":{"type":"string","title":"Endpoint"}},{"name":"series_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Series ID parameter","title":"Series Id"},"description":"Series ID parameter"},{"name":"category_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Category ID parameter","title":"Category Id"},"description":"Category ID parameter"},{"name":"release_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Release ID parameter","title":"Release Id"},"description":"Release ID parameter"},{"name":"source_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Source ID parameter","title":"Source Id"},"description":"Source ID parameter"},{"name":"tag_names","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Tag names parameter","title":"Tag Names"},"description":"Tag names parameter"},{"name":"realtime_start","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Realtime start date (YYYY-MM-DD)","title":"Realtime Start"},"description":"Realtime start date (YYYY-MM-DD)"},{"name":"realtime_end","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Realtime end date (YYYY-MM-DD)","title":"Realtime End"},"description":"Realtime end date (YYYY-MM-DD)"},{"name":"observation_start","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Observation start date (YYYY-MM-DD)","title":"Observation Start"},"description":"Observation start date (YYYY-MM-DD)"},{"name":"observation_end","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Observation end date (YYYY-MM-DD)","title":"Observation End"},"description":"Observation end date (YYYY-MM-DD)"},{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":100000,"minimum":1},{"type":"null"}],"description":"Limit number of results","title":"Limit"},"description":"Limit number of results"},{"name":"offset","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"Offset for pagination","title":"Offset"},"description":"Offset for pagination"},{"name":"order_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Order by parameter","title":"Order By"},"description":"Order by parameter"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort order (asc/desc)","title":"Sort Order"},"description":"Sort order (asc/desc)"},{"name":"search_text","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search text","title":"Search Text"},"description":"Search text"},{"name":"search_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search type","title":"Search Type"},"description":"Search type"},{"name":"frequency","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Data frequency","title":"Frequency"},"description":"Data frequency"},{"name":"aggregation_method","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Aggregation method","title":"Aggregation Method"},"description":"Aggregation method"},{"name":"output_type","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Output type","title":"Output Type"},"description":"Output type"},{"name":"vintage_dates","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Vintage dates","title":"Vintage Dates"},"description":"Vintage dates"},{"name":"exclude_tag_names","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Exclude tag names","title":"Exclude Tag Names"},"description":"Exclude tag names"},{"name":"tag_group_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Tag group ID","title":"Tag Group Id"},"description":"Tag group ID"},{"name":"bypass_limit_check","in":"query","required":false,"schema":{"type":"boolean","description":"Bypass daily limit check (admin only)","default":false,"title":"Bypass Limit Check"},"description":"Bypass daily limit check (admin only)"},{"name":"force_refresh","in":"query","required":false,"schema":{"type":"boolean","description":"Force refresh from API, bypass cache","default":false,"title":"Force Refresh"},"description":"Force refresh from API, bypass cache"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/fred/endpoints":{"get":{"tags":["fred"],"summary":"List supported FRED API endpoints","description":"Get list of supported FRED API endpoints\n\nReturns comprehensive list of all FRED API endpoints that can be accessed\nthrough the proxy service.\n\n**Usage**: Use this to discover available endpoints and their categories.\n\n**Example Response**:\n```json\n{\n \"series_endpoints\": [\n \"series\",\n \"series/observations\", \n \"series/search\",\n \"...\"\n ],\n \"category_endpoints\": [\"...\"],\n \"release_endpoints\": [\"...\"]\n}\n```","operationId":"get_supported_fred_endpoints_api_v1_fred_endpoints_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/news/{ticker}":{"get":{"tags":["news"],"summary":"Get news and social media for a ticker","description":"Fetch recent news articles and social media posts for a ticker from multiple sources.\n\n **News sources**: Yahoo Finance, NewsAPI\n **Social sources**: Reddit (r/stocks, r/investing, r/wallstreetbets, r/SecurityAnalysis, r/ValueInvesting)\n\n Both sources are fetched in parallel. Results are deduplicated and ranked by relevance.\n Cached for **10 minutes**.\n\n **Examples**:\n - `GET /news/AAPL` — last 7 days, up to 20 articles + 15 posts\n - `GET /news/TSLA?days_back=14&max_articles=50&include_social=false` — news-only, 2 weeks","operationId":"get_ticker_news_and_social_api_v1_news__ticker__get","parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string","title":"Ticker"}},{"name":"days_back","in":"query","required":false,"schema":{"type":"integer","maximum":30,"minimum":1,"description":"Number of days to look back for articles (1-30)","default":7,"title":"Days Back"},"description":"Number of days to look back for articles (1-30)"},{"name":"max_articles","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Maximum number of news articles to return (1-100)","default":20,"title":"Max Articles"},"description":"Maximum number of news articles to return (1-100)"},{"name":"max_social_posts","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":0,"description":"Maximum number of social media posts to return (0-50)","default":15,"title":"Max Social Posts"},"description":"Maximum number of social media posts to return (0-50)"},{"name":"include_social","in":"query","required":false,"schema":{"type":"boolean","description":"Whether to include social media data","default":true,"title":"Include Social"},"description":"Whether to include social media data"},{"name":"force_refresh","in":"query","required":false,"schema":{"type":"boolean","description":"Bypass cache and fetch fresh data","default":false,"title":"Force Refresh"},"description":"Bypass cache and fetch fresh data"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsSocialResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/news/{ticker}/news-only":{"get":{"tags":["news"],"summary":"Get news articles for a ticker (no social media)","description":"Faster endpoint that returns only news articles, skipping social media API calls.\n\n **Sources**: Yahoo Finance, NewsAPI\n Cached for **10 minutes**.\n\n **Example**: `GET /news/NVDA/news-only?days_back=3&max_articles=30`","operationId":"get_ticker_news_only_api_v1_news__ticker__news_only_get","parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string","title":"Ticker"}},{"name":"days_back","in":"query","required":false,"schema":{"type":"integer","maximum":30,"minimum":1,"description":"Number of days to look back for articles (1-30)","default":7,"title":"Days Back"},"description":"Number of days to look back for articles (1-30)"},{"name":"max_articles","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Maximum number of news articles to return (1-100)","default":30,"title":"Max Articles"},"description":"Maximum number of news articles to return (1-100)"},{"name":"force_refresh","in":"query","required":false,"schema":{"type":"boolean","description":"Bypass cache and fetch fresh data","default":false,"title":"Force Refresh"},"description":"Bypass cache and fetch fresh data"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsOnlyResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/news/{ticker}/social-only":{"get":{"tags":["news"],"summary":"Get social media posts for a ticker","description":"Returns only Reddit posts for a ticker, skipping news API calls.\n\n **Subreddits**: r/stocks, r/investing, r/wallstreetbets, r/SecurityAnalysis,\n r/StockMarket, r/ValueInvesting, r/financialindependence\n Cached for **10 minutes**.\n\n **Example**: `GET /news/GME/social-only?days_back=3&max_social_posts=30`","operationId":"get_ticker_social_only_api_v1_news__ticker__social_only_get","parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string","title":"Ticker"}},{"name":"days_back","in":"query","required":false,"schema":{"type":"integer","maximum":30,"minimum":1,"description":"Number of days to look back for posts (1-30)","default":7,"title":"Days Back"},"description":"Number of days to look back for posts (1-30)"},{"name":"max_social_posts","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"description":"Maximum number of social media posts to return (1-50)","default":20,"title":"Max Social Posts"},"description":"Maximum number of social media posts to return (1-50)"},{"name":"force_refresh","in":"query","required":false,"schema":{"type":"boolean","description":"Bypass cache and fetch fresh data","default":false,"title":"Force Refresh"},"description":"Bypass cache and fetch fresh data"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SocialOnlyResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/news/v2/headlines":{"get":{"tags":["news-v2"],"summary":"Raw multi-source news headlines","description":"Multi-source raw headline rows. Filter by symbols, time window, and source. Sources: `alpaca_benzinga`, `stocktwits`, `finnhub`, `gdelt`.","operationId":"get_headlines_api_v1_news_v2_headlines_get","parameters":[{"name":"symbols","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"CSV ticker list, max 50 (e.g. AAPL,MSFT)","title":"Symbols"},"description":"CSV ticker list, max 50 (e.g. AAPL,MSFT)"},{"name":"start","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Start time (UTC ISO)","title":"Start"},"description":"Start time (UTC ISO)"},{"name":"end","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"End time (UTC ISO)","title":"End"},"description":"End time (UTC ISO)"},{"name":"sources","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"CSV source filter, subset of ['alpaca_benzinga', 'finnhub', 'gdelt', 'stocktwits']","title":"Sources"},"description":"CSV source filter, subset of ['alpaca_benzinga', 'finnhub', 'gdelt', 'stocktwits']"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"published_at_lt cursor (ISO datetime)","title":"Cursor"},"description":"published_at_lt cursor (ISO datetime)"},{"name":"force_refresh","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Force Refresh"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__api__v1__endpoints__news_v2__HeadlinesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/news/v2/session_aggregate":{"get":{"tags":["news-v2"],"summary":"Session-aggregated news for one ticker","operationId":"get_session_aggregate_api_v1_news_v2_session_aggregate_get","parameters":[{"name":"symbol","in":"query","required":true,"schema":{"type":"string","description":"Ticker symbol","title":"Symbol"},"description":"Ticker symbol"},{"name":"session_date","in":"query","required":true,"schema":{"type":"string","format":"date","description":"ET session date (YYYY-MM-DD)","title":"Session Date"},"description":"ET session date (YYYY-MM-DD)"},{"name":"window","in":"query","required":false,"schema":{"type":"string","description":"One of ['full_session', 'intraday', 'post', 'premarket']","default":"premarket","title":"Window"},"description":"One of ['full_session', 'intraday', 'post', 'premarket']"},{"name":"sources","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"CSV source filter, subset of ['alpaca_benzinga', 'finnhub', 'gdelt', 'stocktwits']","title":"Sources"},"description":"CSV source filter, subset of ['alpaca_benzinga', 'finnhub', 'gdelt', 'stocktwits']"},{"name":"force_refresh","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Force Refresh"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionAggregateItem"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/news/v2/session_aggregate/batch":{"post":{"tags":["news-v2"],"summary":"Session-aggregated news for many tickers in one call","description":"Batch variant. Caching is intentionally NOT applied at this layer — fithia2 maintains a client-side disk cache as the primary defense; Oracle absorbs only burst load. Use the GET single endpoint for Redis-cached single-ticker reads.","operationId":"post_session_aggregate_batch_api_v1_news_v2_session_aggregate_batch_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionAggregateBatchRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionAggregateBatchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/news/v2/coverage":{"get":{"tags":["news-v2"],"summary":"Per-source ingest coverage probe","operationId":"get_coverage_api_v1_news_v2_coverage_get","parameters":[{"name":"source","in":"query","required":true,"schema":{"type":"string","description":"One of ['alpaca_benzinga', 'finnhub', 'gdelt', 'stocktwits']","title":"Source"},"description":"One of ['alpaca_benzinga', 'finnhub', 'gdelt', 'stocktwits']"},{"name":"symbol","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional ticker filter","title":"Symbol"},"description":"Optional ticker filter"},{"name":"force_refresh","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Force Refresh"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoverageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/etf/holdings/{ticker}":{"get":{"tags":["etf"],"summary":"Get ETF portfolio holdings","description":"Fetch the constituent holdings of an ETF (e.g., SPY, QQQ, IWM). Data is sourced from SEC 13-F filings and cached for 1 hour.\n\nUse `top_n` to limit to the N largest positions, or `top_percentage` to return the minimal set of holdings that covers X% of the portfolio (e.g., `top_percentage=0.8` for the holdings making up 80% of the ETF).\n\n**Examples**:\n- `GET /etf/holdings/SPY` — all holdings\n- `GET /etf/holdings/QQQ?top_n=10` — top 10 positions\n- `GET /etf/holdings/IWM?top_percentage=0.5` — holdings covering 50% of portfolio","operationId":"get_etf_holdings_api_v1_etf_holdings__ticker__get","parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string","title":"Ticker"}},{"name":"as_of_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"YYYY-MM-DD","title":"As Of Date"},"description":"YYYY-MM-DD"},{"name":"top_n","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Return top N holdings by weight/value (mutually exclusive with top_percentage)","title":"Top N"},"description":"Return top N holdings by weight/value (mutually exclusive with top_percentage)"},{"name":"top_percentage","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Return minimal set covering X percent (e.g., 0.5 or 50 for 50%). Mutually exclusive with top_n","title":"Top Percentage"},"description":"Return minimal set covering X percent (e.g., 0.5 or 50 for 50%). Mutually exclusive with top_n"},{"name":"force_refresh","in":"query","required":false,"schema":{"type":"boolean","description":"Bypass cache","default":false,"title":"Force Refresh"},"description":"Bypass cache"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ETFHoldingsOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/etf/admin/refresh-maps":{"post":{"tags":["etf","etf"],"summary":"Refresh ETF CIK and CUSIP mapping tables","description":"Re-fetches and upserts the ETF→CIK and CUSIP→ticker mapping tables from SEC data. Run this when new ETFs need to be supported. Returns the number of rows updated.","operationId":"refresh_etf_maps_api_v1_etf_admin_refresh_maps_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshMapsOut"}}}}}}},"/api/v1/filings/search/{ticker}":{"get":{"tags":["filings"],"summary":"Search SEC filings for a ticker","description":"Search SEC filings for the given ticker. Supported form types: **8-K, 6-K, 20-F, 40-F**.\n\nAuto-indexes filings from EDGAR on first request (or when `force_refresh=true`). Results are cached for 1 hour.\n\n**현재 DB 보유**: 1994-01-05 ~ 현재, 1598 티커. 처음 조회하는 티커는 SEC EDGAR에서 자동 인덱싱 (수 초 소요).\n\n**Example**: `GET /filings/search/AAPL?form_type=8-K&limit=10`","operationId":"search_filings_api_v1_filings_search__ticker__get","parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string","title":"Ticker"}},{"name":"form_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated form types (e.g. '8-K,6-K'). Default: all supported.","title":"Form Type"},"description":"Comma-separated form types (e.g. '8-K,6-K'). Default: all supported."},{"name":"start_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Start date YYYY-MM-DD","title":"Start Date"},"description":"Start date YYYY-MM-DD"},{"name":"end_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"End date YYYY-MM-DD","title":"End Date"},"description":"End date YYYY-MM-DD"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"force_refresh","in":"query","required":false,"schema":{"type":"boolean","description":"Force re-indexing from SEC","default":false,"title":"Force Refresh"},"description":"Force re-indexing from SEC"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FilingSearchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/filings/documents/{accession_number}":{"get":{"tags":["filings"],"summary":"List documents in a SEC filing","description":"List all documents attached to a SEC filing by accession number.\n\nReturns filename, document type, size, and SEC URL for each document. Cached for 24 hours.\n\n**Example**: `GET /filings/documents/0001193125-24-123456`","operationId":"get_filing_documents_api_v1_filings_documents__accession_number__get","parameters":[{"name":"accession_number","in":"path","required":true,"schema":{"type":"string","title":"Accession Number"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FilingDocumentListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/filings/exhibit/{accession_number}":{"get":{"tags":["filings"],"summary":"Extract exhibit content from a filing","description":"Extract the text content of a specific exhibit (e.g., press release **EX-99.1**) from a SEC filing.\n\nReturns the full text content along with content type, filename, and SEC URL. 404 responses are negative-cached for 1 hour. Cached for 24 hours.\n\n**Example**: `GET /filings/exhibit/0001193125-24-123456?exhibit_type=EX-99.1`","operationId":"get_exhibit_content_api_v1_filings_exhibit__accession_number__get","parameters":[{"name":"accession_number","in":"path","required":true,"schema":{"type":"string","title":"Accession Number"}},{"name":"exhibit_type","in":"query","required":false,"schema":{"type":"string","description":"Exhibit type (e.g. EX-99.1)","default":"EX-99.1","title":"Exhibit Type"},"description":"Exhibit type (e.g. EX-99.1)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExhibitContentResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/filings/search/bulk":{"post":{"tags":["filings"],"summary":"Bulk search SEC filings for multiple tickers","description":"Search SEC filings for up to many tickers in a single request. Auto-indexes from EDGAR for any ticker not yet in the database.\n\n**Timeout**: 600 seconds. Each ticker is processed concurrently.\n\n**Example body**:\n```json\n{\"tickers\": [\"AAPL\", \"MSFT\", \"NVDA\"], \"form_type\": \"8-K\", \"start_date\": \"2024-01-01\", \"limit_per_ticker\": 5}\n```","operationId":"search_filings_bulk_api_v1_filings_search_bulk_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkFilingSearchRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkFilingSearchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/filings/exhibit/bulk":{"post":{"tags":["filings"],"summary":"Bulk fetch exhibit content","description":"Fetch exhibit content for multiple accession numbers in one request. Up to 4 concurrent fetches; max 300 second timeout.\n\n**Example body**:\n```json\n{\"items\": [{\"accession_number\": \"0001193125-24-123456\", \"exhibit_type\": \"EX-99.1\"}]}\n```","operationId":"get_exhibit_bulk_api_v1_filings_exhibit_bulk_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkExhibitRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkExhibitResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/filings/events/{ticker}":{"get":{"tags":["filings"],"summary":"Get parsed 8-K events for a ticker","description":"Returns structured events parsed from 8-K filings. Each event corresponds to one 8-K Item (e.g., Item 8.01 → other_material_event, Item 2.02 → earnings_result).\\n\\nIf there are unprocessed (pending) filings, they are lazily parsed on first request.\\n\\n**Example**: `GET /filings/events/AVGO?start_date=2026-04-01&event_type=other_material_event`","operationId":"get_filing_events_api_v1_filings_events__ticker__get","parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string","title":"Ticker"}},{"name":"start_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Start date YYYY-MM-DD","title":"Start Date"},"description":"Start date YYYY-MM-DD"},{"name":"end_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"End date YYYY-MM-DD","title":"End Date"},"description":"End date YYYY-MM-DD"},{"name":"event_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by event type (e.g. other_material_event)","title":"Event Type"},"description":"Filter by event type (e.g. other_material_event)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FilingEventsSearchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/filings/events/parse/bulk":{"post":{"tags":["filings"],"summary":"Bulk parse pending 8-K filings","description":"Parse 8-K filings and create structured events.\\n\\n- **Default**: processes only `pending` filings.\\n- **`force_reparse=true`**: resets `succeeded`/`failed` filings to `pending` and re-parses them.\\n\\n**Example — reparse specific ticker**: `{\"tickers\": [\"AVGO\"], \"limit\": 50, \"force_reparse\": true}`\\n**Example — backfill all pending**: `{\"limit\": 200}`","operationId":"parse_8k_bulk_api_v1_filings_events_parse_bulk_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkParseRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkParseResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/filings/events/parse/{accession_number}":{"post":{"tags":["filings"],"summary":"Force-reparse a single 8-K filing","description":"Reparse a specific filing by accession number, regardless of current `parsed_status`.\\n\\n**Example**: `POST /filings/events/parse/0001193125-26-144028`","operationId":"parse_8k_single_api_v1_filings_events_parse__accession_number__post","parameters":[{"name":"accession_number","in":"path","required":true,"schema":{"type":"string","title":"Accession Number"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkParseResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/metadata/catalog":{"get":{"tags":["metadata"],"summary":"Get data catalog","description":"Get a comprehensive catalog of all available data fields.\n \n This endpoint returns:\n - All available financial metrics and their descriptions\n - Data types and units for each field\n - Calculation methods where applicable\n - Data sources for each field\n \n The catalog is organized by categories:\n - Company Information\n - Income Statement\n - Balance Sheet\n - Cash Flow Statement\n - Valuation Ratios\n - Profitability Metrics\n - Growth Metrics\n - Liquidity & Solvency\n - Efficiency Metrics\n - Market Data (Future)","operationId":"get_catalog_api_v1_metadata_catalog_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataCatalogResponse"}}}}}}},"/api/v1/admin/migrate":{"post":{"tags":["admin"],"summary":"Migrate data from another instance","description":"Migrate financial data from another SEC Investment API instance.\n \n This endpoint allows you to:\n - Transfer all data from one instance to another\n - Migrate specific tickers only\n - Migrate data within specific date ranges\n \n Requires valid migration API key in X-API-Key header.","operationId":"migrate_data_api_v1_admin_migrate_post","parameters":[{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MigrationRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MigrationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/migration/export/{ticker}":{"get":{"tags":["admin"],"summary":"Export data for migration","description":"Export financial data for a specific ticker (used by migration process)","operationId":"export_data_api_v1_admin_migration_export__ticker__get","parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string","title":"Ticker"}},{"name":"start_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Start Date"}},{"name":"end_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"End Date"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/database/stats":{"get":{"tags":["database"],"summary":"Database record counts and date ranges","description":"Returns aggregate statistics across all core tables:\n\n - `companies` — total companies, how many have financial/price data\n - `financial_data` — total records, real vs estimated, date range, breakdown by source\n - `price_data` — total records, date range, list of tickers\n - `calculated_metrics` — total records and date range","operationId":"get_database_stats_api_v1_database_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Database Stats Api V1 Database Stats Get"}}}}}}},"/api/v1/database/health":{"get":{"tags":["database"],"summary":"Database connection health check","description":"데이터베이스 연결 상태를 확인합니다.","operationId":"get_database_health_api_v1_database_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Database Health Api V1 Database Health Get"}}}}}}},"/api/v1/database/tables":{"get":{"tags":["database"],"summary":"Table row counts for all core tables","description":"데이터베이스 테이블 정보를 반환합니다.","operationId":"get_table_info_api_v1_database_tables_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Table Info Api V1 Database Tables Get"}}}}}}},"/api/v1/database/cleanup/duplicates":{"post":{"tags":["database"],"summary":"Remove duplicate financial and metrics records","description":"Remove duplicate financial and metrics records, keeping the most recent real data.","operationId":"cleanup_duplicate_records_api_v1_database_cleanup_duplicates_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Cleanup Duplicate Records Api V1 Database Cleanup Duplicates Post"}}}}}}},"/api/v1/database/tickers":{"get":{"tags":["database"],"summary":"List tickers available in the database","description":"사용 가능한 종목 목록을 반환합니다.","operationId":"get_available_tickers_api_v1_database_tickers_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"items":{"type":"string"},"type":"array"},"type":"object","title":"Response Get Available Tickers Api V1 Database Tickers Get"}}}}}}},"/api/v1/database/etf/snapshots":{"get":{"tags":["database"],"summary":"List persisted ETF holdings snapshots","description":"Browse ETF holdings snapshots stored in the database. Each snapshot represents\n the portfolio as reported in a SEC 13-F filing.\n\n Filter by `ticker`, `start_date`, `end_date`. Results are ordered by snapshot date (newest first).\n\n **Example**: `GET /database/etf/snapshots?ticker=SPY&limit=10`","operationId":"list_etf_snapshots_api_v1_database_etf_snapshots_get","parameters":[{"name":"ticker","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ticker"}},{"name":"start_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start Date"}},{"name":"end_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End Date"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/database/etf/snapshot/{snapshot_id}":{"get":{"tags":["database"],"summary":"Get ETF snapshot with full holdings list","operationId":"get_etf_snapshot_api_v1_database_etf_snapshot__snapshot_id__get","parameters":[{"name":"snapshot_id","in":"path","required":true,"schema":{"type":"string","title":"Snapshot Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/database/financial/records":{"get":{"tags":["database"],"summary":"Browse raw financial data records","description":"List raw financial data rows from the `financial_data` table.\n\n Supports filtering by `ticker`, `period_type` (`quarterly`/`annual`),\n `start_date`, and `end_date`. Results ordered by `period_date` descending.\n\n **Example**: `GET /database/financial/records?ticker=AAPL&period_type=quarterly&limit=8`","operationId":"list_financial_records_api_v1_database_financial_records_get","parameters":[{"name":"ticker","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ticker"}},{"name":"period_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Period Type"}},{"name":"start_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start Date"}},{"name":"end_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End Date"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":100,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/errors/logs":{"get":{"tags":["error-logs"],"summary":"Get error logs","description":"Retrieve error logs with filtering and pagination options.\n \n **Filters:**\n - Date range (start_date, end_date)\n - Error type\n - Status code range\n - Endpoint pattern\n - Resolution status\n \n **Sorting:**\n - By date (newest first by default)\n - By status code\n - By response time\n \n **Pagination:**\n - Configurable page size (default: 50, max: 200)\n - Page-based navigation","operationId":"get_error_logs_api_v1_admin_errors_logs_get","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number","default":1,"title":"Page"},"description":"Page number"},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"Items per page","default":50,"title":"Page Size"},"description":"Items per page"},{"name":"start_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Filter by start date","title":"Start Date"},"description":"Filter by start date"},{"name":"end_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Filter by end date","title":"End Date"},"description":"Filter by end date"},{"name":"error_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by error type","title":"Error Type"},"description":"Filter by error type"},{"name":"status_code","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by status code","title":"Status Code"},"description":"Filter by status code"},{"name":"endpoint","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by endpoint (supports wildcards)","title":"Endpoint"},"description":"Filter by endpoint (supports wildcards)"},{"name":"is_resolved","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter by resolution status","title":"Is Resolved"},"description":"Filter by resolution status"},{"name":"sort_by","in":"query","required":false,"schema":{"type":"string","description":"Sort field: created_at, status_code, response_time_ms","default":"created_at","title":"Sort By"},"description":"Sort field: created_at, status_code, response_time_ms"},{"name":"sort_order","in":"query","required":false,"schema":{"type":"string","description":"Sort order: asc or desc","default":"desc","title":"Sort Order"},"description":"Sort order: asc or desc"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorLogListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["error-logs"],"summary":"Delete all error logs","description":"Delete all error logs (use with caution)","operationId":"delete_all_error_logs_api_v1_admin_errors_logs_delete","parameters":[{"name":"confirm","in":"query","required":false,"schema":{"type":"boolean","description":"Must be true to confirm deletion","default":false,"title":"Confirm"},"description":"Must be true to confirm deletion"},{"name":"only_resolved","in":"query","required":false,"schema":{"type":"boolean","description":"Only delete resolved errors","default":false,"title":"Only Resolved"},"description":"Only delete resolved errors"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/errors/logs/{log_id}":{"get":{"tags":["error-logs"],"summary":"Get error log by ID","description":"Retrieve detailed information about a specific error log","operationId":"get_error_log_api_v1_admin_errors_logs__log_id__get","parameters":[{"name":"log_id","in":"path","required":true,"schema":{"type":"integer","title":"Log Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorLogResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["error-logs"],"summary":"Update error log","description":"Update error log resolution status and notes","operationId":"update_error_log_api_v1_admin_errors_logs__log_id__patch","parameters":[{"name":"log_id","in":"path","required":true,"schema":{"type":"integer","title":"Log Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorLogUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorLogResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/errors/by-request/{request_id}":{"get":{"tags":["error-logs"],"summary":"Get error log by request ID","description":"Retrieve error log information for a specific request ID","operationId":"get_error_by_request_id_api_v1_admin_errors_by_request__request_id__get","parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","title":"Request Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorLogResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/errors/stats":{"get":{"tags":["error-logs"],"summary":"Get error statistics","description":"Get aggregated statistics about errors.\n \n **Statistics include:**\n - Total error count\n - Errors by type\n - Errors by status code\n - Errors by endpoint\n - Time-based trends\n - Resolution rate","operationId":"get_error_stats_api_v1_admin_errors_stats_get","parameters":[{"name":"start_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Start date for statistics","title":"Start Date"},"description":"Start date for statistics"},{"name":"end_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"End date for statistics","title":"End Date"},"description":"End date for statistics"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorLogStats"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/errors/logs/old":{"delete":{"tags":["error-logs"],"summary":"Delete old error logs","description":"Delete error logs older than specified days","operationId":"delete_old_logs_api_v1_admin_errors_logs_old_delete","parameters":[{"name":"days_old","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"description":"Delete logs older than this many days","default":30,"title":"Days Old"},"description":"Delete logs older than this many days"},{"name":"only_resolved","in":"query","required":false,"schema":{"type":"boolean","description":"Only delete resolved errors","default":true,"title":"Only Resolved"},"description":"Only delete resolved errors"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/requests/logs":{"get":{"tags":["request-logs"],"summary":"Get request logs","description":"Retrieve request logs with filtering and pagination options.\n \n **Filters:**\n - Date range (start_date, end_date)\n - HTTP method\n - Status code range\n - Endpoint pattern\n - Response time range\n \n **Sorting:**\n - By date (newest first by default)\n - By status code\n - By response time\n \n **Pagination:**\n - Configurable page size (default: 50, max: 200)\n - Page-based navigation","operationId":"get_request_logs_api_v1_admin_requests_logs_get","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number","default":1,"title":"Page"},"description":"Page number"},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"Items per page","default":50,"title":"Page Size"},"description":"Items per page"},{"name":"start_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Filter by start date","title":"Start Date"},"description":"Filter by start date"},{"name":"end_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Filter by end date","title":"End Date"},"description":"Filter by end date"},{"name":"method","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by HTTP method","title":"Method"},"description":"Filter by HTTP method"},{"name":"status_code","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by exact status code","title":"Status Code"},"description":"Filter by exact status code"},{"name":"min_status_code","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by minimum status code (e.g. 500 for all 5xx)","title":"Min Status Code"},"description":"Filter by minimum status code (e.g. 500 for all 5xx)"},{"name":"max_status_code","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by maximum status code (e.g. 599 for all 5xx)","title":"Max Status Code"},"description":"Filter by maximum status code (e.g. 599 for all 5xx)"},{"name":"endpoint","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by endpoint (supports wildcards)","title":"Endpoint"},"description":"Filter by endpoint (supports wildcards)"},{"name":"min_response_time","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Minimum response time in ms","title":"Min Response Time"},"description":"Minimum response time in ms"},{"name":"max_response_time","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Maximum response time in ms","title":"Max Response Time"},"description":"Maximum response time in ms"},{"name":"sort_by","in":"query","required":false,"schema":{"type":"string","description":"Sort field: created_at, status_code, response_time_ms","default":"created_at","title":"Sort By"},"description":"Sort field: created_at, status_code, response_time_ms"},{"name":"sort_order","in":"query","required":false,"schema":{"type":"string","description":"Sort order: asc or desc","default":"desc","title":"Sort Order"},"description":"Sort order: asc or desc"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestLogListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["request-logs"],"summary":"Delete all request logs","description":"Delete all request logs (use with caution)","operationId":"delete_all_request_logs_api_v1_admin_requests_logs_delete","parameters":[{"name":"confirm","in":"query","required":false,"schema":{"type":"boolean","description":"Must be true to confirm deletion","default":false,"title":"Confirm"},"description":"Must be true to confirm deletion"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/requests/logs/{log_id}":{"get":{"tags":["request-logs"],"summary":"Get request log by ID","description":"Retrieve detailed information about a specific request log","operationId":"get_request_log_api_v1_admin_requests_logs__log_id__get","parameters":[{"name":"log_id","in":"path","required":true,"schema":{"type":"integer","title":"Log Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestLogResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/requests/stats":{"get":{"tags":["request-logs"],"summary":"Get request statistics","description":"Get aggregated statistics about API requests.\n \n **Statistics include:**\n - Total request count\n - Success/error rates\n - Requests by method\n - Requests by status code\n - Requests by endpoint\n - Time-based trends\n - Average response time","operationId":"get_request_stats_api_v1_admin_requests_stats_get","parameters":[{"name":"start_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Start date for statistics","title":"Start Date"},"description":"Start date for statistics"},{"name":"end_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"End date for statistics","title":"End Date"},"description":"End date for statistics"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestLogStats"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/requests/logs/old":{"delete":{"tags":["request-logs"],"summary":"Delete old request logs","description":"Delete request logs older than specified days","operationId":"delete_old_request_logs_api_v1_admin_requests_logs_old_delete","parameters":[{"name":"days_old","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"description":"Delete logs older than this many days","default":30,"title":"Days Old"},"description":"Delete logs older than this many days"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/alpaca/status":{"get":{"tags":["alpaca"],"summary":"Alpaca connection status","description":"Check Alpaca API key validity and connection health.","operationId":"alpaca_status_api_v1_alpaca_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/alpaca/intraday":{"get":{"tags":["alpaca"],"summary":"Get historical intraday bars for multiple tickers (SIP feed, DB-backed)","description":"멀티 종목 과거 분봉 데이터를 Alpaca **SIP 피드**로 가져옵니다. DB에 저장되며 재요청 시 Alpaca 미호출.\n\n**⚠️ 장 중 당일 데이터 불가** — 장 마감(오후 4시 ET) 후에는 당일 날짜도 조회 가능\n\n| 항목 | 내용 |\n|------|------|\n| 피드 | **SIP** (전체 미국 거래소 통합) |\n| 거래량 | **100%** 정확 |\n| 조회 범위 | **2016년~오늘(장 마감 후)** |\n| DB 저장 | 있음 (재요청 시 Alpaca 미사용) |\n\n**권장 용도**: 백테스트, 과거 분봉 분석\n\n- `tickers`: comma-separated, e.g. `AAPL,MSFT,BF-B`\n- `interval`: `1m`, `5m`, `15m`, `30m`, `1h`\n- 내부 100개 단위 자동 배치 분할 (500종목 → Alpaca 5회 호출)\n- Requires `ALPACA_API_KEY` / `ALPACA_SECRET_KEY`","operationId":"get_alpaca_intraday_multi_api_v1_alpaca_intraday_get","parameters":[{"name":"tickers","in":"query","required":true,"schema":{"type":"string","description":"Comma-separated tickers, e.g. AAPL,MSFT,BF-B","title":"Tickers"},"description":"Comma-separated tickers, e.g. AAPL,MSFT,BF-B"},{"name":"interval","in":"query","required":false,"schema":{"type":"string","description":"Interval: 1m, 5m, 15m, 30m, 1h","default":"5m","title":"Interval"},"description":"Interval: 1m, 5m, 15m, 30m, 1h"},{"name":"start_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Start date (YYYY-MM-DD). Default: yesterday","title":"Start Date"},"description":"Start date (YYYY-MM-DD). Default: yesterday"},{"name":"end_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"End date (YYYY-MM-DD). Must be before today. Default: yesterday","title":"End Date"},"description":"End date (YYYY-MM-DD). Must be before today. Default: yesterday"},{"name":"force_refresh","in":"query","required":false,"schema":{"type":"boolean","description":"Re-fetch from Alpaca even if DB has data","default":false,"title":"Force Refresh"},"description":"Re-fetch from Alpaca even if DB has data"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlpacaMultiBarsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/alpaca/intraday/today":{"get":{"tags":["alpaca"],"summary":"Get today's real-time intraday bars for multiple tickers (IEX feed, DB-backed)","description":"당일(오늘) 실시간 분봉 데이터를 Alpaca **IEX 피드**로 가져옵니다. 장 중 재요청 시 항상 Alpaca에서 최신 데이터를 가져옵니다.\n\n**⚠️ 오늘 데이터만 조회 가능** — 과거 데이터는 `/intraday` 사용\n\n| 항목 | 내용 |\n|------|------|\n| 피드 | **IEX** (IEX 거래소 단일) |\n| 지연 | **실시간** (지연 없음) |\n| 거래량 | 실제의 약 **2~5%** (IEX 거래소 거래만 집계) |\n| High/Low range | SIP 대비 좁게 표시될 수 있음 |\n| DB 저장 | 있음 (장 중 항상 재조회) |\n\n**권장 용도**: 당일 ORB 전략, 실시간 장 중 모니터링\n\n- `tickers`: comma-separated, e.g. `AAPL,MSFT,BF-B`\n- `interval`: `1m`, `5m`, `15m`, `30m`, `1h`\n- 내부 100개 단위 자동 배치 분할\n- Requires `ALPACA_API_KEY` / `ALPACA_SECRET_KEY`","operationId":"get_alpaca_intraday_today_api_v1_alpaca_intraday_today_get","parameters":[{"name":"tickers","in":"query","required":true,"schema":{"type":"string","description":"Comma-separated tickers, e.g. AAPL,MSFT,BF-B","title":"Tickers"},"description":"Comma-separated tickers, e.g. AAPL,MSFT,BF-B"},{"name":"interval","in":"query","required":false,"schema":{"type":"string","description":"Interval: 1m, 5m, 15m, 30m, 1h","default":"5m","title":"Interval"},"description":"Interval: 1m, 5m, 15m, 30m, 1h"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlpacaMultiBarsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/alpaca/snapshot":{"get":{"tags":["alpaca"],"summary":"Real-time snapshots for multiple tickers (IEX feed)","description":"멀티 종목 실시간 스냅샷. 최신 체결가, bid/ask, 당일 OHLCV, 전일 대비 변동률 포함.\n\n단일 종목도 `?tickers=AAPL`로 조회 가능.\n\n| 항목 | 내용 |\n|------|------|\n| 피드 | **IEX** — 무료 플랜에서 snapshot은 SIP 불가 |\n| 지연 | **실시간** (지연 없음) |\n| 거래량 | IEX 기준 (실제의 2~5%) |\n| 캐시 | **없음** — 매 요청마다 Alpaca 직접 호출 |\n\n- Requires `ALPACA_API_KEY` / `ALPACA_SECRET_KEY`","operationId":"get_snapshots_api_v1_alpaca_snapshot_get","parameters":[{"name":"tickers","in":"query","required":true,"schema":{"type":"string","description":"Comma-separated ticker symbols, e.g. AAPL,MSFT,NVDA","title":"Tickers"},"description":"Comma-separated ticker symbols, e.g. AAPL,MSFT,NVDA"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlpacaMultiSnapshotResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/finra/short-volume/{symbol}":{"get":{"tags":["finra"],"summary":"Get short volume data for a symbol","description":"Query FINRA RegSHO short sale volume. Auto-ingests if data is missing.\n\n**DB 보유**: 2021년 ~ 현재 (5년치 백필 완료). 추가 백필: `POST /finra/admin/ingest?start_date=YYYY-MM-DD&end_date=YYYY-MM-DD`\n\n**데이터 소스**: FINRA RegSHO CDN (공개, API 키 불필요). 주말/공휴일 데이터 없음.","operationId":"get_short_volume_api_v1_finra_short_volume__symbol__get","parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string","title":"Symbol"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":3650,"minimum":1,"description":"Number of days to look back (max ~10 years)","default":30,"title":"Days"},"description":"Number of days to look back (max ~10 years)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":10000,"minimum":1,"description":"Max entries to return","default":100,"title":"Limit"},"description":"Max entries to return"},{"name":"force_refresh","in":"query","required":false,"schema":{"type":"boolean","description":"Bypass cache","default":false,"title":"Force Refresh"},"description":"Bypass cache"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShortVolumeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/finra/short-ratio/{symbol}":{"get":{"tags":["finra"],"summary":"Get short ratio history for a symbol","description":"Return daily short_ratio (aggregated across markets) for the last N days.\n\n**DB 보유**: 2021년 ~ 현재 (5년치). days 최대 3650 (10년).\n\n추가 백필: `POST /finra/admin/ingest?start_date=YYYY-MM-DD&end_date=YYYY-MM-DD`","operationId":"get_short_ratio_api_v1_finra_short_ratio__symbol__get","parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string","title":"Symbol"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":3650,"minimum":1,"description":"Number of days (max ~10 years)","default":60,"title":"Days"},"description":"Number of days (max ~10 years)"},{"name":"force_refresh","in":"query","required":false,"schema":{"type":"boolean","description":"Bypass cache","default":false,"title":"Force Refresh"},"description":"Bypass cache"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShortRatioHistoryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/finra/admin/ingest":{"post":{"tags":["finra"],"summary":"Manually ingest FINRA short volume data","description":"Download and ingest FINRA short volume file(s) for a specific date or date range.\n\n**백필 예시**:\n- 단일 날짜: `?date=2025-01-15`\n- 날짜 범위: `?start_date=2025-01-01&end_date=2025-12-31`\n- 이미 있는 데이터 재인제스트: `?start_date=...&end_date=...&force=true`\n\n주말/공휴일은 자동으로 건너뜀. 1년치 기준 약 20-40분 소요.","operationId":"ingest_short_volume_api_v1_finra_admin_ingest_post","parameters":[{"name":"date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Single date (YYYY-MM-DD)","title":"Date"},"description":"Single date (YYYY-MM-DD)"},{"name":"start_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Range start (YYYY-MM-DD)","title":"Start Date"},"description":"Range start (YYYY-MM-DD)"},{"name":"end_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Range end (YYYY-MM-DD)","title":"End Date"},"description":"Range end (YYYY-MM-DD)"},{"name":"force","in":"query","required":false,"schema":{"type":"boolean","description":"Re-ingest even if data exists","default":false,"title":"Force"},"description":"Re-ingest even if data exists"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IngestResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/overlay/admin/job-log":{"get":{"tags":["overlay","overlay-admin"],"summary":"Overlay job log","operationId":"get_job_log_api_v1_overlay_admin_job_log_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobLogResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/overlay/{symbol}/headlines":{"get":{"tags":["overlay"],"summary":"Recent headlines for a symbol","operationId":"get_headlines_api_v1_overlay__symbol__headlines_get","parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string","title":"Symbol"}},{"name":"hours","in":"query","required":false,"schema":{"type":"integer","maximum":168,"minimum":1,"default":24,"title":"Hours"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__api__v1__endpoints__overlay__HeadlinesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/screener/stocks":{"get":{"tags":["screener"],"summary":"Screen stocks by financial criteria","description":"Screen stocks based on financial criteria using yfinance.\n\nFilters stocks from US exchanges (NYSE, NASDAQ, AMEX, NYSE_ARCA) by market cap,\nvolume, price, P/E ratio, sector, and more. Results are paginated and cached for\n5 minutes.\n\n**Exchange mapping**:\n- `NYSE` → NYQ\n- `NASDAQ` → NMS, NGM, NCM\n- `AMEX` → ASE\n- `NYSE_ARCA` → PCX\n\n**Important limitations**:\n- `page_size` maximum is 250 (Yahoo Finance API limit)\n- `sector` filtering works but sector is NOT returned per-stock in the response\n- Results reflect real-time Yahoo Finance data\n\n**Example**:\n```\nGET /screener/stocks?market_cap_min=500000000&market_cap_max=10000000000\n &exchange=NYSE,NASDAQ&min_avg_volume=500000&exclude_types=ETF,FUND\n &sort_by=market_cap&page=1&page_size=100\n```","operationId":"screen_stocks_api_v1_screener_stocks_get","parameters":[{"name":"market_cap_min","in":"query","required":false,"schema":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}],"description":"Minimum market cap in USD (e.g. 500000000 for $500M)","title":"Market Cap Min"},"description":"Minimum market cap in USD (e.g. 500000000 for $500M)"},{"name":"market_cap_max","in":"query","required":false,"schema":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}],"description":"Maximum market cap in USD (e.g. 10000000000 for $10B)","title":"Market Cap Max"},"description":"Maximum market cap in USD (e.g. 10000000000 for $10B)"},{"name":"exchange","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated exchange names: NYSE, NASDAQ, AMEX, NYSE_ARCA. Omit for all US exchanges.","title":"Exchange"},"description":"Comma-separated exchange names: NYSE, NASDAQ, AMEX, NYSE_ARCA. Omit for all US exchanges."},{"name":"min_avg_volume","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"Minimum 3-month average daily volume (e.g. 500000)","title":"Min Avg Volume"},"description":"Minimum 3-month average daily volume (e.g. 500000)"},{"name":"exclude_types","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated quote types to exclude (e.g. ETF,FUND). Only EQUITY results are kept when specified.","title":"Exclude Types"},"description":"Comma-separated quote types to exclude (e.g. ETF,FUND). Only EQUITY results are kept when specified."},{"name":"sector","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by sector (e.g. Technology, Healthcare, 'Financial Services'). Note: sector is not returned per-stock in the response.","title":"Sector"},"description":"Filter by sector (e.g. Technology, Healthcare, 'Financial Services'). Note: sector is not returned per-stock in the response."},{"name":"pe_min","in":"query","required":false,"schema":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}],"description":"Minimum trailing P/E ratio","title":"Pe Min"},"description":"Minimum trailing P/E ratio"},{"name":"pe_max","in":"query","required":false,"schema":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}],"description":"Maximum trailing P/E ratio","title":"Pe Max"},"description":"Maximum trailing P/E ratio"},{"name":"price_min","in":"query","required":false,"schema":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}],"description":"Minimum stock price in USD","title":"Price Min"},"description":"Minimum stock price in USD"},{"name":"price_max","in":"query","required":false,"schema":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}],"description":"Maximum stock price in USD","title":"Price Max"},"description":"Maximum stock price in USD"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number (1-based)","default":1,"title":"Page"},"description":"Page number (1-based)"},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":250,"minimum":1,"description":"Results per page (max 250, Yahoo API limit)","default":100,"title":"Page Size"},"description":"Results per page (max 250, Yahoo API limit)"},{"name":"sort_by","in":"query","required":false,"schema":{"type":"string","description":"Sort field: market_cap, volume, avg_volume, price, pe_ratio, change_percent, name, eps, dividend_yield, forward_pe, price_to_book","default":"market_cap","title":"Sort By"},"description":"Sort field: market_cap, volume, avg_volume, price, pe_ratio, change_percent, name, eps, dividend_yield, forward_pe, price_to_book"},{"name":"sort_ascending","in":"query","required":false,"schema":{"type":"boolean","description":"Sort ascending (default: descending)","default":false,"title":"Sort Ascending"},"description":"Sort ascending (default: descending)"},{"name":"force_refresh","in":"query","required":false,"schema":{"type":"boolean","description":"Bypass cache and fetch fresh data","default":false,"title":"Force Refresh"},"description":"Bypass cache and fetch fresh data"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/screener/fields":{"get":{"tags":["screener"],"summary":"Available screener filter options and valid values","description":"Return metadata about available screener filter options.\n\nUseful for building dynamic filter UIs — lists all valid exchange names,\nsectors, sort fields, and parameter descriptions.","operationId":"get_screener_fields_api_v1_screener_fields_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/attention/admin/resolve/{ticker}":{"post":{"tags":["attention","attention-admin"],"summary":"Resolve ticker → canonical entity","description":"Maps a ticker symbol to a canonical company entity by looking up the company name, normalizing it, and validating against Wikipedia. Stores the result (canonical name, wiki_title, gdelt_query) in `company_entity_map`.\n\nSkips re-resolution if `is_manual_override` is set. If the company name in the DB is a placeholder (e.g. 'AMZN Corporation'), falls back to SEC company_tickers.json to fetch the real name and updates the DB.","operationId":"admin_resolve_entity_api_v1_attention_admin_resolve__ticker__post","parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string","title":"Ticker"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntityResolveResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/attention/admin/collect/wiki/{ticker}":{"post":{"tags":["attention","attention-admin"],"summary":"Collect Wikipedia pageviews for an event date","description":"Fetches daily Wikipedia pageview counts for the ticker's canonical wiki_title, covering `event_date` and enough lookback days (≥20) to compute spike and z-score. Safe to call on-demand — Wikipedia API has no meaningful rate limit for this use.\n\nRequires entity resolution to have been run first (`wiki_title` must be set).","operationId":"admin_collect_wiki_api_v1_attention_admin_collect_wiki__ticker__post","parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string","title":"Ticker"}},{"name":"event_date","in":"query","required":true,"schema":{"type":"string","format":"date","description":"Event date in YYYY-MM-DD format","title":"Event Date"},"description":"Event date in YYYY-MM-DD format"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/attention/admin/collect/gdelt/{ticker}":{"post":{"tags":["attention","attention-admin"],"summary":"Collect GDELT news articles for an event date","description":"Fetches news articles from GDELT V2 DOC API for the window `event_date ± 1 day`.\n\n**Coverage**: 2017-01-01 onwards. Requests for earlier dates return 0 immediately.\n\n**Rate limit**: GDELT enforces a global per-IP quota. This endpoint is protected by a process-wide lock (10s minimum interval) and retries with exponential backoff (30s → 60s → 120s) on 429 responses.\n\n⚠️ **Call this endpoint from a scheduler only** — never trigger it in response to user requests. Concurrent or rapid calls will exhaust the IP quota and cause temporary bans. The main `/event/{ticker}` endpoint intentionally does NOT collect GDELT on-demand for this reason.","operationId":"admin_collect_gdelt_api_v1_attention_admin_collect_gdelt__ticker__post","parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string","title":"Ticker"}},{"name":"event_date","in":"query","required":true,"schema":{"type":"string","format":"date","description":"Event date in YYYY-MM-DD format","title":"Event Date"},"description":"Event date in YYYY-MM-DD format"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/attention/entity/{ticker}":{"get":{"tags":["attention"],"summary":"Get entity mapping for a ticker","description":"Returns the stored entity mapping for a ticker: canonical name, Wikipedia title,\n GDELT query string, and resolver confidence score.\n\n Returns **404** if no mapping exists — run `POST /admin/resolve/{ticker}` first.\n\n **Example**: `GET /attention/entity/AAPL`","operationId":"get_entity_api_v1_attention_entity__ticker__get","parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string","title":"Ticker"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntityResolveResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/attention/event/{ticker}":{"get":{"tags":["attention"],"summary":"Get attention features for a ticker on an event date","description":"Returns Wikipedia pageview spike/z-score and GDELT news volume for a ticker\n centered on a specific event date. Designed for event-driven backtesting.\n\n **Wikipedia signals** (collected on-demand):\n - `wiki.views` — raw pageview count on `event_date`\n - `wiki.spike_10d` — views / 10-day median baseline; >1 = above-average interest\n - `wiki.zscore_20d` — standard-deviation units above 20-day mean\n\n **GDELT news signals** (pre-populated by scheduler only):\n - `news.article_count_1d` — articles published on `event_date`\n - `news.article_count_3d` — articles in `event_date ± 1 day` window\n - `news.unique_domains_3d` — distinct publisher domains in that window\n - `news.gdelt_status` — data availability flag:\n - `collected` — scheduler ran; counts are accurate (0 = genuinely no articles)\n - `not_collected` — scheduler has not run yet; use `POST /admin/collect/gdelt/{ticker}`\n - `not_available` — event date is before GDELT V2 coverage (2017-01-01)\n\n **Auto-resolution**: if no entity mapping exists, resolution runs automatically first.\n\n **Examples**:\n - `GET /attention/event/AAPL?event_date=2024-02-01` — Q1 earnings day attention\n - `GET /attention/event/NVDA?event_date=2024-05-22` — post-earnings spike","operationId":"get_event_attention_api_v1_attention_event__ticker__get","parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string","title":"Ticker"}},{"name":"event_date","in":"query","required":true,"schema":{"type":"string","format":"date","description":"Event date in YYYY-MM-DD format","title":"Event Date"},"description":"Event date in YYYY-MM-DD format"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventAttentionResponse"}}}},"404":{"description":"Ticker not found or entity resolution failed"},"500":{"description":"Feature materialization or collection error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/insider/transactions/{symbol}":{"get":{"tags":["insider"],"summary":"Get insider transactions for a symbol","description":"Query SEC Form 4 insider trading data. Auto-fetches from SEC EDGAR if data is missing.\n\n**데이터 소스**: SEC EDGAR (무료, API 키 불필요). 첫 조회 시 자동 인덱싱.\n\n**Transaction codes**: P=Purchase, S=Sale, A=Award, M=Exercise, G=Gift, F=Tax Withholding","operationId":"get_insider_transactions_api_v1_insider_transactions__symbol__get","parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string","title":"Symbol"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":3650,"minimum":1,"description":"Days to look back (max ~10 years)","default":90,"title":"Days"},"description":"Days to look back (max ~10 years)"},{"name":"transaction_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter: P=Purchase, S=Sale, A=Award, M=Exercise","title":"Transaction Type"},"description":"Filter: P=Purchase, S=Sale, A=Award, M=Exercise"},{"name":"insider_title","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by title keyword (e.g., CEO, CFO, Director)","title":"Insider Title"},"description":"Filter by title keyword (e.g., CEO, CFO, Director)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"description":"Max entries to return","default":50,"title":"Limit"},"description":"Max entries to return"},{"name":"force_refresh","in":"query","required":false,"schema":{"type":"boolean","description":"Bypass cache and re-fetch from SEC","default":false,"title":"Force Refresh"},"description":"Bypass cache and re-fetch from SEC"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InsiderTransactionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/insider/summary/{symbol}":{"get":{"tags":["insider"],"summary":"Get insider trading summary","description":"Aggregated insider buy/sell activity for 3, 6, and 12 month periods.\n\nIncludes net buy/sell shares and values, plus top 5 notable transactions by value.","operationId":"get_insider_summary_api_v1_insider_summary__symbol__get","parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string","title":"Symbol"}},{"name":"force_refresh","in":"query","required":false,"schema":{"type":"boolean","description":"Bypass cache","default":false,"title":"Force Refresh"},"description":"Bypass cache"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InsiderSummaryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/insider/form4/{ticker}":{"get":{"tags":["insider"],"summary":"PIT-safe Form 4 insider transactions","description":"Returns Form 4 transactions for a ticker where **filing_date ≤ as_of** (point-in-time safe).\n\n`as_of` is required to prevent lookahead in backtests.\n\n`start`/`end` also filter by `filing_date` (not transaction_date).\n\nIf no data exists for the ticker, auto-fetches ~2 years of history from SEC EDGAR (first call may take 1–3 min).","operationId":"get_form4_api_v1_insider_form4__ticker__get","parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string","title":"Ticker"}},{"name":"as_of","in":"query","required":true,"schema":{"type":"string","format":"date","description":"Point-in-time cutoff (filing_date ≤ as_of). Required.","title":"As Of"},"description":"Point-in-time cutoff (filing_date ≤ as_of). Required."},{"name":"start","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Window start (filing_date ≥ start)","title":"Start"},"description":"Window start (filing_date ≥ start)"},{"name":"end","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Window end (filing_date ≤ end)","title":"End"},"description":"Window end (filing_date ≤ end)"},{"name":"buy_only","in":"query","required":false,"schema":{"type":"boolean","description":"Only return open-market purchases (transaction_code=P, shares > 0). Excludes awards/grants.","default":false,"title":"Buy Only"},"description":"Only return open-market purchases (transaction_code=P, shares > 0). Excludes awards/grants."},{"name":"csuite_only","in":"query","required":false,"schema":{"type":"boolean","description":"Only return C-suite insider transactions","default":false,"title":"Csuite Only"},"description":"Only return C-suite insider transactions"},{"name":"force_refresh","in":"query","required":false,"schema":{"type":"boolean","description":"Re-fetch ~2yr of Form 4 history from SEC EDGAR before querying. Slow on first call.","default":false,"title":"Force Refresh"},"description":"Re-fetch ~2yr of Form 4 history from SEC EDGAR before querying. Slow on first call."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Form4Response"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/insider/form4/by-date/{filing_date}":{"get":{"tags":["insider"],"summary":"Form 4 filings by a specific date (cross-ticker)","description":"Returns all Form 4 transactions where filing_date equals the given date. Useful for pre-market screening.","operationId":"get_form4_by_date_api_v1_insider_form4_by_date__filing_date__get","parameters":[{"name":"filing_date","in":"path","required":true,"schema":{"type":"string","format":"date","title":"Filing Date"}},{"name":"buy_only","in":"query","required":false,"schema":{"type":"boolean","description":"Only return open-market purchases (transaction_code=P). Excludes awards/grants.","default":false,"title":"Buy Only"},"description":"Only return open-market purchases (transaction_code=P). Excludes awards/grants."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Form4ByDateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/insider/form4/aggregate/{ticker}":{"get":{"tags":["insider"],"summary":"Aggregate Form 4 buy activity (PIT-safe)","description":"Aggregated insider buy metrics within [as_of - window_days, as_of].\n\nAll based on `filing_date` (PIT-safe). Returns buy_count, buy_dollar_total, cluster_size (unique insiders), csuite_count, avg_pct_of_holding, recency_days.\n\nIf no data exists for the ticker, auto-fetches ~2 years of history from SEC EDGAR.","operationId":"get_form4_aggregate_api_v1_insider_form4_aggregate__ticker__get","parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string","title":"Ticker"}},{"name":"as_of","in":"query","required":true,"schema":{"type":"string","format":"date","description":"Point-in-time cutoff. Required.","title":"As Of"},"description":"Point-in-time cutoff. Required."},{"name":"window_days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"description":"Lookback window in days","default":30,"title":"Window Days"},"description":"Lookback window in days"},{"name":"force_refresh","in":"query","required":false,"schema":{"type":"boolean","description":"Re-fetch ~2yr of Form 4 history from SEC EDGAR before querying.","default":false,"title":"Force Refresh"},"description":"Re-fetch ~2yr of Form 4 history from SEC EDGAR before querying."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Form4AggregateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/earnings/calendar/{symbol}":{"get":{"tags":["earnings"],"summary":"Get upcoming earnings dates for a symbol","description":"Upcoming earnings announcement dates with EPS estimates.\n\n**데이터 소스**: yfinance-plus (`Ticker.earnings_dates`). API 키 불필요.\n**earnings_time**: `pre_market` / `post_market` / `during_market` / `unknown`.\n\n**PIT (Point-in-Time) backtesting**: `as_of_date`를 지정하면 해당 날짜 기준 upcoming earnings를 반환합니다. 이미 보고된 earnings도 당시엔 예정이었으므로 `reported_eps`가 채워진 상태로 반환됩니다.\n\n**Note**: Revenue estimates are not available from this source.","operationId":"get_earnings_calendar_api_v1_earnings_calendar__symbol__get","parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string","title":"Symbol"}},{"name":"days_ahead","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"description":"Days to look ahead from as_of_date (or today)","default":30,"title":"Days Ahead"},"description":"Days to look ahead from as_of_date (or today)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":20,"minimum":1,"description":"Max earnings dates to return","default":4,"title":"Limit"},"description":"Max earnings dates to return"},{"name":"as_of_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"PIT date for backtesting (YYYY-MM-DD). Defaults to today.","title":"As Of Date"},"description":"PIT date for backtesting (YYYY-MM-DD). Defaults to today."},{"name":"force_refresh","in":"query","required":false,"schema":{"type":"boolean","description":"Bypass cache and re-fetch from yfinance","default":false,"title":"Force Refresh"},"description":"Bypass cache and re-fetch from yfinance"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EarningsCalendarResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/earnings/calendar/bulk":{"post":{"tags":["earnings"],"summary":"Bulk future earnings calendar","description":"Fetch upcoming earnings dates for multiple symbols (max 50).\n\nReturns a flat list of calendar entries sorted by `earnings_date` ascending.\nUseful for checking upcoming earnings of sector peers or candidates.","operationId":"get_bulk_earnings_calendar_api_v1_earnings_calendar_bulk_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkEarningsCalendarRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkEarningsCalendarResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/earnings/surprise/{symbol}":{"get":{"tags":["earnings"],"summary":"Get earnings surprise history","description":"Quarterly EPS surprise: reported vs analyst consensus estimate.\n\n**데이터 소스**: yfinance-plus (`Ticker.earnings_dates`). API 키 불필요.\n**커버리지**: ~25분기 (6년+). 첫 조회 시 자동 인덱싱.\n\n**surprise** = reported_eps - estimated_eps.\n**surprise_percentage** = (surprise / estimated) × 100.\n**streak**: 연속 beat (양수) 또는 miss (음수) 횟수.","operationId":"get_earnings_surprise_api_v1_earnings_surprise__symbol__get","parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string","title":"Symbol"}},{"name":"quarters","in":"query","required":false,"schema":{"type":"integer","maximum":40,"minimum":1,"description":"Number of recent quarters (max ~25 available)","default":8,"title":"Quarters"},"description":"Number of recent quarters (max ~25 available)"},{"name":"force_refresh","in":"query","required":false,"schema":{"type":"boolean","description":"Bypass cache and re-fetch from yfinance","default":false,"title":"Force Refresh"},"description":"Bypass cache and re-fetch from yfinance"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EarningsSurpriseResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/universe/screen":{"get":{"tags":["universe"],"summary":"Screen stocks at a historical date","description":"Query monthly market_cap snapshots to find stocks matching criteria at a past date.\\n\\n**용도**: 백테스팅 전략 유니버스 구성 — 특정 시점 시총/섹터 기준 종목 필터링.\\n\\n**데이터 소스**: SEC EDGAR shares_outstanding × yfinance monthly close.\\n**제한**: 현재 상장 종목만 포함 (survivorship bias). 상폐 종목 미포함.\\n\\n**사전 조건**: `/universe/admin/discover` 후 `/universe/admin/build-snapshots` 실행 필요.","operationId":"screen_historical_api_v1_universe_screen_get","parameters":[{"name":"date","in":"query","required":true,"schema":{"type":"string","description":"Historical date YYYY-MM-DD (rounded to month start)","title":"Date"},"description":"Historical date YYYY-MM-DD (rounded to month start)"},{"name":"market_cap_min","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Min market cap (USD), e.g. 2e9","title":"Market Cap Min"},"description":"Min market cap (USD), e.g. 2e9"},{"name":"market_cap_max","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Max market cap (USD), e.g. 20e9","title":"Market Cap Max"},"description":"Max market cap (USD), e.g. 20e9"},{"name":"sector","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sector filter (e.g. Technology, Healthcare)","title":"Sector"},"description":"Sector filter (e.g. Technology, Healthcare)"},{"name":"exchange","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Exchange filter (NYSE, NASDAQ, AMEX)","title":"Exchange"},"description":"Exchange filter (NYSE, NASDAQ, AMEX)"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number","default":1,"title":"Page"},"description":"Page number"},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"description":"Results per page","default":100,"title":"Page Size"},"description":"Results per page"},{"name":"sort_by","in":"query","required":false,"schema":{"type":"string","description":"Sort field: market_cap or ticker","default":"market_cap","title":"Sort By"},"description":"Sort field: market_cap or ticker"},{"name":"sort_ascending","in":"query","required":false,"schema":{"type":"boolean","description":"Sort direction","default":false,"title":"Sort Ascending"},"description":"Sort direction"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UniverseScreenResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/universe/registry":{"get":{"tags":["universe"],"summary":"Browse registered ticker universe","description":"List tickers registered in the universe (populated via /admin/discover).","operationId":"get_registry_api_v1_universe_registry_get","parameters":[{"name":"sector","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by sector","title":"Sector"},"description":"Filter by sector"},{"name":"exchange","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by exchange","title":"Exchange"},"description":"Filter by exchange"},{"name":"is_active","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter by active status","title":"Is Active"},"description":"Filter by active status"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":100,"title":"Page Size"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegistryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/universe/admin/discover":{"post":{"tags":["universe"],"summary":"Discover and register US tickers","description":"Scrapes US-listed stocks via yfinance screener and registers them in the universe.\\n\\n**소요 시간**: 약 1~5분 (시총 기준에 따라 다름).\\n**권장**: `market_cap_min=100000000` ($100M) → ~3000~5000 종목.","operationId":"discover_tickers_api_v1_universe_admin_discover_post","parameters":[{"name":"market_cap_min","in":"query","required":false,"schema":{"type":"number","description":"Min market cap for inclusion (USD). Default $100M.","default":100000000.0,"title":"Market Cap Min"},"description":"Min market cap for inclusion (USD). Default $100M."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/universe/admin/build-snapshots":{"post":{"tags":["universe"],"summary":"Build monthly market_cap snapshots","description":"Computes monthly market_cap snapshots for registered tickers and stores them in `universe_snapshot`.\\n\\n**데이터 소스**: SEC EDGAR companyfacts (shares_outstanding) + yfinance monthly close.\\n\\n**소요 시간**: 전체 유니버스(~4000 종목) × 10년 기준 30~60분. 백그라운드에서 실행되므로 응답은 즉시 반환됩니다.\\n\\n**권장 시작점**: `tickers=[AAPL,MSFT,GOOGL]`로 소규모 테스트 후 전체 빌드.","operationId":"build_snapshots_api_v1_universe_admin_build_snapshots_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SnapshotBuildRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/dividends/upcoming":{"get":{"tags":["dividends"],"summary":"PIT upcoming ex-dividend calendar","description":"Point-in-Time 배당락 캘린더. `as_of_date` 기준으로 당시 알려져 있었던 배당 일정 중 `from_ex_date` ~ `to_ex_date` 범위의 ex-date를 반환.\n\n**PIT 의미**: 같은 (ticker, ex_date)에 여러 revision이 있으면 `as_of_date <= query_as_of_date` 조건 내에서 가장 최신 revision만 반환.\n\n**데이터 소스**: yfinance-plus. API 키 불필요. symbols 파라미터 없이 조회 시 이미 인덱싱된 종목 전체 반환.\n\n**백필**: `POST /dividends/admin/ingest` 로 원하는 종목 선인덱싱 가능.","operationId":"get_upcoming_dividends_api_v1_dividends_upcoming_get","parameters":[{"name":"as_of_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"PIT 기준일 (YYYY-MM-DD). 생략 시 오늘.","title":"As Of Date"},"description":"PIT 기준일 (YYYY-MM-DD). 생략 시 오늘."},{"name":"from_ex_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Ex-date 시작 (YYYY-MM-DD). 생략 시 오늘.","title":"From Ex Date"},"description":"Ex-date 시작 (YYYY-MM-DD). 생략 시 오늘."},{"name":"to_ex_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Ex-date 끝 (YYYY-MM-DD). 생략 시 오늘 + 60일.","title":"To Ex Date"},"description":"Ex-date 끝 (YYYY-MM-DD). 생략 시 오늘 + 60일."},{"name":"symbols","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"종목 필터 (e.g. ?symbols=AAPL&symbols=MSFT). 생략 시 전체.","title":"Symbols"},"description":"종목 필터 (e.g. ?symbols=AAPL&symbols=MSFT). 생략 시 전체."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":5000,"minimum":1,"description":"최대 반환 개수","default":500,"title":"Limit"},"description":"최대 반환 개수"},{"name":"force_refresh","in":"query","required":false,"schema":{"type":"boolean","description":"캐시 무시","default":false,"title":"Force Refresh"},"description":"캐시 무시"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DividendUpcomingResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/dividends/history/{symbol}":{"get":{"tags":["dividends"],"summary":"종목별 배당 이력","description":"단일 종목의 전체 배당 이력. yfinance 데이터가 없으면 자동 인덱싱.\n\n각 ex-date별 최신 revision을 반환 (ex-date 내림차순).\n\n`annual_yield_estimate`: 최근 12개월 배당 합산액 (주가 대비 yield는 클라이언트 계산 필요).","operationId":"get_dividend_history_api_v1_dividends_history__symbol__get","parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string","title":"Symbol"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"description":"최대 반환 개수","default":100,"title":"Limit"},"description":"최대 반환 개수"},{"name":"force_refresh","in":"query","required":false,"schema":{"type":"boolean","description":"캐시 무시 + yfinance 재조회","default":false,"title":"Force Refresh"},"description":"캐시 무시 + yfinance 재조회"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DividendHistoryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/dividends/admin/ingest":{"post":{"tags":["dividends"],"summary":"배당 데이터 벌크 인제스트","description":"yfinance에서 지정 종목 배당 이력을 가져와 DB에 저장.\n\n**예시**:\n- `{\"symbols\": [\"AAPL\", \"MSFT\", \"JNJ\"]}` — 신규 종목 인덱싱\n- `{\"symbols\": [...], \"force_refresh\": true}` — 기존 데이터 재인제스트\n\n종목당 약 25년치 이력. 100종목 기준 5~10분 소요 (yfinance rate limit).\n\n이미 인덱싱된 종목은 `force_refresh: false`일 때 건너뜀 (멱등성).","operationId":"ingest_dividends_api_v1_dividends_admin_ingest_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DividendIngestRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DividendIngestResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/company/{ticker}":{"get":{"tags":["company"],"summary":"Get company metadata","description":"Returns sector, industry, exchange, market_cap, country, and other metadata for a ticker. Valid tickers without financial statements still return 200. Unknown tickers return 404.","operationId":"get_company_api_v1_company__ticker__get","parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string","title":"Ticker"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyMetadataResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/company/bulk":{"post":{"tags":["company"],"summary":"Bulk company metadata","description":"Fetch metadata for up to 100 tickers in one request. Partial failures are allowed — each item has either `data` or `error`.","operationId":"bulk_company_api_v1_company_bulk_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkCompanyRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkCompanyResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ownership/13dg/active":{"get":{"tags":["ownership"],"summary":"Active activist positions as-of a date","description":"Returns the latest SC 13D/13G filing per (filer, issuer) pair where **filing_date ≤ as_of** and **ownership_pct ≥ min_ownership_pct**.\n\nPositions with `ownership_pct = null` (not yet enriched) are excluded.\n\n`as_of` is required.","operationId":"get_13dg_active_api_v1_ownership_13dg_active_get","parameters":[{"name":"as_of","in":"query","required":true,"schema":{"type":"string","format":"date","description":"Point-in-time cutoff. Required.","title":"As Of"},"description":"Point-in-time cutoff. Required."},{"name":"min_ownership_pct","in":"query","required":false,"schema":{"type":"number","maximum":100.0,"minimum":0.0,"description":"Minimum ownership %","default":5.0,"title":"Min Ownership Pct"},"description":"Minimum ownership %"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivistActiveResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ownership/13dg/{ticker}":{"get":{"tags":["ownership"],"summary":"SC 13D/13G activist ownership events for a ticker","description":"Returns SC 13D and SC 13G filings (including amendments) where **filing_date ≤ as_of**.\n\n`as_of` is required for PIT safety in backtests.\n\nNote: `ownership_pct` / `shares_owned` will be `null` until background enrichment runs (~30 min).","operationId":"get_13dg_events_api_v1_ownership_13dg__ticker__get","parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string","title":"Ticker"}},{"name":"as_of","in":"query","required":true,"schema":{"type":"string","format":"date","description":"Point-in-time cutoff (filing_date ≤ as_of). Required.","title":"As Of"},"description":"Point-in-time cutoff (filing_date ≤ as_of). Required."},{"name":"start","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Window start (filing_date ≥ start)","title":"Start"},"description":"Window start (filing_date ≥ start)"},{"name":"end","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Window end (filing_date ≤ end)","title":"End"},"description":"Window end (filing_date ≤ end)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivistEventsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"ActivistActiveResponse":{"properties":{"as_of":{"type":"string","format":"date","title":"As Of"},"min_ownership_pct":{"type":"number","title":"Min Ownership Pct"},"positions":{"items":{"$ref":"#/components/schemas/ActivistEventEntry"},"type":"array","title":"Positions"},"total_count":{"type":"integer","title":"Total Count"}},"type":"object","required":["as_of","min_ownership_pct","positions","total_count"],"title":"ActivistActiveResponse"},"ActivistEventEntry":{"properties":{"symbol":{"type":"string","title":"Symbol"},"filing_date":{"type":"string","format":"date","title":"Filing Date"},"filer_name":{"type":"string","title":"Filer Name"},"filer_cik":{"type":"string","title":"Filer Cik"},"form_type":{"type":"string","title":"Form Type"},"ownership_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Ownership Pct"},"shares_owned":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Shares Owned"},"is_amendment":{"type":"boolean","title":"Is Amendment","default":false},"change_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Change Pct"},"accession_number":{"type":"string","title":"Accession Number"},"parse_status":{"type":"string","title":"Parse Status"}},"type":"object","required":["symbol","filing_date","filer_name","filer_cik","form_type","accession_number","parse_status"],"title":"ActivistEventEntry"},"ActivistEventsResponse":{"properties":{"symbol":{"type":"string","title":"Symbol"},"as_of":{"type":"string","format":"date","title":"As Of"},"window":{"additionalProperties":true,"type":"object","title":"Window"},"events":{"items":{"$ref":"#/components/schemas/ActivistEventEntry"},"type":"array","title":"Events"},"total_count":{"type":"integer","title":"Total Count"}},"type":"object","required":["symbol","as_of","events","total_count"],"title":"ActivistEventsResponse"},"AlpacaMultiBarsResponse":{"properties":{"source":{"type":"string","title":"Source","default":"ALPACA"},"interval":{"type":"string","title":"Interval"},"count":{"type":"integer","title":"Count"},"bars":{"additionalProperties":{"items":{"additionalProperties":true,"type":"object"},"type":"array"},"type":"object","title":"Bars"}},"type":"object","required":["interval","count","bars"],"title":"AlpacaMultiBarsResponse","description":"Multi-ticker OHLCV bars from Alpaca (daily or intraday).\n\n``bars`` maps each ticker (using the original input symbol, e.g. BF-B)\nto a list of bar dicts. Daily bars include a ``date`` field; intraday\nbars include a ``timestamp`` field."},"AlpacaMultiSnapshotResponse":{"properties":{"source":{"type":"string","title":"Source","default":"ALPACA"},"count":{"type":"integer","title":"Count"},"snapshots":{"items":{"$ref":"#/components/schemas/AlpacaSnapshotResponse"},"type":"array","title":"Snapshots"}},"type":"object","required":["count","snapshots"],"title":"AlpacaMultiSnapshotResponse","description":"Real-time snapshots for multiple tickers."},"AlpacaSnapshotResponse":{"properties":{"ticker":{"type":"string","title":"Ticker"},"source":{"type":"string","title":"Source","default":"ALPACA"},"timestamp":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timestamp"},"price":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Price"},"trade_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Trade Size"},"bid":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Bid"},"ask":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Ask"},"bid_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Bid Size"},"ask_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Ask Size"},"open":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Open"},"high":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"High"},"low":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Low"},"volume":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Volume"},"vwap":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Vwap"},"prev_close":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Prev Close"},"change":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Change"},"change_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Change Pct"}},"type":"object","required":["ticker"],"title":"AlpacaSnapshotResponse","description":"Real-time snapshot for a single ticker via Alpaca."},"BulkCompanyItem":{"properties":{"ticker":{"type":"string","title":"Ticker"},"data":{"anyOf":[{"$ref":"#/components/schemas/CompanyMetadataResponse"},{"type":"null"}]},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["ticker"],"title":"BulkCompanyItem"},"BulkCompanyRequest":{"properties":{"tickers":{"items":{"type":"string"},"type":"array","title":"Tickers"}},"type":"object","required":["tickers"],"title":"BulkCompanyRequest"},"BulkCompanyResponse":{"properties":{"results":{"items":{"$ref":"#/components/schemas/BulkCompanyItem"},"type":"array","title":"Results"},"total":{"type":"integer","title":"Total"},"success_count":{"type":"integer","title":"Success Count"},"error_count":{"type":"integer","title":"Error Count"}},"type":"object","required":["results","total","success_count","error_count"],"title":"BulkCompanyResponse"},"BulkEarningsCalendarRequest":{"properties":{"symbols":{"items":{"type":"string"},"type":"array","maxItems":50,"minItems":1,"title":"Symbols"},"days_ahead":{"type":"integer","maximum":365.0,"minimum":1.0,"title":"Days Ahead","default":30},"limit":{"type":"integer","maximum":20.0,"minimum":1.0,"title":"Limit","default":4},"as_of_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"As Of Date","description":"PIT date for backtesting (YYYY-MM-DD). Defaults to today."}},"type":"object","required":["symbols"],"title":"BulkEarningsCalendarRequest"},"BulkEarningsCalendarResponse":{"properties":{"entries":{"items":{"$ref":"#/components/schemas/EarningsCalendarEntry"},"type":"array","title":"Entries"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"}},"type":"object","required":["entries"],"title":"BulkEarningsCalendarResponse"},"BulkExhibitItem":{"properties":{"accession_number":{"type":"string","title":"Accession Number"},"exhibit_type":{"type":"string","title":"Exhibit Type"},"success":{"type":"boolean","title":"Success"},"content":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content"},"content_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content Type"},"filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filename"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["accession_number","exhibit_type","success"],"title":"BulkExhibitItem"},"BulkExhibitRequest":{"properties":{"items":{"items":{"additionalProperties":{"type":"string"},"type":"object"},"type":"array","maxItems":50,"minItems":1,"title":"Items"}},"type":"object","required":["items"],"title":"BulkExhibitRequest","example":{"items":[{"accession_number":"0000320193-24-000006","exhibit_type":"EX-99.1"},{"accession_number":"0001045810-24-000010","exhibit_type":"EX-99.1"}]}},"BulkExhibitResponse":{"properties":{"results":{"items":{"$ref":"#/components/schemas/BulkExhibitItem"},"type":"array","title":"Results"},"total_items":{"type":"integer","title":"Total Items"},"successful_count":{"type":"integer","title":"Successful Count"},"failed_count":{"type":"integer","title":"Failed Count"},"query_time_seconds":{"type":"number","title":"Query Time Seconds"}},"type":"object","required":["results","total_items","successful_count","failed_count","query_time_seconds"],"title":"BulkExhibitResponse"},"BulkFilingSearchItem":{"properties":{"ticker":{"type":"string","title":"Ticker"},"success":{"type":"boolean","title":"Success"},"filings":{"items":{"$ref":"#/components/schemas/FilingSummary"},"type":"array","title":"Filings","default":[]},"total_count":{"type":"integer","title":"Total Count","default":0},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["ticker","success"],"title":"BulkFilingSearchItem"},"BulkFilingSearchRequest":{"properties":{"tickers":{"items":{"type":"string"},"type":"array","maxItems":200,"minItems":1,"title":"Tickers"},"form_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Form Type"},"start_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start Date"},"end_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End Date"},"limit_per_ticker":{"type":"integer","maximum":100.0,"minimum":1.0,"title":"Limit Per Ticker","default":20}},"type":"object","required":["tickers"],"title":"BulkFilingSearchRequest","example":{"end_date":"2024-12-31","form_type":"8-K","limit_per_ticker":5,"start_date":"2024-01-01","tickers":["AAPL","MSFT","NVDA"]}},"BulkFilingSearchResponse":{"properties":{"results":{"items":{"$ref":"#/components/schemas/BulkFilingSearchItem"},"type":"array","title":"Results"},"total_tickers":{"type":"integer","title":"Total Tickers"},"successful_count":{"type":"integer","title":"Successful Count"},"failed_count":{"type":"integer","title":"Failed Count"},"query_time_seconds":{"type":"number","title":"Query Time Seconds"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"}},"type":"object","required":["results","total_tickers","successful_count","failed_count","query_time_seconds"],"title":"BulkFilingSearchResponse"},"BulkFinancialDataItem":{"properties":{"ticker":{"type":"string","title":"Ticker"},"success":{"type":"boolean","title":"Success"},"data":{"anyOf":[{"$ref":"#/components/schemas/FinancialDataResponse"},{"type":"null"}]},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["ticker","success"],"title":"BulkFinancialDataItem"},"BulkFinancialDataRequest":{"properties":{"tickers":{"items":{"type":"string"},"type":"array","maxItems":500,"minItems":1,"title":"Tickers","description":"List of stock ticker symbols (max 500 for efficient bulk processing)"},"start_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Start Date","description":"Start date for data retrieval. Cannot be used with quarters or period."},"end_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"End Date","description":"End date for data retrieval. Cannot be used with quarters or period."},"quarters":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":40,"minItems":1},{"type":"null"}],"title":"Quarters","description":"List of quarters in format 'YYYYQN' (e.g., ['2020Q1', '2020Q2']). Cannot be used with start_date/end_date or period. If provided, dates are ignored."},"period":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Period","description":"Period string like '1d', '7d', '1m', '3m', '1y', '2y'. Cannot be used with start_date/end_date or quarters."},"period_type":{"$ref":"#/components/schemas/PeriodType","description":"Type of financial periods to retrieve","default":"all"},"include_metrics":{"type":"boolean","title":"Include Metrics","description":"Include calculated metrics in response","default":true},"force_refresh":{"type":"boolean","title":"Force Refresh","description":"Force refresh data from SEC","default":false}},"type":"object","required":["tickers"],"title":"BulkFinancialDataRequest"},"BulkFinancialDataResponse":{"properties":{"results":{"items":{"$ref":"#/components/schemas/BulkFinancialDataItem"},"type":"array","title":"Results"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"}},"type":"object","required":["results"],"title":"BulkFinancialDataResponse"},"BulkParseRequest":{"properties":{"tickers":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Tickers"},"limit":{"type":"integer","maximum":1000.0,"minimum":1.0,"title":"Limit","default":100},"force_reparse":{"type":"boolean","title":"Force Reparse","description":"If True, also reparse filings with status succeeded or failed (resets to pending first)","default":false}},"type":"object","title":"BulkParseRequest","example":{"force_reparse":false,"limit":50,"tickers":["AVGO","AAPL"]}},"BulkParseResponse":{"properties":{"succeeded":{"type":"integer","title":"Succeeded"},"failed":{"type":"integer","title":"Failed"},"skipped":{"type":"integer","title":"Skipped"},"total":{"type":"integer","title":"Total"},"query_time_seconds":{"type":"number","title":"Query Time Seconds"}},"type":"object","required":["succeeded","failed","skipped","total","query_time_seconds"],"title":"BulkParseResponse"},"BulkPriceDataItem":{"properties":{"ticker":{"type":"string","title":"Ticker"},"success":{"type":"boolean","title":"Success"},"data":{"anyOf":[{"$ref":"#/components/schemas/PriceDataResponse"},{"type":"null"}]},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["ticker","success"],"title":"BulkPriceDataItem"},"BulkPriceDataRequest":{"properties":{"tickers":{"items":{"type":"string"},"type":"array","maxItems":500,"minItems":1,"title":"Tickers","description":"List of stock ticker symbols (max 500 for efficient bulk processing)"},"start_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Start Date","description":"Start date for data retrieval. Cannot be used with quarters or period."},"end_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"End Date","description":"End date for data retrieval. Cannot be used with quarters or period."},"quarters":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":40,"minItems":1},{"type":"null"}],"title":"Quarters","description":"List of quarters in format 'YYYYQN' (e.g., ['2020Q1', '2020Q2']). Cannot be used with start_date/end_date or period. If provided, dates are ignored."},"period":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Period","description":"Period string like '1d', '7d', '1m', '3m', '1y', '2y'. Cannot be used with start_date/end_date or quarters."},"interval":{"type":"string","title":"Interval","description":"Data interval: 1d, 1w, 1m, 5d, 1h, etc.","default":"1d"},"force_refresh":{"type":"boolean","title":"Force Refresh","description":"Force refresh data from Yahoo Finance","default":false}},"type":"object","required":["tickers"],"title":"BulkPriceDataRequest"},"BulkPriceDataResponse":{"properties":{"results":{"items":{"$ref":"#/components/schemas/BulkPriceDataItem"},"type":"array","title":"Results"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"}},"type":"object","required":["results"],"title":"BulkPriceDataResponse"},"CollectionStatusResponse":{"properties":{"ticker":{"type":"string","title":"Ticker"},"source":{"type":"string","title":"Source"},"records_collected":{"type":"integer","title":"Records Collected"},"date_range":{"additionalProperties":true,"type":"object","title":"Date Range"},"status":{"type":"string","title":"Status"}},"type":"object","required":["ticker","source","records_collected","status"],"title":"CollectionStatusResponse","example":{"date_range":{"event_date":"2024-02-01"},"records_collected":22,"source":"wiki","status":"success","ticker":"AAPL"}},"CompanyInfo":{"properties":{"ticker":{"type":"string","title":"Ticker"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"cik":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cik"},"exchange":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Exchange"},"sector":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sector"},"industry":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Industry"},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country"},"market_cap":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Market Cap"},"business_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Business Description"}},"type":"object","required":["ticker"],"title":"CompanyInfo"},"CompanyMetadataResponse":{"properties":{"ticker":{"type":"string","title":"Ticker"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"cik":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cik"},"exchange":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Exchange"},"sector":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sector"},"industry":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Industry"},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country"},"market_cap":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Market Cap"},"business_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Business Description"}},"type":"object","required":["ticker"],"title":"CompanyMetadataResponse"},"CoverageResponse":{"properties":{"source":{"type":"string","title":"Source"},"symbol":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Symbol"},"earliest":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Earliest"},"latest":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Latest"},"ingested_count":{"type":"integer","title":"Ingested Count"}},"type":"object","required":["source","ingested_count"],"title":"CoverageResponse"},"DataCatalogItem":{"properties":{"field_name":{"type":"string","title":"Field Name"},"description":{"type":"string","title":"Description"},"data_type":{"type":"string","title":"Data Type"},"unit":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Unit"},"calculation":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Calculation"},"source":{"type":"string","title":"Source"}},"type":"object","required":["field_name","description","data_type","source"],"title":"DataCatalogItem"},"DataCatalogResponse":{"properties":{"categories":{"additionalProperties":{"items":{"$ref":"#/components/schemas/DataCatalogItem"},"type":"array"},"type":"object","title":"Categories"},"last_updated":{"type":"string","format":"date-time","title":"Last Updated"}},"type":"object","required":["categories","last_updated"],"title":"DataCatalogResponse"},"DividendCalendarEntry":{"properties":{"ticker":{"type":"string","title":"Ticker"},"ex_dividend_date":{"type":"string","format":"date","title":"Ex Dividend Date"},"amount":{"type":"number","title":"Amount"},"declaration_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Declaration Date"},"record_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Record Date"},"payment_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Payment Date"},"currency":{"type":"string","title":"Currency","default":"USD"},"dividend_type":{"type":"string","title":"Dividend Type","default":"regular"},"frequency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Frequency"},"as_of_date":{"type":"string","format":"date","title":"As Of Date"},"source":{"type":"string","title":"Source"}},"type":"object","required":["ticker","ex_dividend_date","amount","as_of_date","source"],"title":"DividendCalendarEntry"},"DividendHistoryResponse":{"properties":{"symbol":{"type":"string","title":"Symbol"},"dividends":{"items":{"$ref":"#/components/schemas/DividendCalendarEntry"},"type":"array","title":"Dividends"},"total_count":{"type":"integer","title":"Total Count"},"annual_yield_estimate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Annual Yield Estimate"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"}},"type":"object","required":["symbol","dividends","total_count"],"title":"DividendHistoryResponse","description":"Response for single-symbol dividend history."},"DividendIngestRequest":{"properties":{"symbols":{"items":{"type":"string"},"type":"array","maxItems":200,"minItems":1,"title":"Symbols"},"force_refresh":{"type":"boolean","title":"Force Refresh","description":"Re-ingest even if data exists","default":false}},"type":"object","required":["symbols"],"title":"DividendIngestRequest","description":"Request body for bulk backfill ingest."},"DividendIngestResponse":{"properties":{"symbols_processed":{"type":"integer","title":"Symbols Processed"},"total_records_upserted":{"type":"integer","title":"Total Records Upserted"},"failed_symbols":{"items":{"type":"string"},"type":"array","title":"Failed Symbols"},"status":{"type":"string","title":"Status"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"}},"type":"object","required":["symbols_processed","total_records_upserted","status"],"title":"DividendIngestResponse","description":"Response for admin ingest endpoint."},"DividendUpcomingResponse":{"properties":{"dividends":{"items":{"$ref":"#/components/schemas/DividendCalendarEntry"},"type":"array","title":"Dividends"},"total_count":{"type":"integer","title":"Total Count"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"}},"type":"object","required":["dividends","total_count"],"title":"DividendUpcomingResponse","description":"Response for PIT upcoming dividends query."},"ETFHoldingsOut":{"properties":{"success":{"type":"boolean","title":"Success"},"ticker":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ticker"},"as_of_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"As Of Date"},"cik":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cik"},"holdings_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Holdings Count"},"holdings":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"Holdings"},"availability":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Availability"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["success"],"title":"ETFHoldingsOut"},"EarningsCalendarEntry":{"properties":{"symbol":{"type":"string","title":"Symbol"},"earnings_date":{"type":"string","format":"date-time","title":"Earnings Date"},"earnings_time":{"type":"string","title":"Earnings Time"},"estimated_eps":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Estimated Eps"},"reported_eps":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Reported Eps"},"source":{"type":"string","title":"Source","default":"yfinance"},"fetched_at":{"type":"string","format":"date-time","title":"Fetched At"}},"type":"object","required":["symbol","earnings_date","earnings_time","fetched_at"],"title":"EarningsCalendarEntry"},"EarningsCalendarResponse":{"properties":{"symbol":{"type":"string","title":"Symbol"},"upcoming_earnings":{"items":{"$ref":"#/components/schemas/EarningsCalendarEntry"},"type":"array","title":"Upcoming Earnings"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"}},"type":"object","required":["symbol","upcoming_earnings"],"title":"EarningsCalendarResponse"},"EarningsSurpriseEntry":{"properties":{"fiscal_date_ending":{"type":"string","format":"date","title":"Fiscal Date Ending"},"reported_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Reported Date"},"reported_eps":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Reported Eps"},"estimated_eps":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Estimated Eps"},"surprise":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Surprise"},"surprise_percentage":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Surprise Percentage"},"beat":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Beat"}},"type":"object","required":["fiscal_date_ending"],"title":"EarningsSurpriseEntry"},"EarningsSurpriseResponse":{"properties":{"symbol":{"type":"string","title":"Symbol"},"quarters":{"items":{"$ref":"#/components/schemas/EarningsSurpriseEntry"},"type":"array","title":"Quarters"},"streak":{"type":"integer","title":"Streak","default":0},"avg_surprise_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Surprise Pct"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"}},"type":"object","required":["symbol","quarters"],"title":"EarningsSurpriseResponse"},"EntityInfo":{"properties":{"ticker":{"type":"string","title":"Ticker"},"canonical_name":{"type":"string","title":"Canonical Name","description":"Normalized company name with legal suffixes stripped (e.g. 'Apple')"},"wiki_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Wiki Title","description":"Matched Wikipedia article title; null if unresolved"},"gdelt_query":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Gdelt Query","description":"GDELT DOC API query string (quoted OR phrases)"},"aliases":{"items":{"type":"string"},"type":"array","title":"Aliases","description":"Intermediate forms used during name normalization"},"resolver_confidence":{"type":"number","title":"Resolver Confidence","description":"Wikipedia match confidence [0, 1]","default":0.0},"is_manual_override":{"type":"boolean","title":"Is Manual Override","description":"If true, automated re-resolution is skipped","default":false}},"type":"object","required":["ticker","canonical_name"],"title":"EntityInfo","example":{"aliases":["Apple Inc."],"canonical_name":"Apple","gdelt_query":"\"Apple\" OR \"Apple Inc.\"","is_manual_override":false,"resolver_confidence":0.92,"ticker":"AAPL","wiki_title":"Apple Inc."}},"EntityResolveResponse":{"properties":{"ticker":{"type":"string","title":"Ticker"},"entity":{"$ref":"#/components/schemas/EntityInfo"},"status":{"type":"string","title":"Status"},"message":{"type":"string","title":"Message"}},"type":"object","required":["ticker","entity","status","message"],"title":"EntityResolveResponse","example":{"entity":{"aliases":["Apple Inc."],"canonical_name":"Apple","gdelt_query":"\"Apple\" OR \"Apple Inc.\"","is_manual_override":false,"resolver_confidence":0.92,"ticker":"AAPL","wiki_title":"Apple Inc."},"message":"Entity resolved: wiki_title='Apple Inc.' confidence=0.92","status":"resolved","ticker":"AAPL"}},"ErrorLogListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ErrorLogResponse"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"},"total_pages":{"type":"integer","title":"Total Pages"}},"type":"object","required":["items","total","page","page_size","total_pages"],"title":"ErrorLogListResponse","description":"Response schema for error log list"},"ErrorLogResponse":{"properties":{"request_id":{"type":"string","title":"Request Id"},"endpoint":{"type":"string","title":"Endpoint"},"method":{"type":"string","title":"Method"},"path":{"type":"string","title":"Path"},"query_params":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Query Params"},"request_body":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Request Body"},"error_type":{"type":"string","title":"Error Type"},"error_message":{"type":"string","title":"Error Message"},"error_detail":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Error Detail"},"status_code":{"type":"integer","title":"Status Code"},"stack_trace":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stack Trace"},"user_agent":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Agent"},"client_ip":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Ip"},"response_time_ms":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Response Time Ms"},"id":{"type":"integer","title":"Id"},"headers":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Headers"},"is_resolved":{"type":"boolean","title":"Is Resolved","default":false},"resolved_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resolved At"},"resolution_notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resolution Notes"},"created_at":{"type":"string","title":"Created At"}},"type":"object","required":["request_id","endpoint","method","path","error_type","error_message","status_code","id","created_at"],"title":"ErrorLogResponse","description":"Response schema for error log"},"ErrorLogStats":{"properties":{"total_errors":{"type":"integer","title":"Total Errors"},"resolved_errors":{"type":"integer","title":"Resolved Errors"},"unresolved_errors":{"type":"integer","title":"Unresolved Errors"},"resolution_rate":{"type":"number","title":"Resolution Rate"},"errors_by_type":{"additionalProperties":{"type":"integer"},"type":"object","title":"Errors By Type"},"errors_by_status_code":{"additionalProperties":{"type":"integer"},"type":"object","title":"Errors By Status Code"},"errors_by_endpoint":{"additionalProperties":{"type":"integer"},"type":"object","title":"Errors By Endpoint"},"average_response_time_ms":{"type":"number","title":"Average Response Time Ms"},"hourly_trend":{"additionalProperties":{"type":"integer"},"type":"object","title":"Hourly Trend"},"start_date":{"type":"string","title":"Start Date"},"end_date":{"type":"string","title":"End Date"}},"type":"object","required":["total_errors","resolved_errors","unresolved_errors","resolution_rate","errors_by_type","errors_by_status_code","errors_by_endpoint","average_response_time_ms","hourly_trend","start_date","end_date"],"title":"ErrorLogStats","description":"Statistics about error logs"},"ErrorLogUpdate":{"properties":{"is_resolved":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Resolved"},"resolution_notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resolution Notes"}},"type":"object","title":"ErrorLogUpdate","description":"Schema for updating error log"},"ErrorResponse":{"properties":{"error_type":{"$ref":"#/components/schemas/ErrorType"},"message":{"type":"string","title":"Message"},"detail":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Detail"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"}},"type":"object","required":["error_type","message"],"title":"ErrorResponse"},"ErrorType":{"type":"string","enum":["PARSING_ERROR","DATA_NOT_FOUND","INVALID_PERIOD","SEC_API_ERROR","DATABASE_ERROR","VALIDATION_ERROR","AUTHENTICATION_ERROR","RATE_LIMIT_ERROR"],"title":"ErrorType"},"EventAttentionResponse":{"properties":{"ticker":{"type":"string","title":"Ticker"},"event_date":{"type":"string","format":"date","title":"Event Date"},"entity":{"$ref":"#/components/schemas/EntityInfo"},"wiki":{"$ref":"#/components/schemas/WikiFeatures"},"news":{"$ref":"#/components/schemas/NewsFeatures"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"}},"type":"object","required":["ticker","event_date","entity","wiki","news"],"title":"EventAttentionResponse","example":{"entity":{"aliases":["Apple Inc."],"canonical_name":"Apple","gdelt_query":"\"Apple\" OR \"Apple Inc.\"","is_manual_override":false,"resolver_confidence":0.92,"ticker":"AAPL","wiki_title":"Apple Inc."},"event_date":"2024-02-01","metadata":{"resolver_confidence":0.92,"wiki_title":"Apple Inc."},"news":{"article_count_1d":18,"article_count_3d":52,"gdelt_status":"collected","unique_domains_3d":34,"us_article_count_3d":41},"ticker":"AAPL","wiki":{"baseline_10d":12400.0,"spike_10d":3.65,"views":45230,"zscore_20d":4.21}}},"ExhibitContentResponse":{"properties":{"accession_number":{"type":"string","title":"Accession Number"},"exhibit_type":{"type":"string","title":"Exhibit Type"},"content":{"type":"string","title":"Content"},"content_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content Type"},"filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filename"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url"}},"type":"object","required":["accession_number","exhibit_type","content"],"title":"ExhibitContentResponse","example":{"accession_number":"0000320193-24-000006","content":"Apple Reports First Quarter Results...\nCUPERTINO, California — February 1, 2024 — Apple Inc. today announced financial results for its fiscal 2024 first quarter...","content_type":"text/html","exhibit_type":"EX-99.1","filename":"ex991pressrelease.htm","url":"https://www.sec.gov/Archives/edgar/data/320193/000032019324000006/ex991pressrelease.htm"}},"FilingDocumentInfo":{"properties":{"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Type"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filename"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url"},"size":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Size"}},"type":"object","title":"FilingDocumentInfo","example":{"description":"Press Release","filename":"ex991pressrelease.htm","size":"42 KB","type":"EX-99.1","url":"https://www.sec.gov/Archives/edgar/data/320193/000032019324000006/ex991pressrelease.htm"}},"FilingDocumentListResponse":{"properties":{"accession_number":{"type":"string","title":"Accession Number"},"documents":{"items":{"$ref":"#/components/schemas/FilingDocumentInfo"},"type":"array","title":"Documents"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"}},"type":"object","required":["accession_number","documents"],"title":"FilingDocumentListResponse","example":{"accession_number":"0000320193-24-000006","documents":[{"description":"8-K","filename":"a8-k20240201.htm","size":"8 KB","type":"8-K","url":"https://www.sec.gov/Archives/edgar/data/320193/000032019324000006/a8-k20240201.htm"},{"description":"Press Release","filename":"ex991pressrelease.htm","size":"42 KB","type":"EX-99.1","url":"https://www.sec.gov/Archives/edgar/data/320193/000032019324000006/ex991pressrelease.htm"}],"metadata":{"total_documents":4}}},"FilingEventResponse":{"properties":{"id":{"type":"string","title":"Id"},"ticker":{"type":"string","title":"Ticker"},"accession_number":{"type":"string","title":"Accession Number"},"form_type":{"type":"string","title":"Form Type"},"filing_date":{"type":"string","title":"Filing Date"},"item_number":{"type":"string","title":"Item Number"},"event_type":{"type":"string","title":"Event Type"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summary"},"content_source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content Source"}},"type":"object","required":["id","ticker","accession_number","form_type","filing_date","item_number","event_type"],"title":"FilingEventResponse","example":{"accession_number":"0001193125-26-144028","content_source":"primary_doc","event_type":"other_material_event","filing_date":"2026-04-06","form_type":"8-K","id":"550e8400-e29b-41d4-a716-446655440000","item_number":"8.01","summary":"Broadcom Inc. and Google LLC have entered into a Long Term Agreement...","ticker":"AVGO","title":"Other Events"}},"FilingEventsSearchResponse":{"properties":{"ticker":{"type":"string","title":"Ticker"},"events":{"items":{"$ref":"#/components/schemas/FilingEventResponse"},"type":"array","title":"Events"},"total_count":{"type":"integer","title":"Total Count"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"}},"type":"object","required":["ticker","events","total_count"],"title":"FilingEventsSearchResponse"},"FilingSearchResponse":{"properties":{"ticker":{"type":"string","title":"Ticker"},"filings":{"items":{"$ref":"#/components/schemas/FilingSummary"},"type":"array","title":"Filings"},"total_count":{"type":"integer","title":"Total Count"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"}},"type":"object","required":["ticker","filings","total_count"],"title":"FilingSearchResponse","example":{"filings":[{"accepted_at":"2024-02-01T21:00:05+00:00","accession_number":"0000320193-24-000006","documents_count":4,"filing_date":"2024-02-01","filing_description":"Results of Operations and Financial Condition","form_type":"8-K","primary_document":"a8-k20240201.htm"}],"metadata":{"form_types":["8-K"],"limit":20,"offset":0},"ticker":"AAPL","total_count":42}},"FilingSummary":{"properties":{"accession_number":{"type":"string","title":"Accession Number"},"form_type":{"type":"string","title":"Form Type"},"filing_date":{"type":"string","title":"Filing Date"},"accepted_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Accepted At"},"primary_document":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Primary Document"},"filing_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filing Description"},"documents_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Documents Count"},"parsed_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Parsed Status"},"items":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Items"}},"type":"object","required":["accession_number","form_type","filing_date"],"title":"FilingSummary","example":{"accepted_at":"2024-02-01T21:00:05+00:00","accession_number":"0000320193-24-000006","documents_count":4,"filing_date":"2024-02-01","filing_description":"Results of Operations and Financial Condition","form_type":"8-K","items":["2.02","9.01"],"parsed_status":"succeeded","primary_document":"a8-k20240201.htm"}},"FinancialDataPoint":{"properties":{"period_date":{"type":"string","format":"date-time","title":"Period Date"},"period_type":{"type":"string","title":"Period Type"},"filing_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filing Type"},"revenue":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Revenue"},"gross_profit":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Gross Profit"},"operating_income":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Operating Income"},"net_income":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Net Income"},"eps":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Eps"},"total_assets":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Total Assets"},"total_equity":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Total Equity"},"total_debt":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Total Debt"},"cash":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Cash"},"shares_outstanding":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Shares Outstanding"},"operating_cash_flow":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Operating Cash Flow"},"free_cash_flow":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Free Cash Flow"},"capex":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Capex"},"pe_ratio":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Pe Ratio"},"pb_ratio":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Pb Ratio"},"ps_ratio":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Ps Ratio"},"roe":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Roe"},"roa":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Roa"},"gross_margin":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Gross Margin"},"operating_margin":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Operating Margin"},"net_margin":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Net Margin"},"debt_to_equity":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Debt To Equity"},"debt_to_assets":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Debt To Assets"},"ocf_margin":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Ocf Margin"},"fcf_margin":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Fcf Margin"},"market_cap":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Market Cap"},"data_source":{"type":"string","title":"Data Source"},"is_estimated":{"type":"boolean","title":"Is Estimated"}},"type":"object","required":["period_date","period_type","data_source","is_estimated"],"title":"FinancialDataPoint"},"FinancialDataRequest":{"properties":{"ticker":{"type":"string","maxLength":10,"minLength":1,"title":"Ticker","description":"Stock ticker symbol"},"start_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Start Date","description":"Start date for data retrieval. Cannot be used with quarters or period."},"end_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"End Date","description":"End date for data retrieval. Cannot be used with quarters or period."},"quarters":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":40,"minItems":1},{"type":"null"}],"title":"Quarters","description":"List of quarters in format 'YYYYQN' (e.g., ['2020Q1', '2020Q2']). Cannot be used with start_date/end_date or period. If provided, dates are ignored."},"period":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Period","description":"Period string like '1d', '7d', '1m', '3m', '1y', '2y'. Cannot be used with start_date/end_date or quarters."},"period_type":{"$ref":"#/components/schemas/PeriodType","description":"Type of financial periods to retrieve","default":"all"},"include_metrics":{"type":"boolean","title":"Include Metrics","description":"Include calculated metrics in response","default":true},"force_refresh":{"type":"boolean","title":"Force Refresh","description":"Force refresh data from SEC","default":false}},"type":"object","required":["ticker"],"title":"FinancialDataRequest","description":"Request for financial data with flexible time period specification.\n\n**Three ways to specify time period (choose one):**\n1. **Date Range**: Use start_date and end_date \n2. **Quarters**: Use quarters list (e.g., ['2024Q1', '2024Q2'])\n3. **Period**: Use period string (e.g., '1d', '3m', '2y')\n\n**Important**: Cannot mix approaches in the same request."},"FinancialDataResponse":{"properties":{"company":{"$ref":"#/components/schemas/CompanyInfo"},"financial_data":{"items":{"$ref":"#/components/schemas/FinancialDataPoint"},"type":"array","title":"Financial Data"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"}},"type":"object","required":["company","financial_data"],"title":"FinancialDataResponse"},"Form4AggregateResponse":{"properties":{"symbol":{"type":"string","title":"Symbol"},"as_of":{"type":"string","format":"date","title":"As Of"},"window_days":{"type":"integer","title":"Window Days"},"buy_count":{"type":"integer","title":"Buy Count"},"buy_dollar_total":{"type":"number","title":"Buy Dollar Total"},"cluster_size":{"type":"integer","title":"Cluster Size"},"csuite_count":{"type":"integer","title":"Csuite Count"},"avg_pct_of_holding":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Pct Of Holding"},"recency_days":{"type":"integer","title":"Recency Days"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"}},"type":"object","required":["symbol","as_of","window_days","buy_count","buy_dollar_total","cluster_size","csuite_count","recency_days"],"title":"Form4AggregateResponse","description":"Aggregate Form 4 insider activity over a rolling window.\n\nAll fields are computed over open-market purchases only (transaction_code='P',\nshares > 0, non-derivative). Awards/grants (A-code) are excluded."},"Form4ByDateResponse":{"properties":{"filing_date":{"type":"string","format":"date","title":"Filing Date"},"buy_only":{"type":"boolean","title":"Buy Only"},"transactions":{"items":{"$ref":"#/components/schemas/Form4Entry"},"type":"array","title":"Transactions"},"total_count":{"type":"integer","title":"Total Count"}},"type":"object","required":["filing_date","buy_only","transactions","total_count"],"title":"Form4ByDateResponse"},"Form4Entry":{"properties":{"symbol":{"type":"string","title":"Symbol"},"filing_date":{"type":"string","format":"date","title":"Filing Date"},"transaction_date":{"type":"string","format":"date","title":"Transaction Date"},"owner_cik":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owner Cik"},"owner_name":{"type":"string","title":"Owner Name"},"owner_relationship":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owner Relationship"},"is_officer":{"type":"boolean","title":"Is Officer","default":false},"is_director":{"type":"boolean","title":"Is Director","default":false},"is_ten_percent_owner":{"type":"boolean","title":"Is Ten Percent Owner","default":false},"is_ceo":{"type":"boolean","title":"Is Ceo","default":false},"is_cfo":{"type":"boolean","title":"Is Cfo","default":false},"is_c_suite":{"type":"boolean","title":"Is C Suite","default":false},"transaction_code":{"type":"string","title":"Transaction Code"},"transaction_type":{"type":"string","title":"Transaction Type"},"shares":{"type":"number","title":"Shares"},"price":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Price"},"total_value":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Total Value"},"shares_owned_following":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Shares Owned Following"},"purchase_pct_of_holding":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Purchase Pct Of Holding"},"accession_number":{"type":"string","title":"Accession Number"}},"type":"object","required":["symbol","filing_date","transaction_date","owner_name","transaction_code","transaction_type","shares","accession_number"],"title":"Form4Entry"},"Form4Response":{"properties":{"symbol":{"type":"string","title":"Symbol"},"as_of":{"type":"string","format":"date","title":"As Of"},"window":{"additionalProperties":true,"type":"object","title":"Window"},"transactions":{"items":{"$ref":"#/components/schemas/Form4Entry"},"type":"array","title":"Transactions"},"total_count":{"type":"integer","title":"Total Count"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"}},"type":"object","required":["symbol","as_of","transactions","total_count"],"title":"Form4Response"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HealthCheckResponse":{"properties":{"status":{"type":"string","title":"Status"},"version":{"type":"string","title":"Version"},"database":{"type":"string","title":"Database"},"cache":{"type":"string","title":"Cache"},"sec_data_available":{"type":"boolean","title":"Sec Data Available"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"}},"type":"object","required":["status","version","database","cache","sec_data_available","timestamp"],"title":"HealthCheckResponse"},"IngestResponse":{"properties":{"date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date"},"date_range":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Date Range"},"records_ingested":{"type":"integer","title":"Records Ingested"},"status":{"type":"string","title":"Status"}},"type":"object","required":["records_ingested","status"],"title":"IngestResponse"},"InsiderSummaryPeriod":{"properties":{"period_label":{"type":"string","title":"Period Label"},"buy_count":{"type":"integer","title":"Buy Count","default":0},"sell_count":{"type":"integer","title":"Sell Count","default":0},"buy_shares":{"type":"number","title":"Buy Shares","default":0.0},"sell_shares":{"type":"number","title":"Sell Shares","default":0.0},"buy_value":{"type":"number","title":"Buy Value","default":0.0},"sell_value":{"type":"number","title":"Sell Value","default":0.0},"net_shares":{"type":"number","title":"Net Shares","default":0.0},"net_value":{"type":"number","title":"Net Value","default":0.0},"unique_buyers":{"type":"integer","title":"Unique Buyers","default":0},"unique_sellers":{"type":"integer","title":"Unique Sellers","default":0}},"type":"object","required":["period_label"],"title":"InsiderSummaryPeriod"},"InsiderSummaryResponse":{"properties":{"symbol":{"type":"string","title":"Symbol"},"periods":{"items":{"$ref":"#/components/schemas/InsiderSummaryPeriod"},"type":"array","title":"Periods"},"notable_transactions":{"items":{"$ref":"#/components/schemas/InsiderTransactionEntry"},"type":"array","title":"Notable Transactions"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"}},"type":"object","required":["symbol","periods","notable_transactions"],"title":"InsiderSummaryResponse"},"InsiderTransactionEntry":{"properties":{"filing_date":{"type":"string","format":"date","title":"Filing Date"},"transaction_date":{"type":"string","format":"date","title":"Transaction Date"},"owner_name":{"type":"string","title":"Owner Name"},"owner_cik":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owner Cik"},"is_officer":{"type":"boolean","title":"Is Officer","default":false},"is_director":{"type":"boolean","title":"Is Director","default":false},"is_ten_percent_owner":{"type":"boolean","title":"Is Ten Percent Owner","default":false},"officer_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Officer Title"},"security_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Security Title"},"transaction_code":{"type":"string","title":"Transaction Code"},"transaction_type":{"type":"string","title":"Transaction Type"},"shares":{"type":"number","title":"Shares"},"price_per_share":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Price Per Share"},"total_value":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Total Value"},"shares_owned_after":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Shares Owned After"},"is_derivative":{"type":"boolean","title":"Is Derivative","default":false}},"type":"object","required":["filing_date","transaction_date","owner_name","transaction_code","transaction_type","shares"],"title":"InsiderTransactionEntry"},"InsiderTransactionResponse":{"properties":{"symbol":{"type":"string","title":"Symbol"},"transactions":{"items":{"$ref":"#/components/schemas/InsiderTransactionEntry"},"type":"array","title":"Transactions"},"total_count":{"type":"integer","title":"Total Count"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"}},"type":"object","required":["symbol","transactions","total_count"],"title":"InsiderTransactionResponse"},"IntradayCandle":{"properties":{"timestamp":{"type":"string","format":"date-time","title":"Timestamp"},"open":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Open"},"high":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"High"},"low":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Low"},"close":{"type":"number","title":"Close"},"volume":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Volume"}},"type":"object","required":["timestamp","close"],"title":"IntradayCandle"},"IntradayResponse":{"properties":{"ticker":{"type":"string","title":"Ticker"},"interval":{"type":"string","title":"Interval"},"period":{"type":"string","title":"Period"},"candles":{"items":{"$ref":"#/components/schemas/IntradayCandle"},"type":"array","title":"Candles"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"}},"type":"object","required":["ticker","interval","period","candles"],"title":"IntradayResponse"},"JobLogEntry":{"properties":{"id":{"type":"string","title":"Id"},"job_type":{"type":"string","title":"Job Type"},"status":{"type":"string","title":"Status"},"started_at":{"type":"string","format":"date-time","title":"Started At"},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Completed At"},"records_processed":{"type":"integer","title":"Records Processed","default":0},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"}},"type":"object","required":["id","job_type","status","started_at"],"title":"JobLogEntry"},"JobLogResponse":{"properties":{"logs":{"items":{"$ref":"#/components/schemas/JobLogEntry"},"type":"array","title":"Logs"},"total_count":{"type":"integer","title":"Total Count"}},"type":"object","required":["logs","total_count"],"title":"JobLogResponse"},"MigrationRequest":{"properties":{"source_url":{"type":"string","title":"Source Url","description":"Source API URL to migrate from"},"api_key":{"type":"string","title":"Api Key","description":"API key for authentication"},"tickers":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Tickers","description":"Specific tickers to migrate, or all if not specified"},"start_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Start Date"},"end_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"End Date"}},"type":"object","required":["source_url","api_key"],"title":"MigrationRequest"},"MigrationResponse":{"properties":{"status":{"type":"string","title":"Status"},"total_records":{"type":"integer","title":"Total Records"},"migrated_records":{"type":"integer","title":"Migrated Records"},"failed_records":{"type":"integer","title":"Failed Records"},"errors":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Errors"},"duration_seconds":{"type":"number","title":"Duration Seconds"}},"type":"object","required":["status","total_records","migrated_records","failed_records","duration_seconds"],"title":"MigrationResponse"},"NewsFeatures":{"properties":{"article_count_1d":{"type":"integer","title":"Article Count 1D","description":"GDELT articles published on the event date","default":0},"article_count_3d":{"type":"integer","title":"Article Count 3D","description":"GDELT articles in the event_date ± 1 day window","default":0},"unique_domains_3d":{"type":"integer","title":"Unique Domains 3D","description":"Distinct publisher domains in the 3-day window","default":0},"us_article_count_3d":{"type":"integer","title":"Us Article Count 3D","description":"US-sourced articles in the 3-day window","default":0},"gdelt_status":{"type":"string","title":"Gdelt Status","description":"GDELT data availability for this event date. 'collected' — scheduler has run; counts are accurate (0 means genuinely no articles). 'not_collected' — scheduler has not run yet; POST /admin/collect/gdelt/{ticker}?event_date=... to populate. 'not_available' — event date is before GDELT V2 coverage start (2017-01-01).","default":"not_collected"}},"type":"object","title":"NewsFeatures","example":{"article_count_1d":18,"article_count_3d":52,"gdelt_status":"collected","unique_domains_3d":34,"us_article_count_3d":41}},"NewsOnlyResponse":{"properties":{"ticker":{"type":"string","title":"Ticker"},"retrieved_at":{"type":"string","title":"Retrieved At"},"news":{"additionalProperties":true,"type":"object","title":"News"},"summary":{"additionalProperties":true,"type":"object","title":"Summary"}},"type":"object","required":["ticker","retrieved_at","news","summary"],"title":"NewsOnlyResponse"},"NewsSocialResponse":{"properties":{"ticker":{"type":"string","title":"Ticker"},"retrieved_at":{"type":"string","title":"Retrieved At"},"news":{"additionalProperties":true,"type":"object","title":"News","description":"News articles and sources breakdown"},"social_media":{"additionalProperties":true,"type":"object","title":"Social Media","description":"Social media posts and platforms breakdown"},"summary":{"$ref":"#/components/schemas/NewsSocialSummarySchema"}},"type":"object","required":["ticker","retrieved_at","news","social_media","summary"],"title":"NewsSocialResponse","description":"Complete response for ticker news and social data"},"NewsSocialSummarySchema":{"properties":{"total_items":{"type":"integer","title":"Total Items"},"time_range_days":{"type":"integer","title":"Time Range Days"},"oldest_item":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Oldest Item"},"newest_item":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Newest Item"}},"type":"object","required":["total_items","time_range_days"],"title":"NewsSocialSummarySchema","description":"Summary of news and social data"},"PeriodType":{"type":"string","enum":["quarterly","annual","all"],"title":"PeriodType"},"PriceDataPoint":{"properties":{"date":{"type":"string","format":"date","title":"Date"},"open":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Open"},"high":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"High"},"low":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Low"},"close":{"type":"number","title":"Close"},"volume":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Volume"},"adjusted_close":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Adjusted Close"},"data_source":{"type":"string","title":"Data Source"}},"type":"object","required":["date","close","data_source"],"title":"PriceDataPoint"},"PriceDataRequest":{"properties":{"ticker":{"type":"string","maxLength":10,"minLength":1,"title":"Ticker","description":"Stock ticker symbol"},"start_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Start Date","description":"Start date for data retrieval. Cannot be used with quarters or period."},"end_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"End Date","description":"End date for data retrieval. Cannot be used with quarters or period."},"quarters":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":40,"minItems":1},{"type":"null"}],"title":"Quarters","description":"List of quarters in format 'YYYYQN' (e.g., ['2020Q1', '2020Q2']). Cannot be used with start_date/end_date or period. If provided, dates are ignored."},"period":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Period","description":"Period string like '1d', '7d', '1m', '3m', '1y', '2y'. Cannot be used with start_date/end_date or quarters."},"interval":{"type":"string","title":"Interval","description":"Data interval: 1d, 1w, 1m, 5d, 1h, etc.","default":"1d"},"force_refresh":{"type":"boolean","title":"Force Refresh","description":"Force refresh data from Yahoo Finance","default":false}},"type":"object","required":["ticker"],"title":"PriceDataRequest","description":"Request for price data with flexible time period specification.\n\n**Three ways to specify time period (choose one):**\n1. **Date Range**: Use start_date and end_date\n2. **Quarters**: Use quarters list (e.g., ['2024Q1', '2024Q2'])\n3. **Period**: Use period string (e.g., '1d', '3m', '2y')\n\n**Important**: Cannot mix approaches in the same request."},"PriceDataResponse":{"properties":{"ticker":{"type":"string","title":"Ticker"},"interval":{"type":"string","title":"Interval"},"data":{"items":{"$ref":"#/components/schemas/PriceDataPoint"},"type":"array","title":"Data"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"}},"type":"object","required":["ticker","interval","data"],"title":"PriceDataResponse"},"QuoteResponse":{"properties":{"ticker":{"type":"string","title":"Ticker"},"price":{"type":"number","title":"Price"},"regular_price":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Regular Price"},"pre_market_price":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Pre Market Price"},"post_market_price":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Post Market Price"},"currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Currency"},"exchange":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Exchange"},"market_state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Market State"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"},"source":{"type":"string","title":"Source","default":"YAHOO_FINANCE"},"delayed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Delayed","default":true}},"type":"object","required":["ticker","price","timestamp"],"title":"QuoteResponse"},"RefreshMapsOut":{"properties":{"cusip_rows":{"type":"integer","title":"Cusip Rows"},"etf_rows":{"type":"integer","title":"Etf Rows"}},"type":"object","required":["cusip_rows","etf_rows"],"title":"RefreshMapsOut"},"RegistryResponse":{"properties":{"tickers":{"items":{"$ref":"#/components/schemas/TickerRegistryItem"},"type":"array","title":"Tickers"},"total_count":{"type":"integer","title":"Total Count"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"},"total_pages":{"type":"integer","title":"Total Pages"}},"type":"object","required":["tickers","total_count","page","page_size","total_pages"],"title":"RegistryResponse"},"RequestLogListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/RequestLogResponse"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"},"total_pages":{"type":"integer","title":"Total Pages"}},"type":"object","required":["items","total","page","page_size","total_pages"],"title":"RequestLogListResponse","description":"Response schema for paginated request logs"},"RequestLogResponse":{"properties":{"id":{"type":"integer","title":"Id"},"request_id":{"type":"string","title":"Request Id"},"endpoint":{"type":"string","title":"Endpoint"},"method":{"type":"string","title":"Method"},"path":{"type":"string","title":"Path"},"query_params":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Query Params"},"request_body":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Request Body"},"headers":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Headers"},"status_code":{"type":"integer","title":"Status Code"},"response_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Response Size"},"user_agent":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Agent"},"client_ip":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Ip"},"response_time_ms":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Response Time Ms"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"}},"type":"object","required":["id","request_id","endpoint","method","path","status_code"],"title":"RequestLogResponse","description":"Response schema for individual request log"},"RequestLogStats":{"properties":{"total_requests":{"type":"integer","title":"Total Requests"},"success_requests":{"type":"integer","title":"Success Requests"},"client_error_requests":{"type":"integer","title":"Client Error Requests"},"server_error_requests":{"type":"integer","title":"Server Error Requests"},"success_rate":{"type":"number","title":"Success Rate"},"requests_by_method":{"additionalProperties":{"type":"integer"},"type":"object","title":"Requests By Method"},"requests_by_status_code":{"additionalProperties":{"type":"integer"},"type":"object","title":"Requests By Status Code"},"requests_by_endpoint":{"additionalProperties":{"type":"integer"},"type":"object","title":"Requests By Endpoint"},"average_response_time_ms":{"type":"number","title":"Average Response Time Ms"},"hourly_trend":{"additionalProperties":{"type":"integer"},"type":"object","title":"Hourly Trend"},"start_date":{"type":"string","title":"Start Date"},"end_date":{"type":"string","title":"End Date"}},"type":"object","required":["total_requests","success_requests","client_error_requests","server_error_requests","success_rate","requests_by_method","requests_by_status_code","requests_by_endpoint","average_response_time_ms","hourly_trend","start_date","end_date"],"title":"RequestLogStats","description":"Response schema for request log statistics"},"SessionAggregateBatchRequest":{"properties":{"session_date":{"type":"string","format":"date","title":"Session Date"},"window":{"type":"string","title":"Window"},"symbols":{"items":{"type":"string"},"type":"array","title":"Symbols"},"sources":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Sources"}},"type":"object","required":["session_date","window","symbols"],"title":"SessionAggregateBatchRequest"},"SessionAggregateBatchResponse":{"properties":{"items":{"additionalProperties":{"$ref":"#/components/schemas/SessionAggregateItem"},"type":"object","title":"Items"}},"type":"object","required":["items"],"title":"SessionAggregateBatchResponse"},"SessionAggregateItem":{"properties":{"ticker":{"type":"string","title":"Ticker"},"session_date":{"type":"string","title":"Session Date"},"window":{"type":"string","title":"Window"},"headline_count":{"type":"integer","title":"Headline Count","default":0},"primary_count":{"type":"integer","title":"Primary Count","default":0},"first_headline_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Headline At"},"last_headline_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Headline At"},"category_counts":{"additionalProperties":{"type":"integer"},"type":"object","title":"Category Counts"},"sentiment_mean":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Sentiment Mean"},"sentiment_recency_weighted":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Sentiment Recency Weighted"},"social":{"$ref":"#/components/schemas/SocialStatsItem"},"sources_present":{"items":{"type":"string"},"type":"array","title":"Sources Present"}},"type":"object","required":["ticker","session_date","window"],"title":"SessionAggregateItem"},"ShortRatioHistoryResponse":{"properties":{"symbol":{"type":"string","title":"Symbol"},"history":{"items":{"$ref":"#/components/schemas/ShortRatioPoint"},"type":"array","title":"History"},"avg_short_ratio":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Short Ratio"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"}},"type":"object","required":["symbol","history"],"title":"ShortRatioHistoryResponse"},"ShortRatioPoint":{"properties":{"date":{"type":"string","format":"date","title":"Date"},"short_volume":{"type":"number","title":"Short Volume"},"short_exempt_volume":{"type":"number","title":"Short Exempt Volume"},"total_volume":{"type":"number","title":"Total Volume"},"short_ratio":{"type":"number","title":"Short Ratio"}},"type":"object","required":["date","short_volume","short_exempt_volume","total_volume","short_ratio"],"title":"ShortRatioPoint"},"ShortVolumeEntry":{"properties":{"date":{"type":"string","format":"date","title":"Date"},"symbol":{"type":"string","title":"Symbol"},"short_volume":{"type":"number","title":"Short Volume"},"short_exempt_volume":{"type":"number","title":"Short Exempt Volume","default":0.0},"total_volume":{"type":"number","title":"Total Volume"},"market":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Market"},"short_ratio":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Short Ratio"}},"type":"object","required":["date","symbol","short_volume","total_volume"],"title":"ShortVolumeEntry"},"ShortVolumeResponse":{"properties":{"symbol":{"type":"string","title":"Symbol"},"entries":{"items":{"$ref":"#/components/schemas/ShortVolumeEntry"},"type":"array","title":"Entries"},"total_count":{"type":"integer","title":"Total Count"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"}},"type":"object","required":["symbol","entries","total_count"],"title":"ShortVolumeResponse"},"SnapshotBuildRequest":{"properties":{"tickers":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Tickers","description":"Specific tickers to build. Omit for all registry tickers."},"start_date":{"type":"string","title":"Start Date","description":"Start date YYYY-MM-DD (e.g. 2015-01-01)"},"end_date":{"type":"string","title":"End Date","description":"End date YYYY-MM-DD (e.g. 2025-12-01)"},"force_rebuild":{"type":"boolean","title":"Force Rebuild","description":"Delete existing snapshots for these tickers before rebuilding","default":false}},"type":"object","required":["start_date","end_date"],"title":"SnapshotBuildRequest"},"SocialOnlyResponse":{"properties":{"ticker":{"type":"string","title":"Ticker"},"retrieved_at":{"type":"string","title":"Retrieved At"},"social_media":{"additionalProperties":true,"type":"object","title":"Social Media"},"summary":{"additionalProperties":true,"type":"object","title":"Summary"}},"type":"object","required":["ticker","retrieved_at","social_media","summary"],"title":"SocialOnlyResponse"},"SocialStatsItem":{"properties":{"message_count":{"type":"integer","title":"Message Count","default":0},"bull_count":{"type":"integer","title":"Bull Count","default":0},"bear_count":{"type":"integer","title":"Bear Count","default":0},"bull_bear_ratio":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Bull Bear Ratio"}},"type":"object","title":"SocialStatsItem"},"TickerRegistryItem":{"properties":{"ticker":{"type":"string","title":"Ticker"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"sector":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sector"},"industry":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Industry"},"exchange":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Exchange"},"cik":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cik"},"is_active":{"type":"boolean","title":"Is Active","default":true}},"type":"object","required":["ticker"],"title":"TickerRegistryItem"},"TodayOHLCResponse":{"properties":{"ticker":{"type":"string","title":"Ticker"},"date":{"type":"string","format":"date","title":"Date"},"open":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Open"},"high":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"High"},"low":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Low"},"close":{"type":"number","title":"Close"},"volume":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Volume"},"source":{"type":"string","title":"Source","default":"YAHOO_FINANCE"},"method":{"type":"string","title":"Method","default":"daily"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"}},"type":"object","required":["ticker","date","close"],"title":"TodayOHLCResponse"},"UniverseScreenResponse":{"properties":{"stocks":{"items":{"$ref":"#/components/schemas/UniverseSnapshotItem"},"type":"array","title":"Stocks"},"total_count":{"type":"integer","title":"Total Count"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"},"total_pages":{"type":"integer","title":"Total Pages"},"snapshot_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Snapshot Date"},"filters_applied":{"additionalProperties":true,"type":"object","title":"Filters Applied","default":{}},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata","default":{}}},"type":"object","required":["stocks","total_count","page","page_size","total_pages"],"title":"UniverseScreenResponse"},"UniverseSnapshotItem":{"properties":{"ticker":{"type":"string","title":"Ticker"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"market_cap":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Market Cap"},"close_price":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Close Price"},"shares_outstanding":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Shares Outstanding"},"sector":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sector"},"industry":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Industry"},"exchange":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Exchange"},"snapshot_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Snapshot Date"}},"type":"object","required":["ticker"],"title":"UniverseSnapshotItem"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"WikiFeatures":{"properties":{"views":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Views","description":"Wikipedia pageviews on the event date"},"baseline_10d":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Baseline 10D","description":"Median pageviews over the prior 10 days"},"spike_10d":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Spike 10D","description":"views / baseline_10d; >1 means above-average attention"},"zscore_20d":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Zscore 20D","description":"Z-score vs prior 20-day mean/stdev; null if stdev=0"}},"type":"object","title":"WikiFeatures","example":{"baseline_10d":12400.0,"spike_10d":3.65,"views":45230,"zscore_20d":4.21}},"app__api__v1__endpoints__news_v2__HeadlineItem":{"properties":{"source":{"type":"string","title":"Source"},"source_id":{"type":"string","title":"Source Id"},"ticker":{"type":"string","title":"Ticker"},"tickers_all":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Tickers All"},"published_at":{"type":"string","title":"Published At"},"headline":{"type":"string","title":"Headline"},"summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summary"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url"},"language":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Language"},"vendor_categories":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Vendor Categories"},"categories":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Categories"},"raw_sentiment":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Raw Sentiment"},"is_primary":{"type":"boolean","title":"Is Primary"},"ingested_at":{"type":"string","title":"Ingested At"}},"type":"object","required":["source","source_id","ticker","published_at","headline","is_primary","ingested_at"],"title":"HeadlineItem"},"app__api__v1__endpoints__news_v2__HeadlinesResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/app__api__v1__endpoints__news_v2__HeadlineItem"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"}},"type":"object","required":["items"],"title":"HeadlinesResponse"},"app__api__v1__endpoints__overlay__HeadlineItem":{"properties":{"title":{"type":"string","title":"Title"},"publisher":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Publisher"},"published_at":{"type":"string","format":"date-time","title":"Published At"},"article_guid":{"type":"string","title":"Article Guid"}},"type":"object","required":["title","published_at","article_guid"],"title":"HeadlineItem"},"app__api__v1__endpoints__overlay__HeadlinesResponse":{"properties":{"symbol":{"type":"string","title":"Symbol"},"headlines":{"items":{"$ref":"#/components/schemas/app__api__v1__endpoints__overlay__HeadlineItem"},"type":"array","title":"Headlines"},"headline_count_6h":{"type":"integer","title":"Headline Count 6H"},"headline_count_24h":{"type":"integer","title":"Headline Count 24H"},"publisher_breadth_24h":{"type":"integer","title":"Publisher Breadth 24H"}},"type":"object","required":["symbol","headlines","headline_count_6h","headline_count_24h","publisher_breadth_24h"],"title":"HeadlinesResponse"}}},"tags":[{"name":"health","description":"Health check endpoints"},{"name":"financial","description":"Financial data retrieval endpoints"},{"name":"price","description":"Price data endpoints (OHLCV)"},{"name":"news","description":"News and social media endpoints"},{"name":"metadata","description":"Data catalog and metadata endpoints"},{"name":"filings","description":"SEC filings search, document listing, and exhibit extraction (8-K, 6-K, 20-F, 40-F)"},{"name":"etf","description":"ETF holdings endpoints"},{"name":"alpaca","description":"Alpaca Market Data endpoints (OHLCV bars, connection status)"},{"name":"finra","description":"FINRA RegSHO short sale volume data (ingest, query, ratio history)"},{"name":"admin","description":"Administrative endpoints (migration, etc.)"},{"name":"overlay","description":"Overlay headlines — Yahoo RSS headline collector"},{"name":"overlay-admin","description":"Overlay job log"},{"name":"screener","description":"Stock screener — condition-based filtering by market cap, volume, price, P/E, sector, exchange"},{"name":"stocks","description":"Stock market data — most active, 52-week gainers, trending, and index constituents (S&P 500 / Nasdaq 100)"},{"name":"attention","description":"Attention signals — Wikipedia pageview spikes and GDELT news article counts for event-centric backtesting"},{"name":"attention-admin","description":"Attention administrative endpoints — entity resolution, Wikipedia and GDELT data collection"},{"name":"database","description":"Database inspection — record counts, date ranges, raw data browsing, and ETF snapshot history"},{"name":"fred","description":"FRED (Federal Reserve Economic Data) — macroeconomic series via FRED API proxy"},{"name":"ownership","description":"SEC 13D/13G activist ownership events — activist filings, active positions (PIT-safe)"},{"name":"error-logs","description":"Error log management — browse and clear server-side error records"},{"name":"request-logs","description":"Request log management — browse API request history and latency records"}]} \ No newline at end of file +{ + "openapi": "3.1.0", + "info": { + "title": "Stock Oracle", + "version": "1.0.0" + }, + "paths": { + "/api/v1/health": { + "get": { + "tags": [ + "health" + ], + "summary": "Health check", + "description": "Check the health status of the API and its dependencies", + "operationId": "health_check_api_v1_health_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HealthCheckResponse" + } + } + } + } + } + } + }, + "/api/v1/financial/data": { + "post": { + "tags": [ + "financial" + ], + "summary": "Get SEC EDGAR financial data for a ticker", + "description": "Retrieve comprehensive financial data directly from SEC EDGAR filings for a specific ticker and time period.\n \n **🔥 Three Ways to Specify Time Period (choose one):**\n \n 1. **Period String** (NEW! Most convenient):\n - `period`: \"1d\", \"7d\", \"30d\", \"1m\", \"3m\", \"6m\", \"1y\", \"2y\", \"5y\", \"max\"\n - Examples: `{\"ticker\": \"AAPL\", \"period\": \"1y\"}` - Last 1 year of data\n - Example: `{\"ticker\": \"TSLA\", \"period\": \"max\"}` - All available data from listing date to SEC limits\n \n 2. **Date Range** (Traditional):\n - `start_date` + `end_date`: Specific date range\n - Example: `{\"ticker\": \"AAPL\", \"start_date\": \"2024-01-01\", \"end_date\": \"2024-12-31\"}`\n \n 3. **Quarters** (Quarter-based):\n - `quarters`: List of quarters like [\"2024Q1\", \"2024Q2\"]\n - Example: `{\"ticker\": \"AAPL\", \"quarters\": [\"2024Q1\", \"2024Q2\", \"2024Q3\"]}`\n \n **Data Sources:**\n - **Financial Data**: Direct SEC EDGAR API calls (revenue, income, assets, cash flow)\n - **Price Data**: Available via separate price data endpoints using yfinance-plus\n \n **This endpoint returns:**\n - Company information (name, CIK, sector, industry)\n - Financial statements data from SEC filings (income statement, balance sheet, cash flow)\n - Calculated financial metrics (ratios, margins, growth rates)\n - Period types: quarterly (10-Q) and annual (10-K) filings\n \n **Performance Features:**\n - Database caching to avoid repeated SEC API calls\n - Historical data available from 1994-present\n - 15+ years of data typically available for most companies\n - Use `force_refresh=true` to fetch fresh data from SEC EDGAR\n \n **Data Quality:**\n - All financial data sourced directly from official SEC filings\n - No estimated or synthetic data - only actual reported figures\n - Automatic validation and error handling for missing periods\n \n **Example Requests:**\n ```json\n // Using period (simplest)\n {\n \"ticker\": \"AAPL\",\n \"period\": \"1y\",\n \"include_metrics\": true\n }\n \n // Using date range\n {\n \"ticker\": \"MSFT\",\n \"start_date\": \"2024-01-01\",\n \"end_date\": \"2024-12-31\",\n \"period_type\": \"quarterly\"\n }\n \n // Using quarters\n {\n \"ticker\": \"GOOGL\",\n \"quarters\": [\"2024Q1\", \"2024Q2\"],\n \"include_metrics\": true\n }\n ```", + "operationId": "get_financial_data_api_v1_financial_data_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FinancialDataRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FinancialDataResponse" + } + } + } + }, + "400": { + "description": "Invalid request parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Data not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/financial/data/{ticker}": { + "get": { + "tags": [ + "financial" + ], + "summary": "Get financial data by ticker (simplified)", + "description": "Simplified GET endpoint to retrieve financial data with query parameters.\n \n **Time Period Options:**\n - Use `period` for convenience: \"1d\", \"7d\", \"1m\", \"3m\", \"6m\", \"1y\", \"2y\", \"5y\", \"max\"\n - OR use `start_date` and `end_date` for specific date range\n - Cannot use both approaches simultaneously\n \n **Examples:**\n - `/api/v1/financial/data/AAPL?period=1y&include_metrics=true` - Last year of financial data\n - `/api/v1/financial/data/AAPL?start_date=2024-01-01&end_date=2024-12-31&period_type=quarterly` - Specific date range", + "operationId": "get_financial_data_simple_api_v1_financial_data__ticker__get", + "parameters": [ + { + "name": "ticker", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Ticker" + } + }, + { + "name": "period", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Period like '1d', '7d', '1m', '3m', '6m', '1y', '2y', '5y', 'max'", + "title": "Period" + }, + "description": "Period like '1d', '7d', '1m', '3m', '6m', '1y', '2y', '5y', 'max'" + }, + { + "name": "start_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "description": "Start date for data retrieval (use with end_date, not with period)", + "title": "Start Date" + }, + "description": "Start date for data retrieval (use with end_date, not with period)" + }, + { + "name": "end_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "description": "End date for data retrieval (use with start_date, not with period)", + "title": "End Date" + }, + "description": "End date for data retrieval (use with start_date, not with period)" + }, + { + "name": "period_type", + "in": "query", + "required": false, + "schema": { + "type": "string", + "description": "Period type: quarterly, annual, or all", + "default": "all", + "title": "Period Type" + }, + "description": "Period type: quarterly, annual, or all" + }, + { + "name": "include_metrics", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Include calculated metrics", + "default": true, + "title": "Include Metrics" + }, + "description": "Include calculated metrics" + }, + { + "name": "force_refresh", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Force refresh from SEC", + "default": false, + "title": "Force Refresh" + }, + "description": "Force refresh from SEC" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FinancialDataResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/financial/data/bulk": { + "post": { + "tags": [ + "financial" + ], + "summary": "Get SEC EDGAR financial data for multiple tickers", + "description": "Retrieve comprehensive financial data for multiple tickers in a single request directly from SEC EDGAR filings.\n \n **🔥 Three Ways to Specify Time Period (choose one):**\n \n 1. **Period String** (NEW! Most convenient):\n - `period`: \"1d\", \"7d\", \"30d\", \"1m\", \"3m\", \"6m\", \"1y\", \"2y\", \"5y\", \"max\"\n - Example: Last 1 year for multiple tickers, or \"max\" for all available data\n \n 2. **Date Range** (Traditional):\n - `start_date` + `end_date`: Specific date range\n - Example: Specific date range for all tickers\n \n 3. **Quarters** (Quarter-based):\n - `quarters`: List of quarters like [\"2024Q1\", \"2024Q2\"]\n - Example: Specific quarters for all tickers\n \n **Data Sources:**\n - **Financial Data**: Direct SEC EDGAR API calls (revenue, income, assets, cash flow)\n - **Price Data**: Available via separate price data endpoints using yfinance-plus\n \n **Bulk Processing Features:**\n - Processes up to 100 tickers in parallel for maximum efficiency\n - Returns individual success/failure results for each ticker\n - Handles partial failures gracefully (some tickers can fail while others succeed)\n - Uses the same robust SEC data retrieval logic as single ticker endpoint\n \n **SEC EDGAR Integration:**\n - Direct API calls to official SEC EDGAR database\n - All financial data sourced from actual SEC filings (10-K, 10-Q)\n - No estimated or synthetic data - only actual reported figures\n - Historical data available from 1994-present (15+ years for most companies)\n - Automatic validation and error handling for missing periods\n \n **Data Quality & Features:**\n - Company information (name, CIK, sector, industry, business description)\n - Comprehensive financial statements (income statement, balance sheet, cash flow)\n - Calculated financial metrics (ratios, margins, growth rates)\n - Period types: quarterly (10-Q) and annual (10-K) filings\n - Database caching to avoid repeated SEC API calls\n \n **Performance:**\n - Parallel processing for bulk requests\n - Intelligent caching and rate limiting\n - Use `force_refresh=true` to fetch fresh data from SEC EDGAR\n \n **Example Requests:**\n ```json\n // Using period (simplest)\n {\n \"tickers\": [\"AAPL\", \"MSFT\", \"GOOGL\"],\n \"period\": \"1y\",\n \"include_metrics\": true\n }\n \n // Using date range\n {\n \"tickers\": [\"NVDA\", \"AMD\", \"INTC\"],\n \"start_date\": \"2024-01-01\",\n \"end_date\": \"2024-12-31\",\n \"period_type\": \"quarterly\"\n }\n \n // Using quarters\n {\n \"tickers\": [\"TSLA\", \"F\", \"GM\"],\n \"quarters\": [\"2024Q1\", \"2024Q2\"],\n \"include_metrics\": true\n }\n ```\n \n Each ticker result includes the same comprehensive financial data structure as the single ticker endpoint.\n Failed tickers will have detailed error messages while successful ones will have complete SEC filing data.", + "operationId": "get_bulk_financial_data_api_v1_financial_data_bulk_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BulkFinancialDataRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BulkFinancialDataResponse" + } + } + } + }, + "400": { + "description": "Invalid request parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/price/data": { + "post": { + "tags": [ + "price" + ], + "summary": "Get enhanced price data via yfinance-plus", + "description": "Retrieve historical price data for a specific ticker using enhanced yfinance-plus integration.\n \n **🔥 Three Ways to Specify Time Period (choose one):**\n \n 1. **Period String** (NEW! Most convenient):\n - `period`: \"1d\", \"7d\", \"30d\", \"1m\", \"3m\", \"6m\", \"1y\", \"2y\", \"5y\", \"max\"\n - Example: `{\"ticker\": \"AAPL\", \"period\": \"3m\", \"interval\": \"1d\"}` - Last 3 months, daily prices\n - Example: `{\"ticker\": \"TSLA\", \"period\": \"max\", \"interval\": \"1d\"}` - Maximum 20 years of data\n \n 2. **Date Range** (Traditional):\n - `start_date` + `end_date`: Specific date range\n - Example: `{\"ticker\": \"AAPL\", \"start_date\": \"2024-01-01\", \"end_date\": \"2024-12-31\", \"interval\": \"1d\"}`\n \n 3. **Quarters** (Quarter-based):\n - `quarters`: List of quarters like [\"2024Q1\", \"2024Q2\"]\n - Example: `{\"ticker\": \"AAPL\", \"quarters\": [\"2024Q1\", \"2024Q2\"], \"interval\": \"1d\"}`\n \n **Data Source:**\n - **Price Data**: Yahoo Finance via yfinance-plus with enhanced rate limiting and caching\n - **Financial Data**: Available via separate financial endpoints using SEC EDGAR\n \n **This endpoint returns:**\n - OHLCV data (Open, High, Low, Close, Volume)\n - Adjusted close prices with dividend/split adjustments\n - Multiple intervals: 1d, 1w, 1m, 1h (where available)\n - Extensive historical data (decades for most symbols)\n \n **Enhanced Features (yfinance-plus):**\n - Intelligent rate limiting to prevent API throttling\n - Multi-threaded bulk downloads for better performance\n - Advanced caching with cache management\n - Automatic retry with exponential backoff\n - Multiple user agents for improved reliability\n - Enhanced error handling and recovery\n \n **Performance:**\n - Database caching to minimize external API calls\n - Bulk mode capable of 59+ tickers/second throughput\n - 4.3x faster than individual ticker requests\n - Use `force_refresh=true` to fetch fresh data from Yahoo Finance\n \n **Example Requests:**\n ```json\n // Using period (simplest)\n {\n \"ticker\": \"AAPL\",\n \"period\": \"6m\",\n \"interval\": \"1d\"\n }\n \n // Using date range\n {\n \"ticker\": \"TSLA\",\n \"start_date\": \"2024-01-01\",\n \"end_date\": \"2024-12-31\",\n \"interval\": \"1w\"\n }\n \n // Using quarters\n {\n \"ticker\": \"NVDA\",\n \"quarters\": [\"2024Q1\", \"2024Q2\"],\n \"interval\": \"1d\",\n \"force_refresh\": true\n }\n ```", + "operationId": "get_price_data_api_v1_price_data_post", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PriceDataRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PriceDataResponse" + } + } + } + }, + "400": { + "description": "Invalid request parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Data not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "get": { + "tags": [ + "price", + "price" + ], + "summary": "Get daily bars for multiple tickers via yfinance (DB-backed)", + "description": "Fetch OHLCV daily bars for one or more tickers via Yahoo Finance (yfinance-plus). Results are stored in DB; subsequent calls for the same range skip the external API.\n\n- `tickers` or `ticker`: comma-separated list, e.g. `AAPL,MSFT` or single `QQQ`\n- `force_refresh=true`: re-fetch from Yahoo Finance even if DB has data\n- Up to 1000 tickers per request (auto-chunked internally)\n\n**경로 파라미터 대안**: 단일 종목은 `/data/{ticker}?start_date=...&end_date=...` 도 동일하게 동작합니다.", + "operationId": "get_multi_ticker_daily_bars_api_v1_price_data_get", + "parameters": [ + { + "name": "tickers", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Comma-separated tickers, e.g. AAPL,MSFT,QQQ", + "title": "Tickers" + }, + "description": "Comma-separated tickers, e.g. AAPL,MSFT,QQQ" + }, + { + "name": "ticker", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Alias for tickers (single ticker shorthand)", + "title": "Ticker" + }, + "description": "Alias for tickers (single ticker shorthand)" + }, + { + "name": "start_date", + "in": "query", + "required": true, + "schema": { + "type": "string", + "format": "date", + "description": "Start date (YYYY-MM-DD)", + "title": "Start Date" + }, + "description": "Start date (YYYY-MM-DD)" + }, + { + "name": "end_date", + "in": "query", + "required": true, + "schema": { + "type": "string", + "format": "date", + "description": "End date (YYYY-MM-DD)", + "title": "End Date" + }, + "description": "End date (YYYY-MM-DD)" + }, + { + "name": "interval", + "in": "query", + "required": false, + "schema": { + "type": "string", + "description": "Bar interval: 1d, 1w, 1m", + "default": "1d", + "title": "Interval" + }, + "description": "Bar interval: 1d, 1w, 1m" + }, + { + "name": "force_refresh", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Re-fetch from Yahoo Finance even if DB has data", + "default": false, + "title": "Force Refresh" + }, + "description": "Re-fetch from Yahoo Finance even if DB has data" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AlpacaMultiBarsResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/price/data/{ticker}": { + "get": { + "tags": [ + "price" + ], + "summary": "Get price data by ticker (simplified)", + "description": "Simplified GET endpoint to retrieve price data with query parameters.\n \n **Time Period Options:**\n - Use `period` for convenience: \"1d\", \"7d\", \"1m\", \"3m\", \"6m\", \"1y\", \"2y\", \"5y\", \"max\"\n - OR use `start_date` and `end_date` for specific date range\n - Cannot use both approaches simultaneously\n \n **Examples:**\n - `/api/v1/price/data/AAPL?period=1y&interval=1d` - Last year of daily prices\n - `/api/v1/price/data/TSLA?period=max&interval=1d` - Maximum 20 years of data for Tesla\n - `/api/v1/price/data/AAPL?start_date=2024-01-01&end_date=2024-12-31&interval=1d` - Specific date range", + "operationId": "get_price_data_simple_api_v1_price_data__ticker__get", + "parameters": [ + { + "name": "ticker", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Ticker" + } + }, + { + "name": "period", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Period like '1d', '7d', '1m', '3m', '6m', '1y', '2y', '5y', 'max'", + "title": "Period" + }, + "description": "Period like '1d', '7d', '1m', '3m', '6m', '1y', '2y', '5y', 'max'" + }, + { + "name": "start_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "description": "Start date for data retrieval (use with end_date, not with period)", + "title": "Start Date" + }, + "description": "Start date for data retrieval (use with end_date, not with period)" + }, + { + "name": "end_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "description": "End date for data retrieval (use with start_date, not with period)", + "title": "End Date" + }, + "description": "End date for data retrieval (use with start_date, not with period)" + }, + { + "name": "start", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "description": "Alias for start_date", + "title": "Start" + }, + "description": "Alias for start_date" + }, + { + "name": "end", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "description": "Alias for end_date", + "title": "End" + }, + "description": "Alias for end_date" + }, + { + "name": "interval", + "in": "query", + "required": false, + "schema": { + "type": "string", + "description": "Data interval: 1d, 1w, 1m, 5d, 1h, etc.", + "default": "1d", + "title": "Interval" + }, + "description": "Data interval: 1d, 1w, 1m, 5d, 1h, etc." + }, + { + "name": "force_refresh", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Force refresh from Yahoo Finance", + "default": false, + "title": "Force Refresh" + }, + "description": "Force refresh from Yahoo Finance" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PriceDataResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/price/data/bulk": { + "post": { + "tags": [ + "price" + ], + "summary": "Get enhanced price data for multiple tickers via yfinance-plus", + "description": "Retrieve historical price data for multiple tickers in a single request using enhanced yfinance-plus integration.\n \n **🔥 Three Ways to Specify Time Period (choose one):**\n \n 1. **Period String** (NEW! Most convenient):\n - `period`: \"1d\", \"7d\", \"30d\", \"1m\", \"3m\", \"6m\", \"1y\", \"2y\", \"5y\", \"max\"\n - Example: Last 3 months for multiple tickers, or \"max\" for maximum 20 years of data\n \n 2. **Date Range** (Traditional):\n - `start_date` + `end_date`: Specific date range\n - Example: Specific date range for all tickers\n \n 3. **Quarters** (Quarter-based):\n - `quarters`: List of quarters like [\"2024Q1\", \"2024Q2\"]\n - Example: Specific quarters for all tickers\n \n **Data Source:**\n - **Price Data**: Yahoo Finance via yfinance-plus with enhanced rate limiting and caching\n - **Financial Data**: Available via separate financial endpoints using SEC EDGAR\n \n **Bulk Processing Features:**\n - Processes up to 100 tickers in parallel for maximum throughput\n - Returns individual success/failure results for each ticker\n - Handles partial failures gracefully (some tickers can fail while others succeed)\n - Uses the same enhanced data retrieval logic as single ticker endpoint\n \n **Enhanced Performance (yfinance-plus):**\n - Multi-threaded bulk downloads with intelligent rate limiting\n - 4.3x faster than individual ticker requests\n - Bulk mode capable of 59+ tickers/second throughput\n - Advanced caching and automatic retry with exponential backoff\n - Enhanced error handling and recovery mechanisms\n \n **Data Quality:**\n - OHLCV data with dividend/split adjustments\n - Multiple intervals: 1d, 1w, 1m, 1h (where available)\n - Extensive historical data (decades for most symbols)\n - Database caching to minimize external API calls\n \n **Example Requests:**\n ```json\n // Using period (simplest)\n {\n \"tickers\": [\"AAPL\", \"MSFT\", \"GOOGL\"],\n \"period\": \"3m\",\n \"interval\": \"1d\"\n }\n \n // Using date range\n {\n \"tickers\": [\"NVDA\", \"AMD\", \"INTC\"],\n \"start_date\": \"2024-01-01\",\n \"end_date\": \"2024-12-31\",\n \"interval\": \"1w\"\n }\n \n // Using quarters\n {\n \"tickers\": [\"TSLA\", \"F\", \"GM\"],\n \"quarters\": [\"2024Q1\", \"2024Q2\"],\n \"interval\": \"1d\",\n \"force_refresh\": true\n }\n ```\n \n Each ticker result includes the same comprehensive price data structure as the single ticker endpoint.\n Failed tickers will have detailed error messages while successful ones will have complete OHLCV data.", + "operationId": "get_bulk_price_data_api_v1_price_data_bulk_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BulkPriceDataRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BulkPriceDataResponse" + } + } + } + }, + "400": { + "description": "Invalid request parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/price/latest/{ticker}": { + "get": { + "tags": [ + "price" + ], + "summary": "Get latest price for a ticker", + "description": "Get the most recent price data point for a ticker", + "operationId": "get_latest_price_api_v1_price_latest__ticker__get", + "parameters": [ + { + "name": "ticker", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Ticker" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PriceDataPoint" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/price/quote/{ticker}": { + "get": { + "tags": [ + "price" + ], + "summary": "Get latest quote (regular/pre/post)", + "description": "Return latest price with regular/pre/post market fields from yfinance-plus", + "operationId": "get_quote_api_v1_price_quote__ticker__get", + "parameters": [ + { + "name": "ticker", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Ticker" + } + }, + { + "name": "use_prepost", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Include pre/post market prices if available", + "default": true, + "title": "Use Prepost" + }, + "description": "Include pre/post market prices if available" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/QuoteResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/price/intraday": { + "get": { + "tags": [ + "price" + ], + "summary": "Get intraday bars for multiple tickers via Yahoo Finance", + "description": "Fetch intraday OHLCV bars for up to ~500 tickers using Yahoo Finance.\n\n**⚠️ Yahoo Finance 분봉 데이터 한계**\n\n| 항목 | 내용 |\n|------|------|\n| 지연 | **15분 지연** (실시간 아님) |\n| `1m` 최대 조회 기간 | 최근 **7일** 이내 |\n| `2m`/`5m`/`15m`/`30m`/`90m` | 최근 **60일** 이내 |\n| `1h` | 최근 **730일** 이내 |\n| 실시간 거래 전략 | **부적합** — 15분 지연으로 ORB 등 당일 전략에 사용 불가 |\n| 데이터 품질 | Yahoo Finance 자체 집계, 간헐적 누락/오류 가능 |\n\n**권장 용도**: 백테스트, 과거 분봉 분석 (60일 이내)\n\n**실시간 당일 분봉이 필요하면** → `GET /api/v1/alpaca/intraday` 사용 (Alpaca IEX 피드, 실시간)\n\n- `tickers`: comma-separated, e.g. `AAPL,MSFT,BF-B`\n- `interval`: `1m`, `5m`, `15m`, `30m`, `1h`\n- Redis 5분 TTL 캐시 적용", + "operationId": "get_multi_ticker_intraday_api_v1_price_intraday_get", + "parameters": [ + { + "name": "tickers", + "in": "query", + "required": true, + "schema": { + "type": "string", + "description": "Comma-separated tickers", + "title": "Tickers" + }, + "description": "Comma-separated tickers" + }, + { + "name": "interval", + "in": "query", + "required": false, + "schema": { + "type": "string", + "description": "Interval: 1m, 5m, 15m, 30m, 1h", + "default": "5m", + "title": "Interval" + }, + "description": "Interval: 1m, 5m, 15m, 30m, 1h" + }, + { + "name": "start_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "description": "Start date (YYYY-MM-DD)", + "title": "Start Date" + }, + "description": "Start date (YYYY-MM-DD)" + }, + { + "name": "end_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "description": "End date (YYYY-MM-DD)", + "title": "End Date" + }, + "description": "End date (YYYY-MM-DD)" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AlpacaMultiBarsResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/price/intraday/{ticker}": { + "get": { + "tags": [ + "price" + ], + "summary": "Get intraday candles", + "description": "Return intraday candles using yfinance-plus history(period,interval)", + "operationId": "get_intraday_api_v1_price_intraday__ticker__get", + "parameters": [ + { + "name": "ticker", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Ticker" + } + }, + { + "name": "interval", + "in": "query", + "required": false, + "schema": { + "type": "string", + "default": "1m", + "title": "Interval" + } + }, + { + "name": "period", + "in": "query", + "required": false, + "schema": { + "type": "string", + "default": "1d", + "title": "Period" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IntradayResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/price/today/{ticker}": { + "get": { + "tags": [ + "price" + ], + "summary": "Get today's OHLC", + "description": "Return today's OHLC. If daily not finalized yet, aggregate from 1m intraday.", + "operationId": "get_today_ohlc_api_v1_price_today__ticker__get", + "parameters": [ + { + "name": "ticker", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Ticker" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TodayOHLCResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/stocks/index/{index_name}": { + "get": { + "tags": [ + "stocks" + ], + "summary": "Get index constituents (S&P 500 / Nasdaq 100)", + "description": "Get current constituents of a major stock index from Wikipedia.\n\nReturns each stock's symbol, company name, GICS Sector, and GICS Sub-Industry.\n\n**Supported values for `index_name`**:\n- `sp500` — S&P 500 (~503 stocks)\n- `nasdaq100` — Nasdaq 100 (~101 stocks)\n\n**Data Source**: Wikipedia\n**Cache TTL**: 24 hours (`X-Cache: HIT/MISS`, `ETag` headers included)\n**Timeout**: 30 seconds (Wikipedia fetch)\n\n**Error codes**:\n- `400` — unsupported `index_name`\n- `504` — Wikipedia response timed out", + "operationId": "get_index_constituents_api_v1_stocks_index__index_name__get", + "parameters": [ + { + "name": "index_name", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Index Name" + } + }, + { + "name": "force_refresh", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "If true, bypasses cache and fetches fresh data", + "default": false, + "title": "Force Refresh" + }, + "description": "If true, bypasses cache and fetches fresh data" + } + ], + "responses": { + "200": { + "description": "List of constituent stocks with symbol, name, sector, and industry", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/stocks/most-active": { + "get": { + "tags": [ + "stocks" + ], + "summary": "Most actively traded stocks by volume", + "description": "Get most actively traded stocks from Yahoo Finance.\n\n**⚠️ 실시간 전용**: DB에 저장되지 않음. 과거 데이터 조회 불가.\n캐시 TTL: 1시간 (`X-Cache: HIT/MISS` 헤더 포함).", + "operationId": "get_most_active_stocks_api_v1_stocks_most_active_get", + "parameters": [ + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "integer", + "maximum": 500, + "minimum": 1 + }, + { + "type": "null" + } + ], + "description": "Maximum number of stocks to return (1-500). If not specified, returns all available stocks.", + "title": "Limit" + }, + "description": "Maximum number of stocks to return (1-500). If not specified, returns all available stocks." + }, + { + "name": "force_refresh", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "If true, bypasses cache and fetches fresh data", + "default": false, + "title": "Force Refresh" + }, + "description": "If true, bypasses cache and fetches fresh data" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/stocks/52-week-gainers": { + "get": { + "tags": [ + "stocks" + ], + "summary": "Top 52-week gaining stocks", + "description": "Get 52-week top gaining stocks from Yahoo Finance.\n\n**⚠️ 실시간 전용**: DB에 저장되지 않음. 과거 데이터 조회 불가.\n캐시 TTL: 1시간. 첫 호출 시 15-30초 소요 (웹 스크래핑).", + "operationId": "get_52week_gainers_api_v1_stocks_52_week_gainers_get", + "parameters": [ + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "integer", + "maximum": 1000, + "minimum": 1 + }, + { + "type": "null" + } + ], + "description": "Maximum number of stocks to return (1-1000). If not specified, returns first 600 stocks (3 pages) for performance.", + "title": "Limit" + }, + "description": "Maximum number of stocks to return (1-1000). If not specified, returns first 600 stocks (3 pages) for performance." + }, + { + "name": "max_pages", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "integer", + "maximum": 10, + "minimum": 1 + }, + { + "type": "null" + } + ], + "description": "Maximum pages to fetch (1-10). Each page has ~200 stocks. Higher values may cause rate limiting.", + "default": 3, + "title": "Max Pages" + }, + "description": "Maximum pages to fetch (1-10). Each page has ~200 stocks. Higher values may cause rate limiting." + }, + { + "name": "force_refresh", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Bypass cache", + "default": false, + "title": "Force Refresh" + }, + "description": "Bypass cache" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/stocks/gainers": { + "get": { + "tags": [ + "stocks" + ], + "summary": "Today's top gaining stocks (Yahoo Finance day_gainers)", + "description": "Top gaining stocks for today via Yahoo Finance's `day_gainers` predefined screener.\n\nCriteria: price change > 3%, market cap >= $2B, price >= $5, volume > 15,000.\nSorted by percent change descending. Real-time — no cache.\n\nData source: `query1.finance.yahoo.com/v1/finance/screener/predefined/saved`\nwith browser fingerprint rotation for 429 bypass.", + "operationId": "get_day_gainers_api_v1_stocks_gainers_get", + "parameters": [ + { + "name": "count", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 250, + "minimum": 1, + "description": "Number of results to return (max 250)", + "default": 100, + "title": "Count" + }, + "description": "Number of results to return (max 250)" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/stocks/gainers/snapshots": { + "get": { + "tags": [ + "stocks" + ], + "summary": "Historical top gainers snapshot (5-min interval, DB)", + "description": "Return top gainers stored in the DB at the requested point in time.\n\n- **at** omitted → most recent 5-min snapshot.\n- **at** provided → as-of semantics: the latest snapshot whose `snapshot_at ≤ floor(at, 5min)`.\n- Returns `404` when no snapshot exists before the requested time.", + "operationId": "get_gainer_snapshot_api_v1_stocks_gainers_snapshots_get", + "parameters": [ + { + "name": "at", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "description": "UTC timestamp to query (ISO 8601). Omit for the latest snapshot.", + "title": "At" + }, + "description": "UTC timestamp to query (ISO 8601). Omit for the latest snapshot." + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 200, + "minimum": 1, + "description": "Number of top gainers to return (max 200)", + "default": 100, + "title": "Limit" + }, + "description": "Number of top gainers to return (max 200)" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/stocks/trending": { + "get": { + "tags": [ + "stocks" + ], + "summary": "Trending stocks combining most active and 52-week gainers", + "description": "Get trending stocks by combining most-active + 52-week gainers.\n\n**⚠️ 실시간 전용**: DB에 저장되지 않음. 과거 데이터 조회 불가.\n캐시 TTL: 30분. 병렬 스크래핑으로 최적화.", + "operationId": "get_trending_stocks_api_v1_stocks_trending_get", + "parameters": [ + { + "name": "n", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "integer", + "minimum": 1 + }, + { + "type": "null" + } + ], + "description": "Total number of trending stocks to return after combining most active + gainers (default: 500)", + "default": 500, + "title": "N" + }, + "description": "Total number of trending stocks to return after combining most active + gainers (default: 500)" + }, + { + "name": "most_active_limit", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "integer", + "minimum": 1 + }, + { + "type": "null" + } + ], + "description": "Number of most active stocks to include. If not specified, returns all available stocks (~170).", + "title": "Most Active Limit" + }, + "description": "Number of most active stocks to include. If not specified, returns all available stocks (~170)." + }, + { + "name": "gainers_limit", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "integer", + "minimum": 1 + }, + { + "type": "null" + } + ], + "description": "Number of 52-week gainers to fetch. If not specified, fetches enough to reach target 'n' after combining with most active.", + "title": "Gainers Limit" + }, + "description": "Number of 52-week gainers to fetch. If not specified, fetches enough to reach target 'n' after combining with most active." + }, + { + "name": "force_refresh", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Bypass cache", + "default": false, + "title": "Force Refresh" + }, + "description": "Bypass cache" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/fred/stats/usage": { + "get": { + "tags": [ + "fred" + ], + "summary": "FRED API usage statistics and cache performance", + "description": "Get FRED API usage statistics and cache performance\n\nReturns detailed statistics about API usage, cache performance, and daily limits.\nNow includes enhanced proxy service statistics.\n\n**Example Response**:\n```json\n{\n \"success\": true,\n \"data\": {\n \"daily_limit\": 1000,\n \"used_today\": 45,\n \"remaining_today\": 955,\n \"usage_percentage\": 4.5,\n \"can_make_requests\": true,\n \"daily_stats\": [\n {\n \"date\": \"2025-01-14\",\n \"total_calls\": 45,\n \"successful_calls\": 44,\n \"total_records\": 1250,\n \"success_rate\": 97.8\n }\n ],\n \"endpoint_stats\": [\n {\n \"endpoint\": \"series\",\n \"call_count\": 25\n }\n ],\n \"proxy_info\": {\n \"mode\": \"pass_through_proxy\",\n \"supported_endpoints\": \"all_fred_endpoints\"\n }\n }\n}\n```\n\n**Parameters**:\n- `days`: Number of days to include in historical statistics (1-30)\n- `use_proxy_stats`: Use enhanced proxy service statistics (recommended)\n\n**Metrics Included**:\n- Daily API usage and remaining quota\n- Historical usage patterns \n- Endpoint-specific usage statistics (NEW!)\n- Success rates and error tracking\n- Proxy service information (NEW!)", + "operationId": "get_fred_usage_stats_api_v1_fred_stats_usage_get", + "parameters": [ + { + "name": "days", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 30, + "minimum": 1, + "description": "Number of days to include in stats", + "default": 7, + "title": "Days" + }, + "description": "Number of days to include in stats" + }, + { + "name": "use_proxy_stats", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Use enhanced proxy service statistics", + "default": true, + "title": "Use Proxy Stats" + }, + "description": "Use enhanced proxy service statistics" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/fred/proxy/{endpoint}": { + "get": { + "tags": [ + "fred" + ], + "summary": "Universal FRED API proxy", + "description": "FRED API Pass-through Proxy\n\nUniversal proxy endpoint that forwards requests to any FRED API endpoint while maintaining\nour caching and rate limiting logic.\n\n**Supported Endpoints**: All FRED API endpoints are supported\n\n**Examples**:\n```bash\n# Series information\nGET /api/v1/fred/proxy/series?series_id=GDP\n\n# Series observations \nGET /api/v1/fred/proxy/series/observations?series_id=UNRATE&limit=12\n\n# Category information\nGET /api/v1/fred/proxy/category?category_id=125\n\n# Category children\nGET /api/v1/fred/proxy/category/children?category_id=13\n\n# Release information\nGET /api/v1/fred/proxy/release?release_id=53\n\n# Search series\nGET /api/v1/fred/proxy/series/search?search_text=unemployment&limit=25\n\n# Sources\nGET /api/v1/fred/proxy/sources\n\n# Tags\nGET /api/v1/fred/proxy/tags?limit=100\n```\n\n**Key Features**:\n- **Universal Access**: Support for all FRED API endpoints\n- **Smart Caching**: 24-hour DB caching for series and observations (NEW!)\n- **Permanent Storage**: Historical data permanently stored in database (NEW!)\n- **Rate Limiting**: Respects 1,000/day limit with usage tracking \n- **Parameter Forwarding**: Automatically forwards all supported parameters\n- **Error Handling**: Comprehensive error handling and logging\n- **Usage Statistics**: Tracks endpoint usage and performance\n\n**Parameters**:\nAll standard FRED API parameters are supported including:\n- `series_id`, `category_id`, `release_id`, `source_id`\n- `realtime_start`, `realtime_end`, `observation_start`, `observation_end` \n- `limit`, `offset`, `order_by`, `sort_order`\n- `search_text`, `search_type`, `frequency`, `aggregation_method`\n- `force_refresh`: Bypass cache and fetch fresh data from FRED API\n- `bypass_limit_check`: Skip daily limit validation (admin only)\n- And many more...\n\n**Caching Strategy**:\n- **Cache Hit**: Returns instantly from database (no API call)\n- **Cache Miss**: Fetches from FRED API and stores for 24 hours \n- **Permanent Storage**: Historical observations stored permanently\n- **API Limit Reached**: Returns cached data even if expired\n\n**Response Format**: Returns original FRED API response with additional metadata", + "operationId": "fred_proxy_endpoint_api_v1_fred_proxy__endpoint__get", + "parameters": [ + { + "name": "endpoint", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Endpoint" + } + }, + { + "name": "series_id", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Series ID parameter", + "title": "Series Id" + }, + "description": "Series ID parameter" + }, + { + "name": "category_id", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Category ID parameter", + "title": "Category Id" + }, + "description": "Category ID parameter" + }, + { + "name": "release_id", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Release ID parameter", + "title": "Release Id" + }, + "description": "Release ID parameter" + }, + { + "name": "source_id", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Source ID parameter", + "title": "Source Id" + }, + "description": "Source ID parameter" + }, + { + "name": "tag_names", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Tag names parameter", + "title": "Tag Names" + }, + "description": "Tag names parameter" + }, + { + "name": "realtime_start", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Realtime start date (YYYY-MM-DD)", + "title": "Realtime Start" + }, + "description": "Realtime start date (YYYY-MM-DD)" + }, + { + "name": "realtime_end", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Realtime end date (YYYY-MM-DD)", + "title": "Realtime End" + }, + "description": "Realtime end date (YYYY-MM-DD)" + }, + { + "name": "observation_start", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Observation start date (YYYY-MM-DD)", + "title": "Observation Start" + }, + "description": "Observation start date (YYYY-MM-DD)" + }, + { + "name": "observation_end", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Observation end date (YYYY-MM-DD)", + "title": "Observation End" + }, + "description": "Observation end date (YYYY-MM-DD)" + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "integer", + "maximum": 100000, + "minimum": 1 + }, + { + "type": "null" + } + ], + "description": "Limit number of results", + "title": "Limit" + }, + "description": "Limit number of results" + }, + { + "name": "offset", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "integer", + "minimum": 0 + }, + { + "type": "null" + } + ], + "description": "Offset for pagination", + "title": "Offset" + }, + "description": "Offset for pagination" + }, + { + "name": "order_by", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Order by parameter", + "title": "Order By" + }, + "description": "Order by parameter" + }, + { + "name": "sort_order", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Sort order (asc/desc)", + "title": "Sort Order" + }, + "description": "Sort order (asc/desc)" + }, + { + "name": "search_text", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Search text", + "title": "Search Text" + }, + "description": "Search text" + }, + { + "name": "search_type", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Search type", + "title": "Search Type" + }, + "description": "Search type" + }, + { + "name": "frequency", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Data frequency", + "title": "Frequency" + }, + "description": "Data frequency" + }, + { + "name": "aggregation_method", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Aggregation method", + "title": "Aggregation Method" + }, + "description": "Aggregation method" + }, + { + "name": "output_type", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Output type", + "title": "Output Type" + }, + "description": "Output type" + }, + { + "name": "vintage_dates", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Vintage dates", + "title": "Vintage Dates" + }, + "description": "Vintage dates" + }, + { + "name": "exclude_tag_names", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Exclude tag names", + "title": "Exclude Tag Names" + }, + "description": "Exclude tag names" + }, + { + "name": "tag_group_id", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Tag group ID", + "title": "Tag Group Id" + }, + "description": "Tag group ID" + }, + { + "name": "bypass_limit_check", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Bypass daily limit check (admin only)", + "default": false, + "title": "Bypass Limit Check" + }, + "description": "Bypass daily limit check (admin only)" + }, + { + "name": "force_refresh", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Force refresh from API, bypass cache", + "default": false, + "title": "Force Refresh" + }, + "description": "Force refresh from API, bypass cache" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/fred/endpoints": { + "get": { + "tags": [ + "fred" + ], + "summary": "List supported FRED API endpoints", + "description": "Get list of supported FRED API endpoints\n\nReturns comprehensive list of all FRED API endpoints that can be accessed\nthrough the proxy service.\n\n**Usage**: Use this to discover available endpoints and their categories.\n\n**Example Response**:\n```json\n{\n \"series_endpoints\": [\n \"series\",\n \"series/observations\", \n \"series/search\",\n \"...\"\n ],\n \"category_endpoints\": [\"...\"],\n \"release_endpoints\": [\"...\"]\n}\n```", + "operationId": "get_supported_fred_endpoints_api_v1_fred_endpoints_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + } + } + } + }, + "/api/v1/news/{ticker}": { + "get": { + "tags": [ + "news" + ], + "summary": "Get news and social media for a ticker", + "description": "Fetch recent news articles and social media posts for a ticker from multiple sources.\n\n **News sources**: Yahoo Finance, NewsAPI\n **Social sources**: Reddit (r/stocks, r/investing, r/wallstreetbets, r/SecurityAnalysis, r/ValueInvesting)\n\n Both sources are fetched in parallel. Results are deduplicated and ranked by relevance.\n Cached for **10 minutes**.\n\n **Examples**:\n - `GET /news/AAPL` — last 7 days, up to 20 articles + 15 posts\n - `GET /news/TSLA?days_back=14&max_articles=50&include_social=false` — news-only, 2 weeks", + "operationId": "get_ticker_news_and_social_api_v1_news__ticker__get", + "parameters": [ + { + "name": "ticker", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Ticker" + } + }, + { + "name": "days_back", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 30, + "minimum": 1, + "description": "Number of days to look back for articles (1-30)", + "default": 7, + "title": "Days Back" + }, + "description": "Number of days to look back for articles (1-30)" + }, + { + "name": "max_articles", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "description": "Maximum number of news articles to return (1-100)", + "default": 20, + "title": "Max Articles" + }, + "description": "Maximum number of news articles to return (1-100)" + }, + { + "name": "max_social_posts", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 50, + "minimum": 0, + "description": "Maximum number of social media posts to return (0-50)", + "default": 15, + "title": "Max Social Posts" + }, + "description": "Maximum number of social media posts to return (0-50)" + }, + { + "name": "include_social", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Whether to include social media data", + "default": true, + "title": "Include Social" + }, + "description": "Whether to include social media data" + }, + { + "name": "force_refresh", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Bypass cache and fetch fresh data", + "default": false, + "title": "Force Refresh" + }, + "description": "Bypass cache and fetch fresh data" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewsSocialResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/news/{ticker}/news-only": { + "get": { + "tags": [ + "news" + ], + "summary": "Get news articles for a ticker (no social media)", + "description": "Faster endpoint that returns only news articles, skipping social media API calls.\n\n **Sources**: Yahoo Finance, NewsAPI\n Cached for **10 minutes**.\n\n **Example**: `GET /news/NVDA/news-only?days_back=3&max_articles=30`", + "operationId": "get_ticker_news_only_api_v1_news__ticker__news_only_get", + "parameters": [ + { + "name": "ticker", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Ticker" + } + }, + { + "name": "days_back", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 30, + "minimum": 1, + "description": "Number of days to look back for articles (1-30)", + "default": 7, + "title": "Days Back" + }, + "description": "Number of days to look back for articles (1-30)" + }, + { + "name": "max_articles", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "description": "Maximum number of news articles to return (1-100)", + "default": 30, + "title": "Max Articles" + }, + "description": "Maximum number of news articles to return (1-100)" + }, + { + "name": "force_refresh", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Bypass cache and fetch fresh data", + "default": false, + "title": "Force Refresh" + }, + "description": "Bypass cache and fetch fresh data" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewsOnlyResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/news/{ticker}/social-only": { + "get": { + "tags": [ + "news" + ], + "summary": "Get social media posts for a ticker", + "description": "Returns only Reddit posts for a ticker, skipping news API calls.\n\n **Subreddits**: r/stocks, r/investing, r/wallstreetbets, r/SecurityAnalysis,\n r/StockMarket, r/ValueInvesting, r/financialindependence\n Cached for **10 minutes**.\n\n **Example**: `GET /news/GME/social-only?days_back=3&max_social_posts=30`", + "operationId": "get_ticker_social_only_api_v1_news__ticker__social_only_get", + "parameters": [ + { + "name": "ticker", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Ticker" + } + }, + { + "name": "days_back", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 30, + "minimum": 1, + "description": "Number of days to look back for posts (1-30)", + "default": 7, + "title": "Days Back" + }, + "description": "Number of days to look back for posts (1-30)" + }, + { + "name": "max_social_posts", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 50, + "minimum": 1, + "description": "Maximum number of social media posts to return (1-50)", + "default": 20, + "title": "Max Social Posts" + }, + "description": "Maximum number of social media posts to return (1-50)" + }, + { + "name": "force_refresh", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Bypass cache and fetch fresh data", + "default": false, + "title": "Force Refresh" + }, + "description": "Bypass cache and fetch fresh data" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SocialOnlyResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/news/v2/headlines": { + "get": { + "tags": [ + "news-v2" + ], + "summary": "Raw multi-source news headlines", + "description": "Multi-source raw headline rows. Filter by symbols, time window, and source. Sources: `alpaca_benzinga`, `stocktwits`, `finnhub`, `gdelt`.", + "operationId": "get_headlines_api_v1_news_v2_headlines_get", + "parameters": [ + { + "name": "symbols", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "CSV ticker list, max 50 (e.g. AAPL,MSFT)", + "title": "Symbols" + }, + "description": "CSV ticker list, max 50 (e.g. AAPL,MSFT)" + }, + { + "name": "start", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "description": "Start time (UTC ISO)", + "title": "Start" + }, + "description": "Start time (UTC ISO)" + }, + { + "name": "end", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "description": "End time (UTC ISO)", + "title": "End" + }, + "description": "End time (UTC ISO)" + }, + { + "name": "sources", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "CSV source filter, subset of ['alpaca_benzinga', 'finnhub', 'gdelt', 'stocktwits']", + "title": "Sources" + }, + "description": "CSV source filter, subset of ['alpaca_benzinga', 'finnhub', 'gdelt', 'stocktwits']" + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 500, + "minimum": 1, + "default": 100, + "title": "Limit" + } + }, + { + "name": "cursor", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "published_at_lt cursor (ISO datetime)", + "title": "Cursor" + }, + "description": "published_at_lt cursor (ISO datetime)" + }, + { + "name": "force_refresh", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "default": false, + "title": "Force Refresh" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/app__api__v1__endpoints__news_v2__HeadlinesResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/news/v2/session_aggregate": { + "get": { + "tags": [ + "news-v2" + ], + "summary": "Session-aggregated news for one ticker", + "operationId": "get_session_aggregate_api_v1_news_v2_session_aggregate_get", + "parameters": [ + { + "name": "symbol", + "in": "query", + "required": true, + "schema": { + "type": "string", + "description": "Ticker symbol", + "title": "Symbol" + }, + "description": "Ticker symbol" + }, + { + "name": "session_date", + "in": "query", + "required": true, + "schema": { + "type": "string", + "format": "date", + "description": "ET session date (YYYY-MM-DD)", + "title": "Session Date" + }, + "description": "ET session date (YYYY-MM-DD)" + }, + { + "name": "window", + "in": "query", + "required": false, + "schema": { + "type": "string", + "description": "One of ['full_session', 'intraday', 'post', 'premarket']", + "default": "premarket", + "title": "Window" + }, + "description": "One of ['full_session', 'intraday', 'post', 'premarket']" + }, + { + "name": "sources", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "CSV source filter, subset of ['alpaca_benzinga', 'finnhub', 'gdelt', 'stocktwits']", + "title": "Sources" + }, + "description": "CSV source filter, subset of ['alpaca_benzinga', 'finnhub', 'gdelt', 'stocktwits']" + }, + { + "name": "force_refresh", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "default": false, + "title": "Force Refresh" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SessionAggregateItem" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/news/v2/session_aggregate/batch": { + "post": { + "tags": [ + "news-v2" + ], + "summary": "Session-aggregated news for many tickers in one call", + "description": "Batch variant. Caching is intentionally NOT applied at this layer — fithia2 maintains a client-side disk cache as the primary defense; Oracle absorbs only burst load. Use the GET single endpoint for Redis-cached single-ticker reads.", + "operationId": "post_session_aggregate_batch_api_v1_news_v2_session_aggregate_batch_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SessionAggregateBatchRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SessionAggregateBatchResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/news/v2/coverage": { + "get": { + "tags": [ + "news-v2" + ], + "summary": "Per-source ingest coverage probe", + "operationId": "get_coverage_api_v1_news_v2_coverage_get", + "parameters": [ + { + "name": "source", + "in": "query", + "required": true, + "schema": { + "type": "string", + "description": "One of ['alpaca_benzinga', 'finnhub', 'gdelt', 'stocktwits']", + "title": "Source" + }, + "description": "One of ['alpaca_benzinga', 'finnhub', 'gdelt', 'stocktwits']" + }, + { + "name": "symbol", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional ticker filter", + "title": "Symbol" + }, + "description": "Optional ticker filter" + }, + { + "name": "force_refresh", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "default": false, + "title": "Force Refresh" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CoverageResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/etf/holdings/{ticker}": { + "get": { + "tags": [ + "etf" + ], + "summary": "Get ETF portfolio holdings", + "description": "Fetch the constituent holdings of an ETF (e.g., SPY, QQQ, IWM). Data is sourced from SEC 13-F filings and cached for 1 hour.\n\nUse `top_n` to limit to the N largest positions, or `top_percentage` to return the minimal set of holdings that covers X% of the portfolio (e.g., `top_percentage=0.8` for the holdings making up 80% of the ETF).\n\n**Examples**:\n- `GET /etf/holdings/SPY` — all holdings\n- `GET /etf/holdings/QQQ?top_n=10` — top 10 positions\n- `GET /etf/holdings/IWM?top_percentage=0.5` — holdings covering 50% of portfolio", + "operationId": "get_etf_holdings_api_v1_etf_holdings__ticker__get", + "parameters": [ + { + "name": "ticker", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Ticker" + } + }, + { + "name": "as_of_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "YYYY-MM-DD", + "title": "As Of Date" + }, + "description": "YYYY-MM-DD" + }, + { + "name": "top_n", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Return top N holdings by weight/value (mutually exclusive with top_percentage)", + "title": "Top N" + }, + "description": "Return top N holdings by weight/value (mutually exclusive with top_percentage)" + }, + { + "name": "top_percentage", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Return minimal set covering X percent (e.g., 0.5 or 50 for 50%). Mutually exclusive with top_n", + "title": "Top Percentage" + }, + "description": "Return minimal set covering X percent (e.g., 0.5 or 50 for 50%). Mutually exclusive with top_n" + }, + { + "name": "force_refresh", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Bypass cache", + "default": false, + "title": "Force Refresh" + }, + "description": "Bypass cache" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ETFHoldingsOut" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/etf/admin/refresh-maps": { + "post": { + "tags": [ + "etf", + "etf" + ], + "summary": "Refresh ETF CIK and CUSIP mapping tables", + "description": "Re-fetches and upserts the ETF→CIK and CUSIP→ticker mapping tables from SEC data. Run this when new ETFs need to be supported. Returns the number of rows updated.", + "operationId": "refresh_etf_maps_api_v1_etf_admin_refresh_maps_post", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RefreshMapsOut" + } + } + } + } + } + } + }, + "/api/v1/filings/search/{ticker}": { + "get": { + "tags": [ + "filings" + ], + "summary": "Search SEC filings for a ticker", + "description": "Search SEC filings for the given ticker. Supported form types: **8-K, 6-K, 20-F, 40-F**.\n\nAuto-indexes filings from EDGAR on first request (or when `force_refresh=true`). Results are cached for 1 hour.\n\n**현재 DB 보유**: 1994-01-05 ~ 현재, 1598 티커. 처음 조회하는 티커는 SEC EDGAR에서 자동 인덱싱 (수 초 소요).\n\n**Example**: `GET /filings/search/AAPL?form_type=8-K&limit=10`", + "operationId": "search_filings_api_v1_filings_search__ticker__get", + "parameters": [ + { + "name": "ticker", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Ticker" + } + }, + { + "name": "form_type", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Comma-separated form types (e.g. '8-K,6-K'). Default: all supported.", + "title": "Form Type" + }, + "description": "Comma-separated form types (e.g. '8-K,6-K'). Default: all supported." + }, + { + "name": "start_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Start date YYYY-MM-DD", + "title": "Start Date" + }, + "description": "Start date YYYY-MM-DD" + }, + { + "name": "end_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "End date YYYY-MM-DD", + "title": "End Date" + }, + "description": "End date YYYY-MM-DD" + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "default": 20, + "title": "Limit" + } + }, + { + "name": "offset", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 0, + "default": 0, + "title": "Offset" + } + }, + { + "name": "force_refresh", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Force re-indexing from SEC", + "default": false, + "title": "Force Refresh" + }, + "description": "Force re-indexing from SEC" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FilingSearchResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/filings/documents/{accession_number}": { + "get": { + "tags": [ + "filings" + ], + "summary": "List documents in a SEC filing", + "description": "List all documents attached to a SEC filing by accession number.\n\nReturns filename, document type, size, and SEC URL for each document. Cached for 24 hours.\n\n**Example**: `GET /filings/documents/0001193125-24-123456`", + "operationId": "get_filing_documents_api_v1_filings_documents__accession_number__get", + "parameters": [ + { + "name": "accession_number", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Accession Number" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FilingDocumentListResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/filings/exhibit/{accession_number}": { + "get": { + "tags": [ + "filings" + ], + "summary": "Extract exhibit content from a filing", + "description": "Extract the text content of a specific exhibit (e.g., press release **EX-99.1**) from a SEC filing.\n\nReturns the full text content along with content type, filename, and SEC URL. 404 responses are negative-cached for 1 hour. Cached for 24 hours.\n\n**Example**: `GET /filings/exhibit/0001193125-24-123456?exhibit_type=EX-99.1`", + "operationId": "get_exhibit_content_api_v1_filings_exhibit__accession_number__get", + "parameters": [ + { + "name": "accession_number", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Accession Number" + } + }, + { + "name": "exhibit_type", + "in": "query", + "required": false, + "schema": { + "type": "string", + "description": "Exhibit type (e.g. EX-99.1)", + "default": "EX-99.1", + "title": "Exhibit Type" + }, + "description": "Exhibit type (e.g. EX-99.1)" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ExhibitContentResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/filings/search/bulk": { + "post": { + "tags": [ + "filings" + ], + "summary": "Bulk search SEC filings for multiple tickers", + "description": "Search SEC filings for up to many tickers in a single request. Auto-indexes from EDGAR for any ticker not yet in the database.\n\n**Timeout**: 600 seconds. Each ticker is processed concurrently.\n\n**Example body**:\n```json\n{\"tickers\": [\"AAPL\", \"MSFT\", \"NVDA\"], \"form_type\": \"8-K\", \"start_date\": \"2024-01-01\", \"limit_per_ticker\": 5}\n```", + "operationId": "search_filings_bulk_api_v1_filings_search_bulk_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BulkFilingSearchRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BulkFilingSearchResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/filings/exhibit/bulk": { + "post": { + "tags": [ + "filings" + ], + "summary": "Bulk fetch exhibit content", + "description": "Fetch exhibit content for multiple accession numbers in one request. Up to 4 concurrent fetches; max 300 second timeout.\n\n**Example body**:\n```json\n{\"items\": [{\"accession_number\": \"0001193125-24-123456\", \"exhibit_type\": \"EX-99.1\"}]}\n```", + "operationId": "get_exhibit_bulk_api_v1_filings_exhibit_bulk_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BulkExhibitRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BulkExhibitResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/filings/events/{ticker}": { + "get": { + "tags": [ + "filings" + ], + "summary": "Get parsed 8-K events for a ticker", + "description": "Returns structured events parsed from 8-K filings. Each event corresponds to one 8-K Item (e.g., Item 8.01 → other_material_event, Item 2.02 → earnings_result).\\n\\nIf there are unprocessed (pending) filings, they are lazily parsed on first request.\\n\\n**Example**: `GET /filings/events/AVGO?start_date=2026-04-01&event_type=other_material_event`", + "operationId": "get_filing_events_api_v1_filings_events__ticker__get", + "parameters": [ + { + "name": "ticker", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Ticker" + } + }, + { + "name": "start_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Start date YYYY-MM-DD", + "title": "Start Date" + }, + "description": "Start date YYYY-MM-DD" + }, + { + "name": "end_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "End date YYYY-MM-DD", + "title": "End Date" + }, + "description": "End date YYYY-MM-DD" + }, + { + "name": "event_type", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Filter by event type (e.g. other_material_event)", + "title": "Event Type" + }, + "description": "Filter by event type (e.g. other_material_event)" + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 200, + "minimum": 1, + "default": 20, + "title": "Limit" + } + }, + { + "name": "offset", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 0, + "default": 0, + "title": "Offset" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FilingEventsSearchResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/filings/events/parse/bulk": { + "post": { + "tags": [ + "filings" + ], + "summary": "Bulk parse pending 8-K filings", + "description": "Parse 8-K filings and create structured events.\\n\\n- **Default**: processes only `pending` filings.\\n- **`force_reparse=true`**: resets `succeeded`/`failed` filings to `pending` and re-parses them.\\n\\n**Example — reparse specific ticker**: `{\"tickers\": [\"AVGO\"], \"limit\": 50, \"force_reparse\": true}`\\n**Example — backfill all pending**: `{\"limit\": 200}`", + "operationId": "parse_8k_bulk_api_v1_filings_events_parse_bulk_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BulkParseRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BulkParseResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/filings/events/parse/{accession_number}": { + "post": { + "tags": [ + "filings" + ], + "summary": "Force-reparse a single 8-K filing", + "description": "Reparse a specific filing by accession number, regardless of current `parsed_status`.\\n\\n**Example**: `POST /filings/events/parse/0001193125-26-144028`", + "operationId": "parse_8k_single_api_v1_filings_events_parse__accession_number__post", + "parameters": [ + { + "name": "accession_number", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Accession Number" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BulkParseResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/metadata/catalog": { + "get": { + "tags": [ + "metadata" + ], + "summary": "Get data catalog", + "description": "Get a comprehensive catalog of all available data fields.\n \n This endpoint returns:\n - All available financial metrics and their descriptions\n - Data types and units for each field\n - Calculation methods where applicable\n - Data sources for each field\n \n The catalog is organized by categories:\n - Company Information\n - Income Statement\n - Balance Sheet\n - Cash Flow Statement\n - Valuation Ratios\n - Profitability Metrics\n - Growth Metrics\n - Liquidity & Solvency\n - Efficiency Metrics\n - Market Data (Future)", + "operationId": "get_catalog_api_v1_metadata_catalog_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataCatalogResponse" + } + } + } + } + } + } + }, + "/api/v1/admin/migrate": { + "post": { + "tags": [ + "admin" + ], + "summary": "Migrate data from another instance", + "description": "Migrate financial data from another SEC Investment API instance.\n \n This endpoint allows you to:\n - Transfer all data from one instance to another\n - Migrate specific tickers only\n - Migrate data within specific date ranges\n \n Requires valid migration API key in X-API-Key header.", + "operationId": "migrate_data_api_v1_admin_migrate_post", + "parameters": [ + { + "name": "x-api-key", + "in": "header", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Api-Key" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MigrationRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MigrationResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/admin/migration/export/{ticker}": { + "get": { + "tags": [ + "admin" + ], + "summary": "Export data for migration", + "description": "Export financial data for a specific ticker (used by migration process)", + "operationId": "export_data_api_v1_admin_migration_export__ticker__get", + "parameters": [ + { + "name": "ticker", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Ticker" + } + }, + { + "name": "start_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Start Date" + } + }, + { + "name": "end_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "End Date" + } + }, + { + "name": "x-api-key", + "in": "header", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Api-Key" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/database/stats": { + "get": { + "tags": [ + "database" + ], + "summary": "Database record counts and date ranges", + "description": "Returns aggregate statistics across all core tables:\n\n - `companies` — total companies, how many have financial/price data\n - `financial_data` — total records, real vs estimated, date range, breakdown by source\n - `price_data` — total records, date range, list of tickers\n - `calculated_metrics` — total records and date range", + "operationId": "get_database_stats_api_v1_database_stats_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "additionalProperties": true, + "type": "object", + "title": "Response Get Database Stats Api V1 Database Stats Get" + } + } + } + } + } + } + }, + "/api/v1/database/health": { + "get": { + "tags": [ + "database" + ], + "summary": "Database connection health check", + "description": "데이터베이스 연결 상태를 확인합니다.", + "operationId": "get_database_health_api_v1_database_health_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "additionalProperties": true, + "type": "object", + "title": "Response Get Database Health Api V1 Database Health Get" + } + } + } + } + } + } + }, + "/api/v1/database/tables": { + "get": { + "tags": [ + "database" + ], + "summary": "Table row counts for all core tables", + "description": "데이터베이스 테이블 정보를 반환합니다.", + "operationId": "get_table_info_api_v1_database_tables_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "additionalProperties": true, + "type": "object", + "title": "Response Get Table Info Api V1 Database Tables Get" + } + } + } + } + } + } + }, + "/api/v1/database/cleanup/duplicates": { + "post": { + "tags": [ + "database" + ], + "summary": "Remove duplicate financial and metrics records", + "description": "Remove duplicate financial and metrics records, keeping the most recent real data.", + "operationId": "cleanup_duplicate_records_api_v1_database_cleanup_duplicates_post", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "additionalProperties": true, + "type": "object", + "title": "Response Cleanup Duplicate Records Api V1 Database Cleanup Duplicates Post" + } + } + } + } + } + } + }, + "/api/v1/database/tickers": { + "get": { + "tags": [ + "database" + ], + "summary": "List tickers available in the database", + "description": "사용 가능한 종목 목록을 반환합니다.", + "operationId": "get_available_tickers_api_v1_database_tickers_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "additionalProperties": { + "items": { + "type": "string" + }, + "type": "array" + }, + "type": "object", + "title": "Response Get Available Tickers Api V1 Database Tickers Get" + } + } + } + } + } + } + }, + "/api/v1/database/etf/snapshots": { + "get": { + "tags": [ + "database" + ], + "summary": "List persisted ETF holdings snapshots", + "description": "Browse ETF holdings snapshots stored in the database. Each snapshot represents\n the portfolio as reported in a SEC 13-F filing.\n\n Filter by `ticker`, `start_date`, `end_date`. Results are ordered by snapshot date (newest first).\n\n **Example**: `GET /database/etf/snapshots?ticker=SPY&limit=10`", + "operationId": "list_etf_snapshots_api_v1_database_etf_snapshots_get", + "parameters": [ + { + "name": "ticker", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Ticker" + } + }, + { + "name": "start_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Start Date" + } + }, + { + "name": "end_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "End Date" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "default": 50, + "title": "Limit" + } + }, + { + "name": "offset", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "default": 0, + "title": "Offset" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/database/etf/snapshot/{snapshot_id}": { + "get": { + "tags": [ + "database" + ], + "summary": "Get ETF snapshot with full holdings list", + "operationId": "get_etf_snapshot_api_v1_database_etf_snapshot__snapshot_id__get", + "parameters": [ + { + "name": "snapshot_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Snapshot Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/database/financial/records": { + "get": { + "tags": [ + "database" + ], + "summary": "Browse raw financial data records", + "description": "List raw financial data rows from the `financial_data` table.\n\n Supports filtering by `ticker`, `period_type` (`quarterly`/`annual`),\n `start_date`, and `end_date`. Results ordered by `period_date` descending.\n\n **Example**: `GET /database/financial/records?ticker=AAPL&period_type=quarterly&limit=8`", + "operationId": "list_financial_records_api_v1_database_financial_records_get", + "parameters": [ + { + "name": "ticker", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Ticker" + } + }, + { + "name": "period_type", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Period Type" + } + }, + { + "name": "start_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Start Date" + } + }, + { + "name": "end_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "End Date" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "default": 100, + "title": "Limit" + } + }, + { + "name": "offset", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "default": 0, + "title": "Offset" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/admin/errors/logs": { + "get": { + "tags": [ + "error-logs" + ], + "summary": "Get error logs", + "description": "Retrieve error logs with filtering and pagination options.\n \n **Filters:**\n - Date range (start_date, end_date)\n - Error type\n - Status code range\n - Endpoint pattern\n - Resolution status\n \n **Sorting:**\n - By date (newest first by default)\n - By status code\n - By response time\n \n **Pagination:**\n - Configurable page size (default: 50, max: 200)\n - Page-based navigation", + "operationId": "get_error_logs_api_v1_admin_errors_logs_get", + "parameters": [ + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "description": "Page number", + "default": 1, + "title": "Page" + }, + "description": "Page number" + }, + { + "name": "page_size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 200, + "minimum": 1, + "description": "Items per page", + "default": 50, + "title": "Page Size" + }, + "description": "Items per page" + }, + { + "name": "start_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "description": "Filter by start date", + "title": "Start Date" + }, + "description": "Filter by start date" + }, + { + "name": "end_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "description": "Filter by end date", + "title": "End Date" + }, + "description": "Filter by end date" + }, + { + "name": "error_type", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Filter by error type", + "title": "Error Type" + }, + "description": "Filter by error type" + }, + { + "name": "status_code", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Filter by status code", + "title": "Status Code" + }, + "description": "Filter by status code" + }, + { + "name": "endpoint", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Filter by endpoint (supports wildcards)", + "title": "Endpoint" + }, + "description": "Filter by endpoint (supports wildcards)" + }, + { + "name": "is_resolved", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Filter by resolution status", + "title": "Is Resolved" + }, + "description": "Filter by resolution status" + }, + { + "name": "sort_by", + "in": "query", + "required": false, + "schema": { + "type": "string", + "description": "Sort field: created_at, status_code, response_time_ms", + "default": "created_at", + "title": "Sort By" + }, + "description": "Sort field: created_at, status_code, response_time_ms" + }, + { + "name": "sort_order", + "in": "query", + "required": false, + "schema": { + "type": "string", + "description": "Sort order: asc or desc", + "default": "desc", + "title": "Sort Order" + }, + "description": "Sort order: asc or desc" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorLogListResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "delete": { + "tags": [ + "error-logs" + ], + "summary": "Delete all error logs", + "description": "Delete all error logs (use with caution)", + "operationId": "delete_all_error_logs_api_v1_admin_errors_logs_delete", + "parameters": [ + { + "name": "confirm", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Must be true to confirm deletion", + "default": false, + "title": "Confirm" + }, + "description": "Must be true to confirm deletion" + }, + { + "name": "only_resolved", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Only delete resolved errors", + "default": false, + "title": "Only Resolved" + }, + "description": "Only delete resolved errors" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/admin/errors/logs/{log_id}": { + "get": { + "tags": [ + "error-logs" + ], + "summary": "Get error log by ID", + "description": "Retrieve detailed information about a specific error log", + "operationId": "get_error_log_api_v1_admin_errors_logs__log_id__get", + "parameters": [ + { + "name": "log_id", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "title": "Log Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorLogResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "patch": { + "tags": [ + "error-logs" + ], + "summary": "Update error log", + "description": "Update error log resolution status and notes", + "operationId": "update_error_log_api_v1_admin_errors_logs__log_id__patch", + "parameters": [ + { + "name": "log_id", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "title": "Log Id" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorLogUpdate" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorLogResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/admin/errors/by-request/{request_id}": { + "get": { + "tags": [ + "error-logs" + ], + "summary": "Get error log by request ID", + "description": "Retrieve error log information for a specific request ID", + "operationId": "get_error_by_request_id_api_v1_admin_errors_by_request__request_id__get", + "parameters": [ + { + "name": "request_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Request Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorLogResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/admin/errors/stats": { + "get": { + "tags": [ + "error-logs" + ], + "summary": "Get error statistics", + "description": "Get aggregated statistics about errors.\n \n **Statistics include:**\n - Total error count\n - Errors by type\n - Errors by status code\n - Errors by endpoint\n - Time-based trends\n - Resolution rate", + "operationId": "get_error_stats_api_v1_admin_errors_stats_get", + "parameters": [ + { + "name": "start_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "description": "Start date for statistics", + "title": "Start Date" + }, + "description": "Start date for statistics" + }, + { + "name": "end_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "description": "End date for statistics", + "title": "End Date" + }, + "description": "End date for statistics" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorLogStats" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/admin/errors/logs/old": { + "delete": { + "tags": [ + "error-logs" + ], + "summary": "Delete old error logs", + "description": "Delete error logs older than specified days", + "operationId": "delete_old_logs_api_v1_admin_errors_logs_old_delete", + "parameters": [ + { + "name": "days_old", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 365, + "minimum": 1, + "description": "Delete logs older than this many days", + "default": 30, + "title": "Days Old" + }, + "description": "Delete logs older than this many days" + }, + { + "name": "only_resolved", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Only delete resolved errors", + "default": true, + "title": "Only Resolved" + }, + "description": "Only delete resolved errors" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/admin/requests/logs": { + "get": { + "tags": [ + "request-logs" + ], + "summary": "Get request logs", + "description": "Retrieve request logs with filtering and pagination options.\n \n **Filters:**\n - Date range (start_date, end_date)\n - HTTP method\n - Status code range\n - Endpoint pattern\n - Response time range\n \n **Sorting:**\n - By date (newest first by default)\n - By status code\n - By response time\n \n **Pagination:**\n - Configurable page size (default: 50, max: 200)\n - Page-based navigation", + "operationId": "get_request_logs_api_v1_admin_requests_logs_get", + "parameters": [ + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "description": "Page number", + "default": 1, + "title": "Page" + }, + "description": "Page number" + }, + { + "name": "page_size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 200, + "minimum": 1, + "description": "Items per page", + "default": 50, + "title": "Page Size" + }, + "description": "Items per page" + }, + { + "name": "start_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "description": "Filter by start date", + "title": "Start Date" + }, + "description": "Filter by start date" + }, + { + "name": "end_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "description": "Filter by end date", + "title": "End Date" + }, + "description": "Filter by end date" + }, + { + "name": "method", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Filter by HTTP method", + "title": "Method" + }, + "description": "Filter by HTTP method" + }, + { + "name": "status_code", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Filter by exact status code", + "title": "Status Code" + }, + "description": "Filter by exact status code" + }, + { + "name": "min_status_code", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Filter by minimum status code (e.g. 500 for all 5xx)", + "title": "Min Status Code" + }, + "description": "Filter by minimum status code (e.g. 500 for all 5xx)" + }, + { + "name": "max_status_code", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Filter by maximum status code (e.g. 599 for all 5xx)", + "title": "Max Status Code" + }, + "description": "Filter by maximum status code (e.g. 599 for all 5xx)" + }, + { + "name": "endpoint", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Filter by endpoint (supports wildcards)", + "title": "Endpoint" + }, + "description": "Filter by endpoint (supports wildcards)" + }, + { + "name": "min_response_time", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Minimum response time in ms", + "title": "Min Response Time" + }, + "description": "Minimum response time in ms" + }, + { + "name": "max_response_time", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Maximum response time in ms", + "title": "Max Response Time" + }, + "description": "Maximum response time in ms" + }, + { + "name": "sort_by", + "in": "query", + "required": false, + "schema": { + "type": "string", + "description": "Sort field: created_at, status_code, response_time_ms", + "default": "created_at", + "title": "Sort By" + }, + "description": "Sort field: created_at, status_code, response_time_ms" + }, + { + "name": "sort_order", + "in": "query", + "required": false, + "schema": { + "type": "string", + "description": "Sort order: asc or desc", + "default": "desc", + "title": "Sort Order" + }, + "description": "Sort order: asc or desc" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RequestLogListResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "delete": { + "tags": [ + "request-logs" + ], + "summary": "Delete all request logs", + "description": "Delete all request logs (use with caution)", + "operationId": "delete_all_request_logs_api_v1_admin_requests_logs_delete", + "parameters": [ + { + "name": "confirm", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Must be true to confirm deletion", + "default": false, + "title": "Confirm" + }, + "description": "Must be true to confirm deletion" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/admin/requests/logs/{log_id}": { + "get": { + "tags": [ + "request-logs" + ], + "summary": "Get request log by ID", + "description": "Retrieve detailed information about a specific request log", + "operationId": "get_request_log_api_v1_admin_requests_logs__log_id__get", + "parameters": [ + { + "name": "log_id", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "title": "Log Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RequestLogResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/admin/requests/stats": { + "get": { + "tags": [ + "request-logs" + ], + "summary": "Get request statistics", + "description": "Get aggregated statistics about API requests.\n \n **Statistics include:**\n - Total request count\n - Success/error rates\n - Requests by method\n - Requests by status code\n - Requests by endpoint\n - Time-based trends\n - Average response time", + "operationId": "get_request_stats_api_v1_admin_requests_stats_get", + "parameters": [ + { + "name": "start_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "description": "Start date for statistics", + "title": "Start Date" + }, + "description": "Start date for statistics" + }, + { + "name": "end_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "description": "End date for statistics", + "title": "End Date" + }, + "description": "End date for statistics" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RequestLogStats" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/admin/requests/logs/old": { + "delete": { + "tags": [ + "request-logs" + ], + "summary": "Delete old request logs", + "description": "Delete request logs older than specified days", + "operationId": "delete_old_request_logs_api_v1_admin_requests_logs_old_delete", + "parameters": [ + { + "name": "days_old", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 365, + "minimum": 1, + "description": "Delete logs older than this many days", + "default": 30, + "title": "Days Old" + }, + "description": "Delete logs older than this many days" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/alpaca/status": { + "get": { + "tags": [ + "alpaca" + ], + "summary": "Alpaca connection status", + "description": "Check Alpaca API key validity and connection health.", + "operationId": "alpaca_status_api_v1_alpaca_status_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + } + } + } + }, + "/api/v1/alpaca/intraday": { + "get": { + "tags": [ + "alpaca" + ], + "summary": "Get historical intraday bars for multiple tickers (SIP feed, DB-backed)", + "description": "멀티 종목 과거 분봉 데이터를 Alpaca **SIP 피드**로 가져옵니다. DB에 저장되며 재요청 시 Alpaca 미호출.\n\n**⚠️ 장 중 당일 데이터 불가** — 장 마감(오후 4시 ET) 후에는 당일 날짜도 조회 가능\n\n| 항목 | 내용 |\n|------|------|\n| 피드 | **SIP** (전체 미국 거래소 통합) |\n| 거래량 | **100%** 정확 |\n| 조회 범위 | **2016년~오늘(장 마감 후)** |\n| DB 저장 | 있음 (재요청 시 Alpaca 미사용) |\n\n**권장 용도**: 백테스트, 과거 분봉 분석\n\n- `tickers`: comma-separated, e.g. `AAPL,MSFT,BF-B`\n- `interval`: `1m`, `5m`, `15m`, `30m`, `1h`\n- 내부 100개 단위 자동 배치 분할 (500종목 → Alpaca 5회 호출)\n- Requires `ALPACA_API_KEY` / `ALPACA_SECRET_KEY`", + "operationId": "get_alpaca_intraday_multi_api_v1_alpaca_intraday_get", + "parameters": [ + { + "name": "tickers", + "in": "query", + "required": true, + "schema": { + "type": "string", + "description": "Comma-separated tickers, e.g. AAPL,MSFT,BF-B", + "title": "Tickers" + }, + "description": "Comma-separated tickers, e.g. AAPL,MSFT,BF-B" + }, + { + "name": "interval", + "in": "query", + "required": false, + "schema": { + "type": "string", + "description": "Interval: 1m, 5m, 15m, 30m, 1h", + "default": "5m", + "title": "Interval" + }, + "description": "Interval: 1m, 5m, 15m, 30m, 1h" + }, + { + "name": "start_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "description": "Start date (YYYY-MM-DD). Default: yesterday", + "title": "Start Date" + }, + "description": "Start date (YYYY-MM-DD). Default: yesterday" + }, + { + "name": "end_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "description": "End date (YYYY-MM-DD). Must be before today. Default: yesterday", + "title": "End Date" + }, + "description": "End date (YYYY-MM-DD). Must be before today. Default: yesterday" + }, + { + "name": "force_refresh", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Re-fetch from Alpaca even if DB has data", + "default": false, + "title": "Force Refresh" + }, + "description": "Re-fetch from Alpaca even if DB has data" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AlpacaMultiBarsResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/alpaca/intraday/today": { + "get": { + "tags": [ + "alpaca" + ], + "summary": "Get today's real-time intraday bars for multiple tickers (IEX feed, DB-backed)", + "description": "당일(오늘) 실시간 분봉 데이터를 Alpaca **IEX 피드**로 가져옵니다. 장 중 재요청 시 항상 Alpaca에서 최신 데이터를 가져옵니다.\n\n**⚠️ 오늘 데이터만 조회 가능** — 과거 데이터는 `/intraday` 사용\n\n| 항목 | 내용 |\n|------|------|\n| 피드 | **IEX** (IEX 거래소 단일) |\n| 지연 | **실시간** (지연 없음) |\n| 거래량 | 실제의 약 **2~5%** (IEX 거래소 거래만 집계) |\n| High/Low range | SIP 대비 좁게 표시될 수 있음 |\n| DB 저장 | 있음 (장 중 항상 재조회) |\n\n**권장 용도**: 당일 ORB 전략, 실시간 장 중 모니터링\n\n- `tickers`: comma-separated, e.g. `AAPL,MSFT,BF-B`\n- `interval`: `1m`, `5m`, `15m`, `30m`, `1h`\n- 내부 100개 단위 자동 배치 분할\n- Requires `ALPACA_API_KEY` / `ALPACA_SECRET_KEY`", + "operationId": "get_alpaca_intraday_today_api_v1_alpaca_intraday_today_get", + "parameters": [ + { + "name": "tickers", + "in": "query", + "required": true, + "schema": { + "type": "string", + "description": "Comma-separated tickers, e.g. AAPL,MSFT,BF-B", + "title": "Tickers" + }, + "description": "Comma-separated tickers, e.g. AAPL,MSFT,BF-B" + }, + { + "name": "interval", + "in": "query", + "required": false, + "schema": { + "type": "string", + "description": "Interval: 1m, 5m, 15m, 30m, 1h", + "default": "5m", + "title": "Interval" + }, + "description": "Interval: 1m, 5m, 15m, 30m, 1h" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AlpacaMultiBarsResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/alpaca/snapshot": { + "get": { + "tags": [ + "alpaca" + ], + "summary": "Real-time snapshots for multiple tickers (IEX feed)", + "description": "멀티 종목 실시간 스냅샷. 최신 체결가, bid/ask, 당일 OHLCV, 전일 대비 변동률 포함.\n\n단일 종목도 `?tickers=AAPL`로 조회 가능.\n\n| 항목 | 내용 |\n|------|------|\n| 피드 | **IEX** — 무료 플랜에서 snapshot은 SIP 불가 |\n| 지연 | **실시간** (지연 없음) |\n| 거래량 | IEX 기준 (실제의 2~5%) |\n| 캐시 | **없음** — 매 요청마다 Alpaca 직접 호출 |\n\n- Requires `ALPACA_API_KEY` / `ALPACA_SECRET_KEY`", + "operationId": "get_snapshots_api_v1_alpaca_snapshot_get", + "parameters": [ + { + "name": "tickers", + "in": "query", + "required": true, + "schema": { + "type": "string", + "description": "Comma-separated ticker symbols, e.g. AAPL,MSFT,NVDA", + "title": "Tickers" + }, + "description": "Comma-separated ticker symbols, e.g. AAPL,MSFT,NVDA" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AlpacaMultiSnapshotResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/finra/short-volume/{symbol}": { + "get": { + "tags": [ + "finra" + ], + "summary": "Get short volume data for a symbol", + "description": "Query FINRA RegSHO short sale volume. Auto-ingests if data is missing.\n\n**DB 보유**: 2021년 ~ 현재 (5년치 백필 완료). 추가 백필: `POST /finra/admin/ingest?start_date=YYYY-MM-DD&end_date=YYYY-MM-DD`\n\n**데이터 소스**: FINRA RegSHO CDN (공개, API 키 불필요). 주말/공휴일 데이터 없음.", + "operationId": "get_short_volume_api_v1_finra_short_volume__symbol__get", + "parameters": [ + { + "name": "symbol", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Symbol" + } + }, + { + "name": "days", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 3650, + "minimum": 1, + "description": "Number of days to look back (max ~10 years)", + "default": 30, + "title": "Days" + }, + "description": "Number of days to look back (max ~10 years)" + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 10000, + "minimum": 1, + "description": "Max entries to return", + "default": 100, + "title": "Limit" + }, + "description": "Max entries to return" + }, + { + "name": "force_refresh", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Bypass cache", + "default": false, + "title": "Force Refresh" + }, + "description": "Bypass cache" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ShortVolumeResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/finra/short-ratio/{symbol}": { + "get": { + "tags": [ + "finra" + ], + "summary": "Get short ratio history for a symbol", + "description": "Return daily short_ratio (aggregated across markets) for the last N days.\n\n**DB 보유**: 2021년 ~ 현재 (5년치). days 최대 3650 (10년).\n\n추가 백필: `POST /finra/admin/ingest?start_date=YYYY-MM-DD&end_date=YYYY-MM-DD`", + "operationId": "get_short_ratio_api_v1_finra_short_ratio__symbol__get", + "parameters": [ + { + "name": "symbol", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Symbol" + } + }, + { + "name": "days", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 3650, + "minimum": 1, + "description": "Number of days (max ~10 years)", + "default": 60, + "title": "Days" + }, + "description": "Number of days (max ~10 years)" + }, + { + "name": "force_refresh", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Bypass cache", + "default": false, + "title": "Force Refresh" + }, + "description": "Bypass cache" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ShortRatioHistoryResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/finra/admin/ingest": { + "post": { + "tags": [ + "finra" + ], + "summary": "Manually ingest FINRA short volume data", + "description": "Download and ingest FINRA short volume file(s) for a specific date or date range.\n\n**백필 예시**:\n- 단일 날짜: `?date=2025-01-15`\n- 날짜 범위: `?start_date=2025-01-01&end_date=2025-12-31`\n- 이미 있는 데이터 재인제스트: `?start_date=...&end_date=...&force=true`\n\n주말/공휴일은 자동으로 건너뜀. 1년치 기준 약 20-40분 소요.", + "operationId": "ingest_short_volume_api_v1_finra_admin_ingest_post", + "parameters": [ + { + "name": "date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Single date (YYYY-MM-DD)", + "title": "Date" + }, + "description": "Single date (YYYY-MM-DD)" + }, + { + "name": "start_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "description": "Range start (YYYY-MM-DD)", + "title": "Start Date" + }, + "description": "Range start (YYYY-MM-DD)" + }, + { + "name": "end_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "description": "Range end (YYYY-MM-DD)", + "title": "End Date" + }, + "description": "Range end (YYYY-MM-DD)" + }, + { + "name": "force", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Re-ingest even if data exists", + "default": false, + "title": "Force" + }, + "description": "Re-ingest even if data exists" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IngestResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/overlay/admin/job-log": { + "get": { + "tags": [ + "overlay", + "overlay-admin" + ], + "summary": "Overlay job log", + "operationId": "get_job_log_api_v1_overlay_admin_job_log_get", + "parameters": [ + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 500, + "minimum": 1, + "default": 50, + "title": "Limit" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/JobLogResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/overlay/{symbol}/headlines": { + "get": { + "tags": [ + "overlay" + ], + "summary": "Recent headlines for a symbol", + "operationId": "get_headlines_api_v1_overlay__symbol__headlines_get", + "parameters": [ + { + "name": "symbol", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Symbol" + } + }, + { + "name": "hours", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 168, + "minimum": 1, + "default": 24, + "title": "Hours" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/app__api__v1__endpoints__overlay__HeadlinesResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/screener/stocks": { + "get": { + "tags": [ + "screener" + ], + "summary": "Screen stocks by financial criteria", + "description": "Screen stocks based on financial criteria using yfinance.\n\nFilters stocks from US exchanges (NYSE, NASDAQ, AMEX, NYSE_ARCA) by market cap,\nvolume, price, P/E ratio, sector, and more. Results are paginated and cached for\n5 minutes.\n\n**Exchange mapping**:\n- `NYSE` → NYQ\n- `NASDAQ` → NMS, NGM, NCM\n- `AMEX` → ASE\n- `NYSE_ARCA` → PCX\n\n**Important limitations**:\n- `page_size` maximum is 250 (Yahoo Finance API limit)\n- `sector` filtering works but sector is NOT returned per-stock in the response\n- Results reflect real-time Yahoo Finance data\n\n**Example**:\n```\nGET /screener/stocks?market_cap_min=500000000&market_cap_max=10000000000\n &exchange=NYSE,NASDAQ&min_avg_volume=500000&exclude_types=ETF,FUND\n &sort_by=market_cap&page=1&page_size=100\n```", + "operationId": "screen_stocks_api_v1_screener_stocks_get", + "parameters": [ + { + "name": "market_cap_min", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "number", + "minimum": 0 + }, + { + "type": "null" + } + ], + "description": "Minimum market cap in USD (e.g. 500000000 for $500M)", + "title": "Market Cap Min" + }, + "description": "Minimum market cap in USD (e.g. 500000000 for $500M)" + }, + { + "name": "market_cap_max", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "number", + "minimum": 0 + }, + { + "type": "null" + } + ], + "description": "Maximum market cap in USD (e.g. 10000000000 for $10B)", + "title": "Market Cap Max" + }, + "description": "Maximum market cap in USD (e.g. 10000000000 for $10B)" + }, + { + "name": "exchange", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Comma-separated exchange names: NYSE, NASDAQ, AMEX, NYSE_ARCA. Omit for all US exchanges.", + "title": "Exchange" + }, + "description": "Comma-separated exchange names: NYSE, NASDAQ, AMEX, NYSE_ARCA. Omit for all US exchanges." + }, + { + "name": "min_avg_volume", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "integer", + "minimum": 0 + }, + { + "type": "null" + } + ], + "description": "Minimum 3-month average daily volume (e.g. 500000)", + "title": "Min Avg Volume" + }, + "description": "Minimum 3-month average daily volume (e.g. 500000)" + }, + { + "name": "exclude_types", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Comma-separated quote types to exclude (e.g. ETF,FUND). Only EQUITY results are kept when specified.", + "title": "Exclude Types" + }, + "description": "Comma-separated quote types to exclude (e.g. ETF,FUND). Only EQUITY results are kept when specified." + }, + { + "name": "sector", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Filter by sector (e.g. Technology, Healthcare, 'Financial Services'). Note: sector is not returned per-stock in the response.", + "title": "Sector" + }, + "description": "Filter by sector (e.g. Technology, Healthcare, 'Financial Services'). Note: sector is not returned per-stock in the response." + }, + { + "name": "pe_min", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "number", + "minimum": 0 + }, + { + "type": "null" + } + ], + "description": "Minimum trailing P/E ratio", + "title": "Pe Min" + }, + "description": "Minimum trailing P/E ratio" + }, + { + "name": "pe_max", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "number", + "minimum": 0 + }, + { + "type": "null" + } + ], + "description": "Maximum trailing P/E ratio", + "title": "Pe Max" + }, + "description": "Maximum trailing P/E ratio" + }, + { + "name": "price_min", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "number", + "minimum": 0 + }, + { + "type": "null" + } + ], + "description": "Minimum stock price in USD", + "title": "Price Min" + }, + "description": "Minimum stock price in USD" + }, + { + "name": "price_max", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "number", + "minimum": 0 + }, + { + "type": "null" + } + ], + "description": "Maximum stock price in USD", + "title": "Price Max" + }, + "description": "Maximum stock price in USD" + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "description": "Page number (1-based)", + "default": 1, + "title": "Page" + }, + "description": "Page number (1-based)" + }, + { + "name": "page_size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 250, + "minimum": 1, + "description": "Results per page (max 250, Yahoo API limit)", + "default": 100, + "title": "Page Size" + }, + "description": "Results per page (max 250, Yahoo API limit)" + }, + { + "name": "sort_by", + "in": "query", + "required": false, + "schema": { + "type": "string", + "description": "Sort field: market_cap, volume, avg_volume, price, pe_ratio, change_percent, name, eps, dividend_yield, forward_pe, price_to_book", + "default": "market_cap", + "title": "Sort By" + }, + "description": "Sort field: market_cap, volume, avg_volume, price, pe_ratio, change_percent, name, eps, dividend_yield, forward_pe, price_to_book" + }, + { + "name": "sort_ascending", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Sort ascending (default: descending)", + "default": false, + "title": "Sort Ascending" + }, + "description": "Sort ascending (default: descending)" + }, + { + "name": "force_refresh", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Bypass cache and fetch fresh data", + "default": false, + "title": "Force Refresh" + }, + "description": "Bypass cache and fetch fresh data" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/screener/fields": { + "get": { + "tags": [ + "screener" + ], + "summary": "Available screener filter options and valid values", + "description": "Return metadata about available screener filter options.\n\nUseful for building dynamic filter UIs — lists all valid exchange names,\nsectors, sort fields, and parameter descriptions.", + "operationId": "get_screener_fields_api_v1_screener_fields_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + } + } + } + }, + "/api/v1/attention/admin/resolve/{ticker}": { + "post": { + "tags": [ + "attention", + "attention-admin" + ], + "summary": "Resolve ticker → canonical entity", + "description": "Maps a ticker symbol to a canonical company entity by looking up the company name, normalizing it, and validating against Wikipedia. Stores the result (canonical name, wiki_title, gdelt_query) in `company_entity_map`.\n\nSkips re-resolution if `is_manual_override` is set. If the company name in the DB is a placeholder (e.g. 'AMZN Corporation'), falls back to SEC company_tickers.json to fetch the real name and updates the DB.", + "operationId": "admin_resolve_entity_api_v1_attention_admin_resolve__ticker__post", + "parameters": [ + { + "name": "ticker", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Ticker" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntityResolveResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/attention/admin/collect/wiki/{ticker}": { + "post": { + "tags": [ + "attention", + "attention-admin" + ], + "summary": "Collect Wikipedia pageviews for an event date", + "description": "Fetches daily Wikipedia pageview counts for the ticker's canonical wiki_title, covering `event_date` and enough lookback days (≥20) to compute spike and z-score. Safe to call on-demand — Wikipedia API has no meaningful rate limit for this use.\n\nRequires entity resolution to have been run first (`wiki_title` must be set).", + "operationId": "admin_collect_wiki_api_v1_attention_admin_collect_wiki__ticker__post", + "parameters": [ + { + "name": "ticker", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Ticker" + } + }, + { + "name": "event_date", + "in": "query", + "required": true, + "schema": { + "type": "string", + "format": "date", + "description": "Event date in YYYY-MM-DD format", + "title": "Event Date" + }, + "description": "Event date in YYYY-MM-DD format" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CollectionStatusResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/attention/admin/collect/gdelt/{ticker}": { + "post": { + "tags": [ + "attention", + "attention-admin" + ], + "summary": "Collect GDELT news articles for an event date", + "description": "Fetches news articles from GDELT V2 DOC API for the window `event_date ± 1 day`.\n\n**Coverage**: 2017-01-01 onwards. Requests for earlier dates return 0 immediately.\n\n**Rate limit**: GDELT enforces a global per-IP quota. This endpoint is protected by a process-wide lock (10s minimum interval) and retries with exponential backoff (30s → 60s → 120s) on 429 responses.\n\n⚠️ **Call this endpoint from a scheduler only** — never trigger it in response to user requests. Concurrent or rapid calls will exhaust the IP quota and cause temporary bans. The main `/event/{ticker}` endpoint intentionally does NOT collect GDELT on-demand for this reason.", + "operationId": "admin_collect_gdelt_api_v1_attention_admin_collect_gdelt__ticker__post", + "parameters": [ + { + "name": "ticker", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Ticker" + } + }, + { + "name": "event_date", + "in": "query", + "required": true, + "schema": { + "type": "string", + "format": "date", + "description": "Event date in YYYY-MM-DD format", + "title": "Event Date" + }, + "description": "Event date in YYYY-MM-DD format" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CollectionStatusResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/attention/entity/{ticker}": { + "get": { + "tags": [ + "attention" + ], + "summary": "Get entity mapping for a ticker", + "description": "Returns the stored entity mapping for a ticker: canonical name, Wikipedia title,\n GDELT query string, and resolver confidence score.\n\n Returns **404** if no mapping exists — run `POST /admin/resolve/{ticker}` first.\n\n **Example**: `GET /attention/entity/AAPL`", + "operationId": "get_entity_api_v1_attention_entity__ticker__get", + "parameters": [ + { + "name": "ticker", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Ticker" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntityResolveResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/attention/event/{ticker}": { + "get": { + "tags": [ + "attention" + ], + "summary": "Get attention features for a ticker on an event date", + "description": "Returns Wikipedia pageview spike/z-score and GDELT news volume for a ticker\n centered on a specific event date. Designed for event-driven backtesting.\n\n **Wikipedia signals** (collected on-demand):\n - `wiki.views` — raw pageview count on `event_date`\n - `wiki.spike_10d` — views / 10-day median baseline; >1 = above-average interest\n - `wiki.zscore_20d` — standard-deviation units above 20-day mean\n\n **GDELT news signals** (pre-populated by scheduler only):\n - `news.article_count_1d` — articles published on `event_date`\n - `news.article_count_3d` — articles in `event_date ± 1 day` window\n - `news.unique_domains_3d` — distinct publisher domains in that window\n - `news.gdelt_status` — data availability flag:\n - `collected` — scheduler ran; counts are accurate (0 = genuinely no articles)\n - `not_collected` — scheduler has not run yet; use `POST /admin/collect/gdelt/{ticker}`\n - `not_available` — event date is before GDELT V2 coverage (2017-01-01)\n\n **Auto-resolution**: if no entity mapping exists, resolution runs automatically first.\n\n **Examples**:\n - `GET /attention/event/AAPL?event_date=2024-02-01` — Q1 earnings day attention\n - `GET /attention/event/NVDA?event_date=2024-05-22` — post-earnings spike", + "operationId": "get_event_attention_api_v1_attention_event__ticker__get", + "parameters": [ + { + "name": "ticker", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Ticker" + } + }, + { + "name": "event_date", + "in": "query", + "required": true, + "schema": { + "type": "string", + "format": "date", + "description": "Event date in YYYY-MM-DD format", + "title": "Event Date" + }, + "description": "Event date in YYYY-MM-DD format" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EventAttentionResponse" + } + } + } + }, + "404": { + "description": "Ticker not found or entity resolution failed" + }, + "500": { + "description": "Feature materialization or collection error" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/insider/transactions/{symbol}": { + "get": { + "tags": [ + "insider" + ], + "summary": "Get insider transactions for a symbol", + "description": "Query SEC Form 4 insider trading data. Auto-fetches from SEC EDGAR if data is missing.\n\n**데이터 소스**: SEC EDGAR (무료, API 키 불필요). 첫 조회 시 자동 인덱싱.\n\n**Transaction codes**: P=Purchase, S=Sale, A=Award, M=Exercise, G=Gift, F=Tax Withholding", + "operationId": "get_insider_transactions_api_v1_insider_transactions__symbol__get", + "parameters": [ + { + "name": "symbol", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Symbol" + } + }, + { + "name": "days", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 3650, + "minimum": 1, + "description": "Days to look back (max ~10 years)", + "default": 90, + "title": "Days" + }, + "description": "Days to look back (max ~10 years)" + }, + { + "name": "transaction_type", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Filter: P=Purchase, S=Sale, A=Award, M=Exercise", + "title": "Transaction Type" + }, + "description": "Filter: P=Purchase, S=Sale, A=Award, M=Exercise" + }, + { + "name": "insider_title", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Filter by title keyword (e.g., CEO, CFO, Director)", + "title": "Insider Title" + }, + "description": "Filter by title keyword (e.g., CEO, CFO, Director)" + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 500, + "minimum": 1, + "description": "Max entries to return", + "default": 50, + "title": "Limit" + }, + "description": "Max entries to return" + }, + { + "name": "force_refresh", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Bypass cache and re-fetch from SEC", + "default": false, + "title": "Force Refresh" + }, + "description": "Bypass cache and re-fetch from SEC" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InsiderTransactionResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/insider/summary/{symbol}": { + "get": { + "tags": [ + "insider" + ], + "summary": "Get insider trading summary", + "description": "Aggregated insider buy/sell activity for 3, 6, and 12 month periods.\n\nIncludes net buy/sell shares and values, plus top 5 notable transactions by value.", + "operationId": "get_insider_summary_api_v1_insider_summary__symbol__get", + "parameters": [ + { + "name": "symbol", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Symbol" + } + }, + { + "name": "force_refresh", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Bypass cache", + "default": false, + "title": "Force Refresh" + }, + "description": "Bypass cache" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InsiderSummaryResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/insider/form4/{ticker}": { + "get": { + "tags": [ + "insider" + ], + "summary": "PIT-safe Form 4 insider transactions", + "description": "Returns Form 4 transactions for a ticker where **filing_date ≤ as_of** (point-in-time safe).\n\n`as_of` is required to prevent lookahead in backtests.\n\n`start`/`end` also filter by `filing_date` (not transaction_date).\n\nIf no data exists for the ticker, auto-fetches ~2 years of history from SEC EDGAR (first call may take 1–3 min).", + "operationId": "get_form4_api_v1_insider_form4__ticker__get", + "parameters": [ + { + "name": "ticker", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Ticker" + } + }, + { + "name": "as_of", + "in": "query", + "required": true, + "schema": { + "type": "string", + "format": "date", + "description": "Point-in-time cutoff (filing_date ≤ as_of). Required.", + "title": "As Of" + }, + "description": "Point-in-time cutoff (filing_date ≤ as_of). Required." + }, + { + "name": "start", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "description": "Window start (filing_date ≥ start)", + "title": "Start" + }, + "description": "Window start (filing_date ≥ start)" + }, + { + "name": "end", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "description": "Window end (filing_date ≤ end)", + "title": "End" + }, + "description": "Window end (filing_date ≤ end)" + }, + { + "name": "buy_only", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Only return open-market purchases (transaction_code=P, shares > 0). Excludes awards/grants.", + "default": false, + "title": "Buy Only" + }, + "description": "Only return open-market purchases (transaction_code=P, shares > 0). Excludes awards/grants." + }, + { + "name": "csuite_only", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Only return C-suite insider transactions", + "default": false, + "title": "Csuite Only" + }, + "description": "Only return C-suite insider transactions" + }, + { + "name": "force_refresh", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Re-fetch ~2yr of Form 4 history from SEC EDGAR before querying. Slow on first call.", + "default": false, + "title": "Force Refresh" + }, + "description": "Re-fetch ~2yr of Form 4 history from SEC EDGAR before querying. Slow on first call." + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Form4Response" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/insider/form4/by-date/{filing_date}": { + "get": { + "tags": [ + "insider" + ], + "summary": "Form 4 filings by a specific date (cross-ticker)", + "description": "Returns all Form 4 transactions where filing_date equals the given date. Useful for pre-market screening.", + "operationId": "get_form4_by_date_api_v1_insider_form4_by_date__filing_date__get", + "parameters": [ + { + "name": "filing_date", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "date", + "title": "Filing Date" + } + }, + { + "name": "buy_only", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Only return open-market purchases (transaction_code=P). Excludes awards/grants.", + "default": false, + "title": "Buy Only" + }, + "description": "Only return open-market purchases (transaction_code=P). Excludes awards/grants." + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Form4ByDateResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/insider/form4/aggregate/{ticker}": { + "get": { + "tags": [ + "insider" + ], + "summary": "Aggregate Form 4 buy activity (PIT-safe)", + "description": "Aggregated insider buy metrics within [as_of - window_days, as_of].\n\nAll based on `filing_date` (PIT-safe). Returns buy_count, buy_dollar_total, cluster_size (unique insiders), csuite_count, avg_pct_of_holding, recency_days.\n\nIf no data exists for the ticker, auto-fetches ~2 years of history from SEC EDGAR.", + "operationId": "get_form4_aggregate_api_v1_insider_form4_aggregate__ticker__get", + "parameters": [ + { + "name": "ticker", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Ticker" + } + }, + { + "name": "as_of", + "in": "query", + "required": true, + "schema": { + "type": "string", + "format": "date", + "description": "Point-in-time cutoff. Required.", + "title": "As Of" + }, + "description": "Point-in-time cutoff. Required." + }, + { + "name": "window_days", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 365, + "minimum": 1, + "description": "Lookback window in days", + "default": 30, + "title": "Window Days" + }, + "description": "Lookback window in days" + }, + { + "name": "force_refresh", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Re-fetch ~2yr of Form 4 history from SEC EDGAR before querying.", + "default": false, + "title": "Force Refresh" + }, + "description": "Re-fetch ~2yr of Form 4 history from SEC EDGAR before querying." + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Form4AggregateResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/earnings/calendar/{symbol}": { + "get": { + "tags": [ + "earnings" + ], + "summary": "Get upcoming earnings dates for a symbol", + "description": "Upcoming earnings announcement dates with EPS estimates.\n\n**데이터 소스**: yfinance-plus (`Ticker.earnings_dates`). API 키 불필요.\n**earnings_time**: `pre_market` / `post_market` / `during_market` / `unknown`.\n\n**PIT (Point-in-Time) backtesting**: `as_of_date`를 지정하면 해당 날짜 기준 upcoming earnings를 반환합니다. 이미 보고된 earnings도 당시엔 예정이었으므로 `reported_eps`가 채워진 상태로 반환됩니다.\n\n**Note**: Revenue estimates are not available from this source.", + "operationId": "get_earnings_calendar_api_v1_earnings_calendar__symbol__get", + "parameters": [ + { + "name": "symbol", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Symbol" + } + }, + { + "name": "days_ahead", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 365, + "minimum": 1, + "description": "Days to look ahead from as_of_date (or today)", + "default": 30, + "title": "Days Ahead" + }, + "description": "Days to look ahead from as_of_date (or today)" + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 20, + "minimum": 1, + "description": "Max earnings dates to return", + "default": 4, + "title": "Limit" + }, + "description": "Max earnings dates to return" + }, + { + "name": "as_of_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "description": "PIT date for backtesting (YYYY-MM-DD). Defaults to today.", + "title": "As Of Date" + }, + "description": "PIT date for backtesting (YYYY-MM-DD). Defaults to today." + }, + { + "name": "force_refresh", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Bypass cache and re-fetch from yfinance", + "default": false, + "title": "Force Refresh" + }, + "description": "Bypass cache and re-fetch from yfinance" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EarningsCalendarResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/earnings/calendar/bulk": { + "post": { + "tags": [ + "earnings" + ], + "summary": "Bulk future earnings calendar", + "description": "Fetch upcoming earnings dates for multiple symbols (max 50).\n\nReturns a flat list of calendar entries sorted by `earnings_date` ascending.\nUseful for checking upcoming earnings of sector peers or candidates.", + "operationId": "get_bulk_earnings_calendar_api_v1_earnings_calendar_bulk_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BulkEarningsCalendarRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BulkEarningsCalendarResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/earnings/surprise/{symbol}": { + "get": { + "tags": [ + "earnings" + ], + "summary": "Get earnings surprise history", + "description": "Quarterly EPS surprise: reported vs analyst consensus estimate.\n\n**데이터 소스**: yfinance-plus (`Ticker.earnings_dates`). API 키 불필요.\n**커버리지**: ~25분기 (6년+). 첫 조회 시 자동 인덱싱.\n\n**surprise** = reported_eps - estimated_eps.\n**surprise_percentage** = (surprise / estimated) × 100.\n**streak**: 연속 beat (양수) 또는 miss (음수) 횟수.", + "operationId": "get_earnings_surprise_api_v1_earnings_surprise__symbol__get", + "parameters": [ + { + "name": "symbol", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Symbol" + } + }, + { + "name": "quarters", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 40, + "minimum": 1, + "description": "Number of recent quarters (max ~25 available)", + "default": 8, + "title": "Quarters" + }, + "description": "Number of recent quarters (max ~25 available)" + }, + { + "name": "force_refresh", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Bypass cache and re-fetch from yfinance", + "default": false, + "title": "Force Refresh" + }, + "description": "Bypass cache and re-fetch from yfinance" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EarningsSurpriseResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/universe/screen": { + "get": { + "tags": [ + "universe" + ], + "summary": "Screen stocks at a historical date", + "description": "Query monthly market_cap snapshots to find stocks matching criteria at a past date.\\n\\n**용도**: 백테스팅 전략 유니버스 구성 — 특정 시점 시총/섹터 기준 종목 필터링.\\n\\n**데이터 소스**: SEC EDGAR shares_outstanding × yfinance monthly close.\\n**제한**: 현재 상장 종목만 포함 (survivorship bias). 상폐 종목 미포함.\\n\\n**사전 조건**: `/universe/admin/discover` 후 `/universe/admin/build-snapshots` 실행 필요.", + "operationId": "screen_historical_api_v1_universe_screen_get", + "parameters": [ + { + "name": "date", + "in": "query", + "required": true, + "schema": { + "type": "string", + "description": "Historical date YYYY-MM-DD (rounded to month start)", + "title": "Date" + }, + "description": "Historical date YYYY-MM-DD (rounded to month start)" + }, + { + "name": "market_cap_min", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Min market cap (USD), e.g. 2e9", + "title": "Market Cap Min" + }, + "description": "Min market cap (USD), e.g. 2e9" + }, + { + "name": "market_cap_max", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Max market cap (USD), e.g. 20e9", + "title": "Market Cap Max" + }, + "description": "Max market cap (USD), e.g. 20e9" + }, + { + "name": "sector", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Sector filter (e.g. Technology, Healthcare)", + "title": "Sector" + }, + "description": "Sector filter (e.g. Technology, Healthcare)" + }, + { + "name": "exchange", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Exchange filter (NYSE, NASDAQ, AMEX)", + "title": "Exchange" + }, + "description": "Exchange filter (NYSE, NASDAQ, AMEX)" + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "description": "Page number", + "default": 1, + "title": "Page" + }, + "description": "Page number" + }, + { + "name": "page_size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 500, + "minimum": 1, + "description": "Results per page", + "default": 100, + "title": "Page Size" + }, + "description": "Results per page" + }, + { + "name": "sort_by", + "in": "query", + "required": false, + "schema": { + "type": "string", + "description": "Sort field: market_cap or ticker", + "default": "market_cap", + "title": "Sort By" + }, + "description": "Sort field: market_cap or ticker" + }, + { + "name": "sort_ascending", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Sort direction", + "default": false, + "title": "Sort Ascending" + }, + "description": "Sort direction" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UniverseScreenResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/universe/registry": { + "get": { + "tags": [ + "universe" + ], + "summary": "Browse registered ticker universe", + "description": "List tickers registered in the universe (populated via /admin/discover).", + "operationId": "get_registry_api_v1_universe_registry_get", + "parameters": [ + { + "name": "sector", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Filter by sector", + "title": "Sector" + }, + "description": "Filter by sector" + }, + { + "name": "exchange", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Filter by exchange", + "title": "Exchange" + }, + "description": "Filter by exchange" + }, + { + "name": "is_active", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Filter by active status", + "title": "Is Active" + }, + "description": "Filter by active status" + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "default": 1, + "title": "Page" + } + }, + { + "name": "page_size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 1000, + "minimum": 1, + "default": 100, + "title": "Page Size" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RegistryResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/universe/admin/discover": { + "post": { + "tags": [ + "universe" + ], + "summary": "Discover and register US tickers", + "description": "Scrapes US-listed stocks via yfinance screener and registers them in the universe.\\n\\n**소요 시간**: 약 1~5분 (시총 기준에 따라 다름).\\n**권장**: `market_cap_min=100000000` ($100M) → ~3000~5000 종목.", + "operationId": "discover_tickers_api_v1_universe_admin_discover_post", + "parameters": [ + { + "name": "market_cap_min", + "in": "query", + "required": false, + "schema": { + "type": "number", + "description": "Min market cap for inclusion (USD). Default $100M.", + "default": 100000000.0, + "title": "Market Cap Min" + }, + "description": "Min market cap for inclusion (USD). Default $100M." + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/universe/admin/build-snapshots": { + "post": { + "tags": [ + "universe" + ], + "summary": "Build monthly market_cap snapshots", + "description": "Computes monthly market_cap snapshots for registered tickers and stores them in `universe_snapshot`.\\n\\n**데이터 소스**: SEC EDGAR companyfacts (shares_outstanding) + yfinance monthly close.\\n\\n**소요 시간**: 전체 유니버스(~4000 종목) × 10년 기준 30~60분. 백그라운드에서 실행되므로 응답은 즉시 반환됩니다.\\n\\n**권장 시작점**: `tickers=[AAPL,MSFT,GOOGL]`로 소규모 테스트 후 전체 빌드.", + "operationId": "build_snapshots_api_v1_universe_admin_build_snapshots_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SnapshotBuildRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/dividends/upcoming": { + "get": { + "tags": [ + "dividends" + ], + "summary": "PIT upcoming ex-dividend calendar", + "description": "Point-in-Time 배당락 캘린더. `as_of_date` 기준으로 당시 알려져 있었던 배당 일정 중 `from_ex_date` ~ `to_ex_date` 범위의 ex-date를 반환.\n\n**PIT 의미**: 같은 (ticker, ex_date)에 여러 revision이 있으면 `as_of_date <= query_as_of_date` 조건 내에서 가장 최신 revision만 반환.\n\n**데이터 소스**: yfinance-plus. API 키 불필요. symbols 파라미터 없이 조회 시 이미 인덱싱된 종목 전체 반환.\n\n**백필**: `POST /dividends/admin/ingest` 로 원하는 종목 선인덱싱 가능.", + "operationId": "get_upcoming_dividends_api_v1_dividends_upcoming_get", + "parameters": [ + { + "name": "as_of_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "description": "PIT 기준일 (YYYY-MM-DD). 생략 시 오늘.", + "title": "As Of Date" + }, + "description": "PIT 기준일 (YYYY-MM-DD). 생략 시 오늘." + }, + { + "name": "from_ex_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "description": "Ex-date 시작 (YYYY-MM-DD). 생략 시 오늘.", + "title": "From Ex Date" + }, + "description": "Ex-date 시작 (YYYY-MM-DD). 생략 시 오늘." + }, + { + "name": "to_ex_date", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "description": "Ex-date 끝 (YYYY-MM-DD). 생략 시 오늘 + 60일.", + "title": "To Ex Date" + }, + "description": "Ex-date 끝 (YYYY-MM-DD). 생략 시 오늘 + 60일." + }, + { + "name": "symbols", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "종목 필터 (e.g. ?symbols=AAPL&symbols=MSFT). 생략 시 전체.", + "title": "Symbols" + }, + "description": "종목 필터 (e.g. ?symbols=AAPL&symbols=MSFT). 생략 시 전체." + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 5000, + "minimum": 1, + "description": "최대 반환 개수", + "default": 500, + "title": "Limit" + }, + "description": "최대 반환 개수" + }, + { + "name": "force_refresh", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "캐시 무시", + "default": false, + "title": "Force Refresh" + }, + "description": "캐시 무시" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DividendUpcomingResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/dividends/history/{symbol}": { + "get": { + "tags": [ + "dividends" + ], + "summary": "종목별 배당 이력", + "description": "단일 종목의 전체 배당 이력. yfinance 데이터가 없으면 자동 인덱싱.\n\n각 ex-date별 최신 revision을 반환 (ex-date 내림차순).\n\n`annual_yield_estimate`: 최근 12개월 배당 합산액 (주가 대비 yield는 클라이언트 계산 필요).", + "operationId": "get_dividend_history_api_v1_dividends_history__symbol__get", + "parameters": [ + { + "name": "symbol", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Symbol" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 1000, + "minimum": 1, + "description": "최대 반환 개수", + "default": 100, + "title": "Limit" + }, + "description": "최대 반환 개수" + }, + { + "name": "force_refresh", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "캐시 무시 + yfinance 재조회", + "default": false, + "title": "Force Refresh" + }, + "description": "캐시 무시 + yfinance 재조회" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DividendHistoryResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/dividends/admin/ingest": { + "post": { + "tags": [ + "dividends" + ], + "summary": "배당 데이터 벌크 인제스트", + "description": "yfinance에서 지정 종목 배당 이력을 가져와 DB에 저장.\n\n**예시**:\n- `{\"symbols\": [\"AAPL\", \"MSFT\", \"JNJ\"]}` — 신규 종목 인덱싱\n- `{\"symbols\": [...], \"force_refresh\": true}` — 기존 데이터 재인제스트\n\n종목당 약 25년치 이력. 100종목 기준 5~10분 소요 (yfinance rate limit).\n\n이미 인덱싱된 종목은 `force_refresh: false`일 때 건너뜀 (멱등성).", + "operationId": "ingest_dividends_api_v1_dividends_admin_ingest_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DividendIngestRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DividendIngestResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/company/{ticker}": { + "get": { + "tags": [ + "company" + ], + "summary": "Get company metadata", + "description": "Returns sector, industry, exchange, market_cap, country, and other metadata for a ticker. Valid tickers without financial statements still return 200. Unknown tickers return 404.", + "operationId": "get_company_api_v1_company__ticker__get", + "parameters": [ + { + "name": "ticker", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Ticker" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CompanyMetadataResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/company/bulk": { + "post": { + "tags": [ + "company" + ], + "summary": "Bulk company metadata", + "description": "Fetch metadata for up to 100 tickers in one request. Partial failures are allowed — each item has either `data` or `error`.", + "operationId": "bulk_company_api_v1_company_bulk_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BulkCompanyRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BulkCompanyResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/ownership/13dg/active": { + "get": { + "tags": [ + "ownership" + ], + "summary": "Active activist positions as-of a date", + "description": "Returns the latest SC 13D/13G filing per (filer, issuer) pair where **filing_date ≤ as_of** and **ownership_pct ≥ min_ownership_pct**.\n\nPositions with `ownership_pct = null` (not yet enriched) are excluded.\n\n`as_of` is required.", + "operationId": "get_13dg_active_api_v1_ownership_13dg_active_get", + "parameters": [ + { + "name": "as_of", + "in": "query", + "required": true, + "schema": { + "type": "string", + "format": "date", + "description": "Point-in-time cutoff. Required.", + "title": "As Of" + }, + "description": "Point-in-time cutoff. Required." + }, + { + "name": "min_ownership_pct", + "in": "query", + "required": false, + "schema": { + "type": "number", + "maximum": 100.0, + "minimum": 0.0, + "description": "Minimum ownership %", + "default": 5.0, + "title": "Min Ownership Pct" + }, + "description": "Minimum ownership %" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ActivistActiveResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/ownership/13dg/{ticker}": { + "get": { + "tags": [ + "ownership" + ], + "summary": "SC 13D/13G activist ownership events for a ticker", + "description": "Returns SC 13D and SC 13G filings (including amendments) where **filing_date ≤ as_of**.\n\n`as_of` is required for PIT safety in backtests.\n\nNote: `ownership_pct` / `shares_owned` will be `null` until background enrichment runs (~30 min).", + "operationId": "get_13dg_events_api_v1_ownership_13dg__ticker__get", + "parameters": [ + { + "name": "ticker", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Ticker" + } + }, + { + "name": "as_of", + "in": "query", + "required": true, + "schema": { + "type": "string", + "format": "date", + "description": "Point-in-time cutoff (filing_date ≤ as_of). Required.", + "title": "As Of" + }, + "description": "Point-in-time cutoff (filing_date ≤ as_of). Required." + }, + { + "name": "start", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "description": "Window start (filing_date ≥ start)", + "title": "Start" + }, + "description": "Window start (filing_date ≥ start)" + }, + { + "name": "end", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "description": "Window end (filing_date ≤ end)", + "title": "End" + }, + "description": "Window end (filing_date ≤ end)" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ActivistEventsResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "ActivistActiveResponse": { + "properties": { + "as_of": { + "type": "string", + "format": "date", + "title": "As Of" + }, + "min_ownership_pct": { + "type": "number", + "title": "Min Ownership Pct" + }, + "positions": { + "items": { + "$ref": "#/components/schemas/ActivistEventEntry" + }, + "type": "array", + "title": "Positions" + }, + "total_count": { + "type": "integer", + "title": "Total Count" + } + }, + "type": "object", + "required": [ + "as_of", + "min_ownership_pct", + "positions", + "total_count" + ], + "title": "ActivistActiveResponse" + }, + "ActivistEventEntry": { + "properties": { + "symbol": { + "type": "string", + "title": "Symbol" + }, + "filing_date": { + "type": "string", + "format": "date", + "title": "Filing Date" + }, + "filer_name": { + "type": "string", + "title": "Filer Name" + }, + "filer_cik": { + "type": "string", + "title": "Filer Cik" + }, + "form_type": { + "type": "string", + "title": "Form Type" + }, + "ownership_pct": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Ownership Pct" + }, + "shares_owned": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Shares Owned" + }, + "is_amendment": { + "type": "boolean", + "title": "Is Amendment", + "default": false + }, + "change_pct": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Change Pct" + }, + "accession_number": { + "type": "string", + "title": "Accession Number" + }, + "parse_status": { + "type": "string", + "title": "Parse Status" + } + }, + "type": "object", + "required": [ + "symbol", + "filing_date", + "filer_name", + "filer_cik", + "form_type", + "accession_number", + "parse_status" + ], + "title": "ActivistEventEntry" + }, + "ActivistEventsResponse": { + "properties": { + "symbol": { + "type": "string", + "title": "Symbol" + }, + "as_of": { + "type": "string", + "format": "date", + "title": "As Of" + }, + "window": { + "additionalProperties": true, + "type": "object", + "title": "Window" + }, + "events": { + "items": { + "$ref": "#/components/schemas/ActivistEventEntry" + }, + "type": "array", + "title": "Events" + }, + "total_count": { + "type": "integer", + "title": "Total Count" + } + }, + "type": "object", + "required": [ + "symbol", + "as_of", + "events", + "total_count" + ], + "title": "ActivistEventsResponse" + }, + "AlpacaMultiBarsResponse": { + "properties": { + "source": { + "type": "string", + "title": "Source", + "default": "ALPACA" + }, + "interval": { + "type": "string", + "title": "Interval" + }, + "count": { + "type": "integer", + "title": "Count" + }, + "bars": { + "additionalProperties": { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + "type": "object", + "title": "Bars" + } + }, + "type": "object", + "required": [ + "interval", + "count", + "bars" + ], + "title": "AlpacaMultiBarsResponse", + "description": "Multi-ticker OHLCV bars from Alpaca (daily or intraday).\n\n``bars`` maps each ticker (using the original input symbol, e.g. BF-B)\nto a list of bar dicts. Daily bars include a ``date`` field; intraday\nbars include a ``timestamp`` field." + }, + "AlpacaMultiSnapshotResponse": { + "properties": { + "source": { + "type": "string", + "title": "Source", + "default": "ALPACA" + }, + "count": { + "type": "integer", + "title": "Count" + }, + "snapshots": { + "items": { + "$ref": "#/components/schemas/AlpacaSnapshotResponse" + }, + "type": "array", + "title": "Snapshots" + } + }, + "type": "object", + "required": [ + "count", + "snapshots" + ], + "title": "AlpacaMultiSnapshotResponse", + "description": "Real-time snapshots for multiple tickers." + }, + "AlpacaSnapshotResponse": { + "properties": { + "ticker": { + "type": "string", + "title": "Ticker" + }, + "source": { + "type": "string", + "title": "Source", + "default": "ALPACA" + }, + "timestamp": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Timestamp" + }, + "price": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Price" + }, + "trade_size": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Trade Size" + }, + "bid": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Bid" + }, + "ask": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Ask" + }, + "bid_size": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Bid Size" + }, + "ask_size": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Ask Size" + }, + "open": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Open" + }, + "high": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "High" + }, + "low": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Low" + }, + "volume": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Volume" + }, + "vwap": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Vwap" + }, + "prev_close": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Prev Close" + }, + "change": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Change" + }, + "change_pct": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Change Pct" + } + }, + "type": "object", + "required": [ + "ticker" + ], + "title": "AlpacaSnapshotResponse", + "description": "Real-time snapshot for a single ticker via Alpaca." + }, + "BulkCompanyItem": { + "properties": { + "ticker": { + "type": "string", + "title": "Ticker" + }, + "data": { + "anyOf": [ + { + "$ref": "#/components/schemas/CompanyMetadataResponse" + }, + { + "type": "null" + } + ] + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Error" + } + }, + "type": "object", + "required": [ + "ticker" + ], + "title": "BulkCompanyItem" + }, + "BulkCompanyRequest": { + "properties": { + "tickers": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Tickers" + } + }, + "type": "object", + "required": [ + "tickers" + ], + "title": "BulkCompanyRequest" + }, + "BulkCompanyResponse": { + "properties": { + "results": { + "items": { + "$ref": "#/components/schemas/BulkCompanyItem" + }, + "type": "array", + "title": "Results" + }, + "total": { + "type": "integer", + "title": "Total" + }, + "success_count": { + "type": "integer", + "title": "Success Count" + }, + "error_count": { + "type": "integer", + "title": "Error Count" + } + }, + "type": "object", + "required": [ + "results", + "total", + "success_count", + "error_count" + ], + "title": "BulkCompanyResponse" + }, + "BulkEarningsCalendarRequest": { + "properties": { + "symbols": { + "items": { + "type": "string" + }, + "type": "array", + "maxItems": 50, + "minItems": 1, + "title": "Symbols" + }, + "days_ahead": { + "type": "integer", + "maximum": 365.0, + "minimum": 1.0, + "title": "Days Ahead", + "default": 30 + }, + "limit": { + "type": "integer", + "maximum": 20.0, + "minimum": 1.0, + "title": "Limit", + "default": 4 + }, + "as_of_date": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "title": "As Of Date", + "description": "PIT date for backtesting (YYYY-MM-DD). Defaults to today." + } + }, + "type": "object", + "required": [ + "symbols" + ], + "title": "BulkEarningsCalendarRequest" + }, + "BulkEarningsCalendarResponse": { + "properties": { + "entries": { + "items": { + "$ref": "#/components/schemas/EarningsCalendarEntry" + }, + "type": "array", + "title": "Entries" + }, + "metadata": { + "additionalProperties": true, + "type": "object", + "title": "Metadata" + } + }, + "type": "object", + "required": [ + "entries" + ], + "title": "BulkEarningsCalendarResponse" + }, + "BulkExhibitItem": { + "properties": { + "accession_number": { + "type": "string", + "title": "Accession Number" + }, + "exhibit_type": { + "type": "string", + "title": "Exhibit Type" + }, + "success": { + "type": "boolean", + "title": "Success" + }, + "content": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Content" + }, + "content_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Content Type" + }, + "filename": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Filename" + }, + "url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Url" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Error" + } + }, + "type": "object", + "required": [ + "accession_number", + "exhibit_type", + "success" + ], + "title": "BulkExhibitItem" + }, + "BulkExhibitRequest": { + "properties": { + "items": { + "items": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "type": "array", + "maxItems": 50, + "minItems": 1, + "title": "Items" + } + }, + "type": "object", + "required": [ + "items" + ], + "title": "BulkExhibitRequest", + "example": { + "items": [ + { + "accession_number": "0000320193-24-000006", + "exhibit_type": "EX-99.1" + }, + { + "accession_number": "0001045810-24-000010", + "exhibit_type": "EX-99.1" + } + ] + } + }, + "BulkExhibitResponse": { + "properties": { + "results": { + "items": { + "$ref": "#/components/schemas/BulkExhibitItem" + }, + "type": "array", + "title": "Results" + }, + "total_items": { + "type": "integer", + "title": "Total Items" + }, + "successful_count": { + "type": "integer", + "title": "Successful Count" + }, + "failed_count": { + "type": "integer", + "title": "Failed Count" + }, + "query_time_seconds": { + "type": "number", + "title": "Query Time Seconds" + } + }, + "type": "object", + "required": [ + "results", + "total_items", + "successful_count", + "failed_count", + "query_time_seconds" + ], + "title": "BulkExhibitResponse" + }, + "BulkFilingSearchItem": { + "properties": { + "ticker": { + "type": "string", + "title": "Ticker" + }, + "success": { + "type": "boolean", + "title": "Success" + }, + "filings": { + "items": { + "$ref": "#/components/schemas/FilingSummary" + }, + "type": "array", + "title": "Filings", + "default": [] + }, + "total_count": { + "type": "integer", + "title": "Total Count", + "default": 0 + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Error" + } + }, + "type": "object", + "required": [ + "ticker", + "success" + ], + "title": "BulkFilingSearchItem" + }, + "BulkFilingSearchRequest": { + "properties": { + "tickers": { + "items": { + "type": "string" + }, + "type": "array", + "maxItems": 200, + "minItems": 1, + "title": "Tickers" + }, + "form_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Form Type" + }, + "start_date": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Start Date" + }, + "end_date": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "End Date" + }, + "limit_per_ticker": { + "type": "integer", + "maximum": 100.0, + "minimum": 1.0, + "title": "Limit Per Ticker", + "default": 20 + } + }, + "type": "object", + "required": [ + "tickers" + ], + "title": "BulkFilingSearchRequest", + "example": { + "end_date": "2024-12-31", + "form_type": "8-K", + "limit_per_ticker": 5, + "start_date": "2024-01-01", + "tickers": [ + "AAPL", + "MSFT", + "NVDA" + ] + } + }, + "BulkFilingSearchResponse": { + "properties": { + "results": { + "items": { + "$ref": "#/components/schemas/BulkFilingSearchItem" + }, + "type": "array", + "title": "Results" + }, + "total_tickers": { + "type": "integer", + "title": "Total Tickers" + }, + "successful_count": { + "type": "integer", + "title": "Successful Count" + }, + "failed_count": { + "type": "integer", + "title": "Failed Count" + }, + "query_time_seconds": { + "type": "number", + "title": "Query Time Seconds" + }, + "metadata": { + "additionalProperties": true, + "type": "object", + "title": "Metadata" + } + }, + "type": "object", + "required": [ + "results", + "total_tickers", + "successful_count", + "failed_count", + "query_time_seconds" + ], + "title": "BulkFilingSearchResponse" + }, + "BulkFinancialDataItem": { + "properties": { + "ticker": { + "type": "string", + "title": "Ticker" + }, + "success": { + "type": "boolean", + "title": "Success" + }, + "data": { + "anyOf": [ + { + "$ref": "#/components/schemas/FinancialDataResponse" + }, + { + "type": "null" + } + ] + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Error" + } + }, + "type": "object", + "required": [ + "ticker", + "success" + ], + "title": "BulkFinancialDataItem" + }, + "BulkFinancialDataRequest": { + "properties": { + "tickers": { + "items": { + "type": "string" + }, + "type": "array", + "maxItems": 500, + "minItems": 1, + "title": "Tickers", + "description": "List of stock ticker symbols (max 500 for efficient bulk processing)" + }, + "start_date": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "title": "Start Date", + "description": "Start date for data retrieval. Cannot be used with quarters or period." + }, + "end_date": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "title": "End Date", + "description": "End date for data retrieval. Cannot be used with quarters or period." + }, + "quarters": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array", + "maxItems": 40, + "minItems": 1 + }, + { + "type": "null" + } + ], + "title": "Quarters", + "description": "List of quarters in format 'YYYYQN' (e.g., ['2020Q1', '2020Q2']). Cannot be used with start_date/end_date or period. If provided, dates are ignored." + }, + "period": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Period", + "description": "Period string like '1d', '7d', '1m', '3m', '1y', '2y'. Cannot be used with start_date/end_date or quarters." + }, + "period_type": { + "$ref": "#/components/schemas/PeriodType", + "description": "Type of financial periods to retrieve", + "default": "all" + }, + "include_metrics": { + "type": "boolean", + "title": "Include Metrics", + "description": "Include calculated metrics in response", + "default": true + }, + "force_refresh": { + "type": "boolean", + "title": "Force Refresh", + "description": "Force refresh data from SEC", + "default": false + } + }, + "type": "object", + "required": [ + "tickers" + ], + "title": "BulkFinancialDataRequest" + }, + "BulkFinancialDataResponse": { + "properties": { + "results": { + "items": { + "$ref": "#/components/schemas/BulkFinancialDataItem" + }, + "type": "array", + "title": "Results" + }, + "metadata": { + "additionalProperties": true, + "type": "object", + "title": "Metadata" + } + }, + "type": "object", + "required": [ + "results" + ], + "title": "BulkFinancialDataResponse" + }, + "BulkParseRequest": { + "properties": { + "tickers": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Tickers" + }, + "limit": { + "type": "integer", + "maximum": 1000.0, + "minimum": 1.0, + "title": "Limit", + "default": 100 + }, + "force_reparse": { + "type": "boolean", + "title": "Force Reparse", + "description": "If True, also reparse filings with status succeeded or failed (resets to pending first)", + "default": false + } + }, + "type": "object", + "title": "BulkParseRequest", + "example": { + "force_reparse": false, + "limit": 50, + "tickers": [ + "AVGO", + "AAPL" + ] + } + }, + "BulkParseResponse": { + "properties": { + "succeeded": { + "type": "integer", + "title": "Succeeded" + }, + "failed": { + "type": "integer", + "title": "Failed" + }, + "skipped": { + "type": "integer", + "title": "Skipped" + }, + "total": { + "type": "integer", + "title": "Total" + }, + "query_time_seconds": { + "type": "number", + "title": "Query Time Seconds" + } + }, + "type": "object", + "required": [ + "succeeded", + "failed", + "skipped", + "total", + "query_time_seconds" + ], + "title": "BulkParseResponse" + }, + "BulkPriceDataItem": { + "properties": { + "ticker": { + "type": "string", + "title": "Ticker" + }, + "success": { + "type": "boolean", + "title": "Success" + }, + "data": { + "anyOf": [ + { + "$ref": "#/components/schemas/PriceDataResponse" + }, + { + "type": "null" + } + ] + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Error" + } + }, + "type": "object", + "required": [ + "ticker", + "success" + ], + "title": "BulkPriceDataItem" + }, + "BulkPriceDataRequest": { + "properties": { + "tickers": { + "items": { + "type": "string" + }, + "type": "array", + "maxItems": 500, + "minItems": 1, + "title": "Tickers", + "description": "List of stock ticker symbols (max 500 for efficient bulk processing)" + }, + "start_date": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "title": "Start Date", + "description": "Start date for data retrieval. Cannot be used with quarters or period." + }, + "end_date": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "title": "End Date", + "description": "End date for data retrieval. Cannot be used with quarters or period." + }, + "quarters": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array", + "maxItems": 40, + "minItems": 1 + }, + { + "type": "null" + } + ], + "title": "Quarters", + "description": "List of quarters in format 'YYYYQN' (e.g., ['2020Q1', '2020Q2']). Cannot be used with start_date/end_date or period. If provided, dates are ignored." + }, + "period": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Period", + "description": "Period string like '1d', '7d', '1m', '3m', '1y', '2y'. Cannot be used with start_date/end_date or quarters." + }, + "interval": { + "type": "string", + "title": "Interval", + "description": "Data interval: 1d, 1w, 1m, 5d, 1h, etc.", + "default": "1d" + }, + "force_refresh": { + "type": "boolean", + "title": "Force Refresh", + "description": "Force refresh data from Yahoo Finance", + "default": false + } + }, + "type": "object", + "required": [ + "tickers" + ], + "title": "BulkPriceDataRequest" + }, + "BulkPriceDataResponse": { + "properties": { + "results": { + "items": { + "$ref": "#/components/schemas/BulkPriceDataItem" + }, + "type": "array", + "title": "Results" + }, + "metadata": { + "additionalProperties": true, + "type": "object", + "title": "Metadata" + } + }, + "type": "object", + "required": [ + "results" + ], + "title": "BulkPriceDataResponse" + }, + "CollectionStatusResponse": { + "properties": { + "ticker": { + "type": "string", + "title": "Ticker" + }, + "source": { + "type": "string", + "title": "Source" + }, + "records_collected": { + "type": "integer", + "title": "Records Collected" + }, + "date_range": { + "additionalProperties": true, + "type": "object", + "title": "Date Range" + }, + "status": { + "type": "string", + "title": "Status" + } + }, + "type": "object", + "required": [ + "ticker", + "source", + "records_collected", + "status" + ], + "title": "CollectionStatusResponse", + "example": { + "date_range": { + "event_date": "2024-02-01" + }, + "records_collected": 22, + "source": "wiki", + "status": "success", + "ticker": "AAPL" + } + }, + "CompanyInfo": { + "properties": { + "ticker": { + "type": "string", + "title": "Ticker" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Name" + }, + "cik": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Cik" + }, + "exchange": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Exchange" + }, + "sector": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Sector" + }, + "industry": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Industry" + }, + "country": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Country" + }, + "market_cap": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Market Cap" + }, + "business_description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Business Description" + } + }, + "type": "object", + "required": [ + "ticker" + ], + "title": "CompanyInfo" + }, + "CompanyMetadataResponse": { + "properties": { + "ticker": { + "type": "string", + "title": "Ticker" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Name" + }, + "cik": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Cik" + }, + "exchange": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Exchange" + }, + "sector": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Sector" + }, + "industry": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Industry" + }, + "country": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Country" + }, + "market_cap": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Market Cap" + }, + "business_description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Business Description" + } + }, + "type": "object", + "required": [ + "ticker" + ], + "title": "CompanyMetadataResponse" + }, + "CoverageResponse": { + "properties": { + "source": { + "type": "string", + "title": "Source" + }, + "symbol": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Symbol" + }, + "earliest": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Earliest" + }, + "latest": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Latest" + }, + "ingested_count": { + "type": "integer", + "title": "Ingested Count" + } + }, + "type": "object", + "required": [ + "source", + "ingested_count" + ], + "title": "CoverageResponse" + }, + "DataCatalogItem": { + "properties": { + "field_name": { + "type": "string", + "title": "Field Name" + }, + "description": { + "type": "string", + "title": "Description" + }, + "data_type": { + "type": "string", + "title": "Data Type" + }, + "unit": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Unit" + }, + "calculation": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Calculation" + }, + "source": { + "type": "string", + "title": "Source" + } + }, + "type": "object", + "required": [ + "field_name", + "description", + "data_type", + "source" + ], + "title": "DataCatalogItem" + }, + "DataCatalogResponse": { + "properties": { + "categories": { + "additionalProperties": { + "items": { + "$ref": "#/components/schemas/DataCatalogItem" + }, + "type": "array" + }, + "type": "object", + "title": "Categories" + }, + "last_updated": { + "type": "string", + "format": "date-time", + "title": "Last Updated" + } + }, + "type": "object", + "required": [ + "categories", + "last_updated" + ], + "title": "DataCatalogResponse" + }, + "DividendCalendarEntry": { + "properties": { + "ticker": { + "type": "string", + "title": "Ticker" + }, + "ex_dividend_date": { + "type": "string", + "format": "date", + "title": "Ex Dividend Date" + }, + "amount": { + "type": "number", + "title": "Amount" + }, + "declaration_date": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "title": "Declaration Date" + }, + "record_date": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "title": "Record Date" + }, + "payment_date": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "title": "Payment Date" + }, + "currency": { + "type": "string", + "title": "Currency", + "default": "USD" + }, + "dividend_type": { + "type": "string", + "title": "Dividend Type", + "default": "regular" + }, + "frequency": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Frequency" + }, + "as_of_date": { + "type": "string", + "format": "date", + "title": "As Of Date" + }, + "source": { + "type": "string", + "title": "Source" + } + }, + "type": "object", + "required": [ + "ticker", + "ex_dividend_date", + "amount", + "as_of_date", + "source" + ], + "title": "DividendCalendarEntry" + }, + "DividendHistoryResponse": { + "properties": { + "symbol": { + "type": "string", + "title": "Symbol" + }, + "dividends": { + "items": { + "$ref": "#/components/schemas/DividendCalendarEntry" + }, + "type": "array", + "title": "Dividends" + }, + "total_count": { + "type": "integer", + "title": "Total Count" + }, + "annual_yield_estimate": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Annual Yield Estimate" + }, + "metadata": { + "additionalProperties": true, + "type": "object", + "title": "Metadata" + } + }, + "type": "object", + "required": [ + "symbol", + "dividends", + "total_count" + ], + "title": "DividendHistoryResponse", + "description": "Response for single-symbol dividend history." + }, + "DividendIngestRequest": { + "properties": { + "symbols": { + "items": { + "type": "string" + }, + "type": "array", + "maxItems": 200, + "minItems": 1, + "title": "Symbols" + }, + "force_refresh": { + "type": "boolean", + "title": "Force Refresh", + "description": "Re-ingest even if data exists", + "default": false + } + }, + "type": "object", + "required": [ + "symbols" + ], + "title": "DividendIngestRequest", + "description": "Request body for bulk backfill ingest." + }, + "DividendIngestResponse": { + "properties": { + "symbols_processed": { + "type": "integer", + "title": "Symbols Processed" + }, + "total_records_upserted": { + "type": "integer", + "title": "Total Records Upserted" + }, + "failed_symbols": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Failed Symbols" + }, + "status": { + "type": "string", + "title": "Status" + }, + "metadata": { + "additionalProperties": true, + "type": "object", + "title": "Metadata" + } + }, + "type": "object", + "required": [ + "symbols_processed", + "total_records_upserted", + "status" + ], + "title": "DividendIngestResponse", + "description": "Response for admin ingest endpoint." + }, + "DividendUpcomingResponse": { + "properties": { + "dividends": { + "items": { + "$ref": "#/components/schemas/DividendCalendarEntry" + }, + "type": "array", + "title": "Dividends" + }, + "total_count": { + "type": "integer", + "title": "Total Count" + }, + "metadata": { + "additionalProperties": true, + "type": "object", + "title": "Metadata" + } + }, + "type": "object", + "required": [ + "dividends", + "total_count" + ], + "title": "DividendUpcomingResponse", + "description": "Response for PIT upcoming dividends query." + }, + "ETFHoldingsOut": { + "properties": { + "success": { + "type": "boolean", + "title": "Success" + }, + "ticker": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Ticker" + }, + "as_of_date": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "As Of Date" + }, + "cik": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Cik" + }, + "holdings_count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Holdings Count" + }, + "holdings": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Holdings" + }, + "availability": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Availability" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Error" + } + }, + "type": "object", + "required": [ + "success" + ], + "title": "ETFHoldingsOut" + }, + "EarningsCalendarEntry": { + "properties": { + "symbol": { + "type": "string", + "title": "Symbol" + }, + "earnings_date": { + "type": "string", + "format": "date-time", + "title": "Earnings Date" + }, + "earnings_time": { + "type": "string", + "title": "Earnings Time" + }, + "estimated_eps": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Estimated Eps" + }, + "reported_eps": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Reported Eps" + }, + "source": { + "type": "string", + "title": "Source", + "default": "yfinance" + }, + "fetched_at": { + "type": "string", + "format": "date-time", + "title": "Fetched At" + } + }, + "type": "object", + "required": [ + "symbol", + "earnings_date", + "earnings_time", + "fetched_at" + ], + "title": "EarningsCalendarEntry" + }, + "EarningsCalendarResponse": { + "properties": { + "symbol": { + "type": "string", + "title": "Symbol" + }, + "upcoming_earnings": { + "items": { + "$ref": "#/components/schemas/EarningsCalendarEntry" + }, + "type": "array", + "title": "Upcoming Earnings" + }, + "metadata": { + "additionalProperties": true, + "type": "object", + "title": "Metadata" + } + }, + "type": "object", + "required": [ + "symbol", + "upcoming_earnings" + ], + "title": "EarningsCalendarResponse" + }, + "EarningsSurpriseEntry": { + "properties": { + "fiscal_date_ending": { + "type": "string", + "format": "date", + "title": "Fiscal Date Ending" + }, + "reported_date": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "title": "Reported Date" + }, + "reported_eps": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Reported Eps" + }, + "estimated_eps": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Estimated Eps" + }, + "surprise": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Surprise" + }, + "surprise_percentage": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Surprise Percentage" + }, + "beat": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Beat" + } + }, + "type": "object", + "required": [ + "fiscal_date_ending" + ], + "title": "EarningsSurpriseEntry" + }, + "EarningsSurpriseResponse": { + "properties": { + "symbol": { + "type": "string", + "title": "Symbol" + }, + "quarters": { + "items": { + "$ref": "#/components/schemas/EarningsSurpriseEntry" + }, + "type": "array", + "title": "Quarters" + }, + "streak": { + "type": "integer", + "title": "Streak", + "default": 0 + }, + "avg_surprise_pct": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Avg Surprise Pct" + }, + "metadata": { + "additionalProperties": true, + "type": "object", + "title": "Metadata" + } + }, + "type": "object", + "required": [ + "symbol", + "quarters" + ], + "title": "EarningsSurpriseResponse" + }, + "EntityInfo": { + "properties": { + "ticker": { + "type": "string", + "title": "Ticker" + }, + "canonical_name": { + "type": "string", + "title": "Canonical Name", + "description": "Normalized company name with legal suffixes stripped (e.g. 'Apple')" + }, + "wiki_title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Wiki Title", + "description": "Matched Wikipedia article title; null if unresolved" + }, + "gdelt_query": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Gdelt Query", + "description": "GDELT DOC API query string (quoted OR phrases)" + }, + "aliases": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Aliases", + "description": "Intermediate forms used during name normalization" + }, + "resolver_confidence": { + "type": "number", + "title": "Resolver Confidence", + "description": "Wikipedia match confidence [0, 1]", + "default": 0.0 + }, + "is_manual_override": { + "type": "boolean", + "title": "Is Manual Override", + "description": "If true, automated re-resolution is skipped", + "default": false + } + }, + "type": "object", + "required": [ + "ticker", + "canonical_name" + ], + "title": "EntityInfo", + "example": { + "aliases": [ + "Apple Inc." + ], + "canonical_name": "Apple", + "gdelt_query": "\"Apple\" OR \"Apple Inc.\"", + "is_manual_override": false, + "resolver_confidence": 0.92, + "ticker": "AAPL", + "wiki_title": "Apple Inc." + } + }, + "EntityResolveResponse": { + "properties": { + "ticker": { + "type": "string", + "title": "Ticker" + }, + "entity": { + "$ref": "#/components/schemas/EntityInfo" + }, + "status": { + "type": "string", + "title": "Status" + }, + "message": { + "type": "string", + "title": "Message" + } + }, + "type": "object", + "required": [ + "ticker", + "entity", + "status", + "message" + ], + "title": "EntityResolveResponse", + "example": { + "entity": { + "aliases": [ + "Apple Inc." + ], + "canonical_name": "Apple", + "gdelt_query": "\"Apple\" OR \"Apple Inc.\"", + "is_manual_override": false, + "resolver_confidence": 0.92, + "ticker": "AAPL", + "wiki_title": "Apple Inc." + }, + "message": "Entity resolved: wiki_title='Apple Inc.' confidence=0.92", + "status": "resolved", + "ticker": "AAPL" + } + }, + "ErrorLogListResponse": { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/ErrorLogResponse" + }, + "type": "array", + "title": "Items" + }, + "total": { + "type": "integer", + "title": "Total" + }, + "page": { + "type": "integer", + "title": "Page" + }, + "page_size": { + "type": "integer", + "title": "Page Size" + }, + "total_pages": { + "type": "integer", + "title": "Total Pages" + } + }, + "type": "object", + "required": [ + "items", + "total", + "page", + "page_size", + "total_pages" + ], + "title": "ErrorLogListResponse", + "description": "Response schema for error log list" + }, + "ErrorLogResponse": { + "properties": { + "request_id": { + "type": "string", + "title": "Request Id" + }, + "endpoint": { + "type": "string", + "title": "Endpoint" + }, + "method": { + "type": "string", + "title": "Method" + }, + "path": { + "type": "string", + "title": "Path" + }, + "query_params": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Query Params" + }, + "request_body": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Request Body" + }, + "error_type": { + "type": "string", + "title": "Error Type" + }, + "error_message": { + "type": "string", + "title": "Error Message" + }, + "error_detail": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Error Detail" + }, + "status_code": { + "type": "integer", + "title": "Status Code" + }, + "stack_trace": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Stack Trace" + }, + "user_agent": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "User Agent" + }, + "client_ip": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Client Ip" + }, + "response_time_ms": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Response Time Ms" + }, + "id": { + "type": "integer", + "title": "Id" + }, + "headers": { + "anyOf": [ + { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Headers" + }, + "is_resolved": { + "type": "boolean", + "title": "Is Resolved", + "default": false + }, + "resolved_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Resolved At" + }, + "resolution_notes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Resolution Notes" + }, + "created_at": { + "type": "string", + "title": "Created At" + } + }, + "type": "object", + "required": [ + "request_id", + "endpoint", + "method", + "path", + "error_type", + "error_message", + "status_code", + "id", + "created_at" + ], + "title": "ErrorLogResponse", + "description": "Response schema for error log" + }, + "ErrorLogStats": { + "properties": { + "total_errors": { + "type": "integer", + "title": "Total Errors" + }, + "resolved_errors": { + "type": "integer", + "title": "Resolved Errors" + }, + "unresolved_errors": { + "type": "integer", + "title": "Unresolved Errors" + }, + "resolution_rate": { + "type": "number", + "title": "Resolution Rate" + }, + "errors_by_type": { + "additionalProperties": { + "type": "integer" + }, + "type": "object", + "title": "Errors By Type" + }, + "errors_by_status_code": { + "additionalProperties": { + "type": "integer" + }, + "type": "object", + "title": "Errors By Status Code" + }, + "errors_by_endpoint": { + "additionalProperties": { + "type": "integer" + }, + "type": "object", + "title": "Errors By Endpoint" + }, + "average_response_time_ms": { + "type": "number", + "title": "Average Response Time Ms" + }, + "hourly_trend": { + "additionalProperties": { + "type": "integer" + }, + "type": "object", + "title": "Hourly Trend" + }, + "start_date": { + "type": "string", + "title": "Start Date" + }, + "end_date": { + "type": "string", + "title": "End Date" + } + }, + "type": "object", + "required": [ + "total_errors", + "resolved_errors", + "unresolved_errors", + "resolution_rate", + "errors_by_type", + "errors_by_status_code", + "errors_by_endpoint", + "average_response_time_ms", + "hourly_trend", + "start_date", + "end_date" + ], + "title": "ErrorLogStats", + "description": "Statistics about error logs" + }, + "ErrorLogUpdate": { + "properties": { + "is_resolved": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Is Resolved" + }, + "resolution_notes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Resolution Notes" + } + }, + "type": "object", + "title": "ErrorLogUpdate", + "description": "Schema for updating error log" + }, + "ErrorResponse": { + "properties": { + "error_type": { + "$ref": "#/components/schemas/ErrorType" + }, + "message": { + "type": "string", + "title": "Message" + }, + "detail": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Detail" + }, + "timestamp": { + "type": "string", + "format": "date-time", + "title": "Timestamp" + } + }, + "type": "object", + "required": [ + "error_type", + "message" + ], + "title": "ErrorResponse" + }, + "ErrorType": { + "type": "string", + "enum": [ + "PARSING_ERROR", + "DATA_NOT_FOUND", + "INVALID_PERIOD", + "SEC_API_ERROR", + "DATABASE_ERROR", + "VALIDATION_ERROR", + "AUTHENTICATION_ERROR", + "RATE_LIMIT_ERROR" + ], + "title": "ErrorType" + }, + "EventAttentionResponse": { + "properties": { + "ticker": { + "type": "string", + "title": "Ticker" + }, + "event_date": { + "type": "string", + "format": "date", + "title": "Event Date" + }, + "entity": { + "$ref": "#/components/schemas/EntityInfo" + }, + "wiki": { + "$ref": "#/components/schemas/WikiFeatures" + }, + "news": { + "$ref": "#/components/schemas/NewsFeatures" + }, + "metadata": { + "additionalProperties": true, + "type": "object", + "title": "Metadata" + } + }, + "type": "object", + "required": [ + "ticker", + "event_date", + "entity", + "wiki", + "news" + ], + "title": "EventAttentionResponse", + "example": { + "entity": { + "aliases": [ + "Apple Inc." + ], + "canonical_name": "Apple", + "gdelt_query": "\"Apple\" OR \"Apple Inc.\"", + "is_manual_override": false, + "resolver_confidence": 0.92, + "ticker": "AAPL", + "wiki_title": "Apple Inc." + }, + "event_date": "2024-02-01", + "metadata": { + "resolver_confidence": 0.92, + "wiki_title": "Apple Inc." + }, + "news": { + "article_count_1d": 18, + "article_count_3d": 52, + "gdelt_status": "collected", + "unique_domains_3d": 34, + "us_article_count_3d": 41 + }, + "ticker": "AAPL", + "wiki": { + "baseline_10d": 12400.0, + "spike_10d": 3.65, + "views": 45230, + "zscore_20d": 4.21 + } + } + }, + "ExhibitContentResponse": { + "properties": { + "accession_number": { + "type": "string", + "title": "Accession Number" + }, + "exhibit_type": { + "type": "string", + "title": "Exhibit Type" + }, + "content": { + "type": "string", + "title": "Content" + }, + "content_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Content Type" + }, + "filename": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Filename" + }, + "url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Url" + } + }, + "type": "object", + "required": [ + "accession_number", + "exhibit_type", + "content" + ], + "title": "ExhibitContentResponse", + "example": { + "accession_number": "0000320193-24-000006", + "content": "Apple Reports First Quarter Results...\nCUPERTINO, California — February 1, 2024 — Apple Inc. today announced financial results for its fiscal 2024 first quarter...", + "content_type": "text/html", + "exhibit_type": "EX-99.1", + "filename": "ex991pressrelease.htm", + "url": "https://www.sec.gov/Archives/edgar/data/320193/000032019324000006/ex991pressrelease.htm" + } + }, + "FilingDocumentInfo": { + "properties": { + "type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Type" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "filename": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Filename" + }, + "url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Url" + }, + "size": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Size" + } + }, + "type": "object", + "title": "FilingDocumentInfo", + "example": { + "description": "Press Release", + "filename": "ex991pressrelease.htm", + "size": "42 KB", + "type": "EX-99.1", + "url": "https://www.sec.gov/Archives/edgar/data/320193/000032019324000006/ex991pressrelease.htm" + } + }, + "FilingDocumentListResponse": { + "properties": { + "accession_number": { + "type": "string", + "title": "Accession Number" + }, + "documents": { + "items": { + "$ref": "#/components/schemas/FilingDocumentInfo" + }, + "type": "array", + "title": "Documents" + }, + "metadata": { + "additionalProperties": true, + "type": "object", + "title": "Metadata" + } + }, + "type": "object", + "required": [ + "accession_number", + "documents" + ], + "title": "FilingDocumentListResponse", + "example": { + "accession_number": "0000320193-24-000006", + "documents": [ + { + "description": "8-K", + "filename": "a8-k20240201.htm", + "size": "8 KB", + "type": "8-K", + "url": "https://www.sec.gov/Archives/edgar/data/320193/000032019324000006/a8-k20240201.htm" + }, + { + "description": "Press Release", + "filename": "ex991pressrelease.htm", + "size": "42 KB", + "type": "EX-99.1", + "url": "https://www.sec.gov/Archives/edgar/data/320193/000032019324000006/ex991pressrelease.htm" + } + ], + "metadata": { + "total_documents": 4 + } + } + }, + "FilingEventResponse": { + "properties": { + "id": { + "type": "string", + "title": "Id" + }, + "ticker": { + "type": "string", + "title": "Ticker" + }, + "accession_number": { + "type": "string", + "title": "Accession Number" + }, + "form_type": { + "type": "string", + "title": "Form Type" + }, + "filing_date": { + "type": "string", + "title": "Filing Date" + }, + "item_number": { + "type": "string", + "title": "Item Number" + }, + "event_type": { + "type": "string", + "title": "Event Type" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Title" + }, + "summary": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Summary" + }, + "content_source": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Content Source" + } + }, + "type": "object", + "required": [ + "id", + "ticker", + "accession_number", + "form_type", + "filing_date", + "item_number", + "event_type" + ], + "title": "FilingEventResponse", + "example": { + "accession_number": "0001193125-26-144028", + "content_source": "primary_doc", + "event_type": "other_material_event", + "filing_date": "2026-04-06", + "form_type": "8-K", + "id": "550e8400-e29b-41d4-a716-446655440000", + "item_number": "8.01", + "summary": "Broadcom Inc. and Google LLC have entered into a Long Term Agreement...", + "ticker": "AVGO", + "title": "Other Events" + } + }, + "FilingEventsSearchResponse": { + "properties": { + "ticker": { + "type": "string", + "title": "Ticker" + }, + "events": { + "items": { + "$ref": "#/components/schemas/FilingEventResponse" + }, + "type": "array", + "title": "Events" + }, + "total_count": { + "type": "integer", + "title": "Total Count" + }, + "metadata": { + "additionalProperties": true, + "type": "object", + "title": "Metadata" + } + }, + "type": "object", + "required": [ + "ticker", + "events", + "total_count" + ], + "title": "FilingEventsSearchResponse" + }, + "FilingSearchResponse": { + "properties": { + "ticker": { + "type": "string", + "title": "Ticker" + }, + "filings": { + "items": { + "$ref": "#/components/schemas/FilingSummary" + }, + "type": "array", + "title": "Filings" + }, + "total_count": { + "type": "integer", + "title": "Total Count" + }, + "metadata": { + "additionalProperties": true, + "type": "object", + "title": "Metadata" + } + }, + "type": "object", + "required": [ + "ticker", + "filings", + "total_count" + ], + "title": "FilingSearchResponse", + "example": { + "filings": [ + { + "accepted_at": "2024-02-01T21:00:05+00:00", + "accession_number": "0000320193-24-000006", + "documents_count": 4, + "filing_date": "2024-02-01", + "filing_description": "Results of Operations and Financial Condition", + "form_type": "8-K", + "primary_document": "a8-k20240201.htm" + } + ], + "metadata": { + "form_types": [ + "8-K" + ], + "limit": 20, + "offset": 0 + }, + "ticker": "AAPL", + "total_count": 42 + } + }, + "FilingSummary": { + "properties": { + "accession_number": { + "type": "string", + "title": "Accession Number" + }, + "form_type": { + "type": "string", + "title": "Form Type" + }, + "filing_date": { + "type": "string", + "title": "Filing Date" + }, + "accepted_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Accepted At" + }, + "primary_document": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Primary Document" + }, + "filing_description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Filing Description" + }, + "documents_count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Documents Count" + }, + "parsed_status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Parsed Status" + }, + "items": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Items" + } + }, + "type": "object", + "required": [ + "accession_number", + "form_type", + "filing_date" + ], + "title": "FilingSummary", + "example": { + "accepted_at": "2024-02-01T21:00:05+00:00", + "accession_number": "0000320193-24-000006", + "documents_count": 4, + "filing_date": "2024-02-01", + "filing_description": "Results of Operations and Financial Condition", + "form_type": "8-K", + "items": [ + "2.02", + "9.01" + ], + "parsed_status": "succeeded", + "primary_document": "a8-k20240201.htm" + } + }, + "FinancialDataPoint": { + "properties": { + "period_date": { + "type": "string", + "format": "date-time", + "title": "Period Date" + }, + "period_type": { + "type": "string", + "title": "Period Type" + }, + "filing_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Filing Type" + }, + "revenue": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Revenue" + }, + "gross_profit": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Gross Profit" + }, + "operating_income": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Operating Income" + }, + "net_income": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Net Income" + }, + "eps": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Eps" + }, + "total_assets": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Total Assets" + }, + "total_equity": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Total Equity" + }, + "total_debt": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Total Debt" + }, + "cash": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Cash" + }, + "shares_outstanding": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Shares Outstanding" + }, + "operating_cash_flow": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Operating Cash Flow" + }, + "free_cash_flow": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Free Cash Flow" + }, + "capex": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Capex" + }, + "pe_ratio": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Pe Ratio" + }, + "pb_ratio": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Pb Ratio" + }, + "ps_ratio": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Ps Ratio" + }, + "roe": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Roe" + }, + "roa": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Roa" + }, + "gross_margin": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Gross Margin" + }, + "operating_margin": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Operating Margin" + }, + "net_margin": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Net Margin" + }, + "debt_to_equity": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Debt To Equity" + }, + "debt_to_assets": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Debt To Assets" + }, + "ocf_margin": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Ocf Margin" + }, + "fcf_margin": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Fcf Margin" + }, + "market_cap": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Market Cap" + }, + "data_source": { + "type": "string", + "title": "Data Source" + }, + "is_estimated": { + "type": "boolean", + "title": "Is Estimated" + } + }, + "type": "object", + "required": [ + "period_date", + "period_type", + "data_source", + "is_estimated" + ], + "title": "FinancialDataPoint" + }, + "FinancialDataRequest": { + "properties": { + "ticker": { + "type": "string", + "maxLength": 10, + "minLength": 1, + "title": "Ticker", + "description": "Stock ticker symbol" + }, + "start_date": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "title": "Start Date", + "description": "Start date for data retrieval. Cannot be used with quarters or period." + }, + "end_date": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "title": "End Date", + "description": "End date for data retrieval. Cannot be used with quarters or period." + }, + "quarters": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array", + "maxItems": 40, + "minItems": 1 + }, + { + "type": "null" + } + ], + "title": "Quarters", + "description": "List of quarters in format 'YYYYQN' (e.g., ['2020Q1', '2020Q2']). Cannot be used with start_date/end_date or period. If provided, dates are ignored." + }, + "period": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Period", + "description": "Period string like '1d', '7d', '1m', '3m', '1y', '2y'. Cannot be used with start_date/end_date or quarters." + }, + "period_type": { + "$ref": "#/components/schemas/PeriodType", + "description": "Type of financial periods to retrieve", + "default": "all" + }, + "include_metrics": { + "type": "boolean", + "title": "Include Metrics", + "description": "Include calculated metrics in response", + "default": true + }, + "force_refresh": { + "type": "boolean", + "title": "Force Refresh", + "description": "Force refresh data from SEC", + "default": false + } + }, + "type": "object", + "required": [ + "ticker" + ], + "title": "FinancialDataRequest", + "description": "Request for financial data with flexible time period specification.\n\n**Three ways to specify time period (choose one):**\n1. **Date Range**: Use start_date and end_date \n2. **Quarters**: Use quarters list (e.g., ['2024Q1', '2024Q2'])\n3. **Period**: Use period string (e.g., '1d', '3m', '2y')\n\n**Important**: Cannot mix approaches in the same request." + }, + "FinancialDataResponse": { + "properties": { + "company": { + "$ref": "#/components/schemas/CompanyInfo" + }, + "financial_data": { + "items": { + "$ref": "#/components/schemas/FinancialDataPoint" + }, + "type": "array", + "title": "Financial Data" + }, + "metadata": { + "additionalProperties": true, + "type": "object", + "title": "Metadata" + } + }, + "type": "object", + "required": [ + "company", + "financial_data" + ], + "title": "FinancialDataResponse" + }, + "Form4AggregateResponse": { + "properties": { + "symbol": { + "type": "string", + "title": "Symbol" + }, + "as_of": { + "type": "string", + "format": "date", + "title": "As Of" + }, + "window_days": { + "type": "integer", + "title": "Window Days" + }, + "buy_count": { + "type": "integer", + "title": "Buy Count" + }, + "buy_dollar_total": { + "type": "number", + "title": "Buy Dollar Total" + }, + "cluster_size": { + "type": "integer", + "title": "Cluster Size" + }, + "csuite_count": { + "type": "integer", + "title": "Csuite Count" + }, + "avg_pct_of_holding": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Avg Pct Of Holding" + }, + "recency_days": { + "type": "integer", + "title": "Recency Days" + }, + "metadata": { + "additionalProperties": true, + "type": "object", + "title": "Metadata" + } + }, + "type": "object", + "required": [ + "symbol", + "as_of", + "window_days", + "buy_count", + "buy_dollar_total", + "cluster_size", + "csuite_count", + "recency_days" + ], + "title": "Form4AggregateResponse", + "description": "Aggregate Form 4 insider activity over a rolling window.\n\nAll fields are computed over open-market purchases only (transaction_code='P',\nshares > 0, non-derivative). Awards/grants (A-code) are excluded." + }, + "Form4ByDateResponse": { + "properties": { + "filing_date": { + "type": "string", + "format": "date", + "title": "Filing Date" + }, + "buy_only": { + "type": "boolean", + "title": "Buy Only" + }, + "transactions": { + "items": { + "$ref": "#/components/schemas/Form4Entry" + }, + "type": "array", + "title": "Transactions" + }, + "total_count": { + "type": "integer", + "title": "Total Count" + } + }, + "type": "object", + "required": [ + "filing_date", + "buy_only", + "transactions", + "total_count" + ], + "title": "Form4ByDateResponse" + }, + "Form4Entry": { + "properties": { + "symbol": { + "type": "string", + "title": "Symbol" + }, + "filing_date": { + "type": "string", + "format": "date", + "title": "Filing Date" + }, + "transaction_date": { + "type": "string", + "format": "date", + "title": "Transaction Date" + }, + "owner_cik": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Owner Cik" + }, + "owner_name": { + "type": "string", + "title": "Owner Name" + }, + "owner_relationship": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Owner Relationship" + }, + "is_officer": { + "type": "boolean", + "title": "Is Officer", + "default": false + }, + "is_director": { + "type": "boolean", + "title": "Is Director", + "default": false + }, + "is_ten_percent_owner": { + "type": "boolean", + "title": "Is Ten Percent Owner", + "default": false + }, + "is_ceo": { + "type": "boolean", + "title": "Is Ceo", + "default": false + }, + "is_cfo": { + "type": "boolean", + "title": "Is Cfo", + "default": false + }, + "is_c_suite": { + "type": "boolean", + "title": "Is C Suite", + "default": false + }, + "transaction_code": { + "type": "string", + "title": "Transaction Code" + }, + "transaction_type": { + "type": "string", + "title": "Transaction Type" + }, + "shares": { + "type": "number", + "title": "Shares" + }, + "price": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Price" + }, + "total_value": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Total Value" + }, + "shares_owned_following": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Shares Owned Following" + }, + "purchase_pct_of_holding": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Purchase Pct Of Holding" + }, + "accession_number": { + "type": "string", + "title": "Accession Number" + } + }, + "type": "object", + "required": [ + "symbol", + "filing_date", + "transaction_date", + "owner_name", + "transaction_code", + "transaction_type", + "shares", + "accession_number" + ], + "title": "Form4Entry" + }, + "Form4Response": { + "properties": { + "symbol": { + "type": "string", + "title": "Symbol" + }, + "as_of": { + "type": "string", + "format": "date", + "title": "As Of" + }, + "window": { + "additionalProperties": true, + "type": "object", + "title": "Window" + }, + "transactions": { + "items": { + "$ref": "#/components/schemas/Form4Entry" + }, + "type": "array", + "title": "Transactions" + }, + "total_count": { + "type": "integer", + "title": "Total Count" + }, + "metadata": { + "additionalProperties": true, + "type": "object", + "title": "Metadata" + } + }, + "type": "object", + "required": [ + "symbol", + "as_of", + "transactions", + "total_count" + ], + "title": "Form4Response" + }, + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + "type": "array", + "title": "Detail" + } + }, + "type": "object", + "title": "HTTPValidationError" + }, + "HealthCheckResponse": { + "properties": { + "status": { + "type": "string", + "title": "Status" + }, + "version": { + "type": "string", + "title": "Version" + }, + "database": { + "type": "string", + "title": "Database" + }, + "cache": { + "type": "string", + "title": "Cache" + }, + "sec_data_available": { + "type": "boolean", + "title": "Sec Data Available" + }, + "timestamp": { + "type": "string", + "format": "date-time", + "title": "Timestamp" + } + }, + "type": "object", + "required": [ + "status", + "version", + "database", + "cache", + "sec_data_available", + "timestamp" + ], + "title": "HealthCheckResponse" + }, + "IngestResponse": { + "properties": { + "date": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Date" + }, + "date_range": { + "anyOf": [ + { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Date Range" + }, + "records_ingested": { + "type": "integer", + "title": "Records Ingested" + }, + "status": { + "type": "string", + "title": "Status" + } + }, + "type": "object", + "required": [ + "records_ingested", + "status" + ], + "title": "IngestResponse" + }, + "InsiderSummaryPeriod": { + "properties": { + "period_label": { + "type": "string", + "title": "Period Label" + }, + "buy_count": { + "type": "integer", + "title": "Buy Count", + "default": 0 + }, + "sell_count": { + "type": "integer", + "title": "Sell Count", + "default": 0 + }, + "buy_shares": { + "type": "number", + "title": "Buy Shares", + "default": 0.0 + }, + "sell_shares": { + "type": "number", + "title": "Sell Shares", + "default": 0.0 + }, + "buy_value": { + "type": "number", + "title": "Buy Value", + "default": 0.0 + }, + "sell_value": { + "type": "number", + "title": "Sell Value", + "default": 0.0 + }, + "net_shares": { + "type": "number", + "title": "Net Shares", + "default": 0.0 + }, + "net_value": { + "type": "number", + "title": "Net Value", + "default": 0.0 + }, + "unique_buyers": { + "type": "integer", + "title": "Unique Buyers", + "default": 0 + }, + "unique_sellers": { + "type": "integer", + "title": "Unique Sellers", + "default": 0 + } + }, + "type": "object", + "required": [ + "period_label" + ], + "title": "InsiderSummaryPeriod" + }, + "InsiderSummaryResponse": { + "properties": { + "symbol": { + "type": "string", + "title": "Symbol" + }, + "periods": { + "items": { + "$ref": "#/components/schemas/InsiderSummaryPeriod" + }, + "type": "array", + "title": "Periods" + }, + "notable_transactions": { + "items": { + "$ref": "#/components/schemas/InsiderTransactionEntry" + }, + "type": "array", + "title": "Notable Transactions" + }, + "metadata": { + "additionalProperties": true, + "type": "object", + "title": "Metadata" + } + }, + "type": "object", + "required": [ + "symbol", + "periods", + "notable_transactions" + ], + "title": "InsiderSummaryResponse" + }, + "InsiderTransactionEntry": { + "properties": { + "filing_date": { + "type": "string", + "format": "date", + "title": "Filing Date" + }, + "transaction_date": { + "type": "string", + "format": "date", + "title": "Transaction Date" + }, + "owner_name": { + "type": "string", + "title": "Owner Name" + }, + "owner_cik": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Owner Cik" + }, + "is_officer": { + "type": "boolean", + "title": "Is Officer", + "default": false + }, + "is_director": { + "type": "boolean", + "title": "Is Director", + "default": false + }, + "is_ten_percent_owner": { + "type": "boolean", + "title": "Is Ten Percent Owner", + "default": false + }, + "officer_title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Officer Title" + }, + "security_title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Security Title" + }, + "transaction_code": { + "type": "string", + "title": "Transaction Code" + }, + "transaction_type": { + "type": "string", + "title": "Transaction Type" + }, + "shares": { + "type": "number", + "title": "Shares" + }, + "price_per_share": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Price Per Share" + }, + "total_value": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Total Value" + }, + "shares_owned_after": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Shares Owned After" + }, + "is_derivative": { + "type": "boolean", + "title": "Is Derivative", + "default": false + } + }, + "type": "object", + "required": [ + "filing_date", + "transaction_date", + "owner_name", + "transaction_code", + "transaction_type", + "shares" + ], + "title": "InsiderTransactionEntry" + }, + "InsiderTransactionResponse": { + "properties": { + "symbol": { + "type": "string", + "title": "Symbol" + }, + "transactions": { + "items": { + "$ref": "#/components/schemas/InsiderTransactionEntry" + }, + "type": "array", + "title": "Transactions" + }, + "total_count": { + "type": "integer", + "title": "Total Count" + }, + "metadata": { + "additionalProperties": true, + "type": "object", + "title": "Metadata" + } + }, + "type": "object", + "required": [ + "symbol", + "transactions", + "total_count" + ], + "title": "InsiderTransactionResponse" + }, + "IntradayCandle": { + "properties": { + "timestamp": { + "type": "string", + "format": "date-time", + "title": "Timestamp" + }, + "open": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Open" + }, + "high": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "High" + }, + "low": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Low" + }, + "close": { + "type": "number", + "title": "Close" + }, + "volume": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Volume" + } + }, + "type": "object", + "required": [ + "timestamp", + "close" + ], + "title": "IntradayCandle" + }, + "IntradayResponse": { + "properties": { + "ticker": { + "type": "string", + "title": "Ticker" + }, + "interval": { + "type": "string", + "title": "Interval" + }, + "period": { + "type": "string", + "title": "Period" + }, + "candles": { + "items": { + "$ref": "#/components/schemas/IntradayCandle" + }, + "type": "array", + "title": "Candles" + }, + "metadata": { + "additionalProperties": true, + "type": "object", + "title": "Metadata" + } + }, + "type": "object", + "required": [ + "ticker", + "interval", + "period", + "candles" + ], + "title": "IntradayResponse" + }, + "JobLogEntry": { + "properties": { + "id": { + "type": "string", + "title": "Id" + }, + "job_type": { + "type": "string", + "title": "Job Type" + }, + "status": { + "type": "string", + "title": "Status" + }, + "started_at": { + "type": "string", + "format": "date-time", + "title": "Started At" + }, + "completed_at": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Completed At" + }, + "records_processed": { + "type": "integer", + "title": "Records Processed", + "default": 0 + }, + "error_message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Error Message" + } + }, + "type": "object", + "required": [ + "id", + "job_type", + "status", + "started_at" + ], + "title": "JobLogEntry" + }, + "JobLogResponse": { + "properties": { + "logs": { + "items": { + "$ref": "#/components/schemas/JobLogEntry" + }, + "type": "array", + "title": "Logs" + }, + "total_count": { + "type": "integer", + "title": "Total Count" + } + }, + "type": "object", + "required": [ + "logs", + "total_count" + ], + "title": "JobLogResponse" + }, + "MigrationRequest": { + "properties": { + "source_url": { + "type": "string", + "title": "Source Url", + "description": "Source API URL to migrate from" + }, + "api_key": { + "type": "string", + "title": "Api Key", + "description": "API key for authentication" + }, + "tickers": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Tickers", + "description": "Specific tickers to migrate, or all if not specified" + }, + "start_date": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Start Date" + }, + "end_date": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "End Date" + } + }, + "type": "object", + "required": [ + "source_url", + "api_key" + ], + "title": "MigrationRequest" + }, + "MigrationResponse": { + "properties": { + "status": { + "type": "string", + "title": "Status" + }, + "total_records": { + "type": "integer", + "title": "Total Records" + }, + "migrated_records": { + "type": "integer", + "title": "Migrated Records" + }, + "failed_records": { + "type": "integer", + "title": "Failed Records" + }, + "errors": { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array", + "title": "Errors" + }, + "duration_seconds": { + "type": "number", + "title": "Duration Seconds" + } + }, + "type": "object", + "required": [ + "status", + "total_records", + "migrated_records", + "failed_records", + "duration_seconds" + ], + "title": "MigrationResponse" + }, + "NewsFeatures": { + "properties": { + "article_count_1d": { + "type": "integer", + "title": "Article Count 1D", + "description": "GDELT articles published on the event date", + "default": 0 + }, + "article_count_3d": { + "type": "integer", + "title": "Article Count 3D", + "description": "GDELT articles in the event_date ± 1 day window", + "default": 0 + }, + "unique_domains_3d": { + "type": "integer", + "title": "Unique Domains 3D", + "description": "Distinct publisher domains in the 3-day window", + "default": 0 + }, + "us_article_count_3d": { + "type": "integer", + "title": "Us Article Count 3D", + "description": "US-sourced articles in the 3-day window", + "default": 0 + }, + "gdelt_status": { + "type": "string", + "title": "Gdelt Status", + "description": "GDELT data availability for this event date. 'collected' — scheduler has run; counts are accurate (0 means genuinely no articles). 'not_collected' — scheduler has not run yet; POST /admin/collect/gdelt/{ticker}?event_date=... to populate. 'not_available' — event date is before GDELT V2 coverage start (2017-01-01).", + "default": "not_collected" + } + }, + "type": "object", + "title": "NewsFeatures", + "example": { + "article_count_1d": 18, + "article_count_3d": 52, + "gdelt_status": "collected", + "unique_domains_3d": 34, + "us_article_count_3d": 41 + } + }, + "NewsOnlyResponse": { + "properties": { + "ticker": { + "type": "string", + "title": "Ticker" + }, + "retrieved_at": { + "type": "string", + "title": "Retrieved At" + }, + "news": { + "additionalProperties": true, + "type": "object", + "title": "News" + }, + "summary": { + "additionalProperties": true, + "type": "object", + "title": "Summary" + } + }, + "type": "object", + "required": [ + "ticker", + "retrieved_at", + "news", + "summary" + ], + "title": "NewsOnlyResponse" + }, + "NewsSocialResponse": { + "properties": { + "ticker": { + "type": "string", + "title": "Ticker" + }, + "retrieved_at": { + "type": "string", + "title": "Retrieved At" + }, + "news": { + "additionalProperties": true, + "type": "object", + "title": "News", + "description": "News articles and sources breakdown" + }, + "social_media": { + "additionalProperties": true, + "type": "object", + "title": "Social Media", + "description": "Social media posts and platforms breakdown" + }, + "summary": { + "$ref": "#/components/schemas/NewsSocialSummarySchema" + } + }, + "type": "object", + "required": [ + "ticker", + "retrieved_at", + "news", + "social_media", + "summary" + ], + "title": "NewsSocialResponse", + "description": "Complete response for ticker news and social data" + }, + "NewsSocialSummarySchema": { + "properties": { + "total_items": { + "type": "integer", + "title": "Total Items" + }, + "time_range_days": { + "type": "integer", + "title": "Time Range Days" + }, + "oldest_item": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Oldest Item" + }, + "newest_item": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Newest Item" + } + }, + "type": "object", + "required": [ + "total_items", + "time_range_days" + ], + "title": "NewsSocialSummarySchema", + "description": "Summary of news and social data" + }, + "PeriodType": { + "type": "string", + "enum": [ + "quarterly", + "annual", + "all" + ], + "title": "PeriodType" + }, + "PriceDataPoint": { + "properties": { + "date": { + "type": "string", + "format": "date", + "title": "Date" + }, + "open": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Open" + }, + "high": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "High" + }, + "low": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Low" + }, + "close": { + "type": "number", + "title": "Close" + }, + "volume": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Volume" + }, + "adjusted_close": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Adjusted Close" + }, + "data_source": { + "type": "string", + "title": "Data Source" + } + }, + "type": "object", + "required": [ + "date", + "close", + "data_source" + ], + "title": "PriceDataPoint" + }, + "PriceDataRequest": { + "properties": { + "ticker": { + "type": "string", + "maxLength": 10, + "minLength": 1, + "title": "Ticker", + "description": "Stock ticker symbol" + }, + "start_date": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "title": "Start Date", + "description": "Start date for data retrieval. Cannot be used with quarters or period." + }, + "end_date": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "title": "End Date", + "description": "End date for data retrieval. Cannot be used with quarters or period." + }, + "quarters": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array", + "maxItems": 40, + "minItems": 1 + }, + { + "type": "null" + } + ], + "title": "Quarters", + "description": "List of quarters in format 'YYYYQN' (e.g., ['2020Q1', '2020Q2']). Cannot be used with start_date/end_date or period. If provided, dates are ignored." + }, + "period": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Period", + "description": "Period string like '1d', '7d', '1m', '3m', '1y', '2y'. Cannot be used with start_date/end_date or quarters." + }, + "interval": { + "type": "string", + "title": "Interval", + "description": "Data interval: 1d, 1w, 1m, 5d, 1h, etc.", + "default": "1d" + }, + "force_refresh": { + "type": "boolean", + "title": "Force Refresh", + "description": "Force refresh data from Yahoo Finance", + "default": false + } + }, + "type": "object", + "required": [ + "ticker" + ], + "title": "PriceDataRequest", + "description": "Request for price data with flexible time period specification.\n\n**Three ways to specify time period (choose one):**\n1. **Date Range**: Use start_date and end_date\n2. **Quarters**: Use quarters list (e.g., ['2024Q1', '2024Q2'])\n3. **Period**: Use period string (e.g., '1d', '3m', '2y')\n\n**Important**: Cannot mix approaches in the same request." + }, + "PriceDataResponse": { + "properties": { + "ticker": { + "type": "string", + "title": "Ticker" + }, + "interval": { + "type": "string", + "title": "Interval" + }, + "data": { + "items": { + "$ref": "#/components/schemas/PriceDataPoint" + }, + "type": "array", + "title": "Data" + }, + "metadata": { + "additionalProperties": true, + "type": "object", + "title": "Metadata" + } + }, + "type": "object", + "required": [ + "ticker", + "interval", + "data" + ], + "title": "PriceDataResponse" + }, + "QuoteResponse": { + "properties": { + "ticker": { + "type": "string", + "title": "Ticker" + }, + "price": { + "type": "number", + "title": "Price" + }, + "regular_price": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Regular Price" + }, + "pre_market_price": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Pre Market Price" + }, + "post_market_price": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Post Market Price" + }, + "currency": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Currency" + }, + "exchange": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Exchange" + }, + "market_state": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Market State" + }, + "timestamp": { + "type": "string", + "format": "date-time", + "title": "Timestamp" + }, + "source": { + "type": "string", + "title": "Source", + "default": "YAHOO_FINANCE" + }, + "delayed": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Delayed", + "default": true + } + }, + "type": "object", + "required": [ + "ticker", + "price", + "timestamp" + ], + "title": "QuoteResponse" + }, + "RefreshMapsOut": { + "properties": { + "cusip_rows": { + "type": "integer", + "title": "Cusip Rows" + }, + "etf_rows": { + "type": "integer", + "title": "Etf Rows" + } + }, + "type": "object", + "required": [ + "cusip_rows", + "etf_rows" + ], + "title": "RefreshMapsOut" + }, + "RegistryResponse": { + "properties": { + "tickers": { + "items": { + "$ref": "#/components/schemas/TickerRegistryItem" + }, + "type": "array", + "title": "Tickers" + }, + "total_count": { + "type": "integer", + "title": "Total Count" + }, + "page": { + "type": "integer", + "title": "Page" + }, + "page_size": { + "type": "integer", + "title": "Page Size" + }, + "total_pages": { + "type": "integer", + "title": "Total Pages" + } + }, + "type": "object", + "required": [ + "tickers", + "total_count", + "page", + "page_size", + "total_pages" + ], + "title": "RegistryResponse" + }, + "RequestLogListResponse": { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/RequestLogResponse" + }, + "type": "array", + "title": "Items" + }, + "total": { + "type": "integer", + "title": "Total" + }, + "page": { + "type": "integer", + "title": "Page" + }, + "page_size": { + "type": "integer", + "title": "Page Size" + }, + "total_pages": { + "type": "integer", + "title": "Total Pages" + } + }, + "type": "object", + "required": [ + "items", + "total", + "page", + "page_size", + "total_pages" + ], + "title": "RequestLogListResponse", + "description": "Response schema for paginated request logs" + }, + "RequestLogResponse": { + "properties": { + "id": { + "type": "integer", + "title": "Id" + }, + "request_id": { + "type": "string", + "title": "Request Id" + }, + "endpoint": { + "type": "string", + "title": "Endpoint" + }, + "method": { + "type": "string", + "title": "Method" + }, + "path": { + "type": "string", + "title": "Path" + }, + "query_params": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Query Params" + }, + "request_body": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Request Body" + }, + "headers": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Headers" + }, + "status_code": { + "type": "integer", + "title": "Status Code" + }, + "response_size": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Response Size" + }, + "user_agent": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "User Agent" + }, + "client_ip": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Client Ip" + }, + "response_time_ms": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Response Time Ms" + }, + "created_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Created At" + } + }, + "type": "object", + "required": [ + "id", + "request_id", + "endpoint", + "method", + "path", + "status_code" + ], + "title": "RequestLogResponse", + "description": "Response schema for individual request log" + }, + "RequestLogStats": { + "properties": { + "total_requests": { + "type": "integer", + "title": "Total Requests" + }, + "success_requests": { + "type": "integer", + "title": "Success Requests" + }, + "client_error_requests": { + "type": "integer", + "title": "Client Error Requests" + }, + "server_error_requests": { + "type": "integer", + "title": "Server Error Requests" + }, + "success_rate": { + "type": "number", + "title": "Success Rate" + }, + "requests_by_method": { + "additionalProperties": { + "type": "integer" + }, + "type": "object", + "title": "Requests By Method" + }, + "requests_by_status_code": { + "additionalProperties": { + "type": "integer" + }, + "type": "object", + "title": "Requests By Status Code" + }, + "requests_by_endpoint": { + "additionalProperties": { + "type": "integer" + }, + "type": "object", + "title": "Requests By Endpoint" + }, + "average_response_time_ms": { + "type": "number", + "title": "Average Response Time Ms" + }, + "hourly_trend": { + "additionalProperties": { + "type": "integer" + }, + "type": "object", + "title": "Hourly Trend" + }, + "start_date": { + "type": "string", + "title": "Start Date" + }, + "end_date": { + "type": "string", + "title": "End Date" + } + }, + "type": "object", + "required": [ + "total_requests", + "success_requests", + "client_error_requests", + "server_error_requests", + "success_rate", + "requests_by_method", + "requests_by_status_code", + "requests_by_endpoint", + "average_response_time_ms", + "hourly_trend", + "start_date", + "end_date" + ], + "title": "RequestLogStats", + "description": "Response schema for request log statistics" + }, + "SessionAggregateBatchRequest": { + "properties": { + "session_date": { + "type": "string", + "format": "date", + "title": "Session Date" + }, + "window": { + "type": "string", + "title": "Window" + }, + "symbols": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Symbols" + }, + "sources": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Sources" + } + }, + "type": "object", + "required": [ + "session_date", + "window", + "symbols" + ], + "title": "SessionAggregateBatchRequest" + }, + "SessionAggregateBatchResponse": { + "properties": { + "items": { + "additionalProperties": { + "$ref": "#/components/schemas/SessionAggregateItem" + }, + "type": "object", + "title": "Items" + } + }, + "type": "object", + "required": [ + "items" + ], + "title": "SessionAggregateBatchResponse" + }, + "SessionAggregateItem": { + "properties": { + "ticker": { + "type": "string", + "title": "Ticker" + }, + "session_date": { + "type": "string", + "title": "Session Date" + }, + "window": { + "type": "string", + "title": "Window" + }, + "headline_count": { + "type": "integer", + "title": "Headline Count", + "default": 0 + }, + "primary_count": { + "type": "integer", + "title": "Primary Count", + "default": 0 + }, + "first_headline_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "First Headline At" + }, + "last_headline_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Last Headline At" + }, + "category_counts": { + "additionalProperties": { + "type": "integer" + }, + "type": "object", + "title": "Category Counts" + }, + "sentiment_mean": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Sentiment Mean" + }, + "sentiment_recency_weighted": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Sentiment Recency Weighted" + }, + "social": { + "$ref": "#/components/schemas/SocialStatsItem" + }, + "sources_present": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Sources Present" + } + }, + "type": "object", + "required": [ + "ticker", + "session_date", + "window" + ], + "title": "SessionAggregateItem" + }, + "ShortRatioHistoryResponse": { + "properties": { + "symbol": { + "type": "string", + "title": "Symbol" + }, + "history": { + "items": { + "$ref": "#/components/schemas/ShortRatioPoint" + }, + "type": "array", + "title": "History" + }, + "avg_short_ratio": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Avg Short Ratio" + }, + "metadata": { + "additionalProperties": true, + "type": "object", + "title": "Metadata" + } + }, + "type": "object", + "required": [ + "symbol", + "history" + ], + "title": "ShortRatioHistoryResponse" + }, + "ShortRatioPoint": { + "properties": { + "date": { + "type": "string", + "format": "date", + "title": "Date" + }, + "short_volume": { + "type": "number", + "title": "Short Volume" + }, + "short_exempt_volume": { + "type": "number", + "title": "Short Exempt Volume" + }, + "total_volume": { + "type": "number", + "title": "Total Volume" + }, + "short_ratio": { + "type": "number", + "title": "Short Ratio" + } + }, + "type": "object", + "required": [ + "date", + "short_volume", + "short_exempt_volume", + "total_volume", + "short_ratio" + ], + "title": "ShortRatioPoint" + }, + "ShortVolumeEntry": { + "properties": { + "date": { + "type": "string", + "format": "date", + "title": "Date" + }, + "symbol": { + "type": "string", + "title": "Symbol" + }, + "short_volume": { + "type": "number", + "title": "Short Volume" + }, + "short_exempt_volume": { + "type": "number", + "title": "Short Exempt Volume", + "default": 0.0 + }, + "total_volume": { + "type": "number", + "title": "Total Volume" + }, + "market": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Market" + }, + "short_ratio": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Short Ratio" + } + }, + "type": "object", + "required": [ + "date", + "symbol", + "short_volume", + "total_volume" + ], + "title": "ShortVolumeEntry" + }, + "ShortVolumeResponse": { + "properties": { + "symbol": { + "type": "string", + "title": "Symbol" + }, + "entries": { + "items": { + "$ref": "#/components/schemas/ShortVolumeEntry" + }, + "type": "array", + "title": "Entries" + }, + "total_count": { + "type": "integer", + "title": "Total Count" + }, + "metadata": { + "additionalProperties": true, + "type": "object", + "title": "Metadata" + } + }, + "type": "object", + "required": [ + "symbol", + "entries", + "total_count" + ], + "title": "ShortVolumeResponse" + }, + "SnapshotBuildRequest": { + "properties": { + "tickers": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Tickers", + "description": "Specific tickers to build. Omit for all registry tickers." + }, + "start_date": { + "type": "string", + "title": "Start Date", + "description": "Start date YYYY-MM-DD (e.g. 2015-01-01)" + }, + "end_date": { + "type": "string", + "title": "End Date", + "description": "End date YYYY-MM-DD (e.g. 2025-12-01)" + }, + "force_rebuild": { + "type": "boolean", + "title": "Force Rebuild", + "description": "Delete existing snapshots for these tickers before rebuilding", + "default": false + } + }, + "type": "object", + "required": [ + "start_date", + "end_date" + ], + "title": "SnapshotBuildRequest" + }, + "SocialOnlyResponse": { + "properties": { + "ticker": { + "type": "string", + "title": "Ticker" + }, + "retrieved_at": { + "type": "string", + "title": "Retrieved At" + }, + "social_media": { + "additionalProperties": true, + "type": "object", + "title": "Social Media" + }, + "summary": { + "additionalProperties": true, + "type": "object", + "title": "Summary" + } + }, + "type": "object", + "required": [ + "ticker", + "retrieved_at", + "social_media", + "summary" + ], + "title": "SocialOnlyResponse" + }, + "SocialStatsItem": { + "properties": { + "message_count": { + "type": "integer", + "title": "Message Count", + "default": 0 + }, + "bull_count": { + "type": "integer", + "title": "Bull Count", + "default": 0 + }, + "bear_count": { + "type": "integer", + "title": "Bear Count", + "default": 0 + }, + "bull_bear_ratio": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Bull Bear Ratio" + } + }, + "type": "object", + "title": "SocialStatsItem" + }, + "TickerRegistryItem": { + "properties": { + "ticker": { + "type": "string", + "title": "Ticker" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Name" + }, + "sector": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Sector" + }, + "industry": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Industry" + }, + "exchange": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Exchange" + }, + "cik": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Cik" + }, + "is_active": { + "type": "boolean", + "title": "Is Active", + "default": true + } + }, + "type": "object", + "required": [ + "ticker" + ], + "title": "TickerRegistryItem" + }, + "TodayOHLCResponse": { + "properties": { + "ticker": { + "type": "string", + "title": "Ticker" + }, + "date": { + "type": "string", + "format": "date", + "title": "Date" + }, + "open": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Open" + }, + "high": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "High" + }, + "low": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Low" + }, + "close": { + "type": "number", + "title": "Close" + }, + "volume": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Volume" + }, + "source": { + "type": "string", + "title": "Source", + "default": "YAHOO_FINANCE" + }, + "method": { + "type": "string", + "title": "Method", + "default": "daily" + }, + "metadata": { + "additionalProperties": true, + "type": "object", + "title": "Metadata" + } + }, + "type": "object", + "required": [ + "ticker", + "date", + "close" + ], + "title": "TodayOHLCResponse" + }, + "UniverseScreenResponse": { + "properties": { + "stocks": { + "items": { + "$ref": "#/components/schemas/UniverseSnapshotItem" + }, + "type": "array", + "title": "Stocks" + }, + "total_count": { + "type": "integer", + "title": "Total Count" + }, + "page": { + "type": "integer", + "title": "Page" + }, + "page_size": { + "type": "integer", + "title": "Page Size" + }, + "total_pages": { + "type": "integer", + "title": "Total Pages" + }, + "snapshot_date": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Snapshot Date" + }, + "filters_applied": { + "additionalProperties": true, + "type": "object", + "title": "Filters Applied", + "default": {} + }, + "metadata": { + "additionalProperties": true, + "type": "object", + "title": "Metadata", + "default": {} + } + }, + "type": "object", + "required": [ + "stocks", + "total_count", + "page", + "page_size", + "total_pages" + ], + "title": "UniverseScreenResponse" + }, + "UniverseSnapshotItem": { + "properties": { + "ticker": { + "type": "string", + "title": "Ticker" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Name" + }, + "market_cap": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Market Cap" + }, + "close_price": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Close Price" + }, + "shares_outstanding": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Shares Outstanding" + }, + "sector": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Sector" + }, + "industry": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Industry" + }, + "exchange": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Exchange" + }, + "snapshot_date": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Snapshot Date" + } + }, + "type": "object", + "required": [ + "ticker" + ], + "title": "UniverseSnapshotItem" + }, + "ValidationError": { + "properties": { + "loc": { + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + }, + "type": "array", + "title": "Location" + }, + "msg": { + "type": "string", + "title": "Message" + }, + "type": { + "type": "string", + "title": "Error Type" + }, + "input": { + "title": "Input" + }, + "ctx": { + "type": "object", + "title": "Context" + } + }, + "type": "object", + "required": [ + "loc", + "msg", + "type" + ], + "title": "ValidationError" + }, + "WikiFeatures": { + "properties": { + "views": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Views", + "description": "Wikipedia pageviews on the event date" + }, + "baseline_10d": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Baseline 10D", + "description": "Median pageviews over the prior 10 days" + }, + "spike_10d": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Spike 10D", + "description": "views / baseline_10d; >1 means above-average attention" + }, + "zscore_20d": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Zscore 20D", + "description": "Z-score vs prior 20-day mean/stdev; null if stdev=0" + } + }, + "type": "object", + "title": "WikiFeatures", + "example": { + "baseline_10d": 12400.0, + "spike_10d": 3.65, + "views": 45230, + "zscore_20d": 4.21 + } + }, + "app__api__v1__endpoints__news_v2__HeadlineItem": { + "properties": { + "source": { + "type": "string", + "title": "Source" + }, + "source_id": { + "type": "string", + "title": "Source Id" + }, + "ticker": { + "type": "string", + "title": "Ticker" + }, + "tickers_all": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Tickers All" + }, + "published_at": { + "type": "string", + "title": "Published At" + }, + "headline": { + "type": "string", + "title": "Headline" + }, + "summary": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Summary" + }, + "url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Url" + }, + "language": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Language" + }, + "vendor_categories": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Vendor Categories" + }, + "categories": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Categories" + }, + "raw_sentiment": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Raw Sentiment" + }, + "is_primary": { + "type": "boolean", + "title": "Is Primary" + }, + "ingested_at": { + "type": "string", + "title": "Ingested At" + } + }, + "type": "object", + "required": [ + "source", + "source_id", + "ticker", + "published_at", + "headline", + "is_primary", + "ingested_at" + ], + "title": "HeadlineItem" + }, + "app__api__v1__endpoints__news_v2__HeadlinesResponse": { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/app__api__v1__endpoints__news_v2__HeadlineItem" + }, + "type": "array", + "title": "Items" + }, + "next_cursor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Next Cursor" + } + }, + "type": "object", + "required": [ + "items" + ], + "title": "HeadlinesResponse" + }, + "app__api__v1__endpoints__overlay__HeadlineItem": { + "properties": { + "title": { + "type": "string", + "title": "Title" + }, + "publisher": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Publisher" + }, + "published_at": { + "type": "string", + "format": "date-time", + "title": "Published At" + }, + "article_guid": { + "type": "string", + "title": "Article Guid" + } + }, + "type": "object", + "required": [ + "title", + "published_at", + "article_guid" + ], + "title": "HeadlineItem" + }, + "app__api__v1__endpoints__overlay__HeadlinesResponse": { + "properties": { + "symbol": { + "type": "string", + "title": "Symbol" + }, + "headlines": { + "items": { + "$ref": "#/components/schemas/app__api__v1__endpoints__overlay__HeadlineItem" + }, + "type": "array", + "title": "Headlines" + }, + "headline_count_6h": { + "type": "integer", + "title": "Headline Count 6H" + }, + "headline_count_24h": { + "type": "integer", + "title": "Headline Count 24H" + }, + "publisher_breadth_24h": { + "type": "integer", + "title": "Publisher Breadth 24H" + } + }, + "type": "object", + "required": [ + "symbol", + "headlines", + "headline_count_6h", + "headline_count_24h", + "publisher_breadth_24h" + ], + "title": "HeadlinesResponse" + } + } + }, + "tags": [ + { + "name": "health", + "description": "Health check endpoints" + }, + { + "name": "financial", + "description": "Financial data retrieval endpoints" + }, + { + "name": "price", + "description": "Price data endpoints (OHLCV)" + }, + { + "name": "news", + "description": "News and social media endpoints" + }, + { + "name": "metadata", + "description": "Data catalog and metadata endpoints" + }, + { + "name": "filings", + "description": "SEC filings search, document listing, and exhibit extraction (8-K, 6-K, 20-F, 40-F)" + }, + { + "name": "etf", + "description": "ETF holdings endpoints" + }, + { + "name": "alpaca", + "description": "Alpaca Market Data endpoints (OHLCV bars, connection status)" + }, + { + "name": "finra", + "description": "FINRA RegSHO short sale volume data (ingest, query, ratio history)" + }, + { + "name": "admin", + "description": "Administrative endpoints (migration, etc.)" + }, + { + "name": "overlay", + "description": "Overlay headlines — Yahoo RSS headline collector" + }, + { + "name": "overlay-admin", + "description": "Overlay job log" + }, + { + "name": "screener", + "description": "Stock screener — condition-based filtering by market cap, volume, price, P/E, sector, exchange" + }, + { + "name": "stocks", + "description": "Stock market data — most active, 52-week gainers, trending, and index constituents (S&P 500 / Nasdaq 100)" + }, + { + "name": "attention", + "description": "Attention signals — Wikipedia pageview spikes and GDELT news article counts for event-centric backtesting" + }, + { + "name": "attention-admin", + "description": "Attention administrative endpoints — entity resolution, Wikipedia and GDELT data collection" + }, + { + "name": "database", + "description": "Database inspection — record counts, date ranges, raw data browsing, and ETF snapshot history" + }, + { + "name": "fred", + "description": "FRED (Federal Reserve Economic Data) — macroeconomic series via FRED API proxy" + }, + { + "name": "ownership", + "description": "SEC 13D/13G activist ownership events — activist filings, active positions (PIT-safe)" + }, + { + "name": "error-logs", + "description": "Error log management — browse and clear server-side error records" + }, + { + "name": "request-logs", + "description": "Request log management — browse API request history and latency records" + } + ] +}