Onces troy, grammes et kilogrammes : convertir correctement les prix des métaux précieux
Once troy ou avoirdupois, facteurs exacts pour le gramme et le kilo, paramètre unit de l'API, règles d'arrondi et bugs qui faussent les prix de près de 10 %.
Pourquoi l'unité compte
Les métaux précieux sont cotés à l'once troy presque partout : sur les marchés de gros, dans les listes de prix des négociants et dans les API de prix. Ceux qui achètent et vendent du métal, en revanche, raisonnent en grammes, en kilogrammes, en tolas ou en taels, selon leur pays et ce qu'ils négocient. Tout produit qui affiche un prix de métal contient donc au moins une conversion d'unité, et cette conversion est une source fréquente d'erreurs discrètes et plausibles.
L'erreur classique consiste à traiter une once troy comme une once ordinaire. Les deux diffèrent de près de 10 %, un écart assez grand pour peser sur chaque facture, mais assez petit pour passer inaperçu lors d'une démo. Cet article présente les définitions exactes, les facteurs de conversion, la façon de laisser l'API convertir pour vous, la manière d'arrondir et d'afficher les résultats, ainsi qu'une liste de bugs qui méritent des tests.
Once troy et once avoirdupois
Les deux onces sont définies en grains, et le grain a une définition métrique exacte : 1 grain = 64,79891 milligrammes. Tout le reste en découle :
- Une once troy vaut 480 grains, soit exactement 31,1034768 grammes. C'est l'unité de cotation de l'or, de l'argent, du platine et du palladium.
- Une once avoirdupois, l'once courante pour les denrées et les colis aux États-Unis et au Royaume-Uni, vaut 437,5 grains, soit exactement 28,349523125 grammes.
- Une livre troy compte 12 onces troy (373,2417216 g), alors que la livre avoirdupois compte 16 onces avoirdupois (453,59237 g). L'once troy est donc la plus lourde des deux onces, mais la livre troy la plus légère des deux livres.
| Unité | Grains | Grammes (exact) | Onces troy |
|---|---|---|---|
| Grain | 1 | 0,06479891 | 0,0020833… |
| Pennyweight (dwt) | 24 | 1,55517384 | 0,05 |
| Once avoirdupois | 437,5 | 28,349523125 | 0,9114583… |
| Once troy | 480 | 31,1034768 | 1 |
| Livre troy | 5 760 | 373,2417216 | 12 |
| Livre avoirdupois | 7 000 | 453,59237 | 14,5833… |
Une once troy est environ 9,7 % plus lourde qu'une once avoirdupois (480 ÷ 437,5 ≈ 1,0971). Ce rapport correspond exactement à l'ampleur de l'erreur obtenue quand on confond les deux.
Sauf mention contraire de la source, l'once d'un prix de métal précieux est une once troy, souvent notée oz t ou ozt. Dans MetalAPI, l'unité par défaut est troy_oz, et chaque prix de métal est exprimé par once troy sauf si vous demandez autre chose.
Facteurs de conversion exacts
Toutes ces unités étant définies de façon exacte, les conversions ne demandent aucune approximation. Pour transformer un prix par once troy en prix pour une autre unité, multipliez-le par le nombre d'onces troy que contient cette unité :
prix par unité = prix par once troy × grammes par unité ÷ 31,1034768
| Prix par | Grammes dans une unité | Multiplier le prix à l'once troy par |
|---|---|---|
| Gramme | 1 | 0,0321507466 |
| Kilogramme | 1 000 | 32,1507466 |
| Once avoirdupois | 28,349523125 | 0,9114583333 |
| Livre avoirdupois | 453,59237 | 14,5833333 |
| Tonne métrique | 1 000 000 | 32 150,7466 |
| Tonne courte (2 000 lb) | 907 184,74 | 29 166,6667 |
| Tola | 11,6638038 | 0,375 |
| Pennyweight | 1,55517384 | 0,05 |
Le tola, encore largement utilisé pour l'or en Asie du Sud et dans le Golfe, est défini comme 180 grains : exactement 11,6638038 g, soit trois huitièmes d'once troy. Le tael est moins simple, car son poids dépend du marché : environ 37,4 g dans le commerce de l'or à Hong Kong, 37,5 g à Taïwan et 50 g en Chine continentale. Si vous prenez en charge les taels, faites du poids en grammes une valeur de configuration et indiquez de quel tael il s'agit.
Les lingots d'un kilo constituent un contrôle de cohérence pratique. Un kilogramme représente environ 32,15 onces troy : un prix au kilo doit donc toujours valoir environ 32 fois le prix à l'once. S'il est plus proche de 35 fois, quelqu'un a utilisé le facteur avoirdupois.
Convertir à la main
Si vous disposez déjà d'un prix par once troy, le convertir vous-même ne demande qu'une multiplication. Regroupez les constantes exactes dans un seul module et passez par le gramme, pour que toutes les paires d'unités fonctionnent de la même façon :
// Grammes dans une unité de chaque type. Toutes exactes : 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
};
/** Convertit un prix par unité `from` en prix par unité `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.20875En Python, utilisez Decimal lorsque le résultat finit sur une facture ou dans un registre comptable. requests transmet parse_float au parseur JSON : les prix ne passent donc jamais par un flottant binaire :
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. ex. 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 au prix d'exemple
print(per_kg.quantize(CENT, rounding=ROUND_HALF_UP)) # 128535.15Les taux inverses demandent l'opération inverse. rates.XAU est un nombre d'onces troy par unité de la devise de base : le nombre de grammes par unité de devise vaut donc rates.XAU × 31,1034768, et non ÷. Ce piège est une raison de plus de travailler avec les clés de prix préfixées comme USDXAU et de laisser les clés inverses de côté.
Laisser l'API convertir : le paramètre unit
Vous pouvez aussi demander à MetalAPI l'unité dont vous avez besoin. /latest, les endpoints historiques, /timeframe, /ohlc, /convert et /carat acceptent un paramètre unit : troy_oz (par défaut), gram, kilogram, ounce, pound, metric_ton ou short_ton. Cette requête renvoie l'or et l'argent en euros par gramme :
curl "https://metalapi.com/api/v1/latest?base=EUR¤cies=XAU,XAG&unit=gram" \
-H "X-API-Key: $METALAPI_KEY"Lorsque l'unité n'est pas celle par défaut, la réponse la répète dans un champ unit de premier niveau. Les valeurs ci-dessous sont un exemple tiré de la documentation, pas des prix en direct :
{
"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
}
}L'API utilise les mêmes facteurs exacts que les tableaux ci-dessus, et la clé inverse suit elle aussi l'unité : avec unit=gram, rates.XAU est le nombre de grammes d'or par euro. Quelques règles à connaître :
- Les formes courtes sont acceptées, comme
g,kg,lbettonne.ozdésigne l'once avoirdupois : ne l'utilisez donc jamais comme abréviation de l'once troy. - Une unité inconnue renvoie l'erreur
209(invalid_unit). unitne s'applique qu'aux métaux précieux et industriels. L'énergie reste au baril, au MMBtu ou au gallon, et les devises et cryptos ne sont pas affectées : mélanger des symboles dans une même requête ne pose donc aucun problème.- Les métaux industriels sont eux aussi cotés par once troy par défaut, si bien que tous les métaux se comparent directement. Passez
unit=poundpour le cuivre,unit=metric_tonpour l'aluminium et le zinc, etunit=short_tonpour l'acier afin d'obtenir les unités dans lesquelles ces marchés se négocient.
/convert accepte également unit, ce qui transforme un poids en montant en une seule étape. Cette requête valorise 250 grammes d'or en dollars américains :
curl "https://metalapi.com/api/v1/convert?from=XAU&to=USD&amount=250&unit=gram" \
-H "X-API-Key: $METALAPI_KEY"info.rate est le prix d'un gramme en dollars américains et result la valeur du montant complet. Avec le cours de l'or d'exemple, la réponse ressemble à ceci :
{
"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
}Arrondi et affichage
Les taux arrivent sous forme de nombres JSON comptant jusqu'à 10 chiffres significatifs. Cette précision est là pour que les valeurs dérivées restent exactes : conservez-la donc jusqu'au dernier moment possible.
- Convertissez d'abord, arrondissez en dernier. Arrondir le prix au gramme au centime puis le multiplier par 1 000 pour un lingot d'un kilo transforme une erreur d'arrondi d'un demi-centime en une erreur pouvant atteindre cinq unités monétaires.
- Arrondissez selon la devise. La plupart des devises utilisent deux décimales, le yen japonais aucune et le dinar koweïtien trois. Laissez
Intl.NumberFormatou votre bibliothèque de localisation choisir les valeurs par défaut au lieu de coder deux décimales en dur. - Prévoyez des décimales supplémentaires pour les petits prix. Au prix d'exemple de 53,94 USD l'once troy, l'argent coûte environ 1,73 USD le gramme, et deux décimales masquent l'essentiel de ses variations quotidiennes.
- Utilisez des types décimaux pour les montants.
Decimalen Python,BigDecimalen Java, ou des unités mineures entières dans votre base de données pour tout ce qui est facturé ou comptabilisé. Les flottants binaires conviennent pour les graphiques. - Indiquez l'unité. Placez « par once troy », « par gramme » ou « par kg » à côté de chaque prix. Un simple « par once » est ambigu pour de nombreux lecteurs.
Voici un petit utilitaire qui reprend les décimales standard de la devise depuis Intl et en ajoute éventuellement quelques-unes :
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" or au gramme
formatPrice(1.7342112699117933, "USD", "en-US", 2); // "$1.7342" argent au gramme
formatPrice(110.4064149, "EUR", "de-DE"); // "110,41 €"Tableau de conversion récapitulatif
Le tableau convertit les prix d'exemple utilisés dans la documentation MetalAPI : 3 997,89 USD l'once troy pour l'or et 53,94 USD l'once troy pour l'argent. Ils illustrent le calcul et ne sont pas des prix de marché actuels :
| Prix par | Or (USD) | Argent (USD) |
|---|---|---|
| Once troy | 3 997,89 | 53,94 |
| Gramme | 128,54 | 1,7342 |
| Kilogramme | 128 535,15 | 1 734,21 |
| Tola (11,6638 g) | 1 499,21 | 20,23 |
| Pennyweight (1,5552 g) | 199,89 | 2,697 |
| Livre troy (12 oz t) | 47 974,68 | 647,28 |
| Once avoirdupois | 3 643,91 | 49,16 |
Regardez la dernière ligne. Si une page présente le chiffre avoirdupois comme le prix à l'once, elle sous-estime le prix des métaux précieux de près de 9 %. L'erreur inverse, diviser un prix à l'once troy par 28,35 pour obtenir un prix au gramme, le surestime d'environ 9,7 % : 141,02 au lieu de 128,54 par gramme d'or.
Bugs de conversion courants et comment les tester
La plupart des bugs d'unité relèvent d'une poignée de schémas :
- Diviser par 28,35. Utiliser le facteur avoirdupois pour un prix à l'once troy. Utilisez 31,1034768.
- Traiter `oz` comme l'once troy. Dans MetalAPI, comme dans la plupart des bibliothèques d'unités,
ozest l'once avoirdupois. Les prix des métaux précieux demandenttroy_oz, ou pas deunitdu tout. - Convertir la clé inverse.
rates.XAUest un nombre d'onces par unité de devise, pas un prix. Le convertir en grammes implique de multiplier par 31,1034768, ce qui semble faux à quiconque a l'habitude de diviser. - Convertir deux fois. Demander
unit=grampuis diviser encore par 31,1034768 donne un prix environ 31 fois trop petit. Décidez si la conversion a lieu dans l'API ou dans votre code, jamais les deux. - Arrondir trop tôt. Arrondissez une seule fois, à l'affichage.
- Mélanger les unités dans le cache. Si votre clé de cache ignore la chaîne de requête, une réponse au gramme peut être servie là où un prix à l'once était attendu. Incluez
unitetbasedans la clé. - Appliquer des unités de masse à l'énergie.
unitn'a aucun effet sur le pétrole ou le gaz, et diviser un prix au baril par 31,1 n'a aucun sens. Conditionnez les conversions à la catégorie, que/symbols?details=1renvoie pour chaque symbole.
Quelques tests de propriétés détectent la plupart de ces bugs avant leur mise en production. Ils utilisent le lanceur de tests intégré de Node et la fonction convertPrice présentée plus haut ; exécutez-les avec node --test :
import { test } from "node:test";
import assert from "node:assert/strict";
import { convertPrice } from "./units.mjs";
const PER_OZ = 3997.89; // prix d'exemple, USD par once 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 vous fixez le prix de bijoux, l'étape suivante est le titre : Les prix de l'or par carat expliqués construit les prix 22K et 18K à partir de ces conversions. Le guide des formats de données et la section unités de la documentation de l'API documentent toutes les valeurs d'unité, et la page des symboles indique l'unité dans laquelle se négocie chaque marché.
Essayez avec vos propres données
Créez un compte gratuit et envoyez votre première requête en moins de deux minutes. 100 requêtes par mois, sans carte bancaire.
À lire aussi
API du cours de l'or : le guide complet pour les développeurs
Utiliser une API du cours de l'or : obtenir une clé, l'appeler en curl, JavaScript et Python, bien lire les taux, gérer historique, erreurs, quotas et cache.
Prix de l'or par carat : 24K, 22K, 18K et comment les calculer
Ce que signifient 24K, 22K et 18K, le lien avec les titres 916 et 750, comment calculer le prix au gramme de l'or par carat et l'obtenir via une API.
Cours historiques de l'or et de l'argent par API : 25 ans de données quotidiennes
Obtenez les cours quotidiens de l'or et de l'argent depuis 2000 avec /historical, /timeframe, /change et /ohlc, paginez par année, stockez et tracez vos séries.