Files
myTradeTracker/docs/TIMEFRAME_FILTERING.md
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

5.8 KiB

Timeframe Filtering Feature

Overview

The timeframe filtering feature allows users to view dashboard metrics and charts for specific date ranges, providing better insights into performance over different time periods.

User Interface

Location

  • Dashboard page (DashboardV2 component)
  • Dropdown filter positioned at the top of the dashboard, above metrics cards

Available Options

  1. All Time - Shows all historical data
  2. Last 30 Days - Shows data from the past 30 days
  3. Last 90 Days - Shows data from the past 90 days
  4. Last 180 Days - Shows data from the past 180 days (default for chart)
  5. Last 1 Year - Shows data from the past 365 days
  6. Year to Date - Shows data from January 1st of current year to today

What Gets Filtered

Metrics Cards (Top of Dashboard)

When a timeframe is selected, the following metrics are filtered by position open date:

  • Total Positions count
  • Open Positions count
  • Closed Positions count
  • Total Realized P&L
  • Total Unrealized P&L
  • Win Rate percentage
  • Average Win amount
  • Average Loss amount
  • Current Balance (always shows latest)

Balance History Chart

The chart adjusts to show the requested number of days:

  • All Time: ~10 years (3650 days)
  • Last 30 Days: 30 days
  • Last 90 Days: 90 days
  • Last 180 Days: 180 days
  • Last 1 Year: 365 days
  • Year to Date: Dynamic calculation from Jan 1 to today

Implementation Details

Frontend

Component: DashboardV2.tsx

// State management
const [timeframe, setTimeframe] = useState<TimeframeOption>('all');

// Convert timeframe to days for balance history
const getDaysFromTimeframe = (tf: TimeframeOption): number => {
  switch (tf) {
    case 'last30days': return 30;
    case 'last90days': return 90;
    // ... etc
  }
};

// Get date range for filtering
const { startDate, endDate } = getTimeframeDates(timeframe);

API Calls

  1. Overview Stats:

    • Endpoint: GET /analytics/overview/{account_id}
    • Parameters: start_date, end_date
    • Query key includes timeframe for proper caching
  2. Balance History:

    • Endpoint: GET /analytics/balance-history/{account_id}
    • Parameters: days (calculated from timeframe)
    • Query key includes timeframe for proper caching

Backend

Endpoint: analytics_v2.py

@router.get("/overview/{account_id}")
def get_overview(
    account_id: int,
    refresh_prices: bool = False,
    max_api_calls: int = 5,
    start_date: Optional[date] = None,  # NEW
    end_date: Optional[date] = None,    # NEW
    db: Session = Depends(get_db)
):
    # Passes dates to calculator
    stats = calculator.calculate_account_stats(
        account_id,
        update_prices=True,
        max_api_calls=max_api_calls,
        start_date=start_date,
        end_date=end_date
    )

Service: performance_calculator_v2.py

def calculate_account_stats(
    self,
    account_id: int,
    update_prices: bool = True,
    max_api_calls: int = 10,
    start_date = None,  # NEW
    end_date = None     # NEW
) -> Dict:
    # Filter positions by open date
    query = self.db.query(Position).filter(Position.account_id == account_id)

    if start_date:
        query = query.filter(Position.open_date >= start_date)
    if end_date:
        query = query.filter(Position.open_date <= end_date)

    positions = query.all()
    # ... rest of calculation logic

Filter Logic

Position Filtering

Positions are filtered based on their open_date:

  • Only positions opened on or after start_date are included
  • Only positions opened on or before end_date are included
  • Open positions are always included if they match the date criteria

Balance History

The balance history shows account balance at end of each day:

  • Calculated from transactions within the specified days
  • Does not filter by open date, shows actual historical balances

Caching Strategy

React Query cache keys include timeframe parameters to ensure:

  1. Different timeframes don't conflict in cache
  2. Changing timeframes triggers new API calls
  3. Cache invalidation works correctly

Cache keys:

  • Overview: ['analytics', 'overview', accountId, startDate, endDate]
  • Balance: ['analytics', 'balance-history', accountId, timeframe]

User Experience

Performance

  • Balance history queries are fast (no market data needed)
  • Overview queries use cached prices by default (fast)
  • Users can still trigger price refresh within filtered timeframe

Visual Feedback

  • Filter immediately updates both metrics and chart
  • Loading states handled by React Query
  • Stale data shown while fetching (stale-while-revalidate pattern)

Testing Checklist

  • All timeframe options work correctly
  • Metrics update when timeframe changes
  • Balance history chart adjusts to show correct date range
  • "All Time" shows complete data
  • Year to Date calculation is accurate
  • Filter persists during price refresh
  • Cache invalidation works properly
  • UI shows loading states appropriately

Future Enhancements

Potential improvements:

  1. Add custom date range picker
  2. Compare multiple timeframes side-by-side
  3. Save preferred timeframe in user settings
  4. Add timeframe filter to Transactions table
  5. Add timeframe presets for tax year, quarters
  6. Export filtered data to CSV
  • TimeframeFilter.tsx - Reusable dropdown component
  • getTimeframeDates() - Helper function to convert timeframe to dates
  • TransactionTable.tsx - Already uses timeframe filtering

API Reference

GET /analytics/overview/{account_id}

Query Parameters:
- refresh_prices: boolean (default: false)
- max_api_calls: integer (default: 5)
- start_date: date (optional, format: YYYY-MM-DD)
- end_date: date (optional, format: YYYY-MM-DD)

GET /analytics/balance-history/{account_id}

Query Parameters:
- days: integer (default: 30, max: 3650)