A web application for managing investment portfolios across multiple asset classes with transaction tracking, average cost computation, and realized P&L calculations — no external APIs required.
- Features
- Tech Stack
- Live Demo
- Quick Start
- Configuration
- Project Structure
- Testing
- Deployment
- Roadmap
- License
| Feature | Description |
|---|---|
| Multi-Asset Support | Track Stocks, ETFs, Commodities, and Crypto |
| Portfolio Overview | Total portfolio value and realized ROI per category |
| Fund Management | Deposit/withdraw funds with a full audit trail |
| Transaction Tracking | Buy/sell operations with automatic average cost computation |
| Dividend Income | Record dividend payments per category; income is added to realized P&L automatically |
| Realized P&L | Automatic profit/loss calculations on every sale and dividend received |
| Email Verification | 6-digit OTP sent to email on registration |
| Password Reset | Secure reset link sent via email (expires in 1 hour) |
| Multi-User Auth | Separate accounts with full data isolation; first user becomes admin |
| Account Settings | Profile overview, change password, update email — all in one page |
| Account Deletion | Self-service deletion with 6-digit OTP confirmation sent to email |
| Admin Panel | Manage users, send password reset emails, toggle admin privileges |
| REST API | JSON endpoints for portfolio data integration |
| Manual Entry | Full control over your data, no third-party price feeds |
| Layer | Technology |
|---|---|
| Backend | Python 3.8+ · Flask 3.0.0 |
| Database | SQLite · Flask-SQLAlchemy |
| Frontend | HTML5 · Bootstrap 5 · JavaScript |
| Auth | Flask-Login · Werkzeug password hashing |
| Flask-Mail · Gmail SMTP | |
| Forms | Flask-WTF |
| Testing | pytest |
👉 https://oneportfolio.pythonanywhere.com/
Demo credentials:
| Field | Value |
|---|---|
| Username | demo |
| Password | demo1234 |
Prerequisites: Python 3.8+
# 1. Clone
git clone https://github.com/nasserx/OnePortfolio.git
cd OnePortfolio
# 2. Virtual environment
python -m venv venv
source venv/bin/activate # Linux/Mac
.\venv\Scripts\activate # Windows
# 3. Install dependencies
pip install -r requirements.txt
# 4. Run
python app.pyOpen http://localhost:5000 — the first registered account automatically becomes admin.
Set the following environment variables (in .env or your hosting platform's WSGI file):
| Variable | Required | Description |
|---|---|---|
SECRET_KEY |
✅ | Flask session signing key — generate with secrets.token_hex(32) |
EMAIL_USER |
✅ | Gmail address used to send verification and reset emails |
EMAIL_PASSWORD |
✅ | Gmail App Password (requires 2FA enabled on the account) |
APP_BASE_URL |
✅ | Public URL of your app (e.g. https://yourapp.pythonanywhere.com) |
DATABASE_URL |
— | SQLAlchemy URI — defaults to sqlite:///portfolio.db |
SESSION_COOKIE_SECURE |
— | Set to 1 when serving over HTTPS |
Note: Gmail requires an App Password — your regular password will not work.
OnePortfolio/
├── app.py # Development entry point
├── wsgi.py # Production WSGI entry point
├── config.py # Configuration settings
├── requirements.txt # Python dependencies
├── test_app.py # Test suite
└── portfolio_app/
├── __init__.py # App factory & DB migrations
├── models/ # SQLAlchemy models (User, Fund, Transaction, ...)
├── repositories/ # Data access layer
├── services/ # Business logic (auth, funds, portfolio, ...)
├── calculators/ # P&L and average cost calculators
├── forms/ # WTForms form validation
├── routes/ # Flask blueprints (auth, admin, dashboard, ...)
├── utils/ # Email, token, and formatting helpers
├── static/ # CSS and JS assets
└── templates/ # Jinja2 HTML templates
pytest -vCI runs automatically on every push via GitHub Actions across Python 3.8, 3.10, and 3.12.
# 1. Clone your repo
git clone https://github.com/nasserx/OnePortfolio.git
# 2. Create and activate virtualenv
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txtIn the WSGI file on PythonAnywhere, set environment variables and activate the virtualenv:
activate_this = '/home/YOUR_USERNAME/.virtualenvs/myenv/bin/activate_this.py'
with open(activate_this) as f:
exec(f.read(), {'__file__': activate_this})
import os
os.environ['SECRET_KEY'] = 'your-secret-key'
os.environ['EMAIL_USER'] = 'your-gmail@gmail.com'
os.environ['EMAIL_PASSWORD'] = 'your-app-password'
os.environ['APP_BASE_URL'] = 'https://yourapp.pythonanywhere.com'
os.environ['SESSION_COOKIE_SECURE'] = '1'
from portfolio_app import create_app
application = create_app()Then click Reload in the Web tab.
Note: PythonAnywhere free accounts only allow outbound connections to whitelisted hosts. Use Gmail SMTP (
smtp.gmail.com:587) which is supported.
- Live market price integration
- Multi-user authentication with email verification
- Password reset via email
- Dividend income tracking
- Account settings page with self-service deletion
- Advanced charts and analytics
- Docker deployment support
MIT — see LICENSE for details.
nasserx · @nasserx
⚠️ Disclaimer: This project is for educational and organizational purposes only. It does not provide financial advice.
