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 %
Все статьи
ЗолотоСереброЕдиницы измерения

Тройские унции, граммы и килограммы: как правильно пересчитывать цены на драгоценные металлы

Тройская и торговая унция, точные коэффициенты для граммов и килограммов, параметр unit в API, правила округления и ошибки, искажающие цены почти на 10%.

Автор: MetalAPI Team··9 мин чтения

Почему единица измерения важна

Драгоценные металлы почти везде котируются за тройскую унцию: на оптовых рынках, в прайс-листах дилеров слитков и в API цен. А люди, которые покупают и продают металл, мыслят граммами, килограммами, тола или таэлями — в зависимости от того, где они живут и чем торгуют. Поэтому любой продукт, который показывает людям цену металла, содержит хотя бы один пересчёт единиц, и этот пересчёт — частый источник незаметных, правдоподобно выглядящих ошибок.

Классическая ошибка — считать тройскую унцию обычной унцией. Они различаются почти на 10%: этого достаточно, чтобы разница сказалась в каждом счёте, но слишком мало, чтобы кто-то заметил её на демонстрации. В этой статье — точные определения, коэффициенты пересчёта, способ поручить пересчёт API, правила округления и отображения результатов, а также список ошибок, на которые стоит написать тесты.

Тройская унция и торговая унция (avoirdupois)

Обе унции определены через граны, а у грана есть точное метрическое определение: 1 гран = 64,79891 миллиграмма. Всё остальное следует из него:

  • Тройская унция — это 480 гран, ровно 31,1034768 грамма. Именно в ней оцениваются золото, серебро, платина и палладий.
  • Торговая унция (avoirdupois) — обычная унция для продуктов и посылок в США и Великобритании — это 437,5 грана, ровно 28,349523125 грамма.
  • Тройский фунт состоит из 12 тройских унций (373,2417216 г), а торговый фунт — из 16 торговых унций (453,59237 г). Так что тройская унция тяжелее торговой, а тройский фунт, наоборот, легче торгового.
ЕдиницаГраныГраммы (точно)Тройские унции
Гран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, и цена любого металла указывается за тройскую унцию, если вы не запросили другую единицу.

Точные коэффициенты пересчёта

Поскольку все эти единицы определены точно, для пересчёта не нужны приближения. Чтобы перевести цену за тройскую унцию в цену за другую единицу, умножьте её на количество тройских унций в этой единице:

цена за единицу = цена за тройскую унцию × граммов в единице ÷ 31,1034768

Цена заГраммов в единицеУмножьте цену за тройскую унцию на
Грамм10,0321507466
Килограмм1 00032,1507466
Торговую унцию28,3495231250,9114583333
Торговый фунт453,5923714,5833333
Метрическую тонну1 000 00032 150,7466
Короткую тонну (2 000 фунтов)907 184,7429 166,6667
Тола11,66380380,375
Пеннивейт1,555173840,05

Тола, которая по-прежнему широко используется для золота в Южной Азии и странах Персидского залива, определяется как 180 гран: ровно 11,6638038 г, или три восьмых тройской унции. С таэлем всё не так аккуратно, потому что его масса зависит от рынка: около 37,4 г в торговле золотом в Гонконге, 37,5 г на Тайване и 50 г в континентальном Китае. Если вы поддерживаете таэли, сделайте массу в граммах параметром конфигурации и указывайте, какой именно таэль имеется в виду.

Килограммовые слитки — удобная проверка на здравый смысл. В килограмме около 32,15 тройской унции, поэтому цена за килограмм всегда должна быть примерно в 32 раза выше цены за унцию. Если разница ближе к 35 разам, кто-то использовал коэффициент торговой унции.

Пересчёт вручную

Если у вас уже есть цена за тройскую унцию, пересчитать её самостоятельно можно одним умножением. Храните точные константы в одном модуле и пересчитывайте через граммы — тогда любая пара единиц работает одинаково:

units.mjs
// Grams in one of each unit. All exact: 1 grain = 64.79891 mg.
const GRAMS_PER_UNIT = {
  troy_oz: 31.1034768, // 480 grains
  gram: 1,
  kilogram: 1000,
  ounce: 28.349523125, // avoirdupois, 437.5 grains
  pound: 453.59237, // avoirdupois, 7,000 grains
  metric_ton: 1_000_000,
  short_ton: 907_184.74, // 2,000 lb
  tola: 11.6638038, // 180 grains
  pennyweight: 1.55517384, // 24 grains
};

/** Convert a price per `from` unit into a price per `to` unit. */
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-парсер, поэтому цены никогда не проходят через двоичные числа с плавающей точкой:

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"]  # e.g. 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 at the example price
print(per_kg.quantize(CENT, rounding=ROUND_HALF_UP))  # 128535.15

Для обратных курсов нужна противоположная операция. rates.XAU — это количество тройских унций на одну единицу базовой валюты, поэтому количество граммов на единицу валюты равно rates.XAU × 31,1034768, а не ÷. Эта ловушка — ещё одна причина работать с ключами цен с префиксом, такими как USDXAU, и не трогать обратные ключи.

Пересчёт на стороне API: параметр unit

Можно также запросить у MetalAPI нужную единицу. /latest, исторические эндпоинты, /timeframe, /ohlc, /convert и /carat принимают параметр unit: troy_oz (по умолчанию), gram, kilogram, ounce, pound, metric_ton или short_ton. Этот запрос возвращает цены золота и серебра в евро за грамм:

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 — это граммы золота за один евро. Несколько правил, которые стоит знать:

  • Принимаются краткие формы, например g, kg, lb и tonne. oz означает торговую унцию, поэтому никогда не используйте его как сокращение для тройской.
  • Неизвестная единица возвращает ошибку 209 (invalid_unit).
  • unit применяется только к драгоценным и промышленным металлам. Энергоносители остаются в баррелях, MMBtu или галлонах, а валюты и криптовалюты не затрагиваются, так что смешивать символы в одном запросе безопасно.
  • Промышленные металлы по умолчанию тоже котируются за тройскую унцию, поэтому все металлы можно напрямую сравнивать. Передайте unit=pound для меди, unit=metric_ton для алюминия и цинка и unit=short_ton для стали, чтобы получить единицы, в которых торгуют на этих рынках.

/convert тоже принимает unit, что позволяет одним шагом превратить массу в деньги. Этот запрос оценивает 250 граммов золота в долларах США:

Стоимость 250 г золота
curl "https://metalapi.com/api/v1/convert?from=XAU&to=USD&amount=250&unit=gram" \
  -H "X-API-Key: $METALAPI_KEY"

info.rate — цена одного грамма в долларах США, а 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 для килограммового слитка, ошибка округления в полцента превратится в ошибку до пяти денежных единиц.
  • Округляйте с учётом валюты. В большинстве валют два знака после запятой, в японской иене — ни одного, а в кувейтском динаре — три. Позвольте Intl.NumberFormat или вашей библиотеке локализации выбрать значения по умолчанию, вместо того чтобы жёстко прописывать два знака.
  • Оставляйте больше знаков для малых цен. При примерной цене 53,94 USD за тройскую унцию серебро стоит около 1,73 USD за грамм, и два знака после запятой скрывают большую часть его ежедневных колебаний.
  • Используйте десятичные типы для денег. Decimal в Python, BigDecimal в Java или целые числа в минимальных единицах валюты в базе данных — для всего, что выставляется в счёте или проводится в учёте. Для графиков двоичные числа с плавающей точкой вполне подходят.
  • Подписывайте единицу. Ставьте «за тройскую унцию», «за грамм» или «за кг» рядом с каждой ценой. Просто «за унцию» многие читатели поймут неоднозначно.

Небольшая вспомогательная функция, которая берёт стандартное число знаков валюты из 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"   gold per gram
formatPrice(1.7342112699117933, "USD", "en-US", 2); // "$1.7342"   silver per gram
formatPrice(110.4064149, "EUR", "de-DE"); // "110,41 €"

Таблица пересчёта

В таблице пересчитаны примерные цены из документации MetalAPI: 3 997,89 USD за тройскую унцию для золота и 53,94 USD за тройскую унцию для серебра. Они иллюстрируют арифметику и не являются текущими рыночными ценами:

Цена заЗолото (USD)Серебро (USD)
Тройскую унцию3 997,8953,94
Грамм128,541,7342
Килограмм128 535,151 734,21
Тола (11,6638 г)1 499,2120,23
Пеннивейт (1,5552 г)199,892,697
Тройский фунт (12 oz t)47 974,68647,28
Торговую унцию3 643,9149,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:

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

const PER_OZ = 3997.89; // example price, USD per troy ounce

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 описывают все значения единиц, а на странице символов указано, в какой единице торгуется каждый рынок.

Попробуйте на своих данных

Создайте бесплатный аккаунт и отправьте первый запрос меньше чем за две минуты. 100 запросов в месяц, без банковской карты.

Читайте также