File size: 3,671 Bytes
c2b7eb3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import { tickerMetrics } from './tickerMetrics';

// Helper to generate a realistic random walk for a stock price
const generateRandomWalk = (startPrice, days, volatility) => {
  const data = [];
  let currentPrice = startPrice;
  const now = new Date();
  
  for (let i = days; i >= 0; i--) {
    const date = new Date(now);
    date.setDate(date.getDate() - i);
    
    // Random daily return based on volatility (standard deviation)
    const dailyReturn = (Math.random() - 0.5) * volatility;
    currentPrice = currentPrice * (1 + dailyReturn);
    
    data.push({
      time: date.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' }),
      date: date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }),
      price: Number(currentPrice.toFixed(2))
    });
  }
  return data;
};

// Base starting prices for realism
const basePrices = {
  'SPY': 510.50,
  'VOO': 468.20,
  'BND': 72.15,
  'BNDX': 48.90,
  'AAPL': 175.40,
  'MSFT': 420.10,
  'GOOGL': 155.30,
  'AMZN': 180.25,
  'JNJ': 155.60,
  'BRK-B': 410.80,
  'JPM': 195.40,
  'VXUS': 58.70,
  'TSLA': 175.20,
  'QQQ': 440.50,
  'VTI': 255.60,
  'CASH': 1.00
};

const mockDataCache = {};

export const fetchRealData = async (ticker) => {
  if (ticker === 'CASH') return getHistoricalData('CASH');
  
  try {
    const proxy = 'https://corsproxy.io/?';
    const url = `${proxy}https://query1.finance.yahoo.com/v8/finance/chart/${ticker}?interval=1d&range=1y`;
    const response = await fetch(url);
    const data = await response.json();
    
    if (!data.chart?.result?.[0]) throw new Error('Invalid ticker');
    
    const result = data.chart.result[0];
    const timestamps = result.timestamp;
    const quotes = result.indicators.quote[0].close;
    
    const history = timestamps.map((ts, i) => {
      const date = new Date(ts * 1000);
      return {
        time: date.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' }),
        date: date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }),
        price: Number(quotes[i]?.toFixed(2)) || 0
      };
    }).filter(d => d.price > 0);

    const currentPrice = history[history.length - 1].price;
    const oldPrice = history[0].price;
    const change = currentPrice - oldPrice;
    const percentChange = (change / oldPrice) * 100;

    const finalData = {
      ticker,
      currentPrice: Number(currentPrice.toFixed(2)),
      change: Number(change.toFixed(2)),
      percentChange: Number(percentChange.toFixed(2)),
      isPositive: change >= 0,
      history
    };

    mockDataCache[ticker] = finalData;
    return finalData;
  } catch (error) {
    console.error("Yahoo Finance Error:", error);
    return getHistoricalData(ticker); // Fallback to mock
  }
};

export const getHistoricalData = (ticker) => {
  if (mockDataCache[ticker]) {
    return mockDataCache[ticker];
  }

  const startPrice = basePrices[ticker] || 100;
  const metrics = tickerMetrics[ticker] || { beta: 1 };
  const volatility = (metrics.beta * 0.015);
  
  const history = generateRandomWalk(startPrice, 365, volatility);
  const currentPrice = history[history.length - 1].price;
  const oldPrice = history[0].price;
  const change = currentPrice - oldPrice;
  const percentChange = (change / oldPrice) * 100;

  const result = {
    ticker,
    currentPrice: Number(currentPrice.toFixed(2)),
    change: Number(change.toFixed(2)),
    percentChange: Number(percentChange.toFixed(2)),
    isPositive: change >= 0,
    history
  };

  mockDataCache[ticker] = result;
  return result;
};