数据API接入教程

本页说明如何把九期网的期货手续费、保证金数据接入你自己的程序或网站:开通步骤、推荐的网站接入方式、各语言示例代码,以及接入时最常遇到的问题和解决办法。

一、接入前准备

  • 九期网账号:没有的话先点页面右上角「快速注册」。
  • 一台有固定公网 IP 的服务器:接口只接受已绑定 IP 发来的请求。阿里云、腾讯云等云服务器的公网 IP 是固定的;家用宽带的 IP 经常变化,只适合临时测试。
  • 任意能发 HTTPS 请求的语言:PHP、Python、Java、Go、Node.js、C# 等都可以;只支持 GET,返回 UTF-8 编码的 JSON。

二、开通步骤

  1. 登录后打开数据API页面,在「我的数据API」点「免费试用 7 天」(含专业版全部接口,历史数据可查最近 7 天,每天 1,000 次,每个账号限领一次);或在「购买 / 续费」选择基础版、专业版付款,付款成功后自动开通。
  2. 点「生成密钥」。密钥形如 q9_ 加 40 位字母数字,只显示一次,请立即复制保存到服务器的配置文件或环境变量里。遗失只能重新生成,重新生成后旧密钥立即失效。
  3. 查出服务器的公网 IP:在服务器上执行下面的命令(还没绑定 IP 时会返回 ip_not_bound,提示里的「当前请求 IP」就是要绑定的 IP):
    curl -s "https://www.9qihuo.com/api/data/v1/meta" -H "X-API-Key: 你的密钥"
    也可以执行 curl -4 ifconfig.me。注意要填公网 IP,不是服务器网卡上的内网 IP(10.x、172.16~31.x、192.168.x 开头的都是内网 IP)。
  4. 把 IP 填到「绑定服务器 IP」,每行一个,最多 5 个(例如正式服务器、备用服务器、自己电脑各一个),点「保存 IP」,立即生效。
  5. 再执行一次第 3 步的命令,返回 "ok":true 和套餐信息就说明接通了(meta 不计调用次数)。
  6. 按下面的示例写定时任务,把数据存到你自己的数据库或文件里。

只想看数据、不写程序:开通后直接打开数据中心,可按交易所、品种筛选,导出 CSV 用 Excel 打开。

三、接入自己网站的推荐做法

你的服务器定时拉取 → 存到你的数据库 / 缓存文件 → 你的网页从本地读取展示。

  • 不要在网页的 JavaScript 里直接调用接口:密钥会暴露给所有访客;访客的 IP 不是你绑定的服务器 IP,会返回 403;接口也不允许浏览器跨域调用(CORS)。
  • 不要每个访客打开页面就请求一次:数据一天只更新几次。每晚 21 点夜盘开盘后按交易所最新参数重新计算,21:40、22:40、23:40 更新,日间在 3:40、8:40、12:40、17:40、20:40 更新。建议每小时第 45 分钟拉一次。
  • 一次取全部,再在本地按品种拆分:futures 不带参数一次返回全部约 850 个期货合约(90 个品种,每个品种最多十几个合约),options 一次返回全部期权品种。
  • 可以先查 meta(不计次数):比较 futures_fee_updated、price_updated,没有变化就不用重新拉取。
  • 请求失败时保留上一次的数据,不要用空数据覆盖,等下一次定时任务再取。
做法每天大约调用
每小时取一次全部期货 + 全部期权(推荐)48 次
每 10 分钟取一次全部期货 + 全部期权288 次
每小时按 90 个品种逐个取(pid=)2,160 次
套餐上限:试用 / 基础 / 专业1,000 / 10,000 / 50,000 次

一手保证金(margin_lot)、按金额收取的每手手续费(fee_*_yuan)按昨结算价计算,每个交易日都会变化;保证金率、手续费标准只有交易所调整时才变。

四、示例代码

PHP:定时拉取全部期货合约,存成本地文件

<?php
// fetch_9qihuo.php,用定时任务运行:45 * * * * php /path/fetch_9qihuo.php
$key = getenv('Q9_API_KEY');                 // 密钥放环境变量或配置文件,不要写进网页
$ch = curl_init('https://www.9qihuo.com/api/data/v1/futures');
curl_setopt_array($ch, array(
    CURLOPT_HTTPHEADER => array('X-API-Key: ' . $key),
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 20,
));
$body = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$res = json_decode((string) $body, true);
if ($code !== 200 || empty($res['ok'])) {
    // 失败时保留上一次的文件;记录 error 和 message 方便排查
    error_log('9qihuo api ' . $code . ' ' . ($res['error'] ?? '') . ' ' . ($res['message'] ?? ''));
    exit(1);
}
file_put_contents(__DIR__ . '/futures.json.tmp', json_encode($res['data'], JSON_UNESCAPED_UNICODE));
rename(__DIR__ . '/futures.json.tmp', __DIR__ . '/futures.json');

// 网页里读取(不访问九期网):
// $rows = json_decode(file_get_contents('/path/futures.json'), true);
// foreach ($rows as $r) { if ($r['pid'] === 'rb') echo $r['id'], ' ', $r['fee_open'], ' ', $r['margin_lot'], "\n"; }

Python

import os, time, requests

KEY = os.environ["Q9_API_KEY"]
BASE = "https://www.9qihuo.com/api/data/v1/"

def get(endpoint, **params):
    for i in range(3):
        r = requests.get(BASE + endpoint, params=params, headers={"X-API-Key": KEY}, timeout=20)
        if r.status_code == 429 and "json" not in r.headers.get("Content-Type", ""):
            time.sleep(3 * (i + 1))      # 请求过快,等几秒重试
            continue
        d = r.json()
        if not d.get("ok"):
            raise RuntimeError(f"{r.status_code} {d.get('error')} {d.get('message')}")
        return d
    raise RuntimeError("请求过快,重试后仍失败")

futures = get("futures")["data"]                    # 全部期货合约
rb = [c for c in futures if c["pid"] == "rb"]       # 本地按品种筛选
main = get("futures", main=1)["data"]               # 只要主力合约
day = get("history", date="2026-11-03", pid="rb")  # 某一天(专业版 / 试用版)

Node.js(18 及以上,服务器端运行)

const BASE = 'https://www.9qihuo.com/api/data/v1/';
async function get(endpoint, params = {}) {
  const r = await fetch(BASE + endpoint + '?' + new URLSearchParams(params), {
    headers: { 'X-API-Key': process.env.Q9_API_KEY },
  });
  const d = await r.json().catch(() => ({}));
  if (!r.ok || !d.ok) throw new Error(`${r.status} ${d.error || ''} ${d.message || ''}`);
  return d;
}
get('futures', { pid: 'rb' }).then(d => console.log(d.count, d.data[0]));

命令行测试

curl -s "https://www.9qihuo.com/api/data/v1/futures?pid=rb" -H "X-API-Key: 你的密钥"
curl -s "https://www.9qihuo.com/api/data/v1/history?date=2026-11-03&exch=SHFE" -H "X-API-Key: 你的密钥"

五、历史数据(专业版、试用版)

  • history?date=YYYY-MM-DD:查某一天收盘后(23:50)各合约的保证金率、手续费、最小开仓手数、单笔下单上限,即当晚夜盘开盘重算后九期网显示的数值。可加 exch、pid、id 筛选。
    • 手续费可查 2026-03-27 以后任意一天;保证金每日快照从 2026-11-03 开始,之前的日期只返回手续费(保证金等字段为 null,source 为 fee_history)。
    • 周末、节假日没有快照,返回此前最近一个交易日的数据,snapshot_date 是实际快照日期。当天 23:50 之前查今天,返回的是上一个快照。
  • fee-changes?since=YYYY-MM-DD:手续费调整记录,每条带调整前的数值(prev),适合做「手续费调整提醒」。
  • margin-changes?since=YYYY-MM-DD:保证金率调整记录(相邻两天快照比对得出)。
  • 试用版这三个接口只能查最近 7 天(不带 since 时自动从可查的最早日期开始);专业版不受此限制。

六、常见问题

现象原因和解决办法
401 missing_key没有带密钥。密钥必须放在请求头 X-API-Key 里(注意大小写和中间的横线),不支持放在网址参数里。如果经过公司代理或网关,确认它没有去掉自定义请求头。
401 invalid_key密钥不对:复制时少了字符,或带了空格、换行;或者在页面上重新生成过(旧密钥立即失效)、点过「停用密钥」。重新生成一个,更新到服务器配置里。
403 ip_not_bound还没有绑定服务器 IP。提示里会显示当前请求 IP,把它填到「绑定服务器 IP」保存即可。
403 ip_not_allowed请求来自没有绑定的 IP,提示里的「当前请求 IP」就是我们看到的 IP,把它绑定即可。常见原因:
① 绑定的是服务器内网 IP,应绑定公网出口 IP;
② 云服务器通过 NAT 网关或弹性公网 IP 上网,出口 IP 和控制台显示的不一样,以提示里的 IP 为准;
③ 在自己电脑上测试,电脑的 IP 和服务器不同,测试时把电脑的 IP 也绑上(最多 5 个);
④ 家用宽带、手机网络的 IP 会变;
⑤ 开了代理或 VPN。
403 expired / no_plan会员已到期 / 未开通。到数据API页面续费或购买(试用到期后购买即可继续使用,密钥和绑定的 IP 不用改)。
403 plan基础版调用了专业版接口(history、fee-changes、margin-changes)。升级专业版后即可调用,基础版剩余时间按金额折算并入。
429 quota当天次数用完,北京时间次日 0 点重置。检查程序是否在循环里反复请求,或网站每个访客都在调用接口(应改为定时拉取后缓存)。meta 返回今天已用次数 used_today,不计次数。
429 但返回的不是 JSON请求太快:每个密钥每秒最多 2 次(瞬间最多 10 次),每个 IP 每秒最多 5 次。循环请求时每次间隔 0.5 秒以上,遇到 429 等几秒再重试。
403 trial_range试用版的历史类接口只能查最近 7 天,提示里有可查的最早日期。需要更早的历史请开通专业版。
400 bad_date / bad_since日期格式应为 2026-11-03 这种 YYYY-MM-DD;history 不能早于 2026-03-27,也不能是未来日期。
404 not_found接口名写错,或网址少了 /api/data/v1/。正确示例:https://www.9qihuo.com/api/data/v1/futures。
405 method只支持 GET 请求,不要用 POST。
500 / 503服务器临时故障或数据正在更新,稍后重试;保留上一次的数据,不要覆盖。
浏览器控制台报跨域(CORS)错误接口不支持在网页 JavaScript 里直接调用,必须由你的服务器调用,见第三部分。
数据中心网页能看,程序却报 403数据中心网页查看不检查 IP,程序调用要检查绑定 IP,按上面 ip_not_allowed 处理。
中文乱码接口返回 UTF-8 编码。PHP 用 json_decode、Python 用 r.json() 解析即可;存数据库请用 utf8mb4 字符集。
返回里 truncated 为 true单次最多返回 1000 条。全部期货约 850 条,不会截断;调整记录查很长时间范围时可能截断,加 exch、pid 或缩短 since 分几次取。
手续费和我开户的期货公司不一样接口提供的是交易所标准手续费,期货公司通常在此基础上加收,实际以期货公司为准。
fee_mode 是 money 时数字很小按成交金额收取,单位是万分之几;fee_open_yuan 等字段是按昨结算价折算后的每手金额(元)。
min_open 为 0新合约,交易所还没有公告最小开仓手数。
周末数据没有变化正常。非交易日交易所不调整参数,meta 里可以看到各项数据的更新时间。
换了服务器或 IP 变了到数据API页面修改「绑定服务器 IP」,保存后立即生效,密钥不用换。
密钥泄露了立即在数据API页面点「重新生成密钥」,旧密钥马上失效,再把新密钥更新到服务器。
HTTPS 证书错误(很老的系统)更新系统的根证书(如 ca-certificates),或升级到支持 TLS 1.2 的环境。
能不能直接抓手续费网页?不行。手续费网页每个 IP 每天最多看 300 次,python-requests 等采集程序会被直接拒绝。批量获取请使用本接口。

以上都没有解决:请把接口返回的完整 JSON(含 error 和 message)、请求时间和你的服务器 IP 发给九期网客服。