Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
dc300db
Add frontend design document for React charting webapp
wkf2000 Mar 10, 2026
52d4910
Add frontend implementation plan with 16 bite-sized tasks
wkf2000 Mar 10, 2026
339fb63
feat: scaffold Vite + React + TypeScript frontend with dependencies
wkf2000 Mar 10, 2026
17d247a
feat: configure Tailwind CSS v4 with dark fintech design tokens
wkf2000 Mar 10, 2026
ad5dbc7
feat: add TypeScript types matching backend API models
wkf2000 Mar 10, 2026
bcb0091
feat: add Axios API client and React Query provider
wkf2000 Mar 10, 2026
de39491
feat: add React Query hooks for all API endpoints
wkf2000 Mar 10, 2026
bff1e45
feat: add Zustand UI store for sidebar, indicators, and time range
wkf2000 Mar 10, 2026
4ef8594
feat: add constants, formatters, and indicator computation utilities
wkf2000 Mar 10, 2026
b0a1c0c
feat: add common UI components (Card, Skeleton, Badge, SearchInput, P…
wkf2000 Mar 10, 2026
b0e8bbb
feat: add layout components (Sidebar, TopBar, AppLayout) with respons…
wkf2000 Mar 10, 2026
a8652c3
feat: add React Router routes with page stubs
wkf2000 Mar 10, 2026
76b5d8d
feat: build Dashboard page with ticker cards, sparklines, and add tic…
wkf2000 Mar 10, 2026
b1b9ddd
feat: build Chart page with candlestick chart, toolbar, and symbol he…
wkf2000 Mar 10, 2026
a45dd01
feat: add technical indicators (SMA, EMA, RSI, MACD, Bollinger) to chart
wkf2000 Mar 10, 2026
52ece07
feat: build Watchlist page with sortable table and ticker management
wkf2000 Mar 10, 2026
c0bff84
feat: add placeholder pages for Portfolio and Screener
wkf2000 Mar 10, 2026
faf4c9a
fix: polish responsive behavior, design token consistency, and layout…
wkf2000 Mar 10, 2026
804f501
docs: update README with full project documentation
wkf2000 Mar 10, 2026
dec6004
chore: add VS Code launch config for backend, frontend, and full stack
wkf2000 Mar 10, 2026
bd240a4
feat: integrate frontend build into Docker and CI/CD pipeline
wkf2000 Mar 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
.git
.github
.venv
.vscode
.env
.ruff_cache
.pytest_cache
.mypy_cache
.cursor
__pycache__
*.pyc
data/
*.egg-info
dist/
build/
frontend/node_modules
frontend/dist
4 changes: 2 additions & 2 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@ jobs:

echo "Checking container status..."
if docker compose -f docker-compose.yml ps | grep -q "Up"; then
echo "Containers are running"
echo "Containers are running"
else
echo "Containers are not running"
echo "Containers are not running"
docker compose -f docker-compose.yml logs --tail=20
exit 1
fi
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ dist/
downloads/
eggs/
.eggs/
lib/
lib64/
/lib/
/lib64/
parts/
sdist/
var/
Expand Down Expand Up @@ -200,6 +200,7 @@ cython_debug/
# refer to https://docs.cursor.com/context/ignore-files
.cursorignore
.cursorindexingignore
.cursor/skills/

# Marimo
marimo/_static/
Expand Down
33 changes: 33 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Backend (FastAPI)",
"type": "python",
"request": "launch",
"module": "uvicorn",
"args": ["flow.api.app:app", "--reload", "--host", "0.0.0.0", "--port", "8000"],
"env": {
"PYTHONPATH": "${workspaceFolder}/src"
},
"cwd": "${workspaceFolder}",
"console": "integratedTerminal"
},
{
"name": "Frontend (Vite)",
"type": "node",
"request": "launch",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "dev"],
"cwd": "${workspaceFolder}/frontend",
"console": "integratedTerminal"
}
],
"compounds": [
{
"name": "Full Stack (Backend + Frontend)",
"configurations": ["Backend (FastAPI)", "Frontend (Vite)"],
"stopAll": true
}
]
}
11 changes: 11 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
FROM node:22-slim AS frontend

WORKDIR /app/frontend

COPY frontend/package.json frontend/package-lock.json ./
RUN npm ci

COPY frontend/ ./
RUN npm run build

FROM python:3.11-slim AS builder

WORKDIR /app
Expand All @@ -18,6 +28,7 @@ WORKDIR /app
COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
COPY --from=builder /usr/local/bin/flow /usr/local/bin/flow
COPY --from=builder /usr/local/bin/uvicorn /usr/local/bin/uvicorn
COPY --from=frontend /app/frontend/dist /app/static

ENV FLOW_DATA_DIR=/data

Expand Down
163 changes: 162 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,162 @@
# flow
# Flow

Stock market data platform with OHLCV ingestion, technical charting, and a professional dark-themed web interface.

## Architecture

```
┌─────────────────┐ ┌──────────────────┐ ┌────────────────┐
│ React Frontend │──────▶│ FastAPI Backend │──────▶│ Parquet + DuckDB│
│ (Vite + TW) │ /api │ (uvicorn) │ │ (data/equity) │
└─────────────────┘ └──────────────────┘ └────────────────┘
┌──────────────────┐
│ OpenBB / yfinance │
│ (data provider) │
└──────────────────┘
```

**Backend** — FastAPI serving OHLCV price data, ticker management, and summary statistics. Data is ingested from yfinance via OpenBB, stored in Parquet files with Hive-style partitioning, and queried through DuckDB.

**Frontend** — React SPA with candlestick charting (Lightweight Charts), client-side technical indicators, and a dark fintech UI. Communicates with the backend via REST API.

## Quick Start

### Prerequisites

- Python 3.11+
- Node.js 18+
- [uv](https://docs.astral.sh/uv/) (recommended) or pip

### Backend

```bash
# Install dependencies
uv sync

# Add a ticker and backfill historical data
uv run flow add AAPL
uv run flow add MSFT

# Start the API server
uv run flow serve
```

The API runs at `http://localhost:8000`. See [API Endpoints](#api-endpoints) below.

### Frontend

```bash
cd frontend
npm install
npm run dev
```

Opens at `http://localhost:5173` with automatic proxy to the backend.

### Docker

```bash
cp .env.example .env
docker compose up -d
```

## API Endpoints

| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/health` | Health check |
| `GET` | `/api/tickers` | List registered tickers |
| `POST` | `/api/tickers` | Add ticker (triggers backfill) |
| `DELETE` | `/api/tickers/{symbol}` | Remove ticker and its data |
| `GET` | `/api/equity/{symbol}/prices` | OHLCV price data (`?start=&end=`) |
| `GET` | `/api/equity/{symbol}/summary` | 52w high/low, avg volume, latest close |
| `POST` | `/api/ingest` | Run incremental ingest for all tickers |

## Frontend Pages

| Page | Route | Description |
|------|-------|-------------|
| Dashboard | `/` | Ticker card grid with sparkline charts and summary stats |
| Chart | `/chart/:symbol` | Candlestick chart with volume, SMA/EMA/Bollinger overlays, RSI/MACD sub-panels |
| Watchlist | `/watchlist` | Sortable data table of all tracked tickers |
| Portfolio | `/portfolio` | Coming soon |
| Screener | `/screener` | Coming soon |

## Tech Stack

### Backend

| Component | Technology |
|-----------|-----------|
| API | FastAPI + Uvicorn |
| Data ingestion | OpenBB + yfinance |
| Storage | Parquet (PyArrow) |
| Query engine | DuckDB |
| CLI | Typer |
| Config | Pydantic Settings |

### Frontend

| Component | Technology |
|-----------|-----------|
| Framework | React 19 + TypeScript + Vite |
| Styling | Tailwind CSS v4 (dark theme) |
| Charting | Lightweight Charts (TradingView) |
| Indicators | technicalindicators (client-side) |
| Server state | TanStack React Query v5 |
| Client state | Zustand |
| Routing | React Router v7 |
| Icons | Lucide React |

## CLI Reference

```bash
flow add <SYMBOL> # Add ticker and backfill from 2005
flow remove <SYMBOL> # Remove ticker and its data
flow list # List registered tickers
flow backfill <SYMBOL> # Re-backfill a ticker
flow ingest # Incremental ingest for all tickers
flow serve # Start the API server
```

## Environment Variables

| Variable | Default | Description |
|----------|---------|-------------|
| `PORT` | `8510` | Host port mapping (Docker) |
| `FLOW_DATA_DIR` | `data` | Directory for Parquet files and ticker registry |
| `FLOW_DEFAULT_PROVIDER` | `yfinance` | Data provider |
| `FLOW_BACKFILL_START_DATE` | `2005-01-01` | How far back to fetch on first add |
| `FLOW_OVERLAP_DAYS` | `5` | Days of overlap during incremental ingest |

## Project Structure

```
flow/
├── src/flow/
│ ├── api/ # FastAPI app and routes
│ ├── ingestion/ # Data fetching and pipeline
│ ├── storage/ # Parquet writing and DuckDB queries
│ ├── cli.py # Typer CLI
│ ├── config.py # Pydantic settings
│ └── models.py # Request/response models
├── frontend/
│ └── src/
│ ├── api/ # Axios client
│ ├── components/ # Chart, layout, common, ticker components
│ ├── hooks/ # React Query hooks
│ ├── lib/ # Indicators, formatters, constants
│ ├── pages/ # Dashboard, Chart, Watchlist, Portfolio, Screener
│ ├── stores/ # Zustand UI store
│ └── types/ # TypeScript interfaces
├── tests/ # pytest test suite
├── docker-compose.yml
├── Dockerfile
└── pyproject.toml
```

## License

Private.
Loading
Loading