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>
This commit is contained in:
Chris
2026-01-22 14:27:43 -05:00
commit eea4469095
90 changed files with 14513 additions and 0 deletions

157
apply_patches.py Executable file
View File

@@ -0,0 +1,157 @@
#!/usr/bin/env python3
"""
Apply patches for rate limiting fix.
This Python script works across all platforms.
"""
import os
import sys
import shutil
from pathlib import Path
def backup_file(filepath):
"""Create backup of file."""
backup_path = f"{filepath}.backup"
shutil.copy2(filepath, backup_path)
print(f"✓ Backed up {filepath} to {backup_path}")
return backup_path
def patch_main_py():
"""Patch backend/app/main.py to use analytics_v2."""
filepath = Path("backend/app/main.py")
if not filepath.exists():
print(f"❌ Error: {filepath} not found")
return False
print(f"\n[1/2] Patching {filepath}...")
# Backup
backup_file(filepath)
# Read file
with open(filepath, 'r') as f:
content = f.read()
# Check if already patched
if 'analytics_v2 as analytics' in content or 'import analytics_v2' in content:
print("✓ Backend already patched (analytics_v2 found)")
return True
# Apply patch
old_import = "from app.api.endpoints import accounts, transactions, positions, analytics"
new_import = "from app.api.endpoints import accounts, transactions, positions, analytics_v2 as analytics"
if old_import in content:
content = content.replace(old_import, new_import)
# Write back
with open(filepath, 'w') as f:
f.write(content)
print("✓ Backend patched successfully")
return True
else:
print("❌ Could not find expected import line")
print("\nLooking for:")
print(f" {old_import}")
print("\nPlease manually edit backend/app/main.py")
return False
def patch_app_tsx():
"""Patch frontend/src/App.tsx to use DashboardV2."""
filepath = Path("frontend/src/App.tsx")
if not filepath.exists():
print(f"❌ Error: {filepath} not found")
return False
print(f"\n[2/2] Patching {filepath}...")
# Backup
backup_file(filepath)
# Read file
with open(filepath, 'r') as f:
content = f.read()
# Check if already patched
if 'DashboardV2' in content or "components/DashboardV2" in content:
print("✓ Frontend already patched (DashboardV2 found)")
return True
# Apply patch - handle both single and double quotes
old_import1 = "import Dashboard from './components/Dashboard'"
new_import1 = "import Dashboard from './components/DashboardV2'"
old_import2 = 'import Dashboard from "./components/Dashboard"'
new_import2 = 'import Dashboard from "./components/DashboardV2"'
changed = False
if old_import1 in content:
content = content.replace(old_import1, new_import1)
changed = True
if old_import2 in content:
content = content.replace(old_import2, new_import2)
changed = True
if changed:
# Write back
with open(filepath, 'w') as f:
f.write(content)
print("✓ Frontend patched successfully")
return True
else:
print("❌ Could not find expected import line")
print("\nLooking for:")
print(f" {old_import1}")
print(f" or {old_import2}")
print("\nPlease manually edit frontend/src/App.tsx")
return False
def main():
print("=" * 60)
print("Applying Rate Limiting Fix Patches (Python)")
print("=" * 60)
# Check we're in the right directory
if not Path("docker-compose.yml").exists():
print("\n❌ Error: docker-compose.yml not found")
print("Please run this script from the fidelity project directory")
sys.exit(1)
# Apply patches
backend_ok = patch_main_py()
frontend_ok = patch_app_tsx()
print("\n" + "=" * 60)
if backend_ok and frontend_ok:
print("✅ All patches applied successfully!")
print("=" * 60)
print("\nNext steps:")
print("")
print("1. Rebuild containers:")
print(" docker compose down")
print(" docker compose build --no-cache backend frontend")
print(" docker compose up -d")
print("")
print("2. Run migration:")
print(" sleep 30")
print(" docker compose exec backend alembic upgrade head")
print("")
print("3. Test:")
print(" curl http://localhost:8000/api/analytics/overview/1?refresh_prices=false")
print("")
sys.exit(0)
else:
print("⚠️ Some patches failed - see manual instructions above")
print("=" * 60)
sys.exit(1)
if __name__ == "__main__":
main()