MetalAPI
XAU3.997,89−%1,54XAG53,936−%1,51XPT1.554,47−%0,83XPD1.047,03−%0,44XCU6,5080+%2,29WTI103,27+%3,82BRENT111,70−%1,30EUR1,120400−%0,01GBP1,337500−%0,01JPY0,0063761+%0,14CHF1,213445−%0,25TRY0,020125−%0,12BTC80.640,11−%0,17ETH2.354,39−%0,06
Tüm yazılar
AltınPythonEğitim

Python ile Altın Fiyatı API'si: Veri Çekme, Önbellek ve Grafik

Python'da altın fiyatı API'si kullanın: requests ile canlı fiyatları alın, hataları ve yeniden denemeleri yönetin, önbelleğe alın, pandas ile grafik çizin.

Yazar: MetalAPI Team··7 dk okuma

Python ile altın fiyatı API'si: neye ihtiyacınız var

Bu eğitim, Python'da bir altın fiyatı API'sinin nasıl kullanılacağını ilk istekten önbellekli bir istemciye ve son on ayın grafiğine kadar gösteriyor. Değerli metaller, endüstriyel metaller, enerji, para birimleri ve kripto paralar için bir JSON REST API'si olan MetalAPI'yi, bilinen üç kütüphaneyle birlikte kullanıyor: HTTP için requests, zaman serisi için pandas ve grafik için matplotlib. Her kod parçası Python 3.9 veya daha yeni sürümlerde çalışır.

Ücretsiz bir hesap oluşturun ve paneldeki API keys bölümünde bir API anahtarı oluşturun. Anahtarlar mk_live_ ile başlar ve yalnızca bir kez gösterilir; bu nedenle anahtarınızı doğrudan bir ortam değişkenine kopyalayın. Free plan kredi kartı gerektirmez ve günlük fiyat güncellemeleriyle ayda 100 istek içerir; bu, yazıdaki her şey için yeterlidir.

Kurulum
pip install requests pandas matplotlib

# macOS ve Linux
export METALAPI_KEY="mk_live_your_key_here"

# Windows PowerShell
$env:METALAPI_KEY = "mk_live_your_key_here"

Anahtarı bir betiğe yapıştırmak yerine os.environ["METALAPI_KEY"] ile okuyun; değişken eksik olduğunda bu ifade açıkça hata verir. .env dosyası kullanmayı tercih ediyorsanız python-dotenv paketi onu tek bir load_dotenv() çağrısıyla yükler. Anahtarın deponuza hiç ulaşmaması için .env dosyasını .gitignore listesine ekleyin.

Python'da altın fiyatı nasıl alınır

Her MetalAPI endpoint'i, https://metalapi.com/api/v1 altında bir GET isteğidir. Anahtar bir api_key sorgu parametresinde, bir Authorization: Bearer header'ında veya bir X-API-Key header'ında gönderilebilir. Header kullanın: tam URL'ler loglara düşer ve bazı requests istisnaları URL'yi sorgu dizesiyle birlikte yazdırır. /latest endpoint'i güncel fiyatları döndürür; base para birimini belirler, currencies ise yanıtı ihtiyacınız olan sembollerle sınırlar:

gold.py
import os

import requests

resp = requests.get(
    "https://metalapi.com/api/v1/latest",
    params={"base": "USD", "currencies": "XAU"},
    headers={"X-API-Key": os.environ["METALAPI_KEY"]},
    timeout=10,
)
data = resp.json()
if not data["success"]:
    raise SystemExit(f"MetalAPI error {data['error']['code']}: {data['error']['info']}")

price = data["rates"][data["base"] + "XAU"]
print(f"Gold: {price:,.2f} {data['base']} per troy ounce")

Yanıt şöyle görünür. Sayılar canlı fiyatlar değil, MetalAPI dokümantasyonu boyunca kullanılan örnek değerlerdir:

Örnek yanıt
{
  "success": true,
  "timestamp": 1792834892,
  "date": "2026-10-24",
  "base": "USD",
  "rates": { "XAU": 0.0002501319, "USDXAU": 3997.89 },
  "rate_limit": { "limit": 100, "remaining": 99, "used": 1, "plan": "Free", "...": "..." }
}

Bu değerlerle betik Gold: 3,997.89 USD per troy ounce çıktısını verir. rates["USDXAU"], bir troy ons altının baz para birimi cinsinden fiyatıdır. rates["XAU"] ise bunun tersidir, yani bir dolar başına troy ons altın miktarıdır; onu yanlışlıkla okumak, altın fiyatı kodlarındaki en yaygın hatadır. Anahtarı data["base"] üzerinden oluşturmak, base=EUR (anahtar EURXAU) veya base=INR değerine geçtiğinizde betiğin doğru çalışmaya devam etmesini sağlar. Gram veya kilogram başına fiyat için unit=gram ya da unit=kilogram ekleyin. timestamp, isteğinizin değil fiyat verisinin zamanıdır ve Unix saniyesi cinsindendir.

Python'da altın fiyatı API hatalarını yönetmek

Başarısız bir çağrı, bir HTTP hata durum kodu ve success: false içeren bir JSON gövdesi döndürür; gövdedeki error nesnesi sayısal bir code, bir type ve bir info mesajı taşır. Mesaj metnine göre değil, her zaman koda göre dallanın. Yalnızca birkaç kod yeniden denemeye değer:

  • 104 (too_many_requests, HTTP 429): dakika başına limit. Retry-After header'ındaki saniye sayısı kadar bekleyin.
  • 500, 503 ve ağ hataları: üstel geri çekilmeyle (exponential backoff) yeniden deneyin.
  • Diğer her şey, örneğin 101 veya 102 (eksik ya da geçersiz anahtar), 105 (aylık kota tükendi), 106 (endpoint planınızda yok) ve 2xx doğrulama hataları: bunların yerine isteği, anahtarı veya planı düzeltin.

Bu küçük modül bu mantığı sarmalar. Tek bir requests.Session nesnesini yeniden kullanır, böylece bağlantılar çağrılar arasında açık kalır; hata durumunda da inceleyebileceğiniz bir istisna fırlatır:

metalapi.py
import os
import time

import requests

API_URL = "https://metalapi.com/api/v1"
session = requests.Session()
session.headers["X-API-Key"] = os.environ["METALAPI_KEY"]


class MetalAPIError(Exception):
    def __init__(self, code, type_, info, retry_after=None):
        super().__init__(f"MetalAPI {code} ({type_}): {info}")
        self.code = code
        self.type = type_
        self.retry_after = retry_after


def _get(path, params):
    r = session.get(f"{API_URL}/{path}", params=params, timeout=10)
    try:
        data = r.json()
    except ValueError:  # JSON değil; örneğin bir proxy'den gelen HTML hata sayfası
        raise MetalAPIError(r.status_code, "http_error", r.reason) from None
    if not data.get("success"):
        err = data["error"]
        retry_after = r.headers.get("Retry-After")
        raise MetalAPIError(err["code"], err["type"], err["info"], int(retry_after) if retry_after else None)
    return data


def call(path, params=None, retries=3):
    """Bir endpoint'e GET isteği gönderir. Yalnızca istek limitlerini, sunucu hatalarını ve ağ hatalarını yeniden dener."""
    for attempt in range(retries + 1):
        try:
            return _get(path, params or {})
        except (MetalAPIError, requests.RequestException) as exc:
            code = getattr(exc, "code", None)  # ağ hatalarında None
            if attempt == retries or (code is not None and code != 104 and code < 500):
                raise
            time.sleep(getattr(exc, "retry_after", None) or 2**attempt)

Geri çekilme, vazgeçmeden önce 1, 2 ve 4 saniye bekler. Burada yeniden denemenin hiçbir maliyeti yoktur, çünkü 104 veya bir sunucu hatasıyla reddedilen istekler ücretlendirilmez. Doğrulama hataları ise ücretlendirilir; bu da onları asla bir döngü içinde yeniden denememek için bir neden daha. Hata yönetimi rehberi her kodu HTTP durumuyla birlikte listeler.

İstek tasarrufu için altın fiyatlarını önbelleğe almak

Her plan fiyatları sabit bir aralıkla yeniler: Free planda günde bir kez, Lite'ta 30 dakikada bir, Standard'da 10 dakikada bir, Advanced ve Pro'da ise 60 saniyede bir. Güncellemeler 00:00 UTC'den itibaren sayılan bu aralığın katlarına denk gelir; dolayısıyla bir sonraki güncellemeden önce tekrar sormak aynı sayıları döndürür ve kotayı boşa harcar. Bu önbellek her yanıtı bir sonraki güncellemeye kadar saklar ve API'ye ulaşılamazsa son geçerli fiyatları sunar:

prices.py
import math
import time

import requests

from metalapi import MetalAPIError, call

# Saniye. Free: 86_400, Lite: 3_600 (saatlik sorgu 1.000 isteğe sığar), Standard: 600
UPDATE_INTERVAL = 600
_cache = {}  # (base, symbols, unit) -> (expires_at, data)


def latest(base="USD", symbols="XAU,XAG", unit="troy_oz"):
    key = (base, symbols, unit)
    now = time.time()
    hit = _cache.get(key)
    if hit and now < hit[0]:
        return hit[1]
    try:
        data = call("latest", {"base": base, "currencies": symbols, "unit": unit})
    except (MetalAPIError, requests.RequestException):
        if not hit:
            raise
        _cache[key] = (now + 60, hit[1])  # son geçerli fiyatları sun, bir dakika sonra tekrar dene
        return hit[1]
    next_update = (math.floor(now / UPDATE_INTERVAL) + 1) * UPDATE_INTERVAL
    _cache[key] = (next_update + 5, data)  # bir sonraki güncellemeden birkaç saniye sonra sona erer
    return data

latest("EUR", "XAU", "gram")["rates"]["EURXAU"] gram başına euro fiyatını döndürür. İhtiyacınız olan tüm sembolleri tek bir çağrıda isteyin: XAU,XAG,XPT,XPD dört değil, tek bir isteğe mal olur. Bu önbelleğin bellekte tutulduğunu unutmayın. Cron ile başlatılan bir betik her seferinde boş bir önbellekle başlar; orada önbelleğin yerini zamanlama alır: betiği güncelleme aralığı başına en fazla bir kez çalıştırın. Kotanızı izlemek için kotadan hiçbir zaman düşülmeyen /usage endpoint'ini çağırın.

Altın fiyatı zaman serisini pandas'a yüklemek

Geçmiş için /timeframe endpoint'i (diğer adı /timeseries), start_date ile end_date arasındaki günlük kapanış fiyatlarını tarihe göre anahtarlanmış olarak döndürür. Tek bir istek Free planda en fazla 30 günü, ücretli planlarda 365 günü kapsar; daha uzun bir aralık 207 hatasıyla başarısız olur. Bu fonksiyon herhangi bir aralığı izin verilen parçalara böler ve bir pandas Series döndürür:

history.py
from datetime import date, timedelta

import pandas as pd

from metalapi import call


def gold_history(start, end, base="USD", max_days=30):  # ücretli planlarda max_days=365
    rates = {}
    chunk_start = start
    while chunk_start <= end:
        chunk_end = min(chunk_start + timedelta(days=max_days - 1), end)
        data = call("timeframe", {
            "start_date": chunk_start.isoformat(),
            "end_date": chunk_end.isoformat(),
            "currencies": "XAU",
            "base": base,
        })
        rates.update(data["rates"])
        chunk_start = chunk_end + timedelta(days=1)

    df = pd.DataFrame.from_dict(rates, orient="index")
    df.index = pd.to_datetime(df.index)
    return df[f"{base}XAU"].sort_index().rename(f"gold_{base.lower()}")


gold = gold_history(date(2026, 1, 1), date(2026, 10, 23))
gold.to_csv("gold_usd.csv")
print(f"{len(gold)} trading days, high {gold.max():,.2f}, low {gold.min():,.2f}")

Free planda bu on ay 10 istek tutar. Series'te her işlem günü için bir satır bulunur: hafta sonları ve piyasa tatilleri doldurulmaz, eksik kalır; bu nedenle takvim günlerinden daha az satır bekleyin. Her gün için bir değere ihtiyacınız varsa gold.asfreq("D").ffill() cuma kapanışını hafta sonuna taşır. Buradan sonra günlük getiriler için gold.pct_change() veya hareketli ortalama için gold.rolling(20).mean() gibi alışıldık pandas araçlarını kullanabilirsiniz.

Geçmiş kapanış fiyatları hiçbir zaman değişmez; bu nedenle CSV dosyası geçmiş veriler için önbelleğinizdir: aynı aralığı yeniden istemek yerine bir sonraki sefer onu yükleyin. 2000'den bu yana tüm geçmişi bir veritabanına doldurmak için API ile geçmiş altın ve gümüş fiyatları yazısına bakın.

matplotlib ile altın fiyatı grafiği çizmek

Grafik CSV dosyasını okur; bu nedenle onu yeniden çizmek hiç istek harcamaz. Günlük kapanışı 20 günlük hareketli ortalamayla birlikte çizer:

plot.py
import matplotlib.pyplot as plt
import pandas as pd

gold = pd.read_csv("gold_usd.csv", index_col=0, parse_dates=True)["gold_usd"]
sma20 = gold.rolling(20).mean()

fig, ax = plt.subplots(figsize=(10, 5))
ax.plot(gold.index, gold, linewidth=1, label="Gold, USD per troy oz")
ax.plot(sma20.index, sma20, linewidth=2, label="20-day moving average")
ax.set_title(f"Gold price, {gold.index[0]:%d %b %Y} to {gold.index[-1]:%d %b %Y}")
ax.yaxis.set_major_formatter("{x:,.0f}")
ax.grid(alpha=0.3)
ax.legend()
fig.autofmt_xdate()
fig.tight_layout()
fig.savefig("gold.png", dpi=150)

Dizin gerçek tarihler içerdiği için matplotlib noktaları zamana göre aralıklandırır ve hareketli ortalama 20. işlem gününde başlar. Altını başka bir para biriminde çizmek için gold_history fonksiyonunu base="EUR" ile çağırın: kur anahtarları aynı kalıbı izlediği için fonksiyon değiştirilmeden çalışır.

Sonraki adımlar

Artık çoğu Python entegrasyonunun ihtiyaç duyduğu her şeye sahipsiniz: kimliği doğrulanmış bir istek, makul yeniden denemelerle hata yönetimi, planınızın güncelleme aralığını izleyen bir önbellek ve pandas'ta geçmiş veriler. Hepsini Free planda geliştirip test edin. Daha güncel fiyatlara ihtiyaç duyduğunuzda planı güncelleme aralığına ve hacme göre seçin: 10 dakikada bir çalışan bir iş ayda yaklaşık 4.500 istek kullanır; bu da Standard planın 10.000 isteğine sığar. Planları fiyatlandırma sayfasında karşılaştırın.

Fiyatlar bir web sitesinde gösterilecekse JavaScript ile altın fiyatı API'si yazısı, anahtarınızı açığa çıkarmadan fiyatları bir Node.js route'undan nasıl sunacağınızı gösterir.

Sık sorulan sorular

Python için ücretsiz bir altın fiyatı API'si var mı?

Evet. MetalAPI'nin Free planı, günlük fiyat güncellemeleriyle ayda 100 istek içerir ve kredi kartı gerektirmez; bu yazıdaki her kod parçası bu planda çalışır. Free planda en güncel fiyatlar bir önceki günün kapanışıdır ve tek bir /timeframe isteği en fazla 30 günü kapsar. Ücretsiz altın fiyatı API'si yazısı ücretsiz planı daha ayrıntılı açıklar.

XAU kuru neden bu kadar küçük bir sayı?

rates["XAU"] ters kurdur: baz para biriminin bir birimi başına troy ons altın. Fiyat, önekli anahtarda yer alır: baz USD için rates["USDXAU"], baz EUR için rates["EURXAU"]. Örnek değerlerle 1 ÷ 0,0002501319 yine 3.997,89 sonucunu verir.

Python'da altının gram fiyatını nasıl alırım?

İsteğe unit=gram ekleyin; örneğin call("latest", {"base": "EUR", "currencies": "XAU", "unit": "gram"}). Bu durumda rates["EURXAU"] gram başına euro cinsinden fiyattır ve yanıt "unit": "gram" alanını içerir. unit=ounce kullanmaktan kaçının: bu, altının fiyatlandırıldığı troy ons değil, avoirdupois onstur.

Altın fiyatı geçmişi ne kadar geriye gidiyor?

Günlük altın fiyatları 2000 yılında başlar ve her plan tüm geçmişi sorgulayabilir. Planlar yalnızca tek bir /timeframe isteğinin kaç günü kapsayabileceği konusunda farklılık gösterir: Free planda 30, ücretli planlarda 365. max_days=365 ile 2000'den bugüne kadar her şey 27 istek tutar.

Bir Python betiği API'yi ne sıklıkla çağırmalı?

Planınızın fiyatları güncellediğinden daha sık değil: Free planda günde bir kez, 00:00 UTC'den sonra; Lite'ta saatte bir, çünkü 30 dakikada bir çağırmak 1.000 isteklik kotaya karşı ayda yaklaşık 1.490 istek tutar; Standard'da 10 dakikada bir. Spot altının New York saatiyle cuma 17:00'den pazar 17:00'ye kadar işlem görmediği hafta sonu boyunca fiyatların sabit kalmasını bekleyin.

Kendi verilerinizle deneyin

Ücretsiz bir hesap oluşturun ve ilk isteğinizi iki dakikadan kısa sürede gönderin. Ayda 100 istek, kredi kartı gerekmez.

Okumaya devam edin