Get China Gold SGE PM (XAUCHNPM) - Per Gram Historical Prices using this API — fetch daily time series with start/end dates
If you need China Gold SGE PM (XAUCHNPM) prices per gram for backfilling historical charts, running portfolio analytics, or pricing jewelry in RMB-marked markets, you can fetch a clean daily time series between two dates using Metals-API. This guide shows how to query the XAUCHNPM symbol, normalize from the default “per troy ounce” unit to “per gram,” and build a robust pipeline that handles weekends, holidays, and caching—all with a couple of API calls and some lightweight post-processing. You’ll find endpoint-specific implementation tips, examples, and common pitfalls so you can go from idea to production quickly. For full details on parameters and supported instruments, see the Metals-API Documentation and the always up-to-date Metals-API Supported Symbols. To get started right away, visit the Metals-API Website and grab a free API key.
Why the China Gold SGE PM (XAUCHNPM) time series matters
The Shanghai Gold Exchange (SGE) PM benchmark reflects a critical regional price discovery process for gold in China. For developers and analysts, the XAUCHNPM symbol gives direct programmatic access to that reference via Metals-API. Whether you are building a risk model, an automated pricing engine, or a research workflow, historical XAUCHNPM is essential for:
- Backfilling charts for dashboards and investor reports.
- Computing moving averages, realized volatility, and drawdowns.
- Running factor studies or regressions against macro variables.
- Pricing jewelry and industrial inputs against a regionally relevant benchmark.
- Arbitrage or basis analysis between SGE PM and other benchmarks.
Core workflow: daily XAUCHNPM per gram with start/end dates
Metals-API returns exchange rates by default relative to USD and “per troy ounce.” The XAUCHNPM rate denotes how much XAUCHNPM you get for 1 USD, not the price in USD per ounce. That’s important for unit handling and downstream conversions.
To fetch daily historical values between two dates, use the Time-series endpoint for XAUCHNPM. Then convert the resulting troy-ounce-based quantity into per gram. Finally, normalize the time zone and resample or forward-fill missing dates around weekends and holidays as needed.
Endpoints used in this guide
- Time-series endpoint: daily values between start_date and end_date.
- Historical endpoint: point-in-time value for a single date (useful for rechecks, data repairs, or point lookups).
- Latest endpoint: most recent available value to top off your historical series.
For broader functionality including OHLC, Bid/Ask, and conversion features, refer to the Metals-API Documentation. For symbol verification and metadata, see the Metals-API Supported Symbols.
Unit handling: per troy ounce vs per gram
By default, Metals-API reports metals units as “per troy ounce.” To quote per gram:
- 1 troy ounce = 31.1034768 grams.
- If the response unit is “per troy ounce,” then per-gram conversion is: value_per_gram = value_per_troy_ounce / 31.1034768.
Always store the original unit alongside the rate in your data model. This prevents confusion when mixing symbols or reusing series with different unit baselines (e.g., carats or grain-based data if you later expand). If you normalize to grams across your system, record the conversion factor used and the version of your conversion utility to ensure reproducibility.
For more background on troy ounces, see this troy ounce explainer on Investopedia.
Authentication and request structure
All requests require your access_key. Keep it secret—treat it like a password. Do not embed it directly in client-side code shipped to browsers. Instead, route requests through a backend and inject the key server-side.
- Add your access_key as a query parameter: access_key=YOUR_KEY.
- Use HTTPS only.
- Rotate or revoke keys if you suspect exposure.
Get an API key in minutes at the Metals-API Website.
Time-series endpoint for XAUCHNPM
The time-series endpoint provides daily historical rates across a continuous date range. This is the primary tool to fetch XAUCHNPM per-day values between start_date and end_date for charting, backtests, and analytics.
Purpose and functionality
- Request: a start_date, end_date, and symbol XAUCHNPM.
- Response: a map of ISO dates to rate objects containing XAUCHNPM values.
- Unit: returned “per troy ounce” by default; convert to grams in your application.
- Base: USD by default, reflected in the response’s “base” field.
Example cURL request
curl "https://metals-api.com/api/timeseries?access_key=YOUR_KEY&start_date=2026-09-14&end_date=2026-09-21&symbols=XAUCHNPM"
Example JSON responses
Success with data (daily keys present):
{
"success": true,
"timeseries": true,
"start_date": "2026-09-14",
"end_date": "2026-09-21",
"base": "USD",
"rates": {
"2026-09-14": { "XAUCHNPM": 0.0000 },
"2026-09-15": { "XAUCHNPM": 0.0000 },
"2026-09-16": { "XAUCHNPM": 0.0000 },
"2026-09-17": { "XAUCHNPM": 0.0000 },
"2026-09-18": { "XAUCHNPM": 0.0000 },
"2026-09-19": { "XAUCHNPM": null },
"2026-09-20": { "XAUCHNPM": null },
"2026-09-21": { "XAUCHNPM": 0.0000 }
},
"unit": "per troy ounce"
}
Note: values null or missing on weekends/holidays are realistic. Treat them as non-trading days; forward-fill only if your analysis requires a continuous calendar series.
Error: invalid or missing access key:
{
"success": false,
"error": {
"code": 101,
"type": "invalid_access_key",
"info": "You have not supplied a valid API Access Key."
}
}
Response fields you’ll use
- success: boolean to gate downstream processing.
- timeseries: confirms this is a time-series response.
- start_date, end_date: echo of your query inputs; validate against your requested window.
- base: usually “USD” (default). Store it to avoid unit/currency ambiguity later.
- rates: an object keyed by YYYY-MM-DD where each value contains an XAUCHNPM field. This value is quoted as “XAUCHNPM per 1 USD” and the unit is stated in unit.
- unit: “per troy ounce” by default—convert to grams if needed.
Converting to per gram
- Let oz_val = rates[date]["XAUCHNPM"].
- per_gram_val = oz_val / 31.1034768.
Keep double precision throughout your pipeline and round only at display time.
Per-gram time series in Python
import os
import json
import math
import urllib.request
from datetime import datetime
API_KEY = os.environ.get("METALS_API_KEY") # best practice: inject via env var
START = "2026-09-14"
END = "2026-09-21"
SYMBOL = "XAUCHNPM"
OZ_TO_G = 31.1034768
url = (
"https://metals-api.com/api/timeseries"
f"?access_key={API_KEY}"
f"&start_date={START}&end_date={END}"
f"&symbols={SYMBOL}"
)
with urllib.request.urlopen(url) as resp:
data = json.loads(resp.read().decode("utf-8"))
if not data.get("success"):
raise RuntimeError(f"API error: {data.get('error')}")
unit = data.get("unit")
if unit != "per troy ounce":
raise ValueError(f"Unexpected unit: {unit}; verify conversion logic.")
series_g = []
for day, obj in sorted(data["rates"].items()):
val_oz = obj.get(SYMBOL)
if val_oz is None:
# Non-trading day or missing; store None and handle later.
series_g.append((day, None))
else:
series_g.append((day, val_oz / OZ_TO_G))
# Optional: forward-fill missing days for chart continuity
last = None
series_g_ffill = []
for day, v in series_g:
if v is not None:
last = v
series_g_ffill.append((day, last))
print({
"base": data.get("base"),
"unit_in": unit,
"unit_out": "per gram",
"start_date": data.get("start_date"),
"end_date": data.get("end_date"),
"points": len(series_g_ffill)
})
What developers often miss
- Unit confusion: The numeric value is not USD per ounce; it’s “XAUCHNPM per 1 USD.” If you want an inverted “USD per troy ounce,” you would invert the rate. For per gram, stay consistent and document your transformation.
- Time zones: The date key is UTC-normalized. SGE sessions and PM fixes are local to China Standard Time. If your analysis requires session alignment, map each UTC date to the corresponding local-close calendar date.
- Weekends/holidays: Expect missing or null values; decide whether to forward-fill, leave gaps, or use business-day calendars only.
- Caching: Persist responses keyed by (endpoint, start_date, end_date, symbol) to avoid redundant calls and stay within your plan’s request budget.
Historical endpoint for single-date checks
Use the Historical endpoint to retrieve the XAUCHNPM value for a specific date. This is useful for:
- Data repair—replacing gaps without re-pulling a long range.
- Sanity checks in unit tests (e.g., verify one known day).
- Backfill of a single out-of-sync partition.
Purpose and functionality
- Query a YYYY-MM-DD date for a point-in-time snapshot.
- Same response shape as “latest,” but for the date requested.
Example cURL request
curl "https://metals-api.com/api/2026-09-20?access_key=YOUR_KEY&symbols=XAUCHNPM"
Example JSON responses
Success on a trading day:
{
"success": true,
"timestamp": 1789863290,
"base": "USD",
"date": "2026-09-20",
"rates": { "XAUCHNPM": 0.0000 },
"unit": "per troy ounce"
}
Holiday/weekend (symbol null or missing):
{
"success": true,
"timestamp": 1789863290,
"base": "USD",
"date": "2026-09-19",
"rates": { "XAUCHNPM": null },
"unit": "per troy ounce"
}
Error (invalid date format):
{
"success": false,
"error": {
"code": 301,
"type": "invalid_date",
"info": "You have specified an invalid date."
}
}
Field notes
- timestamp: Unix epoch for the snapshot; store it if you need provenance or reconciliation.
- date: The target date requested; ensure it matches your query.
- rates.XAUCHNPM: The metals value to convert to grams or invert if you prefer “USD per unit.”
- unit: Always check before applying per-gram conversion.
Latest endpoint to top off the series
The Latest endpoint provides the most recent available value. It’s helpful for appending the latest point after you backfilled a historical range.
Example cURL request
curl "https://metals-api.com/api/latest?access_key=YOUR_KEY&symbols=XAUCHNPM"
Example JSON responses
Success:
{
"success": true,
"timestamp": 1789949690,
"base": "USD",
"date": "2026-09-21",
"rates": { "XAUCHNPM": 0.0000 },
"unit": "per troy ounce"
}
Temporary data unavailability (rare but possible):
{
"success": true,
"timestamp": 1789949690,
"base": "USD",
"date": "2026-09-21",
"rates": {},
"unit": "per troy ounce"
}
Practical use
- Run a nightly batch with time-series for previous business days.
- Call latest during market hours or after the PM fix to append today’s value.
- Normalize to per gram and store both the raw and derived values.
Data modeling and transformations
Recommended schema
- symbol: "XAUCHNPM"
- as_of_date: UTC date string (YYYY-MM-DD)
- base_currency: "USD" (store explicitly, do not assume)
- unit_in: "per troy ounce"
- rate_in: numeric (as returned)
- unit_out: "per gram"
- rate_out: numeric (rate_in / 31.1034768)
- source: "metals-api/timeseries|historical|latest"
- timestamp: Unix epoch from response
- pipeline_version: your app version for reproducibility
Inversion vs direct usage
The rate represents “XAUCHNPM per 1 USD” under a USD base. If you want “USD per troy ounce,” invert the value. For per gram pricing in USD, combine inversion and gram conversion carefully:
- Let r = rates["XAUCHNPM"].
- USD per troy ounce = 1 / r (if r > 0).
- USD per gram = (1 / r) / 31.1034768.
Document your choice (per USD vs per unit) and keep it consistent across charts and analytics.
Caching, retries, and rate management
- Cache keys: Include endpoint, date range, symbol, and a checksum of query parameters.
- Expiry: Historical responses can be cached for long periods; latest can be cached for minutes depending on your update cadence.
- Retries: Implement exponential backoff for transient network errors. Do not retry on client errors (4xx).
- Backfills: Schedule outside peak usage; batch long periods into fewer calls if permitted.
Handling weekends, holidays, and gaps
- Expect null or missing values on non-trading days.
- Use a trading calendar aligned with SGE PM if strict session fidelity is required.
- Forward-fill for charts that require continuity; mark imputed points in metadata.
- Never interpolate across long closures without labeling derived data.
For SGE calendars and benchmark details, see the Shanghai Gold Exchange official site.
Security best practices
- Keep access keys on the server; never ship them in client code.
- Use a proxy or backend service to call Metals-API and return only the needed data to clients.
- Log minimal details; avoid logging full URLs containing access_key.
- Rotate keys periodically and upon suspicion of exposure.
Validation, error handling, and monitoring
- Validate response.success before parsing rates.
- Check unit each call; alert on unexpected changes.
- Guard against null or missing XAUCHNPM fields per date.
- Implement dead-letter queues for failed date segments; reprocess later.
- Telemetry: track API latency, error rates, and cache hit ratio to optimize performance and cost.
Architecture patterns
Batch backfill
- Nightly job pulls the prior day’s XAUCHNPM via Historical endpoint.
- Weekly job reconciles the last month via Time-series to catch any late adjustments.
Near real-time chart enrichment
- On page load, fetch precomputed series from your database.
- Call Latest endpoint server-side to append the most recent point.
- Return JSON to clients; avoid exposing the access_key.
Research notebook integration
- Create a thin client wrapper with request signing, retries, and pagination helpers.
- Expose a function get_xauchnpm_timeseries(start, end, unit="g").
- Cache to local parquet with schema and unit metadata.
Performance considerations
- Minimize date range per request to what your analysis needs.
- Parallelize across symbols judiciously; for this article focus remains on XAUCHNPM.
- Compress storage by normalizing to float32 if precision permits; retain float64 for financial-grade calculations.
- Precompute per-gram series once and reuse across services.
Data analytics on XAUCHNPM
- Compute rolling statistics (mean, std, min, max) using business-day windows.
- Create alerts when today’s per-gram value deviates from the 20-day average by a threshold.
- Study relationships with RMB FX, local rates, or commodity indices.
- Segment intrayear seasonality; align to Chinese holiday calendars where relevant.
For further macro context, you may also consult market references such as the CME Group metals overview for comparative studies, while keeping your primary series from XAUCHNPM.
Testing and QA
- Unit tests: verify conversion math (ounce-to-gram), JSON parsing, and null handling.
- Golden files: snapshot a known two-week window and compare aggregates (min/max/count of non-nulls).
- Property tests: no negative rates, unit string matches expectation, date keys sorted and unique.
Compliance and auditability
- Record request parameters and response metadata (date range, base, unit, timestamp, success) in audit logs.
- Version your transformation code; store the version tag alongside datasets produced.
- Add checksums for raw responses to detect accidental corruption.
End-to-end example: backfill and serve per-gram XAUCHNPM
- Backend task calls Time-series for a given quarter with symbols=XAUCHNPM.
- Parse JSON, validate success, confirm unit is per troy ounce.
- Convert each daily XAUCHNPM value to grams; keep nulls for non-trading days.
- Store raw and transformed series in your warehouse with appropriate partitioning (date=YYYY-MM-DD, symbol=XAUCHNPM).
- Expose a read-optimized API to frontends, returning only per-gram values and dates.
- Nightly job uses Historical to reconcile the latest business day if your time-series job is weekly.
- Intraday top-off: call Latest after the PM fix, append to your series, and invalidate page caches.
Practical tips for resiliency
- Graceful degradation: If Latest is temporarily unavailable, fall back to the previous valid close and label the point as stale in the UI.
- Idempotency: Store a hash of (date, symbol, rate_in, unit) to avoid duplicate inserts.
- Observability: Trigger alerts on missing fields, unexpected unit changes, or anomalous rate jumps.
Complete request + quick inspection
One-liner to fetch and inspect metadata
curl "https://metals-api.com/api/timeseries?access_key=YOUR_KEY&start_date=2026-09-14&end_date=2026-09-21&symbols=XAUCHNPM" \
| python -c "import sys,json;d=json.load(sys.stdin);print(d.get('success'), d.get('base'), d.get('unit'), len(d.get('rates',{})))"
Use this during debugging to confirm success, base, unit, and the count of returned days before diving into per-date values.
Linking symbol discovery and docs
- Confirm instrument availability and naming on the Metals-API Supported Symbols page.
- Review endpoint parameters (start_date, end_date, symbols) and response schemas in the Metals-API Documentation.
- Register for your key at the Metals-API Website and start testing within minutes.
Troubleshooting guide
Common errors
- invalid_access_key: Verify the key, rotate if compromised, store as an environment variable.
- invalid_date: Ensure YYYY-MM-DD format; mind zero-padding.
- Empty rates object: Market closure or temporary data unavailability—retry later or fetch neighboring days with Historical for validation.
- Unit mismatch: Always check unit; if it changes, route to a quarantine path and alert.
Data anomalies
- Nulls in the middle of a week: Check SGE holidays; don’t assume Western calendars.
- Sharp jumps: Validate against external references; consider a human-in-the-loop check for production pricing.
- Timezone off-by-one: Align UTC dates to China Standard Time close if required by your reporting rules.
Security considerations specific to this workflow
- Server-side aggregation: Never expose raw API endpoints or your access_key to browsers.
- ACLs: Restrict who can read/write your metals datasets and transformation code.
- Integrity checks: Validate HTTPS certificates, pin domains where possible.
Innovation with gold data: from benchmarks to digital transformation
Programmatic access to XAUCHNPM enables modern price discovery workflows that merge traditional benchmark signals with digital analytics pipelines. Developers can integrate the China PM fix into fintech pricing engines, portfolio risk systems, and ERP modules that dynamically quote per-gram costs. With historical and latest rates at hand, you can blend benchmark data into automated hedging, dynamic product pricing, and quant research—accelerating the digital transformation of precious metals and enabling new data-driven insights at scale.
Call to action
Ready to build your per-gram China Gold SGE PM time series? Get your free API key at the Metals-API Website, verify the XAUCHNPM symbol on the Metals-API Supported Symbols page, and review endpoint specifics in the Metals-API Documentation. Then implement the time-series workflow above to produce production-grade, per-gram historical datasets with confidence.
FAQ
What does XAUCHNPM represent?
It’s the China Gold SGE PM benchmark symbol available via Metals-API. Use it to retrieve the Shanghai Gold Exchange PM reference price programmatically.
Does Metals-API return per gram values?
By default, the unit is “per troy ounce.” Convert to grams by dividing by 31.1034768. Store unit metadata to avoid confusion across systems.
What currency is used?
The default base is USD, shown in the response “base” field. Always store and display the base to prevent misinterpretation.
How do I handle weekends and holidays?
Expect null or missing values for non-trading days. Decide whether to leave gaps, forward-fill, or restrict to business days—document your choice.
Can I top off a historical series with the latest value?
Yes. Pull a historical window with the Time-series endpoint, then call Latest to append the most recent point.
Where can I see all supported symbols?
Visit the Metals-API Supported Symbols page for the full, current list.
How do I get started?
Sign up for an API key at the Metals-API Website, read the Metals-API Documentation, and implement the Time-series workflow for XAUCHNPM as shown above.