金衡盎司、克与千克:正确换算贵金属价格
详解金衡盎司与常衡盎司的区别、精确的克与千克换算系数、API 的 unit 参数和取整规则,以及会让金属价格偏差近 10% 的常见错误。
为什么单位很重要
几乎在任何地方,贵金属都以金衡盎司报价:批发市场、金银条交易商的价目表以及价格 API 都是如此。而买卖金属的人则根据所在地区和交易品种,习惯使用克、千克、托拉(tola)或两(tael)。因此,任何向用户展示金属价格的产品都至少包含一次单位换算,而这种换算常常是一些悄无声息、看似合理的错误的根源。
最典型的错误是把金衡盎司当作普通盎司。两者相差近 10%,这个差距大到足以影响每一张发票,却又小到在演示中没人察觉。本文将介绍精确的定义、换算系数、如何让 API 替您完成换算、如何对结果取整和展示,并列出一份值得编写测试的错误清单。
金衡盎司与常衡盎司
两种盎司都以格令(grain)定义,而格令有精确的公制定义:1 格令 = 64.79891 毫克。其他一切都由此推出:
- 金衡盎司为 480 格令,恰好等于 31.1034768 克。黄金、白银、铂金和钯金都以它计价。
- 常衡盎司是美国和英国日常用于食品和包裹的盎司,为 437.5 格令,恰好等于 28.349523125 克。
- 金衡磅为 12 金衡盎司(373.2417216 克),而常衡磅为 16 常衡盎司(453.59237 克)。因此,金衡盎司是较重的盎司,金衡磅却是较轻的磅。
| 单位 | 格令 | 克(精确值) | 金衡盎司 |
|---|---|---|---|
| 格令 | 1 | 0.06479891 | 0.0020833… |
| 英钱(dwt) | 24 | 1.55517384 | 0.05 |
| 常衡盎司 | 437.5 | 28.349523125 | 0.9114583… |
| 金衡盎司 | 480 | 31.1034768 | 1 |
| 金衡磅 | 5,760 | 373.2417216 | 12 |
| 常衡磅 | 7,000 | 453.59237 | 14.5833… |
金衡盎司比常衡盎司重约 9.7%(480 ÷ 437.5 ≈ 1.0971)。混淆两者时产生的误差恰好就是这个比例。
除非来源另有说明,贵金属价格中的盎司都是指金衡盎司,常写作 oz t 或 ozt。在 MetalAPI 中,默认单位为 troy_oz,除非您另行指定,所有金属价格都以金衡盎司计。
精确的换算系数
由于这些单位都有精确定义,换算时无需任何近似。要将每金衡盎司的价格换算为另一单位的价格,只需乘以该单位所含的金衡盎司数:
每单位价格 = 每金衡盎司价格 × 每单位克数 ÷ 31.1034768
| 计价单位 | 每单位克数 | 金衡盎司价格乘以 |
|---|---|---|
| 克 | 1 | 0.0321507466 |
| 千克 | 1,000 | 32.1507466 |
| 常衡盎司 | 28.349523125 | 0.9114583333 |
| 常衡磅 | 453.59237 | 14.5833333 |
| 公吨 | 1,000,000 | 32,150.7466 |
| 短吨(2,000 磅) | 907,184.74 | 29,166.6667 |
| 托拉 | 11.6638038 | 0.375 |
| 英钱 | 1.55517384 | 0.05 |
托拉(tola)在南亚和海湾地区仍被广泛用于黄金交易,其定义为 180 格令,恰好等于 11.6638038 克,即八分之三金衡盎司。两(tael)则没那么规整,因为它的重量取决于市场:香港黄金交易中约为 37.4 克,台湾为 37.5 克,中国大陆为 50 克。如果您支持以“两”计价,请将其克重设为可配置项,并标明所指的是哪一种“两”。
千克金条是一个便捷的合理性检查。1 千克约等于 32.15 金衡盎司,因此千克价格应始终约为盎司价格的 32 倍。如果接近 35 倍,说明有人用了常衡盎司的系数。
手动换算
如果您已经有每金衡盎司的价格,自行换算只需一次乘法。请将精确常数集中放在一个模块中,并统一以克为中间单位进行换算,这样任意两种单位之间的换算方式都相同:
// 每种单位所含的克数,均为精确值:1 格令 = 64.79891 毫克。
const GRAMS_PER_UNIT = {
troy_oz: 31.1034768, // 480 格令
gram: 1,
kilogram: 1000,
ounce: 28.349523125, // 常衡,437.5 格令
pound: 453.59237, // 常衡,7,000 格令
metric_ton: 1_000_000,
short_ton: 907_184.74, // 2,000 磅
tola: 11.6638038, // 180 格令
pennyweight: 1.55517384, // 24 格令
};
/** 将每 `from` 单位的价格换算为每 `to` 单位的价格。 */
export function convertPrice(price, from, to) {
const a = GRAMS_PER_UNIT[from];
const b = GRAMS_PER_UNIT[to];
if (a === undefined || b === undefined) throw new Error(`Unknown unit: ${a === undefined ? from : to}`);
return (price / a) * b;
}
console.log(convertPrice(3997.89, "troy_oz", "gram")); // 128.535148…
console.log(convertPrice(3997.89, "troy_oz", "kilogram")); // 128535.148…
console.log(convertPrice(3997.89, "troy_oz", "tola")); // 1499.20875在 Python 中,如果结果要写入发票或账簿,请使用 Decimal。requests 会将 parse_float 传递给 JSON 解析器,因此价格永远不会经过二进制浮点数:
import os
from decimal import Decimal, ROUND_HALF_UP
import requests
GRAMS_PER_TROY_OZ = Decimal("31.1034768")
CENT = Decimal("0.01")
r = requests.get(
"https://metalapi.com/api/v1/latest",
params={"currencies": "XAU"},
headers={"X-API-Key": os.environ["METALAPI_KEY"]},
timeout=10,
)
data = r.json(parse_float=Decimal)
if not data["success"]:
raise RuntimeError(data["error"])
per_oz = data["rates"]["USDXAU"] # 例如 Decimal("3997.89")
per_gram = per_oz / GRAMS_PER_TROY_OZ
per_kg = per_gram * 1000
print(per_gram.quantize(CENT, rounding=ROUND_HALF_UP)) # 按示例价格为 128.54
print(per_kg.quantize(CENT, rounding=ROUND_HALF_UP)) # 128535.15倒数汇率需要相反的运算。rates.XAU 是 1 单位基础货币可买到的金衡盎司数,因此每单位货币可买到的克数是 rates.XAU × 31.1034768,而不是 ÷。这个陷阱也是应当使用 USDXAU 等带前缀的价格键、不去碰倒数键的又一个理由。
让 API 来换算:unit 参数
您也可以直接向 MetalAPI 请求所需的单位。/latest、历史端点、/timeframe、/ohlc、/convert 和 /carat 都接受 unit 参数:troy_oz(默认)、gram、kilogram、ounce、pound、metric_ton 或 short_ton。下面的请求返回以欧元/克计的黄金和白银价格:
curl "https://metalapi.com/api/v1/latest?base=EUR¤cies=XAU,XAG&unit=gram" \
-H "X-API-Key: $METALAPI_KEY"当单位不是默认值时,响应会在顶层的 unit 字段中重复该单位。以下数值是文档中的示例,并非实时价格:
{
"success": true,
"timestamp": 1792765800,
"date": "2026-10-23",
"base": "EUR",
"unit": "gram",
"rates": {
"XAU": 0.009057444725,
"EURXAU": 110.4064149,
"XAG": 0.6713138244,
"EURXAG": 1.489616277
}
}API 使用与上表相同的精确系数,倒数键也会随单位变化:使用 unit=gram 时,rates.XAU 表示 1 欧元可买到的黄金克数。以下几条规则值得了解:
- 接受
g、kg、lb和tonne等简写。oz表示常衡盎司,因此切勿将其用作金衡盎司的简写。 - 未知单位会返回错误
209(invalid_unit)。 unit仅适用于贵金属和工业金属。能源仍按桶、MMBtu 或加仑计价,货币和加密货币不受影响,因此在一次请求中混合多种品种是安全的。- 工业金属默认同样以金衡盎司报价,因此所有金属可以直接比较。铜请传入
unit=pound,铝和锌请传入unit=metric_ton,钢材请传入unit=short_ton,即可获得这些市场交易时使用的单位。
/convert 同样接受 unit,一步即可将重量换算为金额。下面的请求计算 250 克黄金的美元价值:
curl "https://metalapi.com/api/v1/convert?from=XAU&to=USD&amount=250&unit=gram" \
-H "X-API-Key: $METALAPI_KEY"info.rate 是 1 克黄金的美元价格,result 是全部数量的价值。按示例金价,响应如下:
{
"success": true,
"query": { "from": "XAU", "to": "USD", "amount": 250, "unit": "gram" },
"info": { "timestamp": 1792834892, "rate": 128.5351482, "quote": 128.5351482 },
"date": "2026-10-24",
"result": 32133.78705
}取整与展示
汇率以 JSON 数字返回,最多 10 位有效数字。保留这样的精度是为了让派生数值保持准确,因此请尽可能晚地取整:
- 先换算,后取整。如果先将每克价格取整到分,再乘以 1,000 得到千克金条的价格,半分的取整误差就会变成最多 5 个货币单位的误差。
- 按货币取整。大多数货币使用两位小数,日元没有小数,科威特第纳尔则使用三位小数。请让
Intl.NumberFormat或您所用的本地化库来选择默认位数,而不要写死两位。 - 为低价品种保留更多位数。按每金衡盎司 53.94 美元的示例价格,白银每克约 1.73 美元,只保留两位小数会掩盖其大部分日常波动。
- 金额使用十进制类型。凡是需要开票或记账的内容,请在 Python 中使用
Decimal,在 Java 中使用BigDecimal,或在数据库中使用以最小货币单位计的整数。图表使用二进制浮点数则没有问题。 - 标注单位。在每个价格旁边注明“每金衡盎司”“每克”或“每千克”。仅写“每盎司”,对许多读者来说含义不明。
下面这个小辅助函数从 Intl 获取货币的标准小数位数,并可选择额外增加几位:
function formatPrice(value, currency, locale = "en-US", extraDigits = 0) {
const { maximumFractionDigits } = new Intl.NumberFormat(locale, { style: "currency", currency }).resolvedOptions();
const digits = maximumFractionDigits + extraDigits;
return new Intl.NumberFormat(locale, {
style: "currency",
currency,
minimumFractionDigits: digits,
maximumFractionDigits: digits,
}).format(value);
}
formatPrice(128.53514819925212, "USD"); // "$128.54" 每克黄金
formatPrice(1.7342112699117933, "USD", "en-US", 2); // "$1.7342" 每克白银
formatPrice(110.4064149, "EUR", "de-DE"); // "110,41 €"换算速查表
下表换算的是 MetalAPI 文档中使用的示例价格:黄金每金衡盎司 3,997.89 美元,白银每金衡盎司 53.94 美元。它们用于说明计算过程,并非当前市场价格:
| 计价单位 | 黄金(美元) | 白银(美元) |
|---|---|---|
| 金衡盎司 | 3,997.89 | 53.94 |
| 克 | 128.54 | 1.7342 |
| 千克 | 128,535.15 | 1,734.21 |
| 托拉(11.6638 克) | 1,499.21 | 20.23 |
| 英钱(1.5552 克) | 199.89 | 2.697 |
| 金衡磅(12 oz t) | 47,974.68 | 647.28 |
| 常衡盎司 | 3,643.91 | 49.16 |
请看最后一行。如果页面把常衡盎司的数字标为盎司价格,就会把金银条价格低估近 9%。反过来的错误,即用金衡盎司价格除以 28.35 来得到每克价格,则会高估约 9.7%:每克黄金显示为 141.02,而不是 128.54。
常见换算错误及其测试方法
大多数单位错误可以归为以下几种模式:
- 除以 28.35。对金衡盎司价格使用了常衡盎司的系数。请使用 31.1034768。
- 把 `oz` 当作金衡盎司。在 MetalAPI 中,和大多数单位库一样,
oz表示常衡盎司。金银条价格需要使用troy_oz,或者干脆不传unit。 - 换算倒数键。
rates.XAU是每单位货币可买到的盎司数,而不是价格。将其换算为克需要乘以 31.1034768,这在习惯做除法的人看来像是写错了。 - 重复换算。请求
unit=gram后又除以一次 31.1034768,得到的价格会小约 31 倍。请确定换算是在 API 中完成还是在您的代码中完成,切勿两处都做。 - 过早取整。只在展示时取整一次。
- 跨单位缓存。如果缓存键忽略了查询字符串,本应返回盎司价格的地方可能会拿到每克价格的响应。请将
unit和base纳入缓存键。 - 对能源套用重量单位。
unit对原油和天然气无效,而用桶价除以 31.1 毫无意义。请按类别限制换算,/symbols?details=1会返回每个品种的类别。
几个属性测试就能在上线前发现其中大部分问题。它们使用 Node 内置的测试运行器和上文的 convertPrice 函数,可通过 node --test 运行:
import { test } from "node:test";
import assert from "node:assert/strict";
import { convertPrice } from "./units.mjs";
const PER_OZ = 3997.89; // 示例价格,美元/金衡盎司
test("a kilogram price is 1,000 gram prices", () => {
const g = convertPrice(PER_OZ, "troy_oz", "gram");
const kg = convertPrice(PER_OZ, "troy_oz", "kilogram");
assert.ok(Math.abs(kg - g * 1000) < 1e-6);
});
test("converting there and back returns the original price", () => {
const g = convertPrice(PER_OZ, "troy_oz", "gram");
assert.ok(Math.abs(convertPrice(g, "gram", "troy_oz") - PER_OZ) < 1e-9);
});
test("an avoirdupois ounce costs less than a troy ounce", () => {
assert.ok(convertPrice(PER_OZ, "troy_oz", "ounce") < PER_OZ);
});
test("a kilogram holds about 32.15 troy ounces", () => {
const kg = convertPrice(PER_OZ, "troy_oz", "kilogram");
assert.ok(Math.abs(kg / PER_OZ - 32.1507466) < 1e-6);
});如果您为首饰定价,下一步就是纯度:K 金价格详解在这些换算的基础上计算 22K 和 18K 金价。数据格式指南和 API 文档的单位部分列出了所有单位取值,品种页面则显示了各市场交易所用的单位。
继续阅读
黄金价格 API:开发者完全指南
黄金价格 API 使用指南:获取密钥,用 curl、JavaScript 和 Python 发起调用,正确解读汇率格式,并妥善处理历史数据、错误、配额与缓存。
K 金价格详解:24K、22K、18K 及其计算方法
24K、22K 和 18K 分别代表什么,916、750 等成色印记如何与 K 数对应,怎样计算每克 K 金价格,以及如何通过金价 API 直接获取各 K 数的金价。
通过 API 获取黄金和白银历史价格:25 年每日数据
使用 /historical、/timeframe、/change 和 /ohlc 获取 2000 年以来的黄金和白银每日历史价格,按年分页拉取长区间数据,并在本地存储和绘制图表。