Skip to content

fix: calculateDayChange returns random numbers instead of real price history #57

Description

@Uchechukwu-Ekezie

Problem

The calculateDayChange function in backend/src/services/analyticsService.ts doesn't use actual price history — it returns a random percentage. The frontend's performance chart and portfolio analytics show made-up numbers.

Looking at the implementation:

// TODO: Replace with actual price history lookup
const dayChange = (Math.random() - 0.5) * 10; // -5% to +5%

Every time the analytics endpoint is called, the "24h change" is a different random number. This makes the analytics dashboard useless for actual portfolio tracking. The PerformanceChart component in frontend/src/components/PerformanceChart.tsx renders a chart based on this data, but the chart is just noise.

Proposed Fix

1. Store price snapshots

The backend already has an analytics_snapshots table that records portfolio values over time. The analyticsService should query this table to compute real day-over-day change:

async calculateDayChange(portfolioId: string): Promise<number> {
    const now = new Date();
    const oneDayAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000);
    
    const latest = await analyticsDb.getLatestSnapshot(portfolioId);
    const previous = await analyticsDb.getSnapshotAt(portfolioId, oneDayAgo);
    
    if (!latest || !previous || previous.totalValue === 0) return 0;
    
    return ((latest.totalValue - previous.totalValue) / previous.totalValue) * 100;
}

2. Ensure snapshots are being recorded

The analyticsSnapshotWorker in backend/src/queue/workers/analyticsSnapshotWorker.ts should be recording snapshots regularly. Verify it's running and storing data. If it's not, fix the worker or add a fallback that records snapshots on portfolio check.

3. Interpolate if no exact 24h snapshot exists

If there's no snapshot exactly 24 hours ago, find the closest one within a 2-hour window and interpolate:

const previous = await analyticsDb.getClosestSnapshot(portfolioId, oneDayAgo, 2 * 60 * 60 * 1000);

If no snapshot exists within the window, return null instead of a random number. The frontend should show "—" or "N/A" instead of fake data.

4. Extend to other time periods

Once 24h change works, add the same pattern for:

  • 7-day change
  • 30-day change
  • All-time change (from first snapshot)

Files to modify

  • backend/src/services/analyticsService.ts — replace random calculation with real query
  • backend/src/db/analyticsDb.ts — add getSnapshotAt and getClosestSnapshot query methods
  • frontend/src/components/PerformanceChart.tsx — handle null change values gracefully
  • frontend/src/components/Dashboard.tsx — show "—" when change data isn't available

Acceptance Criteria

  • calculateDayChange returns the actual percentage change from 24 hours ago
  • If no snapshot exists within a 2-hour window, returns null
  • Frontend shows "—" or "N/A" when change data isn't available (not random numbers)
  • Performance chart renders real historical data, not noise
  • 7-day and 30-day change calculations also use real data
  • Analytics snapshot worker is confirmed to be recording data regularly

References

Affected Area

Backend, Frontend

Checklist

  • I have searched existing issues and this is not a duplicate

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardThird CampaignCampaign: Third CampaignbackendBackend relatedbugSomething isn't workinghelp wantedExtra attention is needed

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions