Files
myTradeTracker/backend/app/api/endpoints/analytics.py
Chris eea4469095 Initial release v1.1.0
- Complete MVP for tracking Fidelity brokerage account performance
- Transaction import from CSV with deduplication
- Automatic FIFO position tracking with options support
- Real-time P&L calculations with market data caching
- Dashboard with timeframe filtering (30/90/180 days, 1 year, YTD, all time)
- Docker-based deployment with PostgreSQL backend
- React/TypeScript frontend with TailwindCSS
- FastAPI backend with SQLAlchemy ORM

Features:
- Multi-account support
- Import via CSV upload or filesystem
- Open and closed position tracking
- Balance history charting
- Performance analytics and metrics
- Top trades analysis
- Responsive UI design

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-22 14:27:43 -05:00

112 lines
2.8 KiB
Python

"""Analytics API endpoints."""
from fastapi import APIRouter, Depends, Query
from sqlalchemy.orm import Session
from typing import Optional
from app.api.deps import get_db
from app.services.performance_calculator import PerformanceCalculator
router = APIRouter()
@router.get("/overview/{account_id}")
def get_overview(account_id: int, db: Session = Depends(get_db)):
"""
Get overview statistics for an account.
Args:
account_id: Account ID
db: Database session
Returns:
Dictionary with performance metrics
"""
calculator = PerformanceCalculator(db)
stats = calculator.calculate_account_stats(account_id)
return stats
@router.get("/balance-history/{account_id}")
def get_balance_history(
account_id: int,
days: int = Query(default=30, ge=1, le=3650),
db: Session = Depends(get_db),
):
"""
Get account balance history for charting.
Args:
account_id: Account ID
days: Number of days to retrieve (default: 30)
db: Database session
Returns:
List of {date, balance} dictionaries
"""
calculator = PerformanceCalculator(db)
history = calculator.get_balance_history(account_id, days)
return {"data": history}
@router.get("/top-trades/{account_id}")
def get_top_trades(
account_id: int,
limit: int = Query(default=20, ge=1, le=100),
db: Session = Depends(get_db),
):
"""
Get top performing trades.
Args:
account_id: Account ID
limit: Maximum number of trades to return (default: 20)
db: Database session
Returns:
List of trade dictionaries
"""
calculator = PerformanceCalculator(db)
trades = calculator.get_top_trades(account_id, limit)
return {"data": trades}
@router.get("/worst-trades/{account_id}")
def get_worst_trades(
account_id: int,
limit: int = Query(default=20, ge=1, le=100),
db: Session = Depends(get_db),
):
"""
Get worst performing trades (biggest losses).
Args:
account_id: Account ID
limit: Maximum number of trades to return (default: 20)
db: Database session
Returns:
List of trade dictionaries
"""
calculator = PerformanceCalculator(db)
trades = calculator.get_worst_trades(account_id, limit)
return {"data": trades}
@router.post("/update-pnl/{account_id}")
def update_unrealized_pnl(account_id: int, db: Session = Depends(get_db)):
"""
Update unrealized P&L for all open positions in an account.
Fetches current market prices and recalculates P&L.
Args:
account_id: Account ID
db: Database session
Returns:
Number of positions updated
"""
calculator = PerformanceCalculator(db)
updated = calculator.update_open_positions_pnl(account_id)
return {"positions_updated": updated}