<!DOCTYPE html>

<html lang="zh-CN">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>巨无霸指数 (Big Mac Index) 经济学看板</title>

    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

    <style>

        :root { --primary: #d32f2f; --bg: #f8f9fa; --card: #ffffff; --text: #333; --border: #e9ecef; }

        body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: var(--bg); color: var(--text); line-height: 1.6; padding: 20px; margin: 0; }

        .container { max-width: 1000px; margin: 0 auto; }

        

        /* 头部与状态 */

        header { text-align: center; margin-bottom: 30px; padding: 20px 0; }

        h1 { color: var(--primary); margin-bottom: 5px; font-size: 2em; }

        .status-bar { font-size: 12px; color: #666; background: #eee; display: inline-block; padding: 4px 12px; border-radius: 12px; margin-top: 8px;}


        /* 知识卡片 */

        .info-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 30px; }

        .card { background: var(--card); padding: 20px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.04); border-left: 4px solid var(--primary); }

        .card h3 { margin-top: 0; color: var(--primary); font-size: 1.1em; }

        .card p, .card ul { font-size: 14px; color: #555; margin-bottom: 8px; }

        .formula-box { background: #fff5f5; padding: 10px; border-radius: 4px; font-family: monospace; font-size: 14px; margin: 8px 0; color: #b71c1c; border: 1px dashed #ffcdd2;}


        /* 图表与表格 */

        .chart-container { position: relative; height: 350px; width: 100%; margin-bottom: 30px; background: var(--card); padding: 20px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.04);}

        table { width: 100%; border-collapse: collapse; background: var(--card); border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.04); }

        th, td { padding: 12px 15px; text-align: left; border-bottom: 1px solid var(--border); font-size: 14px; }

        th { background-color: #f1f3f5; font-weight: bold; color: #495057; }

        .overvalued { color: #d32f2f; font-weight: bold; }

        .undervalued { color: #388e3c; font-weight: bold; }

        .loading { text-align: center; padding: 40px; color: #888; }


        /* 响应式 */

        @media (max-width: 768px) { .info-grid { grid-template-columns: 1fr; } }

    </style>

</head>

<body>


<div class="container">

    <header>

        <h1>🍔 巨无霸指数 (Big Mac Index)</h1>

        <div class="status-bar" id="status">⏳ 正在初始化...</div>

    </header>


    <!-- 1. 背景知识与计算说明 -->

    <div class="info-grid">

        <div class="card">

            <h3>📖 什么是巨无霸指数?</h3>

            <p>巨无霸指数由英国《经济学人》杂志于 <strong>1986年</strong> 推出,是一个非正式的经济指数。</p>

            <p>它的核心理论基础是 <strong>购买力平价(PPP)</strong>:在理想状态下,同一种商品在世界各地的价格应该是一样的。</p>

            <p>麦当劳的巨无霸汉堡因为在全球拥有高度标准化的配方和制作工艺,成为了衡量各国货币实际购买力的完美“标尺”。</p>

        </div>

        <div class="card">

            <h3>🧮 核心计算逻辑</h3>

            <p><strong>1. 隐含汇率 (Implied Rate)</strong></p>

            <div class="formula-box">隐含汇率 = 当地巨无霸价格 ÷ 美国巨无霸价格</div>

            <p><strong>2. 估值偏差 (Deviation)</strong></p>

            <div class="formula-box">偏差% = (隐含汇率 - 实际汇率) ÷ 实际汇率 × 100%</div>

            <p style="font-size:12px; color:#777; margin-bottom:0;">* 偏差为正数表示货币被<strong>高估</strong>,为负数表示被<strong>低估</strong>。</p>

        </div>

    </div>


    <!-- 2. 可视化图表 -->

    <div class="chart-container">

        <canvas id="bigMacChart"></canvas>

    </div>


    <!-- 3. 详细数据列表 -->

    <table>

        <thead>

            <tr>

                <th>国家/货币</th>

                <th>当地售价</th>

                <th>实际汇率 (1 USD = ?)</th>

                <th>隐含汇率 (1 USD = ?)</th>

                <th>估值状态</th>

            </tr>

        </thead>

        <tbody id="tableBody">

            <tr><td colspan="5" class="loading">等待数据加载...</td></tr>

        </tbody>

    </table>

</div>


<script>

    // 1. 巨无霸价格数据 (基于 The Economist 公开数据整理,单位:当地货币)

    const BIG_MAC_PRICES = {

        'USD': 5.69, 'CNY': 24.40, 'JPY': 450, 'EUR': 4.90, 'GBP': 4.20, 'KRW': 5500

    };


    // 2. 免费汇率 API

    const EXCHANGE_API_URL = 'https://api.exchangerate-api.com/v4/latest/USD';

    let chartInstance = null; // 用于存储图表实例,防止重复渲染


    // 获取汇率数据

    async function fetchExchangeRates() {

        try {

            const response = await fetch(EXCHANGE_API_URL);

            if (!response.ok) throw new Error('API 请求失败');

            const data = await response.json();

            return data.rates;

        } catch (error) {

            console.error('获取汇率失败:', error);

            document.getElementById('status').innerText = '⚠️ 汇率获取失败,请检查网络';

            return null;

        }

    }


    // 核心计算与渲染逻辑

    function calculateAndRender(rates) {

        const chartLabels = [];

        const chartValues = [];

        const tbody = document.getElementById('tableBody');

        tbody.innerHTML = ''; 


        const usdPrice = BIG_MAC_PRICES['USD'];


        for (const [currency, localPrice] of Object.entries(BIG_MAC_PRICES)) {

            const actualRate = rates[currency];

            if (!actualRate) continue;


            // 【核心计算】隐含汇率:当地价格 / 美国价格

            const impliedRate = localPrice / usdPrice;

            

            // 【核心计算】估值偏差百分比

            const deviation = currency === 'USD' ? 0 : ((impliedRate - actualRate) / actualRate) * 100;

            const deviationFixed = parseFloat(deviation.toFixed(2));


            chartLabels.push(currency);

            chartValues.push(deviationFixed);


            // 渲染表格行

            const row = `<tr>

                <td><strong>${currency}</strong></td>

                <td>${localPrice} ${currency}</td>

                <td>${actualRate.toFixed(4)}</td>

                <td>${impliedRate.toFixed(4)}</td>

                <td class="${deviationFixed > 0 ? 'overvalued' : (deviationFixed < 0 ? 'undervalued' : '')}">

                    ${deviationFixed > 0 ? '📈 高估' : (deviationFixed < 0 ? '📉 低估' : '基准')} 

                    ${Math.abs(deviationFixed)}%

                </td>

            </tr>`;

            tbody.innerHTML += row;

        }


        // 渲染/更新图表

        const ctx = document.getElementById('bigMacChart').getContext('2d');

        if (chartInstance) chartInstance.destroy(); // 销毁旧图表

        

        chartInstance = new Chart(ctx, {

            type: 'bar',

            data: {

                labels: chartLabels,

                datasets: [{

                    label: '货币估值偏差 (%)',

                    data: chartValues,

                    backgroundColor: chartValues.map(v => v >= 0 ? 'rgba(211, 47, 47, 0.7)' : 'rgba(56, 142, 60, 0.7)'),

                    borderColor: chartValues.map(v => v >= 0 ? 'rgba(211, 47, 47, 1)' : 'rgba(56, 142, 60, 1)'),

                    borderWidth: 1

                }]

            },

            options: {

                responsive: true, maintainAspectRatio: false,

                plugins: { 

                    legend: { display: false },

                    title: { display: true, text: '各国货币估值偏差 (基于巨无霸指数)', font: { size: 16 } }

                },

                scales: {

                    y: { 

                        beginAtZero: true, 

                        title: { display: true, text: '高估 (+) / 低估 (-) 百分比' },

                        grid: { color: '#f1f1f1' }

                    },

                    x: { grid: { display: false } }

                }

            }

        });


        const now = new Date().toLocaleTimeString();

        document.getElementById('status').innerText = `✅ 数据已更新 (${now}) | 下次自动刷新: 1小时后 | 巨无霸价格周期: 2024`;

    }


    // 初始化与定时刷新 (每 1 小时 = 3600000 毫秒)

    window.onload = async () => {

        const rates = await fetchExchangeRates();

        if (rates) calculateAndRender(rates);

        

        setInterval(async () => {

            console.log('⏰ 触发定时汇率刷新...');

            const newRates = await fetchExchangeRates();

            if (newRates) calculateAndRender(newRates);

        }, 3600000);

    };

</script>

</body>

</html>