MetalAPI
XAU3997,89−1,54 %XAG53,936−1,51 %XPT1554,47−0,83 %XPD1047,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 %ETH2329,36−1,13 %
Todos los artículos
OroPlataUnidades

Onzas troy, gramos y kilogramos: cómo convertir bien los precios de los metales preciosos

Onza troy frente a onza avoirdupois, factores exactos para gramos y kilogramos, el parámetro unit de la API, el redondeo y los errores que desvían los precios casi un 10 %.

Por MetalAPI Team··9 min de lectura

Por qué importa la unidad

Los metales preciosos se cotizan por onza troy casi en todas partes: en los mercados mayoristas, en las listas de precios de los distribuidores de lingotes y en las API de precios. En cambio, quienes compran y venden metal piensan en gramos, kilogramos, tolas o taeles, según dónde vivan y qué negocien. Por eso, cualquier producto que muestre un precio de metal a las personas contiene al menos una conversión de unidades, y esa conversión es una fuente habitual de errores silenciosos y de apariencia verosímil.

El error clásico es tratar una onza troy como una onza normal. Las dos difieren casi un 10 %, lo bastante para importar en cada factura, pero lo bastante poco para que nadie lo note en una demo. Este artículo cubre las definiciones exactas, los factores de conversión, cómo dejar que la API convierta por ti, cómo redondear y mostrar los resultados, y una lista de errores para los que vale la pena escribir pruebas.

Onza troy frente a onza avoirdupois

Ambas onzas se definen en granos, y el grano tiene una definición métrica exacta: 1 grano = 64,79891 miligramos. Todo lo demás se deduce de ahí:

  • Una onza troy son 480 granos, exactamente 31,1034768 gramos. Es la unidad en la que se cotizan el oro, la plata, el platino y el paladio.
  • Una onza avoirdupois, la onza cotidiana para alimentos y paquetes en Estados Unidos y el Reino Unido, son 437,5 granos, exactamente 28,349523125 gramos.
  • Una libra troy tiene 12 onzas troy (373,2417216 g), mientras que la libra avoirdupois tiene 16 onzas avoirdupois (453,59237 g). Así que la onza troy es la onza más pesada, pero la libra troy es la libra más ligera.
UnidadGranosGramos (exactos)Onzas troy
Grano10,064798910,0020833…
Pennyweight (dwt)241,555173840,05
Onza avoirdupois437,528,3495231250,9114583…
Onza troy48031,10347681
Libra troy5760373,241721612
Libra avoirdupois7000453,5923714,5833…

Una onza troy es aproximadamente un 9,7 % más pesada que una onza avoirdupois (480 ÷ 437,5 ≈ 1,0971). Esa proporción es exactamente el tamaño del error que se produce cuando se confunden las dos.

Salvo que una fuente diga lo contrario, la onza de un precio de metales preciosos es una onza troy, a menudo escrita oz t u ozt. En MetalAPI la unidad por defecto es troy_oz, y todos los precios de los metales son por onza troy a menos que pidas otra cosa.

Factores de conversión exactos

Como todas estas unidades tienen una definición exacta, las conversiones no necesitan aproximaciones. Para convertir un precio por onza troy en un precio por otra unidad, multiplica por el número de onzas troy que contiene esa unidad:

precio por unidad = precio por onza troy × gramos por unidad ÷ 31,1034768

Precio porGramos en una unidadMultiplica el precio por onza troy por
Gramo10,0321507466
Kilogramo100032,1507466
Onza avoirdupois28,3495231250,9114583333
Libra avoirdupois453,5923714,5833333
Tonelada métrica1.000.00032.150,7466
Tonelada corta (2000 lb)907.184,7429.166,6667
Tola11,66380380,375
Pennyweight1,555173840,05

La tola, todavía muy usada para el oro en el sur de Asia y el Golfo, se define como 180 granos: exactamente 11,6638038 g, o tres octavos de onza troy. El tael es menos regular, porque su peso depende del mercado: unos 37,4 g en el comercio de oro de Hong Kong, 37,5 g en Taiwán y 50 g en China continental. Si admites taeles, haz que el peso en gramos sea un valor de configuración e indica a qué tael te refieres.

Los lingotes de un kilo son una comprobación rápida muy práctica. Un kilogramo son unas 32,15 onzas troy, así que un precio por kilo siempre debería ser aproximadamente 32 veces el precio por onza. Si se acerca más a 35 veces, alguien ha usado el factor avoirdupois.

Convertir a mano

Si ya tienes un precio por onza troy, convertirlo tú mismo es una sola multiplicación. Guarda las constantes exactas en un único módulo y convierte pasando por los gramos, para que cualquier par de unidades funcione igual:

units.mjs
// Gramos en una unidad de cada tipo. Todos exactos: 1 grano = 64.79891 mg.
const GRAMS_PER_UNIT = {
  troy_oz: 31.1034768, // 480 granos
  gram: 1,
  kilogram: 1000,
  ounce: 28.349523125, // avoirdupois, 437.5 granos
  pound: 453.59237, // avoirdupois, 7,000 granos
  metric_ton: 1_000_000,
  short_ton: 907_184.74, // 2,000 lb
  tola: 11.6638038, // 180 granos
  pennyweight: 1.55517384, // 24 granos
};

/** Convierte un precio por unidad `from` en un precio por unidad `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

En Python, usa Decimal cuando el resultado acabe en una factura o en un libro contable. requests pasa parse_float al analizador de JSON, así que los precios nunca pasan por un número de coma flotante binario:

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"]  # p. ej., 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 con el precio de ejemplo
print(per_kg.quantize(CENT, rounding=ROUND_HALF_UP))  # 128535.15

Las cotizaciones inversas requieren la operación contraria. rates.XAU son onzas troy por cada unidad de la divisa base, así que los gramos por unidad de divisa son rates.XAU × 31,1034768, no ÷. Esa trampa es un motivo más para trabajar con las claves de precio con prefijo, como USDXAU, y dejar de lado las claves inversas.

Dejar que la API convierta: el parámetro unit

También puedes pedir a MetalAPI la unidad que necesitas. /latest, los endpoints históricos, /timeframe, /ohlc, /convert y /carat aceptan un parámetro unit: troy_oz (por defecto), gram, kilogram, ounce, pound, metric_ton o short_ton. Esta solicitud devuelve el oro y la plata en euros por gramo:

bash
curl "https://metalapi.com/api/v1/latest?base=EUR&currencies=XAU,XAG&unit=gram" \
  -H "X-API-Key: $METALAPI_KEY"

Cuando la unidad no es la predeterminada, la respuesta la repite en un campo unit de nivel superior. Los valores siguientes son un ejemplo de la documentación, no precios en tiempo real:

Respuesta de ejemplo
{
  "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
  }
}

La API usa los mismos factores exactos que las tablas anteriores, y la clave inversa también sigue la unidad: con unit=gram, rates.XAU son gramos de oro por euro. Algunas reglas que conviene conocer:

  • Se aceptan formas abreviadas como g, kg, lb y tonne. oz significa la onza avoirdupois, así que nunca la uses como abreviatura de onza troy.
  • Una unidad desconocida devuelve el error 209 (invalid_unit).
  • unit solo se aplica a los metales preciosos e industriales. La energía sigue cotizándose por barril, MMBtu o galón, y las divisas y las criptomonedas no se ven afectadas, así que mezclar símbolos en una misma solicitud es seguro.
  • Los metales industriales también se cotizan por onza troy de forma predeterminada, así que todos los metales se pueden comparar directamente. Pasa unit=pound para el cobre, unit=metric_ton para el aluminio y el zinc, y unit=short_ton para el acero, y obtendrás las unidades en las que se negocian esos mercados.

/convert también acepta unit, lo que convierte un peso en dinero en un solo paso. Esto valora 250 gramos de oro en dólares estadounidenses:

Valorar 250 g de oro
curl "https://metalapi.com/api/v1/convert?from=XAU&to=USD&amount=250&unit=gram" \
  -H "X-API-Key: $METALAPI_KEY"

info.rate es el precio de un gramo en dólares estadounidenses y result es el valor de la cantidad completa. Con el precio del oro de ejemplo, la respuesta tiene este aspecto:

Respuesta de ejemplo
{
  "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
}

Redondeo y presentación

Las cotizaciones llegan como números JSON con hasta 10 cifras significativas. Esa precisión existe para que los valores derivados sean exactos, así que consérvala hasta el último momento posible:

  • Convierte primero, redondea al final. Redondear el precio por gramo a céntimos y después multiplicarlo por 1000 para un lingote de un kilo convierte un error de redondeo de medio céntimo en un error de hasta cinco unidades monetarias.
  • Redondea según la divisa. La mayoría de las divisas usan dos decimales, el yen japonés ninguno y el dinar kuwaití tres. Deja que Intl.NumberFormat o tu biblioteca de localización elijan los valores predeterminados en lugar de fijar dos a mano.
  • Admite más decimales en los precios pequeños. Con el precio de ejemplo de 53,94 USD por onza troy, la plata cuesta unos 1,73 USD por gramo, y con dos decimales se pierde la mayor parte de su movimiento diario.
  • Usa tipos decimales para el dinero. Decimal en Python, BigDecimal en Java, o unidades monetarias mínimas enteras en tu base de datos para todo lo que se facture o se contabilice. Los números de coma flotante binarios sirven para los gráficos.
  • Indica la unidad. Pon “por onza troy”, “por gramo” o “por kg” junto a cada precio. Un simple “por onza” resulta ambiguo para muchos lectores.

Una pequeña función auxiliar que toma de Intl los decimales estándar de la divisa y, opcionalmente, añade algunos más:

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"   oro por gramo
formatPrice(1.7342112699117933, "USD", "en-US", 2); // "$1.7342"   plata por gramo
formatPrice(110.4064149, "EUR", "de-DE"); // "110,41 €"

Tabla de conversión de un vistazo

La tabla convierte los precios de ejemplo que se usan en la documentación de MetalAPI, 3997,89 USD por onza troy para el oro y 53,94 USD por onza troy para la plata. Ilustran la aritmética y no son precios de mercado actuales:

Precio porOro (USD)Plata (USD)
Onza troy3997,8953,94
Gramo128,541,7342
Kilogramo128.535,151734,21
Tola (11,6638 g)1499,2120,23
Pennyweight (1,5552 g)199,892,697
Libra troy (12 oz t)47.974,68647,28
Onza avoirdupois3643,9149,16

Fíjate en la última fila. Si una página presenta la cifra avoirdupois como el precio por onza, subestima el precio del lingote en casi un 9 %. El error contrario, dividir un precio por onza troy entre 28,35 para obtener un precio por gramo, lo sobrestima en un 9,7 % aproximadamente: 141,02 en lugar de 128,54 por gramo de oro.

Errores de conversión habituales y cómo detectarlos con pruebas

La mayoría de los errores de unidades siguen unos pocos patrones:

  • Dividir entre 28,35. Usar el factor avoirdupois para un precio por onza troy. Usa 31,1034768.
  • Tratar `oz` como onza troy. En MetalAPI, como en la mayoría de las bibliotecas de unidades, oz es la onza avoirdupois. Los precios de lingotes necesitan troy_oz, o ningún unit.
  • Convertir la clave inversa. rates.XAU son onzas por unidad de divisa, no un precio. Convertirla a gramos significa multiplicar por 31,1034768, lo que parece un error a cualquiera acostumbrado a dividir.
  • Convertir dos veces. Pedir unit=gram y después volver a dividir entre 31,1034768 da un precio unas 31 veces demasiado pequeño. Decide si la conversión se hace en la API o en tu código, nunca en ambos.
  • Redondear demasiado pronto. Redondea una sola vez, al mostrar el valor.
  • Compartir la caché entre unidades. Si la clave de tu caché ignora la cadena de consulta, se puede servir una respuesta por gramo donde se esperaba un precio por onza. Incluye unit y base en la clave.
  • Aplicar unidades de peso a la energía. unit no tiene efecto sobre el petróleo ni el gas, y dividir un precio por barril entre 31,1 no tiene sentido. Limita las conversiones según la categoría, que /symbols?details=1 devuelve para cada símbolo.

Unas pocas pruebas de propiedades detectan la mayoría de estos errores antes de que lleguen a producción. Usan el ejecutor de pruebas integrado de Node y la función convertPrice de arriba; ejecútalas con 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; // precio de ejemplo, USD por onza troy

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

Si pones precio a joyas, el siguiente paso es la pureza: Precios del oro por quilate construye los precios de 22K y 18K sobre estas conversiones. La guía de formatos de datos y la sección de unidades de la documentación de la API documentan todos los valores de unidad, y la página de símbolos muestra la unidad en la que se negocia cada mercado.

Pruébalo con tus propios datos

Crea una cuenta gratuita y haz tu primera solicitud en menos de dos minutos. 100 solicitudes al mes, sin tarjeta de crédito.

Sigue leyendo