MetalAPI
XAU3,997.89−1.54%XAG53.936−1.51%XPT1,554.47−0.83%XPD1,047.03−0.44%XCU6.5080+2.29%WTI103.27+3.82%BRENT111.70−1.30%EUR1.120400−0.01%GBP1.337500−0.01%JPY0.0063761+0.14%CHF1.213445−0.25%TRY0.020125−0.12%BTC80,329.75−0.55%ETH2,329.36−1.13%
すべての記事
金銀単位

トロイオンス、グラム、キログラム:貴金属価格を正しく換算する

トロイオンスと常衡オンスの違い、グラムとキログラムへの正確な換算係数、APIのunitパラメーター、丸めのルール、金属価格が10%近くずれる原因となるバグを解説します。

執筆:MetalAPI Team··9分で読めます

単位が重要な理由

貴金属の価格は、卸売市場でも、地金商の価格表でも、価格APIでも、ほぼどこでもトロイオンスあたりで提示されます。一方、金属を売買する人々は、住んでいる地域や取引する商品に応じて、グラム、キログラム、トラ、テールといった単位で考えます。そのため、金属価格を人に見せる製品には少なくとも1つの単位換算が含まれており、その換算は、気づかれにくくもっともらしく見える誤りの原因になりがちです。

典型的なミスは、トロイオンスを普通のオンスとして扱ってしまうことです。両者の差は10%近くあり、すべての請求書に影響するほど大きい一方で、デモでは誰も気づかないほど小さな差です。この記事では、厳密な定義、換算係数、APIに換算させる方法、結果の丸め方と表示方法、そしてテストを書いておくべきバグの一覧を紹介します。

トロイオンスと常衡オンス

どちらのオンスもグレーンで定義されており、グレーンにはメートル法での厳密な定義があります。1グレーン = 64.79891ミリグラムです。その他はすべてここから導かれます:

  • トロイオンスは480グレーンで、厳密に31.1034768グラムです。金、銀、プラチナ、パラジウムの価格はこの単位で付けられます。
  • 常衡オンスは、米国や英国で食品や小包に使われる日常的なオンスで、437.5グレーン、厳密に28.349523125グラムです。
  • トロイポンドは12トロイオンス(373.2417216 g)ですが、常衡ポンドは16常衡オンス(453.59237 g)です。つまり、オンスはトロイの方が重いのに、ポンドはトロイの方が軽いのです。
単位グレーングラム(厳密値)トロイオンス
グレーン10.064798910.0020833…
ペニーウェイト(dwt)241.555173840.05
常衡オンス437.528.3495231250.9114583…
トロイオンス48031.10347681
トロイポンド5,760373.241721612
常衡ポンド7,000453.5923714.5833…

トロイオンスは常衡オンスより約9.7%重くなります(480 ÷ 437.5 ≈ 1.0971)。この比率が、両者を取り違えたときに生じる誤差の大きさそのものです。

特に断りがない限り、貴金属価格におけるオンスはトロイオンスで、oz tやoztと表記されることもよくあります。MetalAPIのデフォルトの単位はtroy_ozで、別の単位を指定しない限り、すべての金属価格はトロイオンスあたりの価格です。

厳密な換算係数

これらの単位はすべて厳密に定義されているため、換算に近似は必要ありません。トロイオンスあたりの価格を別の単位あたりの価格に変えるには、その単位に含まれるトロイオンス数を掛けます:

単位あたりの価格 = トロイオンスあたりの価格 × 1単位のグラム数 ÷ 31.1034768

価格の単位1単位のグラム数トロイオンス価格に掛ける係数
グラム10.0321507466
キログラム1,00032.1507466
常衡オンス28.3495231250.9114583333
常衡ポンド453.5923714.5833333
メートルトン1,000,00032,150.7466
ショートトン(2,000 lb)907,184.7429,166.6667
トラ11.66380380.375
ペニーウェイト1.555173840.05

南アジアや湾岸諸国で今も金に広く使われているトラ(tola)は180グレーンと定義されており、厳密に11.6638038 g、つまり3/8トロイオンスです。テール(両)はそれほど明快ではなく、重さが市場によって異なります。香港の金取引では約37.4 g、台湾では37.5 g、中国本土では50 gです。テールに対応する場合は、グラム数を設定値にして、どのテールを指しているかを表示してください。

キロバーは手軽な検算に使えます。1キログラムは約32.15トロイオンスなので、キログラムあたりの価格は常にオンスあたりの価格の約32倍になるはずです。35倍に近い場合は、誰かが常衡オンスの係数を使っています。

手作業で換算する

トロイオンスあたりの価格がすでに手元にあれば、自分で換算するのは掛け算1回です。厳密な定数を1つのモジュールにまとめ、グラムを経由して換算すれば、どの単位の組み合わせでも同じように扱えます:

units.mjs
// 各単位1つあたりのグラム数。すべて厳密値:1グレーン = 64.79891 mg。
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 lb
  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パーサーに渡すため、価格が2進浮動小数点を経由することはありません:

per_gram.py
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単位あたりのトロイオンス数なので、通貨1単位あたりのグラム数はrates.XAU × 31.1034768で、÷ではありません。この落とし穴も、USDXAUのような通貨コード付きの価格キーを使い、逆数のキーには手を出さないほうがよい理由の1つです。

APIに換算させる:unitパラメーター

必要な単位をMetalAPIに直接指定することもできます。/latest、過去データのエンドポイント、/timeframe、/ohlc、/convert、/caratはunitパラメーターを受け付けます。指定できる値はtroy_oz(デフォルト)、gram、kilogram、ounce、pound、metric_ton、short_tonです。次のリクエストは、金と銀を1グラムあたりのユーロ建てで返します:

bash
curl "https://metalapi.com/api/v1/latest?base=EUR&currencies=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、ガロンあたりのまま変わらず、通貨と暗号資産にも影響しないため、1つのリクエストにシンボルを混在させても安全です。
  • 産業用金属もデフォルトではトロイオンスあたりの価格で提示されるため、すべての金属を直接比較できます。各市場で取引される単位で取得するには、銅はunit=pound、アルミニウムと亜鉛はunit=metric_ton、鋼はunit=short_tonを指定してください。

/convertもunitを受け付けるため、重量を1ステップで金額に換算できます。次の例は、金250グラムの価値を米ドルで求めます:

金250 gの価値を求める
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
}

丸めと表示

レートは、最大10桁の有効数字を持つJSONの数値で返されます。この精度は派生値を正確に保つためのものなので、できるだけ最後まで保持してください:

  • 先に換算し、丸めは最後に。 グラム価格をセント単位に丸めてから1,000倍してキロバーの価格を求めると、0.5セントの丸め誤差が最大5通貨単位の誤差になります。
  • 通貨ごとに丸める。 ほとんどの通貨は小数点以下2桁ですが、日本円は0桁、クウェート・ディナールは3桁です。2桁をハードコードせず、Intl.NumberFormatやロケールライブラリにデフォルトを選ばせてください。
  • 小さな価格には桁を追加する。 例の価格である1トロイオンス53.94 USDでは、銀は1グラムあたり約1.73 USDとなり、小数点以下2桁では日々の値動きのほとんどが見えなくなります。
  • 金額には10進数型を使う。 請求や記帳の対象となるものには、PythonではDecimal、JavaではBigDecimal、データベースでは整数の補助通貨単位を使ってください。チャートであれば2進浮動小数点で問題ありません。
  • 単位を明記する。 すべての価格の横に「1トロイオンスあたり」「1グラムあたり」「1 kgあたり」と表示してください。「1オンスあたり」だけでは、多くの読者にとって意味があいまいです。

通貨の標準的な桁数をIntlから取得し、必要に応じて桁を追加する小さなヘルパーです:

format.mjs
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"   金1グラムあたり
formatPrice(1.7342112699117933, "USD", "en-US", 2); // "$1.7342"   銀1グラムあたり
formatPrice(110.4064149, "EUR", "de-DE"); // "110,41 €"

換算表

この表は、MetalAPIのドキュメントで使われている例の価格、つまり金が1トロイオンスあたり3,997.89 USD、銀が1トロイオンスあたり53.94 USDを換算したものです。計算方法を示すためのもので、現在の市場価格ではありません:

価格の単位金(USD)銀(USD)
トロイオンス3,997.8953.94
グラム128.541.7342
キログラム128,535.151,734.21
トラ(11.6638 g)1,499.2120.23
ペニーウェイト(1.5552 g)199.892.697
トロイポンド(12 oz t)47,974.68647.28
常衡オンス3,643.9149.16

最後の行を見てください。ページで常衡オンスの数値をオンス価格として表示すると、地金価格を9%近く過小に示すことになります。逆に、トロイオンス価格を28.35で割ってグラム価格を求めると約9.7%過大になり、金1グラムあたり128.54ではなく141.02になってしまいます。

よくある換算バグとそのテスト方法

単位に関するバグのほとんどは、いくつかのパターンに分類できます:

  • 28.35で割る。 トロイオンス価格に常衡オンスの係数を使っています。31.1034768を使ってください。
  • `oz`をトロイオンスとして扱う。 MetalAPIでは、ほとんどの単位ライブラリと同様に、ozは常衡オンスです。地金の価格にはtroy_ozを指定するか、unitを指定しないでください。
  • 逆数のキーを換算する。 rates.XAUは通貨1単位あたりのオンス数であり、価格ではありません。これをグラムに換算するには31.1034768を掛ける必要があり、割り算に慣れた人には誤りに見えます。
  • 二重に換算する。 unit=gramをリクエストしたうえでさらに31.1034768で割ると、価格が約31分の1になってしまいます。換算をAPIで行うか自分のコードで行うかを決め、両方では行わないでください。
  • 早すぎる丸め。 丸めるのは表示時の1回だけにしてください。
  • 単位をまたいだキャッシュ。 キャッシュキーがクエリ文字列を無視していると、オンス価格を期待している箇所でグラムのレスポンスが返されることがあります。キーにはunitとbaseを含めてください。
  • エネルギーに重量単位を適用する。 unitは原油やガスには影響せず、バレル価格を31.1で割っても意味がありません。換算はカテゴリで制限してください。カテゴリは/symbols?details=1ですべてのシンボルについて返されます。

いくつかのプロパティテストで、これらのほとんどをリリース前に発見できます。Node.jsの組み込みテストランナーと上記のconvertPrice関数を使っており、node --testで実行できます:

units.test.mjs
import { test } from "node:test";
import assert from "node:assert/strict";
import { convertPrice } from "./units.mjs";

const PER_OZ = 3997.89; // 例の価格、1トロイオンスあたりUSD

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);
});

ジュエリーの価格を扱う場合、次のステップは純度です。カラット別の金価格の解説では、これらの換算をもとに22Kと18Kの価格を求めます。すべての単位の値はデータ形式ガイドとAPIドキュメントの単位セクションに記載されており、シンボルページでは各市場で取引される単位を確認できます。

ご自身のデータで試してみましょう

無料アカウントを作成すれば、2分以内に最初のリクエストを送信できます。月100リクエスト、クレジットカード不要。

関連記事