In this tutorial, I’m going to share a practical method to fetch London gold (XAU/USD) daily bars using Python, based on what I’ve learned as a financial data analyst. If you’ve ever tried plugging different metals APIs into your backtest and gotten wildly different results, this one’s for you.
Why Daily Data Matters in Your Quant Workflow
I treat daily bars as the directional compass for my gold strategies. They don’t provide entry signals, but they determine whether I should be looking for longs or shorts. If the daily data is polluted with misaligned opens or missing days, my entire signal generation layer becomes unreliable. Gold, with its strong technical structure, demands a particularly clean dataset.
Common Pitfalls with Precious Metals APIs
The two issues I see most often are time misalignment and data gaps. Some APIs define the daily bar by the UTC calendar day, while others use the New York trading close. This creates inconsistencies in high, low, and close values. Additionally, missing dates in the historical record can make volatility calculations appear artificially low unless properly handled.
The Data Structure You Should Expect
Here’s the standard OHLC format I work with:
| Field | Meaning |
|---|---|
| open | Opening price |
| high | Highest price |
| low | Lowest price |
| close | Closing price |
| volume | Volume |
| timestamp | Time |
For gold, I always scrutinize high and low because they capture the extreme points where stop-loss clusters tend to sit. Ignoring these wicks can lead to missing critical reversal signals.
Step-by-Step: Fetching and Cleaning with Python
The code below uses an API that returns UTC-based timestamps consistently. In my experience, picking a source like AllTick that enforces this standard from the start saves a ton of alignment effort.
import requests
import pandas as pd
# API endpoint for historical klines
url = "https://api.alltick.co/v1/klines"
# Request parameters for gold daily data
params = {
"symbol": "XAUUSD",
"interval": "1d",
"limit": 500
}
resp = requests.get(url, params=params)
data = resp.json()
# Convert the JSON data into a pandas DataFrame
df = pd.DataFrame(data["data"])
# Convert the timestamp from milliseconds to datetime
df["timestamp"] = pd.to_datetime(df["timestamp"], unit="ms")
# Ensure data is sorted by time
df = df.sort_values("timestamp")
print(df.head())
Once I have this DataFrame, I run a gap check: I create a full date index using pd.date_range, reindex the data, and forward-fill missing bars while marking them with a flag. This approach keeps the temporal continuity intact without inventing phantom price action.
Integrating into Your Strategy
I’ve used this exact data prep flow for moving average crossovers, Donchian breakouts, and volatility filter modules. The outcome is always the same — more stable signals and fewer false positives during backtesting. Clean daily data isn’t glamorous, but it’s the cheapest performance boost you can give your gold trading system.

Top comments (0)