Skip to content

OWaseem/StockPortfolioTracker

Repository files navigation

Stock Portfolio Tracker API

A RESTful API built with ASP.NET Core (.NET 10) that allows users to manage and track their stock portfolio with real-time pricing and gain/loss calculations.

Built as a demonstration of .NET backend development skills including authentication, database management, external API integration, and caching.


Features

  • User Authentication — Register and login with JWT token-based auth
  • Password Security — Passwords are hashed with BCrypt, never stored in plain text
  • Portfolio Management — Create a portfolio and manage stock holdings
  • Real-Time Stock Prices — Live prices fetched from Alpha Vantage API
  • Gain/Loss Calculations — Automatically calculates current value, gain/loss and percentage per holding and for the overall portfolio
  • In-Memory Caching — Stock prices are cached for 60 seconds to reduce external API calls and respect rate limits
  • API Call Tracking — Every real call to Alpha Vantage is logged to the database so you can monitor daily usage
  • Input Validation — All requests are validated before hitting the database
  • Global Error Handling — Unhandled exceptions return clean error responses

Tech Stack

Technology Purpose
ASP.NET Core (.NET 10) Web API framework
Entity Framework Core ORM for database access
SQLite Database (easily swappable for SQL Server)
JWT Bearer Tokens Authentication
BCrypt.Net Password hashing
Alpha Vantage API Real-time stock prices
IMemoryCache In-memory caching

Architecture

The project follows a layered architecture to keep concerns separated:

Controllers  →  receive HTTP requests, return responses
Services     →  contain all business logic
Data         →  database context and access
Models       →  data shapes and request/response objects
Logs         →  temporary tracking models (e.g. API call logging)

Data Model

User
 └── Portfolio
      └── Holdings (Symbol, Quantity, BuyPrice)

ApiCallLog (separate — tracks Alpha Vantage usage)
  • A User has one Portfolio
  • A Portfolio has many Holdings
  • Each Holding tracks a stock symbol, quantity owned, and the price it was bought at
  • ApiCallLog records every real call made to Alpha Vantage (cached calls are not logged)

API Endpoints

Auth

Method Endpoint Description Auth Required
POST /api/auth/register Register a new user, returns JWT token No
POST /api/auth/login Login, returns JWT token No

Portfolio

Method Endpoint Description Auth Required
GET /api/portfolio Get raw portfolio and holdings Yes
POST /api/portfolio Create a portfolio Yes
GET /api/portfolio/summary Get portfolio with live prices and gain/loss Yes
POST /api/portfolio/holdings Add a stock holding Yes
DELETE /api/portfolio/holdings/{id} Remove a stock holding Yes

Logs

Method Endpoint Description Auth Required
GET /api/logs/usage Check how many Alpha Vantage calls made today Yes
GET /api/logs View all API call logs, newest first Yes

Admin — View

Method Endpoint Description Auth Required
GET /api/admin/portfolios All portfolios with owner info and holdings Yes
GET /api/admin/users All registered users (passwords never exposed) Yes

Admin — Reset

Method Endpoint Description Auth Required
DELETE /api/admin/reset/holdings Clear all holdings Yes
DELETE /api/admin/reset/portfolios Clear all portfolios and holdings Yes
DELETE /api/admin/reset/users Clear all users, portfolios and holdings Yes
DELETE /api/admin/reset/logs Clear all API call logs Yes
DELETE /api/admin/reset/all Full wipe — clears everything Yes

Getting Started

Prerequisites

Setup

  1. Clone the repository
git clone <your-repo-url>
cd StockPortfolioTracker
  1. Add your Alpha Vantage API key to appsettings.json
"AlphaVantage": {
  "ApiKey": "YOUR_API_KEY_HERE"
}
  1. Apply database migrations
dotnet ef database update
  1. Run the app
dotnet run

The API will be available at http://localhost:5104


Testing with Postman

Step 1 — Register

  • Method: POST
  • URL: http://localhost:5104/api/auth/register
  • Body → raw → JSON:
{
  "username": "testuser",
  "email": "test@example.com",
  "password": "Password123!"
}

Copy the token from the response — you'll need it for every request below.


Step 2 — Create a Portfolio

  • Method: POST
  • URL: http://localhost:5104/api/portfolio
  • Authorization tab → Bearer Token → paste your token
  • Body → raw → JSON:
"My Portfolio"

Step 3 — Add a Stock

  • Method: POST
  • URL: http://localhost:5104/api/portfolio/holdings
  • Authorization tab → Bearer Token → paste your token
  • Body → raw → JSON:
{
  "symbol": "TSLA",
  "companyName": "Tesla Inc.",
  "quantity": 5,
  "buyPrice": 200.00
}

Step 4 — Get Portfolio Summary with Live Prices

  • Method: GET
  • URL: http://localhost:5104/api/portfolio/summary
  • Authorization tab → Bearer Token → paste your token

Expected response:

{
  "name": "My Portfolio",
  "holdings": [
    {
      "symbol": "TSLA",
      "quantity": 5,
      "buyPrice": 200.00,
      "currentPrice": 371.75,
      "currentValue": 1858.75,
      "costBasis": 1000.00,
      "gainLoss": 858.75,
      "gainLossPercent": 85.88
    }
  ],
  "totalCostBasis": 1000.00,
  "totalCurrentValue": 1858.75,
  "totalGainLoss": 858.75
}

Step 5 — Check API Usage

  • Method: GET
  • URL: http://localhost:5104/api/logs/usage
  • Authorization tab → Bearer Token → paste your token

Expected response:

{
  "callsToday": 1,
  "remainingEstimate": 24,
  "resetNote": "Alpha Vantage resets your 25 daily calls every 24 hours on their end."
}

Note: Only calls that bypass the cache are logged. If you request the same stock twice within 60 seconds, only the first call is counted.


Viewing the Database Locally

You can inspect the SQLite database visually using DB Browser for SQLite:

  1. Download from https://sqlitebrowser.org/dl/
  2. Open the app and click Open Database
  3. Navigate to your project folder and select portfolio.db:
/Users/omarwaseem/projects/Stock_Portfolio_Tracker_API/StockPortfolioTracker/portfolio.db
  1. Click the Browse Data tab
  2. Use the Table dropdown to switch between:
    • Users — all registered accounts
    • Portfolios — all portfolios
    • Holdings — all stock holdings
    • ApiCallLogs — every Alpha Vantage call made

You can also run raw SQL queries under the Execute SQL tab.


Alpha Vantage Rate Limits

The free tier allows 25 API calls per day. This app handles this in two ways:

  1. Caching — prices are stored in memory for 60 seconds, so repeated requests don't use extra calls
  2. Call logging — every real API call is recorded in the database so you can track daily usage via GET /api/logs/usage

If you exceed the limit, currentPrice will return null in the summary response. The limit resets every 24 hours on Alpha Vantage's end.


Design Decisions

Why JWT? JWT tokens are stateless — the server doesn't need to store session data. Each token contains the user's identity as claims, which we read on every request to identify who is making it.

Why BCrypt? BCrypt is a one-way hashing algorithm designed specifically for passwords. Even if the database is compromised, passwords cannot be reversed.

Why caching? Alpha Vantage's free tier allows 25 requests per day. Caching prices for 60 seconds means repeated requests for the same stock don't burn through the limit. In a production environment this would be replaced with a distributed cache like Redis.

Why SQLite? SQLite requires zero setup and runs as a single file — ideal for development and demos. Since EF Core abstracts the database, switching to SQL Server for production requires only a configuration change.

Why a separate Logs folder? The ApiCallLog model is intentionally kept in a Logs/ folder separate from core Models to signal that it is a utility/tracking concern rather than a core domain model. In production this would be replaced with a proper observability solution like Serilog or Application Insights.


Admin Endpoints

View

Method URL What it returns
GET /api/admin/portfolios All portfolios with owner info and holdings
GET /api/admin/users All registered users (passwords never exposed)

Reset

Method URL What it resets
DELETE /api/admin/reset/holdings Holdings only
DELETE /api/admin/reset/portfolios Portfolios + holdings
DELETE /api/admin/reset/users Users + portfolios + holdings
DELETE /api/admin/reset/logs API call logs only
DELETE /api/admin/reset/all Everything — full wipe

Note: Admin endpoints are currently protected by authentication only — any logged in user can access them. Role-based authorization ([Authorize(Roles = "Admin")]) is planned for a future update so only designated admin accounts can access these endpoints.


Roadmap

Planned improvements for future versions:

  • Role-based authorization — Assign "Admin" and "User" roles at registration. Admin endpoints will be restricted to Admin role only via [Authorize(Roles = "Admin")]
  • Azure deployment — The API is planned to be hosted on Azure App Service, making it publicly accessible. EF Core migrations will be run against Azure SQL replacing the current SQLite database
  • Redis for distributed caching instead of in-memory
  • Rate limiting on API endpoints
  • Refresh tokens alongside JWT for better session management
  • Serilog or Application Insights for production-grade logging

Production Considerations

Things that would be added in a real production environment:

  • Redis for distributed caching instead of in-memory
  • SQL Server or PostgreSQL instead of SQLite
  • Rate limiting on API endpoints
  • HTTPS enforcement in all environments
  • Refresh tokens alongside JWT for better session management
  • Serilog or Application Insights instead of the custom API call log

About

Stock Portfolio Tracker made using the .net framework

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages