mirror of
https://github.com/shawnkim1997/All-in-one-Financial-Analysis.git
synced 2026-08-18 21:08:07 +00:00
feat: add Atlas Terminal — Next.js 14 + FastAPI full-stack migration
Complete migration from Streamlit to Next.js 14 App Router + FastAPI backend. Frontend (Next.js 14): - 10 pages: Overview, Research, Valuation, Technical, Markets, Earnings, News, Portfolio, Filings, Settings - Terminal Noir dark theme with custom Tailwind config - TradingView Lightweight Charts for candlestick/volume - Valuation: DCF, Sensitivity Matrix, Monte Carlo, Tornado, Reverse DCF - Financial Statements table with YoY growth badges and margin rows - SEC EDGAR inline filing viewer with section tabs - News split-view with iframe article embedding - Technical Analysis with RSI, MACD, Bollinger, Fibonacci, Moving Averages - Earnings beat/miss visualization - AI Copilot chat panel with Gemini integration Backend (FastAPI): - 13 routers: market_data, financials, valuation, technical, earnings, insider, edgar, news, portfolio, analysis, chat, estimates, fx - Services: DCF engine, Monte Carlo simulation, sensitivity analysis, risk metrics, SEC parser, technical indicators - yfinance + yahooquery data sources with fallback pattern - SQLite caching layer Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
56a9561f71
commit
b2acda81ee
@@ -0,0 +1,88 @@
|
||||
"""Numeric safety utilities for the ATLAS Terminal backend.
|
||||
|
||||
Provides safe type-coercion helpers used across all services to handle
|
||||
None, NaN, and non-numeric values gracefully without raising exceptions.
|
||||
"""
|
||||
|
||||
from typing import Optional
|
||||
|
||||
import pandas as pd
|
||||
|
||||
|
||||
def _safe_float(x: object) -> Optional[float]:
|
||||
"""Convert *x* to ``float``, returning ``None`` for unconvertible values.
|
||||
|
||||
Handles ``None``, ``NaN`` (both Python ``float('nan')`` and pandas
|
||||
``pd.NA``), and arbitrary objects whose ``float()`` conversion fails.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
x:
|
||||
Any value that might be numeric.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Optional[float]
|
||||
The float representation, or ``None`` if conversion is impossible.
|
||||
"""
|
||||
if x is None or (isinstance(x, float) and (x != x or pd.isna(x))):
|
||||
return None
|
||||
try:
|
||||
return float(x)
|
||||
except (TypeError, ValueError):
|
||||
return None
|
||||
|
||||
|
||||
def _na(x: object) -> object:
|
||||
"""Return the string ``'N/A'`` for ``None``/``NaN``, otherwise *x* unchanged.
|
||||
|
||||
Useful when building display-ready dictionaries or DataFrames where
|
||||
missing numeric values should appear as a human-readable sentinel.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
x:
|
||||
Any value.
|
||||
|
||||
Returns
|
||||
-------
|
||||
object
|
||||
``'N/A'`` when *x* is ``None`` or ``NaN``; *x* otherwise.
|
||||
"""
|
||||
if x is None or (isinstance(x, float) and (pd.isna(x) or x != x)):
|
||||
return "N/A"
|
||||
return x
|
||||
|
||||
|
||||
def _format_shares_display(shares: Optional[float]) -> str:
|
||||
"""Format a share count for human-friendly display.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> _format_shares_display(15_420_000_000)
|
||||
'15.42B Shares'
|
||||
>>> _format_shares_display(1_200_000)
|
||||
'1.20M Shares'
|
||||
>>> _format_shares_display(None)
|
||||
'N/A'
|
||||
|
||||
Parameters
|
||||
----------
|
||||
shares:
|
||||
Raw share count (absolute number, not in millions/billions).
|
||||
|
||||
Returns
|
||||
-------
|
||||
str
|
||||
A concise string such as ``'15.42B Shares'`` or ``'N/A'``.
|
||||
"""
|
||||
if shares is None or shares <= 0:
|
||||
return "N/A"
|
||||
s = float(shares)
|
||||
if s >= 1e9:
|
||||
return f"{s / 1e9:.2f}B Shares"
|
||||
if s >= 1e6:
|
||||
return f"{s / 1e6:.2f}M Shares"
|
||||
if s >= 1e3:
|
||||
return f"{s / 1e3:.2f}K Shares"
|
||||
return f"{s:.0f} Shares"
|
||||
Reference in New Issue
Block a user