Node.js 使用 Tushare 获取上金所 Au9999现货黄金数据

1. 引言

在量化交易和金融数据分析中,获取准确、及时的行情数据是第一步。

上海黄金交易所(上金所)的 Au9999 作为国内主要的现货黄金品种,其日线数据对黄金投资分析具有重要意义。

本文将介绍如何使用 Node.js 通过 Tushare Pro 接口获取 Au9999 的日线行情数据,并提供完整的代码示例和常见问题处理。

原有方案痛点

最开始直接 curl 爬取上金所官网 www.sge.com.cn,部署到云服务器后出现严重问题:请求建立连接后服务器静默断连,返回 curl: (52) Empty reply from server
云机房 IP 被上金所风控标记为爬虫,无论是否携带 UA、Cookie 都无法获取数据。
东方财富、新浪基金、积金好等第三方网页接口也存在 404、403 限流、接口不定期下线等风险,长期定时任务极不稳定。

因此,使用 Tushare Pro 这类专业金融数据接口成为更可靠的选择。

2. 准备工作

2.1 注册 Tushare Pro 并获取 Token

  1. 访问 Tushare Pro 官网 注册账号。
    (可直接扫码登录,也可以手机验证码注册登录 都很方便)
    在这里插入图片描述

  2. 登录后,在个人主页找到 接口TOKEN,复制保存备用。
    在这里插入图片描述

2.2 初始化 Node.js 项目

mkdir gold-data-fetcher
cd gold-data-fetcher
npm init -y

2.3 安装依赖

npm install tushare

3. 核心代码实现

3.1 获取 Au9999 日线数据

创建 fetch_gold.js 文件:

```javascript
const Tushare = require('tushare');

// 初始化 Tushare 客户端
const pro = new Tushare({
  token: '你的Tushare Token' // 替换为你的真实 Token
});

/**
 * 获取 Au9999 日线数据
 * @param {string} startDate - 开始日期,格式:YYYYMMDD
 * @param {string} endDate - 结束日期,格式:YYYYMMDD
 * @returns {Promise<Array>} 日线数据数组
 */
async function fetchAu9999Daily(startDate = '20250101', endDate = '20250616') {
  try {
    // 参数校验
    if (!startDate || !endDate) {
      throw new Error('开始日期和结束日期不能为空');
    }
    
    if (startDate > endDate) {
      throw new Error('开始日期不能晚于结束日期');
    }

    // 调用日线行情接口 - 注意:Tushare 标准接口是 pro.daily()
    const response = await pro.daily({
      ts_code: 'AU9999.SGE', // 上金所 Au9999 代码
      start_date: startDate,
      end_date: endDate,
      fields: 'ts_code,trade_date,open,high,low,close,pre_close,change,pct_chg,vol,amount'
    });

    if (response && response.data && response.data.length > 0) {
      console.log('✅ 成功获取 Au9999 日线数据:');
      console.log(`📊 共获取 ${response.data.length} 条记录`);
      console.log('📈 最新5条数据:');
      console.table(response.data.slice(0, 5));
      
      // 按交易日期排序(从旧到新)
      const sortedData = response.data.sort((a, b) => 
        a.trade_date.localeCompare(b.trade_date)
      );
      
      // 显示统计信息
      const firstDate = sortedData[0].trade_date;
      const lastDate = sortedData[sortedData.length - 1].trade_date;
      console.log(`📅 数据时间范围:${firstDate} 至 ${lastDate}`);
      
      return sortedData;
    } else {
      console.warn('⚠️ 未获取到数据,可能原因:');
      console.warn('  1. Token 无效或过期');
      console.warn('  2. 日期范围内无交易日(周末/节假日)');
      console.warn('  3. 接口调用频率限制');
      return [];
    }
  } catch (error) {
    console.error('❌ 获取数据失败:', error.message);
    console.error('错误详情:', error);
    
    // 根据错误类型提供建议
    if (error.message.includes('token')) {
      console.error('💡 建议:检查 Token 是否正确,或登录 Tushare Pro 确认 Token 状态');
    } else if (error.message.includes('rate limit')) {
      console.error('💡 建议:降低调用频率,免费用户通常限制 200 次/分钟');
    } else if (error.message.includes('network')) {
      console.error('💡 建议:检查网络连接,或稍后重试');
    }
    
    throw error; // 重新抛出错误,让调用者处理
  }
}

// 使用示例
async function main() {
  try {
    const data = await fetchAu9999Daily('20250101', '20250616');
    
    if (data.length > 0) {
      // 计算简单统计
      const closes = data.map(d => parseFloat(d.close));
      const avgClose = closes.reduce((sum, val) => sum + val, 0) / closes.length;
      const maxClose = Math.max(...closes);
      const minClose = Math.min(...closes);
      
      console.log(`📊 统计信息:`);
      console.log(`   平均收盘价:${avgClose.toFixed(2)}/`);
      console.log(`   最高收盘价:${maxClose.toFixed(2)}/`);
      console.log(`   最低收盘价:${minClose.toFixed(2)}/`);
      console.log(`   价格波动范围:${(maxClose - minClose).toFixed(2)}/克`);
    }
  } catch (error) {
    console.error('程序执行失败:', error.message);
  }
}

// 执行主函数
main();

### 3.2 运行脚本

```bash
node fetch_gold.js

4. 数据字段说明

字段名 含义 示例值
ts_code 股票代码 AU9999.SGE
trade_date 交易日 20250613
open 开盘价(元/克) 556.80
high 最高价(元/克) 560.20
low 最低价(元/克) 554.50
close 收盘价(元/克) 558.90
pre_close 昨收价(元/克) 555.00
change 涨跌额(元/克) 3.90
pct_chg 涨跌幅(%) 0.70
vol 成交量(手) 125600
amount 成交额(万元) 7012345.67

5. 进阶用法

5.1 获取指定日期范围的数据

async function fetchByDateRange(startDate, endDate) {
  const response = await pro.daily({
    ts_code: 'AU9999.SGE',
    start_date: startDate,
    end_date: endDate
  });
  return response.data;
}

// 示例:获取2025年第一季度数据
fetchByDateRange('20250101', '20250331').then(data => {
  console.log(`获取到 ${data.length} 条数据`);
});

5.2 数据持久化到 CSV

const fs = require('fs');

function saveToCSV(data, filename = 'au9999_daily.csv') {
  if (!data || data.length === 0) return;
  
  const headers = Object.keys(data[0]).join(',');
  const rows = data.map(row => Object.values(row).join(','));
  const csvContent = [headers, ...rows].join('\n');
  
  fs.writeFileSync(filename, csvContent, 'utf-8');
  console.log(`数据已保存到 ${filename}`);
}

// 在 fetchAu9999Daily 中调用
// saveToCSV(response.data);

6. 常见问题

6.1 Token 无效或过期

  • 检查 Token 是否正确复制,注意不要包含多余空格。
  • 登录 Tushare Pro 确认 Token 状态是否正常。

6.2 返回空数据

  • 确认日期范围内是否有交易日(周末和节假日无数据)。
  • 检查 ts_code 格式是否为 AU9999.SGE

6.3 接口调用频率限制

  • Tushare Pro 对免费用户有频率限制(通常 200 次/分钟)。
  • 如需高频调用,建议升级积分或添加延时。

7. 总结

通过本文,你已经学会了使用 Node.js 调用 Tushare Pro 接口获取上金所 Au9999 现货黄金的日线数据。你可以基于此数据进一步开发:

  • 黄金价格趋势分析
  • 移动平均线计算
  • 波动率分析
  • 自动化交易信号生成

建议将 Token 存储在环境变量中,避免硬编码到代码里。

更多推荐