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

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