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

View File

@@ -0,0 +1,99 @@
"""Base parser interface for brokerage CSV files."""
from abc import ABC, abstractmethod
from typing import List, Dict, Any, NamedTuple
from pathlib import Path
import pandas as pd
class ParseResult(NamedTuple):
"""
Result of parsing a brokerage CSV file.
Attributes:
transactions: List of parsed transaction dictionaries
errors: List of error messages encountered during parsing
row_count: Total number of rows processed
"""
transactions: List[Dict[str, Any]]
errors: List[str]
row_count: int
class BaseParser(ABC):
"""
Abstract base class for brokerage CSV parsers.
Provides a standard interface for parsing CSV files from different brokerages.
Subclasses must implement the parse() method for their specific format.
"""
@abstractmethod
def parse(self, file_path: Path) -> ParseResult:
"""
Parse a brokerage CSV file into standardized transaction dictionaries.
Args:
file_path: Path to the CSV file to parse
Returns:
ParseResult containing transactions, errors, and row count
Raises:
FileNotFoundError: If the file does not exist
ValueError: If the file format is invalid
"""
pass
def _read_csv(self, file_path: Path, **kwargs) -> pd.DataFrame:
"""
Read CSV file into a pandas DataFrame with error handling.
Args:
file_path: Path to CSV file
**kwargs: Additional arguments passed to pd.read_csv()
Returns:
DataFrame containing CSV data
Raises:
FileNotFoundError: If file does not exist
pd.errors.EmptyDataError: If file is empty
"""
if not file_path.exists():
raise FileNotFoundError(f"CSV file not found: {file_path}")
return pd.read_csv(file_path, **kwargs)
@staticmethod
def _safe_decimal(value: Any) -> Any:
"""
Safely convert value to decimal-compatible format, handling NaN and None.
Args:
value: Value to convert
Returns:
Converted value or None if invalid
"""
if pd.isna(value):
return None
if value == "":
return None
return value
@staticmethod
def _safe_date(value: Any) -> Any:
"""
Safely convert value to date, handling NaN and None.
Args:
value: Value to convert
Returns:
Converted date or None if invalid
"""
if pd.isna(value):
return None
if value == "":
return None
return value