Live release feed
Sub-second macro releases for FX backtests
Point-in-time history
Official CPI, jobs, GDP, and central-bank events with point-in-time history.
$25/month 14-day free trial
Start Free Trial
Algo-Trading Bitcoin di Coinbase dengan FXMacroData Makro Signals image
Share headline card X LinkedIn Email
Download

Implementation

How-To Guides

Algo-Trading Bitcoin di Coinbase dengan FXMacroData Makro Signals

Buat robot perdagangan Bitcoin yang didorong oleh sinyal makro di Python: tarik data kebijakan tingkat, inflasi, impas, dan emas USD dari FXMacroData, buat skor rezim, jadwalkan sekitar rilis FOMC dan CPI, dan kirimkan pesanan BTC-USD di Coinbase Advanced Trade secara otomatis.

Juga tersedia dalam English
Share article X LinkedIn Email

Mengapa Makro Data Menggerak Bitcoin

Bitcoin diperdagangkan kurang seperti saham teknologi dan lebih seperti aset makro. Tidak membayar dividen, tidak melaporkan laba, dan tidak memiliki model arus kas untuk menanamkan nilainya. Sebaliknya, BTC bergerak dengan kondisi likuiditas global, harapan suku bunga riil, dan kekuatan dolar kekuatan yang sama yang mendorong EUR / USD dan AUD / JPY. Itu berarti toolkit makro yang dibangun untuk pedagang FX berlaku langsung untuk Bitcoin.

Ketika Fed melonggarkan, likuiditas dolar membanjiri pasar risiko dan BTC cenderung memimpin biaya. Ketika CPI mengejutkan ke atas, narasi penurunan nilai moneter mendorong modal ke aset keras. Ketika inflasi titik impas naik, hasil riil menyusut dan perak naik bersama BTC. Setiap sinyal ini dapat diamati sebelumnya melalui titik akhir indikator FXMacroData bertanda waktu hingga detik dan tersedia melalui API REST yang bersih.

Panduan ini membangun robot perdagangan algoritmik yang didorong oleh sinyal makro untuk BTC-USD pada Coinbase Advanced TradePada akhirnya Anda akan memiliki strategi Python yang bekerja yang:

  • Mengambil data suku bunga kebijakan USD, inflasi, inflation break-even, dan emas dari FXMacroData
  • Menggabungkan mereka ke dalam skor makro rezim komposit
  • Jadwal eksekusi di sekitar rilis makro berdampak tinggi melalui kalender rilis FXMacroData
  • Mengirim pesanan pasar BTC-USD di Coinbase menggunakan resmi coinbase-advanced-py SDK

Tesis Inti

Perubahan rezim makro siklus pengurangan suku bunga, pivot inflasi, pembalikan tren dolar menciptakan angin belakang arah multi-minggu untuk Bitcoin. Membaca sinyal rezim ini dari FXMacroData sebelum sesi perdagangan dibuka memungkinkan Anda menangkap pengaturan daripada mengejar langkah.

Persyaratan

Sebelum memulai, pastikan Anda siapkan:

  • Python 3.10+ semua cuplikan menggunakan sintaksis penulisan modern
  • Kunci API FXMacroData daftar di /langganan dan ambil kunci dari dasbor akun
  • Akun Coinbase Advanced Trade dengan saldo USD yang didanai menciptakan Kunci Perdagangan API Cloud (nama kunci API + kunci pribadi EC) di Platform Pengembang Konsol dengan Perdagangan izin diaktifkan
  • Paket PythonAku tidak tahu. requestsAku akan pergi. coinbase-advanced-pyAku akan pergi. pandasAku akan pergi. schedule
pip install requests coinbase-advanced-py pandas schedule

Simpan kredensial Anda sebagai variabel lingkungan jangan pernah hard-code rahasia dalam file sumber:

export FXMACRO_API_KEY="YOUR_FXMACRODATA_KEY"
export COINBASE_API_KEY_NAME="organizations/ORG_ID/apiKeys/KEY_ID"
export COINBASE_PRIVATE_KEY="-----BEGIN EC PRIVATE KEY-----
MHQCAQEEIBs...
-----END EC PRIVATE KEY-----"

Kunci Perdagangan API Cloud vs Kunci API Legacy

Coinbase sekarang mengeluarkan Kunci Perdagangan API Cloud melalui konsol Developer Platformnya. Ini menggunakan kunci pribadi EC untuk otentikasi JWT dan telah menggantikan format kunci HMAC API yang lebih tua. Pastikan Anda membuat Cloud API Trading Key bukan kunci lama saat menyiapkan kredensial bot Anda.

Langkah 1: Mengambil Sinyal Makro dari FXMacroData

Empat seri makro mengankar model rezim BTC: Nilai tukar mata uangAku akan pergi. Inflasi IPK, yang Tingkat inflasi titik impas 10 tahun, dan harga spot emasBersama-sama mereka menggambarkan lingkungan likuiditas, rezim inflasi, dan sentimen permintaan aset keras.

import os
import requests

BASE_URL = "https://fxmacrodata.com/api/v1"
FXMACRO_KEY = os.environ["FXMACRO_API_KEY"]


def get_series(path: str, start: str = "2024-01-01") -> list[dict]:
    """Fetch a time-series from FXMacroData."""
    resp = requests.get(
        f"{BASE_URL}{path}",
        params={"api_key": FXMACRO_KEY, "start": start},
        timeout=10,
    )
    resp.raise_for_status()
    return resp.json()["data"]


# Macro inputs
policy_rate   = get_series("/announcements/usd/policy_rate")
cpi           = get_series("/announcements/usd/inflation")
breakeven_10y = get_series("/announcements/usd/breakeven_inflation_rate")
gold          = get_series("/commodities/gold")

# data[0] is always the most recent reading
print(f"Policy rate (latest): {policy_rate[0]['val']}%")
print(f"CPI (latest):          {cpi[0]['val']}%")
print(f"10Y breakeven:         {breakeven_10y[0]['val']}%")
print(f"Gold spot:             ${gold[0]['val']:.2f}")

Setiap titik akhir mengembalikan data yang diperintahkan paling baru pertama. val memegang tokoh judul dan announcement_datetime membawa timestamp rilis tingkat dua berguna untuk penjadwalan yang tercakup dalam Langkah 4. val adalah harga spot.

Input Sinyal Makro 2024 2025 Rezim

Nilai ilustratif. Karena Fed mulai memangkas suku bunga pada akhir 2024 dan inflasi titik impas tetap di atas 2,2%, BTC naik dari ~ $ 60k ke atas $ 90k.

Langkah 2: Buat Skor Makro Komposit

Alih-alih bereaksi terhadap satu indikator, skor komposit mensintesis semua empat sinyal menjadi satu angka arah antara -1 (risiko-off, BTC bearish) dan +1 (risko-on, BTC bullish).

def macro_score(
    policy_rate_pct: float,
    cpi_pct: float,
    breakeven_pct: float,
    gold_usd: float,
    *,
    gold_baseline: float = 1900.0,
) -> float:
    """
    Returns a composite macro score in [-1, +1].

    Positive = risk-on / BTC bullish environment.
    Negative = risk-off / BTC bearish environment.
    """
    score = 0.0

    # ── Policy rate regime (weight 0.35) ──────────────────────────────
    # Below 4.5% = accommodative → bullish; above 5.5% = restrictive → bearish
    if policy_rate_pct < 4.5:
        score += 0.35
    elif policy_rate_pct <= 5.5:
        score += 0.35 * (5.5 - policy_rate_pct) / 1.0
    else:
        score -= 0.20

    # ── Inflation regime (weight 0.25) ────────────────────────────────
    # 2–4% moderate inflation → neutral/slightly bullish
    # >6% high inflation → debasement narrative → bullish
    # <1.5% deflationary risk → bearish
    if cpi_pct > 6.0:
        score += 0.25
    elif cpi_pct >= 2.0:
        score += 0.10
    else:
        score -= 0.15

    # ── Breakeven inflation (weight 0.20) ─────────────────────────────
    # Rising breakevens signal re-anchoring inflation expectations → bullish
    if breakeven_pct >= 2.5:
        score += 0.20
    elif breakeven_pct >= 2.0:
        score += 0.10
    else:
        score -= 0.10

    # ── Gold trend (weight 0.20) ──────────────────────────────────────
    # Gold above baseline confirms hard-asset demand → bullish
    gold_ratio = (gold_usd - gold_baseline) / gold_baseline
    score += 0.20 * max(-1.0, min(1.0, gold_ratio * 5))

    return round(max(-1.0, min(1.0, score)), 4)


score = macro_score(
    policy_rate_pct=policy_rate[0]["val"],
    cpi_pct=cpi[0]["val"],
    breakeven_pct=breakeven_10y[0]["val"],
    gold_usd=gold[0]["val"],
)
print(f"Composite macro score: {score:+.4f}")
# e.g. → +0.6000  (bullish regime)

Panduan Interpretasi Skor

Jangkauan Skor Sistem Makro Sinyal yang Disarankan
+0,5 sampai +1,0 Risiko-on suku bunga akomodatif, inflasi sedang hingga tinggi Mengakumulasi / Memegang BTC panjang
+0,1 sampai +0,5 Sedikit mendukung sinyal campuran, rezim transisi Posisi berkurang, menunggu konfirmasi
-0,1 sampai +0,1 Neutral tidak ada sinyal mode yang kuat Dinding / tidak tersedia
-1,0 sampai -0,1 Risiko-off suku bunga tinggi, deflasi atau stagflasi Keluar / Kurangi paparan jangka panjang

Langkah 3: Hubungkan ke Coinbase Advanced Trade API

Pejabat. coinbase-advanced-py library mengelilingi REST API Coinbase dan menangani otentikasi JWT secara otomatis. RESTClient menggunakan nama kunci perdagangan API Cloud Anda dan kunci pribadi EC terkait.

import os
import uuid
from coinbase.rest import RESTClient

CB_KEY_NAME    = os.environ["COINBASE_API_KEY_NAME"]
CB_PRIVATE_KEY = os.environ["COINBASE_PRIVATE_KEY"]

client = RESTClient(api_key=CB_KEY_NAME, api_secret=CB_PRIVATE_KEY)

# Verify connectivity and fetch current BTC-USD price
product = client.get_best_bid_ask(product_ids=["BTC-USD"])
bids = product["pricebooks"][0]["bids"]
asks = product["pricebooks"][0]["asks"]
btc_price = (float(bids[0]["price"]) + float(asks[0]["price"])) / 2
print(f"BTC-USD mid-price: ${btc_price:,.2f}")

# Available USD balance
accounts = client.get_accounts()
usd_balance = 0.0
btc_balance = 0.0
for acct in accounts["accounts"]:
    if acct["currency"] == "USD":
        usd_balance = float(acct["available_balance"]["value"])
    if acct["currency"] == "BTC":
        btc_balance = float(acct["available_balance"]["value"])

print(f"Available USD: ${usd_balance:,.2f}")
print(f"Available BTC: {btc_balance:.6f}")

Gunakan Sandbox untuk Uji Awal

Coinbase Advanced Trade menyediakan lingkungan sandbox di api-public.sandbox.pro.coinbase.com- Pergilah. base_url="https://api-public.sandbox.pro.coinbase.com" Untuk RESTClient untuk menguji logika pesanan tanpa mempertaruhkan dana nyata. memvalidasi aliran sinyal dan ukuran selama setidaknya dua minggu sebelum beralih ke titik akhir produksi.

Langkah 4: Jadwalkan sekitar Macro Release Event

Salah satu fitur FXMacroData yang paling kuat untuk perdagangan algo adalah titik akhir kalender rilis.

import datetime
import schedule
import time


def get_next_release(currency: str, indicator: str) -> datetime.datetime | None:
    """
    Returns the next scheduled release datetime for an indicator.
    The calendar endpoint returns upcoming events in ascending date order.
    """
    resp = requests.get(
        f"{BASE_URL}/calendar/{currency}",
        params={"api_key": FXMACRO_KEY},
        timeout=10,
    )
    resp.raise_for_status()
    events = resp.json().get("data", [])

    now_utc = datetime.datetime.now(tz=datetime.timezone.utc)
    for event in events:
        if event.get("indicator") != indicator:
            continue
        release_str = event.get("release_datetime") or event.get("date")
        if not release_str:
            continue
        release_dt = datetime.datetime.fromisoformat(
            release_str.replace("Z", "+00:00")
        )
        if release_dt > now_utc:
            return release_dt
    return None


# Example: find the next FOMC policy rate decision
next_fomc = get_next_release("usd", "policy_rate")
if next_fomc:
    delta = next_fomc - datetime.datetime.now(tz=datetime.timezone.utc)
    print(f"Next FOMC: {next_fomc.isoformat()}  ({delta.days}d {delta.seconds // 3600}h away)")

# Example: find the next CPI print
next_cpi = get_next_release("usd", "inflation")
if next_cpi:
    print(f"Next CPI:  {next_cpi.isoformat()}")

Dengan timestamp rilis yang tepat, Anda dapat menjadwalkan pembaruan sinyal pasca rilis yang memungkinkan reaksi harga awal untuk menyelesaikan sebelum re-scoring dan perdagangan:

def on_macro_release():
    """Called shortly after a scheduled macro release fires."""
    print("Macro release detected — refreshing signals...")
    run_strategy()


def schedule_next_release(currency: str, indicator: str, delay_seconds: int = 90):
    """
    Schedules the strategy to run 'delay_seconds' after the next release.
    A 90-second delay lets the initial market reaction absorb before entry.
    """
    release_dt = get_next_release(currency, indicator)
    if not release_dt:
        return

    fire_at = release_dt + datetime.timedelta(seconds=delay_seconds)
    fire_str = fire_at.strftime("%H:%M:%S")
    schedule.every().day.at(fire_str).do(on_macro_release).tag(
        f"{currency}_{indicator}"
    )
    print(f"Scheduled refresh at {fire_str} UTC after {currency.upper()} {indicator}")


schedule_next_release("usd", "policy_rate", delay_seconds=90)
schedule_next_release("usd", "inflation", delay_seconds=60)

Langkah 5: Ukuran Posisi dan Kirim Orde di Coinbase

Perintah perdagangan Coinbase Advanced bekerja berbeda dari Binance: membeli Perintah menentukan quote_size (USD jumlah untuk menghabiskan), sementara menjual Perintah menentukan base_size (jumlah BTC untuk dijual). Fungsi ukuran di bawah ini skala alokasi USD dengan besar mutlak skor makro keyakinan yang lebih tinggi menjamin alokase yang lebih besar, dibatasi pada maksimum yang dapat dikonfigurasi.

import math


def compute_usd_allocation(
    score: float,
    usd_balance: float,
    max_position_pct: float = 0.20,
    min_threshold: float = 0.30,
) -> float:
    """
    Returns the USD amount to deploy for a BUY order.
    Scales between 0 and max_position_pct of available USD balance.
    Returns 0.0 if |score| < min_threshold (noise-filtered).
    Minimum order size on Coinbase Advanced Trade is $1 USD.
    """
    if abs(score) < min_threshold:
        return 0.0
    conviction = (abs(score) - min_threshold) / (1.0 - min_threshold)
    usd_to_trade = usd_balance * max_position_pct * conviction
    return max(1.0, round(usd_to_trade, 2))


def place_buy(usd_amount: float) -> dict | None:
    """Submit a market BUY order for a given USD amount."""
    if usd_amount <= 0:
        print("USD amount zero — no buy order placed.")
        return None
    order_id = str(uuid.uuid4())
    try:
        result = client.market_order_buy(
            client_order_id=order_id,
            product_id="BTC-USD",
            quote_size=str(usd_amount),
        )
        print(f"BUY order submitted: ${usd_amount:.2f} USD  (order_id={order_id})")
        return result
    except Exception as exc:
        print(f"Coinbase buy error: {exc}")
        return None


def place_sell(btc_amount: float) -> dict | None:
    """Submit a market SELL order for a given BTC amount."""
    # Minimum BTC lot size on Coinbase Advanced Trade is 0.000001 BTC
    btc_amount = math.floor(btc_amount * 1_000_000) / 1_000_000
    if btc_amount <= 0:
        print("BTC amount zero — no sell order placed.")
        return None
    order_id = str(uuid.uuid4())
    try:
        result = client.market_order_sell(
            client_order_id=order_id,
            product_id="BTC-USD",
            base_size=str(btc_amount),
        )
        print(f"SELL order submitted: {btc_amount:.6f} BTC  (order_id={order_id})")
        return result
    except Exception as exc:
        print(f"Coinbase sell error: {exc}")
        return None

Makro Score vs BTC Price Ilustratif 2024

TEST BACK-TEST: Skor makro melintasi di atas +0.3 di Q1 2024 karena Fed tetap stabil dan inflasi titik impas naik. BTC naik dari ~ $ 40k menjadi $ 70k selama beberapa bulan berikutnya sebelum skor mundur karena ekspektasi penurunan suku bunga sepenuhnya dihargai.

Langkah 6: Mengumpulkan seluruh lingkaran strategi

Sekarang, letakkan semua potongan bersama menjadi satu. run_strategy() Pada setiap panggilan, ia mengambil data makro baru, menghitung ulang skor, mendeteksi perubahan rezim, dan masuk atau keluar sesuai.

import json
import pathlib

STATE_FILE = pathlib.Path("coinbase_strategy_state.json")


def load_state() -> dict:
    if STATE_FILE.exists():
        return json.loads(STATE_FILE.read_text())
    return {"position_btc": 0.0, "last_score": 0.0}


def save_state(state: dict) -> None:
    STATE_FILE.write_text(json.dumps(state, indent=2))


def run_strategy() -> None:
    state = load_state()

    # ── 1. Refresh macro data ──────────────────────────────────────────
    policy_rate_val = get_series("/announcements/usd/policy_rate")[0]["val"]
    cpi_val         = get_series("/announcements/usd/inflation")[0]["val"]
    breakeven_val   = get_series("/announcements/usd/breakeven_inflation_rate")[0]["val"]
    gold_val        = get_series("/commodities/gold")[0]["val"]

    # ── 2. Compute macro score ─────────────────────────────────────────
    score = macro_score(policy_rate_val, cpi_val, breakeven_val, gold_val)
    prev  = state["last_score"]
    print(f"Macro score: {score:+.4f}  (prev: {prev:+.4f})")

    # ── 3. Fetch current Coinbase balances ─────────────────────────────
    accounts  = client.get_accounts()
    usd_avail = 0.0
    btc_avail = 0.0
    for acct in accounts["accounts"]:
        if acct["currency"] == "USD":
            usd_avail = float(acct["available_balance"]["value"])
        if acct["currency"] == "BTC":
            btc_avail = float(acct["available_balance"]["value"])

    # ── 4. Regime change logic ─────────────────────────────────────────
    is_bullish = score >= 0.30
    was_bullish = prev >= 0.30
    is_neutral  = abs(score) < 0.30
    is_bearish  = score < -0.30

    if is_bullish and not was_bullish:
        # New bullish regime — enter long via USD allocation
        usd_to_use = compute_usd_allocation(score, usd_avail)
        place_buy(usd_to_use)

    elif is_neutral and was_bullish and btc_avail > 0.000001:
        # Regime turned neutral — exit position
        place_sell(btc_avail)
        print("Regime neutral — exiting BTC position.")

    elif is_bearish and btc_avail > 0.000001:
        # Hard exit on bearish macro signal
        place_sell(btc_avail)
        print("BEARISH regime — full exit.")

    # ── 5. Persist state ───────────────────────────────────────────────
    state["last_score"] = score
    state["position_btc"] = btc_avail
    save_state(state)


# ── Run once on startup, then on each scheduled macro release ──────────
run_strategy()

while True:
    schedule.run_pending()
    time.sleep(10)

Langkah 7: Manajemen Risiko dan Pertimbangan Operasional

A macro-signal strategy trades infrequently — regime changes driven by FOMC, CPI, and NFP prints typically produce 6–10 actionable signals per year. That low frequency is by design: you are positioning for multi-week directional moves, not intraday noise. But each position carries meaningful risk, so disciplined controls are essential.

✓ Lakukan

  • Perdagangan kertas di kotak pasir Coinbase selama setidaknya dua minggu sebelum mulai beroperasi
  • Alokasi maksimal 20% dari akun per perdagangan
  • Atur pemutus sirkuit penarik harian: berhenti jika kerugian melebihi 5% dalam 24 jam
  • Log setiap skor, perdagangan, dan account snapshot ke file untuk audit
  • Gunakan unik client_order_id UUID untuk mencegah perintah duplikat pada upaya ulang

Hindari

  • Memasuki posisi segera pada saat pelepasan menunggu 60 90 s hingga likuiditas normal
  • Berat skor yang terlalu cocok untuk siklus suku bunga tunggal
  • Menjalankan beberapa instansi bot secara bersamaan pada akun yang sama
  • Kunci API atau kunci pribadi dalam kode sumber atau kontrol versi
  • Ignoring Coinbase order fees (0.05–0.60% maker/taker) in P&L calculations

Semua time stamp dari FXMacroData termasuk announcement_datetime dalam respons indikator dan waktu rilis dari titik akhir kalender adalah UTC. Simpan logika penjadwalan Anda di UTC sepanjang dan mengkonversi hanya untuk tujuan tampilan. Ini menghilangkan ambiguitas penjimatan waktu siang di sekitar rilis data AS, yang merupakan sumber umum dari bug penjadwal.

Batas Rate API Coinbase

Coinbase Advanced Trade memberlakukan batas tingkat per-key (biasanya 30 permintaan/detik). Strategi di atas membuat paling banyak beberapa panggilan API per acara makro, dalam batas. time.sleep() antara panggilan untuk tetap jauh dari batas.

Memperluas Strategi

Kerangka kerja ini modular. Beberapa ekstensi alami layak dieksplorasi selanjutnya:

  • Tambahkan data posisi COT Endpoint CFTC COT FXMacroData menyediakan posisi spekulatif mingguan dalam USD futures. Posisi USD pendek ekstrem secara historis telah menjadi angin belakang untuk BTC. Tarik di /cot/usd dan tambahkan istilah posisi bersih ke skor makro.
  • Indeks likuiditas multi-mata uang menggabungkan sinyal makro EUR, JPY, dan GBP di samping USD. Ketika beberapa bank sentral G10 melonggarkan secara bersamaan, kondisi likuiditas global paling menguntungkan untuk aset berisiko seperti BTC.
  • Sinyal kecepatan penyeimbangan daripada tingkat inflasi titik impas, gunakan tingkat perubahan 4 minggu.
  • Eksekusi perintah batas mengganti market_order_buy/ Aku tidak tahu.market_order_sell dengan limit_order_gtc_buy/ Aku tidak tahu.limit_order_gtc_sell Untuk menghindari membayar seluruh penyebaran pemegang. client.get_best_bid_ask dan duduk satu kutu di dalam penawaran terbaik / meminta.
  • Pengelompokan kalender rilis pertanyaan Kalender rilis untuk semua peristiwa USD satu bulan keluar dan mengidentifikasi jendela di mana beberapa pelepasan dampak tinggi kelompok dalam waktu 48 jam. jendela padat adalah periode-konveksi tertinggi untuk posisi.

Ringkasan

Anda sekarang memiliki robot perdagangan Bitcoin yang didorong oleh sinyal makro yang terhubung ke Coinbase Advanced Trade. Strategi ini membaca tingkat kebijakan USD, CPI, inflasi impas, dan emas dari FXMacroData untuk membangun skor rezim komposit, menjadwalkan dirinya di sekitar peristiwa pengumuman makro dunia nyata, dan mengirimkan pesanan pasar BTC-USD yang proporsional dengan keyakinan rezim.

Pendekatan makro berdagang jarang dan dengan keyakinan tinggi yang tepatnya yang membedakan strategi berbasis rezim dari sistem teknis yang mengejar kebisingan. Langkah logis berikutnya adalah menguji kerangka kerja ini terhadap seri waktu FXMacroData historis untuk mengkalibrasi bobot skor dan mengukur penarikan di beberapa siklus Fed.

Blogroll

AI Answer-Ready

Key Facts

Page
Algo Trading Bitcoin Coinbase FXmacrodata
Section
Articles
Canonical URL
https://fxmacrodata.com/id/articles/algo-trading-bitcoin-coinbase-fxmacrodata
Source
FXMacroData editorial and official publisher references
Last Updated
2026-06-15 11:06 UTC

Provenance And Trust

Cite the canonical URL and source field above. Where available, this page maps to official publisher releases and timestamped updates.

Quick Q&A

What is this page about? This page explains Algo Trading Bitcoin Coinbase FXmacrodata with directly usable context for trading, research, and API workflows.

What source should be cited? Use the canonical URL and the listed source field; cite official publisher references when available.

How fresh is this content? The last updated value above reflects the page metadata or latest available data timestamp.

Can this be used in AI assistants? Yes. This section is intentionally structured for retrieval and citation in chat assistants.

Prompt Packs

Use these in ChatGPT, Claude, Gemini, Mistral, Perplexity, or Grok for consistent source-aware outputs.