Jonathan 5cf3726f59 Improve portfolio chart with historical price-based data points
Chart now plots weekly data points from first purchase to today using
candle/history price data, giving an accurate view of portfolio value
over time rather than just at purchase dates.

Backend seeds up to 365 days of daily close prices from CoinGecko as
synthetic OHLC candles, refreshing stale entries older than 31 days.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 19:30:48 +02:00
2026-03-24 19:10:20 +01:00

BTC Portfolio Tracker

A full-stack Bitcoin portfolio tracker with live EUR pricing, purchase history, and interactive charts.


Features

  • Live BTC price — fetched from CoinGecko in EUR
  • Purchase tracking — log BTC buys with amount (EUR) and price per BTC
  • Portfolio stats — total invested, current value, profit/loss
  • Interactive charts — portfolio value over time and 1-year BTC price history
  • Edit & delete — manage purchases with inline editing
  • JWT authentication — secure per-user portfolios

Tech Stack

Layer Technology
Frontend React 18, Chart.js, dark theme
Backend FastAPI, SQLAlchemy, SQLite
Auth JWT (HS256, 24h expiry) + bcrypt
Pricing CoinGecko API (EUR)
Deploy Docker + Docker Compose

Getting Started

git clone <repo-url>
cd btc-portfolio
docker-compose up

Local Development

Backend

cd btc-portfolio/backend
pip install -r requirements.txt
uvicorn app.main:app --reload

Frontend

cd btc-portfolio/frontend
npm install
npm start

Project Structure

btc-portfolio/
├── backend/
│   └── app/
│       ├── main.py            # FastAPI app + CORS
│       ├── models.py          # User & Purchase ORM models
│       ├── auth.py            # JWT + bcrypt
│       ├── dependencies.py    # Auth dependency injection
│       ├── routes/
│       │   ├── users.py       # POST /register, POST /login
│       │   ├── purchases.py   # CRUD /purchases
│       │   ├── stats.py       # GET /stats
│       │   └── history.py     # GET /history (365-day BTC prices)
│       └── services/
│           └── btc.py         # CoinGecko integration
└── frontend/
    └── src/
        ├── App.js             # Routing
        ├── pages/
        │   └── Dashboard.js   # Main view
        └── components/
            ├── AddPurchase.js      # Purchase form
            ├── PurchaseList.js     # Purchase table (edit/delete)
            ├── PortfolioChart.js   # Invested vs current value
            └── BTCHistoryChart.js  # 1-year BTC price history

API Endpoints

Method Endpoint Description Auth
POST /register Create account No
POST /login Get JWT token No
GET /purchases List user purchases Yes
POST /purchases Add a purchase Yes
PUT /purchases/{id} Edit a purchase Yes
DELETE /purchases/{id} Delete a purchase Yes
GET /stats Portfolio stats (P&L) Yes
GET /history 365-day BTC price history Yes

Database

SQLite, stored at /app/data/btc_portfolio.db (persisted via Docker volume).

Table Columns
users id, username (unique), password (bcrypt hash)
purchases id, amount_eur, price_eur, created_at, user_id (FK)

Notes

  • The SECRET_KEY in auth.py is hardcoded — use an environment variable in production.
  • CoinGecko requests are unauthenticated; failures return 0.0 gracefully.
  • CORS is restricted to localhost:3000 by default.
S
Description
A portfolio of your BTC purchases, showing multiple stats and graphs
Readme 181 KiB
Languages
JavaScript 65.4%
Python 33.4%
Dockerfile 0.7%
HTML 0.5%