A Flask-based web application that provides a backend API for managing stock portfolios and executing trades. The application integrates with Alpha Vantage API for real-time stock data and provides user authentication, portfolio management, and transaction tracking.
- User account management (create account, login, update password)
- Portfolio management (view holdings, calculate total value)
- Stock trading (buy and sell stocks)
- Stock information lookup (current price, historical data)
- Real-time portfolio value calculation
- Python 3.11
- Flask (Web Framework)
- SQLite (Database)
- Alpha Vantage API (Stock Data)
- Docker (Containerization)
stock-trading/
├── app/
│ ├── models/ # Database models
│ ├── routes/ # API endpoints
│ └── utils/ # Utility functions
├── sql/ # Database setup
│ ├── create_db.sh
│ ├── create_users_table.sql
│ └── create_portfolio_table.sql
├── tests/ # Unit tests
│ ├── test_auth.py
│ ├── test_portfolio.py
│ └── test_stock.py
├── .env # Environment variables
├── Dockerfile # Docker configuration
├── entrypoint.sh # Shell script to create application entry point
├── README.md # Project documentation
├── requirements.txt # Python dependencies
├── run_docker.sh # Shell script to create and run docker image
├── run.py # Running flask app
├── setup_venv.sh # Shell script to create and start virtual env
└── smoketest.sh # Smoke test script
-
Get your free API key at:
API signup -
API documentation:
Alpha Vantage API Documentation
Please look through the documentation thoroughly to understand how to use the requests
- Create a virtual environment and install dependencies:
chmod +x setup_venv.sh
source setup_venv.sh- Create
.envfile:
ALPHA_VANTAGE_API_KEY=your_api_key_here
DB_PATH=./db/stock_trading.db
CREATE_DB=true
- Initialize the database:
chmod +x sql/create_db.sh
./sql/create_db.sh- Run the application:
python3 -m run.py- Build the Docker image and run the container:
chmod +x run_docker.sh
./run_docker.shRun the test suite:
python3 -m pytest tests/For smoke tests, after you build and run the docker image:
chmod +x smoketest.sh
./smoketest.shhttp://localhost:5001/api
- Route Name and Path:
GET /health - Purpose: Verify the application service is running and healthy
- Response Format:
{
"status": "healthy"
}- Example:
curl -X GET "http://localhost:5001/api/health"{
"status": "healthy"
}- Route Name and Path:
GET /db-check - Purpose: Verify database connection is healthy
- Response Format:
{
"database_status": "healthy"
}- Example:
curl -X GET "http://localhost:5001/api/db-check"{
"database_status": "healthy"
}- Route Name and Path:
POST /users/create-account - Purpose: Register a new user account
- Request Body Format:
{
"username": "string",
"password": "string"
}- Response Format:
{
"message": "Account created successfully",
"user_id": "integer"
}- Example:
curl -X POST "http://localhost:5001/api/users/create-account" \
-H "Content-Type: application/json" \
-d '{"username": "testuser", "password": "password123"}'{
"message": "Account created successfully",
"user_id": 1
}- Route Name and Path:
POST /users/login - Purpose: Authenticate user credentials
- Request Body Format:
{
"username": "string",
"password": "string"
}- Response Format:
{
"message": "Login successful",
"user_id": "integer"
}- Example:
curl -X POST "http://localhost:5001/api/users/login" \
-H "Content-Type: application/json" \
-d '{"username": "testuser", "password": "password123"}'{
"message": "Login successful",
"user_id": 1
}- Route Name and Path:
POST /users/update-password - Purpose: Change user's password
- Request Body Format:
{
"user_id": "integer",
"current_password": "string",
"new_password": "string"
}- Response Format:
{
"message": "Password updated successfully"
}- Example:
curl -X POST "http://localhost:5001/api/users/update-password" \
-H "Content-Type: application/json" \
-d '{"user_id": 1, "current_password": "password123", "new_password": "newpassword123"}'{
"message": "Password updated successfully"
}- Route Name and Path:
DELETE /users/clear - Purpose: Remove all users (development/testing)
- Response Format:
{
"status": "success",
"message": "All users cleared"
}- Example:
curl -X DELETE "http://localhost:5001/api/users/clear"{
"status": "success",
"message": "All users cleared"
}- Route Name and Path:
GET /portfolio/{user_id} - Purpose: Retrieve user's current portfolio holdings
- Parameters:
- Path:
user_id(integer)
- Path:
- Response Format:
{
"status": "success",
"portfolio": {
// Portfolio details specific to implementation
}
}- Example:
curl -X GET "http://localhost:5001/api/portfolio/1"{
"status": "success",
"portfolio": {
"holdings": [
{
"symbol": "AAPL",
"quantity": 10,
"current_price": 150.50,
"total_value": 1505.00
}
]
}
}- Route Name and Path:
POST /portfolio/buy - Purpose: Purchase shares of a stock
- Request Body Format:
{
"user_id": "integer",
"symbol": "string",
"quantity": "integer"
}- Response Format:
{
"status": "success",
"transaction": {
// Transaction details
}
}- Example:
curl -X POST "http://localhost:5001/api/portfolio/buy" \
-H "Content-Type: application/json" \
-d '{"user_id": 1, "symbol": "AAPL", "quantity": 10}'{
"status": "success",
"transaction": {
"symbol": "AAPL",
"quantity": 10,
"price": 150.50,
"total_cost": 1505.00,
"timestamp": "2024-12-10T10:30:00Z"
}
}- Route Name and Path:
POST /portfolio/sell - Purpose: Sell shares from portfolio
- Request Body Format:
{
"user_id": "integer",
"symbol": "string",
"quantity": "integer"
}- Response Format:
{
"status": "success",
"transaction": {
// Transaction details
}
}- Example:
curl -X POST "http://localhost:5001/api/portfolio/sell" \
-H "Content-Type: application/json" \
-d '{"user_id": 1, "symbol": "AAPL", "quantity": 5}'{
"status": "success",
"transaction": {
"symbol": "AAPL",
"quantity": 5,
"price": 151.00,
"total_proceeds": 755.00,
"timestamp": "2024-12-10T11:30:00Z"
}
}- Route Name and Path:
GET /portfolio/history/{user_id} - Purpose: Retrieve user's trading history
- Parameters:
- Path:
user_id(integer)
- Path:
- Response Format:
{
"status": "success",
"history": [
// Array of transactions
]
}- Example:
curl -X GET "http://localhost:5001/api/portfolio/history/1"{
"status": "success",
"history": [
{
"type": "BUY",
"symbol": "AAPL",
"quantity": 10,
"price": 150.50,
"timestamp": "2024-12-10T10:30:00Z"
},
{
"type": "SELL",
"symbol": "AAPL",
"quantity": 5,
"price": 151.00,
"timestamp": "2024-12-10T11:30:00Z"
}
]
}- Route Name and Path:
DELETE /portfolio/clear - Purpose: Remove all portfolios (development/testing)
- Response Format:
{
"status": "success",
"message": "All portfolios cleared"
}- Example:
curl -X DELETE "http://localhost:5001/api/portfolio/clear"{
"status": "success",
"message": "All portfolios cleared"
}- Route Name and Path:
GET /stock/{symbol} - Purpose: Verify if a stock symbol exists
- Parameters:
- Path:
symbol(string)
- Path:
- Response Format:
{
"status": "success",
"valid": "boolean"
}- Example:
curl -X GET "http://localhost:5001/api/stock/AAPL"{
"status": "success",
"valid": true
}- Route Name and Path:
GET /stock/price/{symbol} - Purpose: Get current stock price information
- Parameters:
- Path:
symbol(string)
- Path:
- Response Format:
{
"status": "success",
"price_info": {
// Price information
}
}- Example:
curl -X GET "http://localhost:5001/api/stock/price/AAPL"{
"status": "success",
"price_info": {
"symbol": "AAPL",
"current_price": 150.50,
"change": 2.30,
"change_percent": 1.55,
"timestamp": "2024-12-10T12:00:00Z"
}
}- Route Name and Path:
GET /stock/history/{symbol} - Purpose: Retrieve historical price data
- Parameters:
- Path:
symbol(string) - Query:
outputsize(string, "compact" or "full")
- Path:
- Response Format:
{
"status": "success",
"history": {
// Historical data
}
}- Example:
curl -X GET "http://localhost:5001/api/stock/history/AAPL?outputsize=compact"{
"status": "success",
"history": {
"2024-12-10": {
"open": 149.00,
"high": 151.20,
"low": 148.80,
"close": 150.50,
"volume": 1234567
}
// Additional historical data entries...
}
}- Route Name and Path:
GET /stock/company/{symbol} - Purpose: Get detailed company information
- Parameters:
- Path:
symbol(string)
- Path:
- Response Format:
{
"status": "success",
"company_info": {
// Company details
}
}- Example:
curl -X GET "http://localhost:5001/api/stock/company/AAPL"{
"status": "success",
"company_info": {
"name": "Apple Inc.",
"description": "Technology company that designs and manufactures smartphones, computers, tablets, and wearables.",
"sector": "Technology",
"industry": "Consumer Electronics",
"market_cap": "2.5T",
"exchange": "NASDAQ"
}
}All routes return appropriate HTTP status codes:
- 200: Successful operation
- 400: Bad request (invalid input)
- 401: Unauthorized
- 404: Resource not found
- 500: Server error
Error responses include a message explaining the error:
{
"error": "Error message description"
}- Clone the repository
- Create a new branch for your feature
- Commit your changes
- Push to the branch
- Create a new Pull Request