feat: OpenBB Investment Analysis API
REST API wrapping OpenBB SDK for stock data, sentiment analysis, technical indicators, macro data, and rule-based portfolio analysis. - Stock data via yfinance (quote, profile, metrics, financials, historical, news) - News sentiment via Alpha Vantage (per-article, per-ticker scores) - Analyst data via Finnhub (recommendations, insider trades, upgrades) - Macro data via FRED (Fed rate, CPI, GDP, unemployment, treasury yields) - Technical indicators via openbb-technical (RSI, MACD, SMA, EMA, Bollinger) - Rule-based portfolio analysis engine (BUY_MORE/HOLD/SELL) - Stock discovery (gainers, losers, active, undervalued, growth) - 102 tests, all passing
This commit is contained in:
68
mappers.py
Normal file
68
mappers.py
Normal file
@@ -0,0 +1,68 @@
|
||||
"""Shared mapping functions from raw dicts to response models."""
|
||||
|
||||
from typing import Any
|
||||
|
||||
from models import (
|
||||
DiscoverItem,
|
||||
MetricsResponse,
|
||||
ProfileResponse,
|
||||
QuoteResponse,
|
||||
)
|
||||
|
||||
|
||||
def quote_from_dict(symbol: str, data: dict[str, Any]) -> QuoteResponse:
|
||||
return QuoteResponse(
|
||||
symbol=symbol,
|
||||
name=data.get("name"),
|
||||
price=data.get("last_price") or data.get("close"),
|
||||
change=data.get("change"),
|
||||
change_percent=data.get("change_percent"),
|
||||
volume=data.get("volume"),
|
||||
market_cap=data.get("market_cap"),
|
||||
currency=data.get("currency"),
|
||||
)
|
||||
|
||||
|
||||
def profile_from_dict(symbol: str, data: dict[str, Any]) -> ProfileResponse:
|
||||
return ProfileResponse(
|
||||
symbol=symbol,
|
||||
name=data.get("name"),
|
||||
sector=data.get("sector"),
|
||||
industry=data.get("industry"),
|
||||
country=data.get("country"),
|
||||
description=data.get("long_description") or data.get("description"),
|
||||
website=data.get("website"),
|
||||
employees=data.get("full_time_employees") or data.get("employees"),
|
||||
)
|
||||
|
||||
|
||||
def metrics_from_dict(symbol: str, data: dict[str, Any]) -> MetricsResponse:
|
||||
return MetricsResponse(
|
||||
symbol=symbol,
|
||||
pe_ratio=data.get("pe_ratio"),
|
||||
pb_ratio=data.get("pb_ratio"),
|
||||
ps_ratio=data.get("ps_ratio"),
|
||||
peg_ratio=data.get("peg_ratio"),
|
||||
roe=data.get("roe") or data.get("return_on_equity"),
|
||||
roa=data.get("roa") or data.get("return_on_assets"),
|
||||
dividend_yield=data.get("dividend_yield"),
|
||||
beta=data.get("beta"),
|
||||
eps=data.get("eps_ttm") or data.get("eps"),
|
||||
revenue_growth=data.get("revenue_growth"),
|
||||
earnings_growth=data.get("earnings_growth"),
|
||||
)
|
||||
|
||||
|
||||
def discover_item_from_dict(data: dict[str, Any]) -> DiscoverItem:
|
||||
return DiscoverItem(
|
||||
symbol=data.get("symbol"),
|
||||
name=data.get("name"),
|
||||
price=data.get("price") or data.get("last_price"),
|
||||
change_percent=data.get("change_percent") or data.get("percent_change"),
|
||||
volume=data.get("volume"),
|
||||
market_cap=data.get("market_cap"),
|
||||
)
|
||||
|
||||
|
||||
def discover_items_from_list(items: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
||||
return [discover_item_from_dict(item).model_dump() for item in items]
|
||||
Reference in New Issue
Block a user