About This Dashboard
How Buy-Son works under the hood
What This Is
Buy-Son is a serverless stock-evaluation dashboard built around a "value investing" lens — it pulls multi-year price history, company fundamentals, and full balance sheets for any US-listed ticker and renders them as interactive Plotly charts in your browser.
Nothing is precomputed. When you select a ticker, a request goes out to AWS, which then queries third-party data sources live and returns a single JSON payload. The charts are rendered client-side, so panning, zooming, and tooltips are instant once data arrives.
Architecture at a Glance
Every line is bidirectional — requests go out, responses return the same way. DNS lookups happen once at page load (Route 53 resolves the custom domain to CloudFront; AWS-managed DNS resolves the API Gateway domain). API calls bypass CloudFront entirely, so Lambda responses travel back as: Lambda → API Gateway → Browser.
What Happens When You Click "Add Symbol & Run"
-
The browser sends an HTTPS request to
/api/stock/{ticker}with your selected start and end years. -
The request goes directly to API Gateway, not through CloudFront —
the API Gateway URL is baked into
config.jsat deploy time. API Gateway then invokes the Lambda function. (Static files like HTML, CSS, and JS take a separate path: browser → CloudFront → S3, edge-cached, and never reach Lambda.) - Lambda fans out to two external sources in parallel: yfinance (Yahoo Finance) for daily OHLC prices and current company info, and SEC EDGAR for 10+ years of annual financial statements and balance sheets pulled directly from SEC filings.
- Lambda computes 50-day and 200-day moving averages on the price series, normalizes fields across the two providers, and merges everything into a single JSON response.
- The browser receives the payload and hands it to Plotly.js, which renders five interactive charts: price + moving averages, volume, financial timeline, company info panel, and a balance sheet (bar chart + sunburst).
-
Saved tickers in the dropdown come from a separate
/api/tickerscall that reads a single record out of DynamoDB.
Where the Computation Happens
Almost all of the heavy lifting happens in two places:
- AWS Lambda (server-side): Fetches data from external APIs, calculates moving averages, normalizes inconsistent field names across providers, and shapes the response. Runs on Python 3.11 / ARM64, cold-starts in 1–3 seconds.
- Your browser (client-side): Plotly.js handles all rendering, interactivity (pan, zoom, tooltips, legend toggles), and the dual-handle year-range slider. No data is persisted client-side — refresh the page and everything reloads from the API.
The dashboard intentionally does not store historical price data. Every chart you see was fetched live from the source within the last few seconds.
Where the Data Comes From
| Data | Source | Notes |
|---|---|---|
| Daily prices (OHLC + volume) | Yahoo Finance via yfinance |
Adjusted for splits and dividends |
| Moving averages (50-day, 200-day) | Computed in Lambda | Rolling mean over the price series |
| Company info, market cap, P/E ratios | Yahoo Finance via yfinance |
Trailing + forward P/E, EBITDA, debt |
| Annual financial statements (10+ years) | SEC EDGAR (data.sec.gov) | Pulled directly from 10-K filings |
| Balance sheets | SEC EDGAR | Detailed line items for sunburst chart |
| Saved ticker dropdown | DynamoDB | Single record keyed by PK = "TICKERS" |
Tech Stack
| Layer | Tools |
|---|---|
| Frontend | Vanilla HTML / CSS / JavaScript, Plotly.js |
| Backend runtime | Python 3.11 on AWS Lambda (ARM64 / Graviton) |
| Data libraries | yfinance, requests (SEC EDGAR), pandas, numpy |
| API layer | AWS API Gateway (HTTP API) |
| Storage | Amazon DynamoDB (on-demand), Amazon S3 |
| CDN / DNS / TLS | CloudFront, Route 53, AWS Certificate Manager |
| Infrastructure as code | AWS CDK (Python) — three stacks: Storage, Api, Frontend |
| Testing | pytest, moto (DynamoDB mocking), ruff, mypy |
Hosting & Cost
The entire stack runs comfortably within AWS free-tier limits at the dashboard's expected usage (single-digit requests per day). Estimated cost: ~$0/month, with ECR image storage being the only meaningful charge after free-tier expiration (~$0.02/month for the ~200 MB Lambda container image).
Because the architecture is serverless, there are no servers to keep running between requests — Lambda spins up on demand and tears down when idle.
Source Code
Everything that powers this site is open source: github.com/JackVance/stock-eval-dashboard