AlphaDash is a full-stack web application designed to help users track their financial asset portfolios, visualize historical performance, and explore basic trading signals. It demonstrates a range of modern software engineering practices and technologies.
- User Authentication (Registration, Login with JWT)
- Portfolio Management:
- Add/Edit/Delete asset holdings (quantity, purchase price, date)
- View portfolio summary with real-time(ish) valuation
- Calculated current values, gains/losses per holding and total
- Asset Management:
- System for defining global assets (stocks, cryptocurrencies)
- Users can create new assets if not already in the system
- Financial Data Integration:
- Fetches current prices and historical data from external financial APIs (primarily Yahoo Finance, with Alpha Vantage as an optional fallback)
- Caching mechanism for external API responses (Redis)
- Data Visualization:
- Historical price charts for individual assets
- Display of Simple Moving Averages (SMA 20, SMA 50) on charts
- Asynchronous Task Processing:
- Background tasks (Celery with Redis broker) for periodic data refresh (all asset prices)
- Containerized Deployment:
- Fully containerized using Docker and Docker Compose for easy setup and consistent environments.
- Automated Testing & CI:
- Comprehensive unit tests for backend (Pytest)
- Basic CI pipeline using GitHub Actions (linting, formatting, testing, build checks)
- Language: Python 3.13
- Framework: FastAPI
- Authentication: JWT (python-jose), Passlib (for password hashing)
- Database: PostgreSQL
- ORM: SQLAlchemy with Alembic for migrations
- Data Validation: Pydantic
- Asynchronous Tasks: Celery, Redis (as broker and result backend)
- Caching: Redis (for application-level shared cache)
- External APIs: Yahoo Finance (via
yfinance
), Alpha Vantage (as fallback) - Linters/Formatters: Ruff, Black
- Language: TypeScript
- Framework/Library: React
- State Management: React Hooks like
useState
,useEffect
- Routing: React Router DOM
- API Client: Axios
- Charting: Chart.js with react-chartjs-2, date-fns adapter
- Styling: Basic CSS/Inline Styles
- Containerization: Docker, Docker Compose
- CI/CD: GitHub Actions (Linting, Formatting, Testing, Docker Build)
- Version Control: Git, GitHub
- Development Methodology: Issue-driven development (using GitHub Issues and PRs for feature tracking and code review)
The application follows a modern full-stack architecture:
- Frontend: A React application responsible for user interaction and presentation.
- Backend: A Python FastAPI application serving a RESTful API for all business logic, data processing, and external API interactions.
- Database: PostgreSQL stores persistent data like user information, asset definitions, and portfolio holdings.
- Caching Layer: Redis is used for caching frequently accessed data (e.g., asset prices from external APIs) to improve performance and reduce external API load.
- Task Queue: Celery with Redis as a broker handles asynchronous background tasks, such as periodic refreshment of asset prices.
- Containerization: All services (frontend, backend, database, Redis, Celery workers/beat) are containerized with Docker and orchestrated using Docker Compose for local development and ensuring a consistent environment.
Simple text diagram:
[ User (Browser) ] <--> [ React Frontend (localhost:3000) ]
^
| (HTTP API Calls)
v
[ FastAPI Backend (localhost:8000) ] <--> [ PostgreSQL DB ]
^ ^ |
| | +--> [ Redis (Cache & Celery Broker) ]
| |
+---------+------> [ Celery Workers & Beat (Background Tasks) ]
|
+------> [ External Financial APIs (Yahoo Finance, Alpha Vantage) ]
- Docker Desktop (or Docker Engine + Docker Compose) installed and running.
- Git installed.
- (For direct backend/frontend dev without full Docker Compose build initially) Python 3.11+ and Node.js latest LTS version installed.
-
Clone the repository:
git clone https://github.com/zhu-weijie/alpha-dash.git cd alpha-dash
-
Environment Configuration:
- Root
.env
for Docker Compose: Create a.env
file in the project root (same directory asdocker-compose.yml
). This file is used by Docker Compose to inject environment variables into services. Refer to.env.example
for required variables. Example content foralpha-dash/.env
:SECRET_KEY="a_very_strong_random_secret_key_for_jwt_at_least_32_chars" ALGORITHM="HS256" ALPHA_VANTAGE_API_KEY="YOUR_OPTIONAL_AV_KEY" # Other variables like PROJECT_NAME, ACCESS_TOKEN_EXPIRE_MINUTES if you want to override defaults
- Backend
.env
for direct Python execution (and source for Pydantic settings if CI env vars not set): Navigate to thebackend/
directory. Copybackend/.env.example
tobackend/.env
and fill in the required values (especially if you plan to run the backend outside Docker for some tests, or if your Celery tasks/Alembic need it when run locally).cd backend cp .env.example .env # Edit backend/.env with your local settings (e.g., DATABASE_URL if running DB outside Docker) # However, for Docker Compose, the DATABASE_URL inside the container is set by docker-compose.yml cd ..
- Root
-
Build and Run with Docker Compose: From the project root directory (where
docker-compose.yml
is located):docker compose up --build -d
--build
: Builds the Docker images for the backend and frontend if they don't exist or if Dockerfiles have changed.-d
: Runs the containers in detached mode (in the background).
-
Apply Database Migrations (if first time or after DB reset): The backend service itself does not automatically run migrations on startup. You need to run them manually against the running database container. Open a new terminal:
# Navigate to project root cd alpha-dash # Execute alembic upgrade command inside the backend container (or locally if DB exposed and configured) docker compose exec backend alembic upgrade head # OR, if running locally from backend directory (ensure venv active, and ensure your backend/.env is configured to point to the Dockerized PostgreSQL (e.g., DATABASE_URL=postgresql://alphadash_user:alphadash_pass@localhost:5432/alphadash_db) if running Alembic locally against the Docker DB.): # cd backend # python3.13 -m venv .venv # source .venv/bin/activate # pip install -r requirements.txt # alembic upgrade head
-
Accessing the Application:
- Frontend: Open your browser and navigate to
http://localhost:3000
- Backend API Docs (Swagger UI):
http://localhost:8000/docs
- Backend API Docs (ReDoc):
http://localhost:8000/redoc
- Frontend: Open your browser and navigate to
-
Stopping the Application: From the project root directory:
docker compose down
To also remove volumes (database data, Redis data, Celery beat schedule):
docker compose down --volumes
The backend provides a RESTful API. Key endpoint groups include:
/api/v1/auth/token
: User login and JWT generation./api/v1/users/
: User registration, fetching current user (/me
)./api/v1/assets/
: CRUD operations for global asset definitions./api/v1/portfolio/holdings/
: CRUD operations for user-specific portfolio holdings./api/v1/market-data/{symbol}/
: Fetching current price and historical data for assets.
For detailed API documentation, please run the application and visit http://localhost:8000/docs
.
Here is a screenshot of the API docs:
- Full-Stack Development: Building both backend (Python/FastAPI) and frontend (React/TypeScript) components.
- API Design & Development: Creating RESTful APIs with FastAPI, including request/response validation (Pydantic), authentication (JWT), and clear endpoint structuring.
- Database Management:
- Working with PostgreSQL.
- Using SQLAlchemy for ORM and database interaction.
- Managing database schema migrations with Alembic.
- Authentication & Authorization: Implementing secure user registration, password hashing (Passlib/bcrypt), and token-based authentication (JWT). Protecting API endpoints.
- Asynchronous Task Processing: Utilizing Celery and Redis for background tasks (periodic data refresh), demonstrating understanding of distributed systems concepts.
- Caching Strategies: Implementing caching (Redis) for external API responses to improve performance and manage rate limits.
- External API Integration: Fetching and processing data from third-party financial APIs (Yahoo Finance, Alpha Vantage).
- Containerization: Dockerizing all application services (backend, frontend, database, Redis, Celery) and orchestrating them with Docker Compose for development and consistent environments.
- Testing:
- Writing unit tests for backend logic (CRUD, services, utilities) using Pytest and
unittest.mock
. - Implementing basic API endpoint tests using FastAPI's
TestClient
.
- Writing unit tests for backend logic (CRUD, services, utilities) using Pytest and
- DevOps & CI/CD: Setting up a basic Continuous Integration pipeline with GitHub Actions for automated linting, formatting, testing, and build checks.
- Modern Python & TypeScript: Utilizing modern language features, type hinting, and asynchronous programming (FastAPI).
- Software Design Patterns: (Implicitly) Service layer, data provider pattern, dependency injection (FastAPI).
- Problem Solving: Addressing challenges like API rate limits, data serialization, and inter-service communication within a Dockerized environment.
- Project Structure & Maintainability: Organizing code into logical modules and packages for better maintainability and scalability.
- Advanced "Alpha" Signals: Implement more complex technical indicators or allow users to define simple signal conditions.
- Real-time Price Updates: Integrate WebSockets for real-time price updates on the portfolio page.
- User Roles & Permissions: Differentiate between regular users and admin users (e.g., for managing global assets).
- More Comprehensive Testing: Add frontend unit/integration tests, expand backend integration test coverage.
- Deployment: Script deployment to a cloud platform (e.g., GCP Cloud Run, AWS ECS/EKS).
- Enhanced UI/UX: Utilize a component library for a more polished UI, improve form validations, and user feedback.
- Scalability Improvements for Data Fetching: Implement more advanced batching or a dedicated data ingestion pipeline for financial data if scaling to many users/assets.
- OAuth2 Scopes: Implement more granular permissions using OAuth2 scopes.
- Portfolio Overview Page
- Asset Chart Page
- Add New Holding Page
- Edit Holding Page
- Add new asset page
- Redis Cache Logs
- Celery Worker Logs
- Celery Beat Logs
To better understand and illustrate the interconnected nature of the data within Alpha-Dash, I've modeled a small, representative subset of its core entities and relationships using Neo4j, a native graph database. This exploration helps visualize how users, their portfolio holdings, and specific assets are linked, which is foundational to knowledge graph concepts and can unlock deeper insights.
Conceptual Graph Visualization:
Core Entities & Relationships Modeled:
- Nodes (Entities):
:User
(Properties:userId
,email
,name
):Asset
(Properties:assetId
,symbol
,name
,type
):PortfolioHolding
(Properties:holdingId
,quantity
,purchase_price
,purchase_date
)
- Relationships (Edges):
(User)-[:OWNS]->(PortfolioHolding)
: Represents a user owning a specific lot/holding.(PortfolioHolding)-[:IS_FOR_ASSET]->(Asset)
: Links a holding to the specific asset it represents.
Sample Cypher Script for Population:
The following Cypher script was used to create the sample graph in Neo4j:
// neo4j_exploration/populate_sample_graph.cypher
// Optional: Clear any existing data from previous runs
MATCH (n) DETACH DELETE n;
// --- Create Nodes ---
// User
CREATE (user1:User {userId: 1, email: 'weijie@example.com', name: 'Zhu Weijie'});
// Assets
CREATE (asset1:Asset {assetId: 101, symbol: 'AAPL', name: 'Apple Inc.', type: 'stock'});
CREATE (asset2:Asset {assetId: 102, symbol: 'BTC', name: 'Bitcoin', type: 'crypto'});
CREATE (asset3:Asset {assetId: 103, symbol: 'MSFT', name: 'Microsoft Corp.', type: 'stock'});
// Portfolio Holdings for User1
CREATE (holding1:PortfolioHolding {holdingId: 201, quantity: 10, purchase_price: 150.00, purchase_date: date("2023-01-10")});
CREATE (holding2:PortfolioHolding {holdingId: 202, quantity: 0.5, purchase_price: 30000.00, purchase_date: date("2023-02-15")});
CREATE (holding3:PortfolioHolding {holdingId: 203, quantity: 5, purchase_price: 160.00, purchase_date: date("2023-03-20")});
// --- Create Relationships ---
// User1 OWNS Holding1 (AAPL)
MATCH (u:User {userId: 1}), (h:PortfolioHolding {holdingId: 201}) CREATE (u)-[:OWNS]->(h);
// User1 OWNS Holding2 (BTC)
MATCH (u:User {userId: 1}), (h:PortfolioHolding {holdingId: 202}) CREATE (u)-[:OWNS]->(h);
// User1 OWNS Holding3 (AAPL, second lot)
MATCH (u:User {userId: 1}), (h:PortfolioHolding {holdingId: 203}) CREATE (u)-[:OWNS]->(h);
// Holding1 IS_FOR_ASSET Asset1 (AAPL)
MATCH (h:PortfolioHolding {holdingId: 201}), (a:Asset {assetId: 101}) CREATE (h)-[:IS_FOR_ASSET]->(a);
// Holding2 IS_FOR_ASSET Asset2 (BTC)
MATCH (h:PortfolioHolding {holdingId: 202}), (a:Asset {assetId: 102}) CREATE (h)-[:IS_FOR_ASSET]->(a);
// Holding3 IS_FOR_ASSET Asset1 (AAPL)
MATCH (h:PortfolioHolding {holdingId: 203}), (a:Asset {assetId: 101}) CREATE (h)-[:IS_FOR_ASSET]->(a);
CALL db.awaitIndexes();
RETURN "Sample Alpha-Dash graph created successfully!" AS status;