Warum Makrodaten Bitcoin antreiben
Bitcoin handelt weniger wie eine Technologie-Aktie und eher wie ein Makro-Asset. Es zahlt keine Dividenden, meldet keine Gewinne und hat kein Cashflow-Modell, um seinen Wert zu verankern. Stattdessen bewegt sich BTC mit globalen Liquiditätsbedingungen, realen Zinssätze Erwartungen und Dollarstärke die gleichen Kräfte, die EUR / USD und AUD / JPY antreiben. Das bedeutet, dass das für FX-Händler entwickelte Makro Toolkit direkt auf Bitcoin anwendet.
Wenn die Fed lockert, überflutet die Dollarliquidität die Risikomarkt und BTC neigt dazu, die Ladung zu führen. Wenn der CPI überrascht, drücken monetäre Abwertungserzählungen das Kapital in harte Vermögenswerte. Wenn die Breakeven-Inflation steigt, komprimieren die realen Renditen und Goldrallyes neben BTC. Jedes dieser Signale ist im Voraus über die Indikatoren-Endpunkte von FXMacroData zeitgestempelt auf die Sekunde und über eine saubere REST-API verfügbar.
Dieser Leitfaden erstellt einen makrosignaldriven algorithmischen Handelsbot für BTC-USD auf Coinbase Advanced Trade (die neue Version von Coinbase)Am Ende haben Sie eine funktionierende Python-Strategie, die:
- Zieht USD-Leistungszins-, Inflations-, Breakeven-Inflations- und Golddaten aus FXMacroData
- Kombiniert sie zu einem zusammengesetzten Makroresignal
- Planung der Ausführung um hochwirksame Makrorelizie über den Release-Kalender von FXMacroData
- Übermittelt BTC-USD-Marktbestellungen auf Coinbase über die offizielle
coinbase-advanced-pySDK
Kernthese
Makro-Regime-Veränderungen Zinssenkungszyklen, Inflationsschwenke, Dollar-Trendumkehrungen schaffen mehrwöchige Richtungsschwinde für Bitcoin.
Voraussetzungen
Bevor Sie anfangen, stellen Sie sicher, daß Sie Folgendes bereit haben:
- Python 3.10+ alle Snippets verwenden eine moderne Typing-Syntax
- FXMacroData-API-Schlüssel melden Sie sich an /abonnieren und holen Sie Ihren Schlüssel aus dem Konto-Dashboard
- Konto für Coinbase Advanced Trade mit einem fungierten USD-Guthaben eine Cloud-API-Handelsschlüssel (API-Schlüsselname + EC-Privatschlüssel) in der Entwicklerplattform - Ich bin mit der Konsole . Handel Berechtigungen aktiviert
- Python-Pakete- Ich weiß .
requests- Ich weiß .coinbase-advanced-py- Ich weiß .pandas- Ich weiß .schedule
pip install requests coinbase-advanced-py pandas schedule
Speichern Sie Ihre Anmeldeinformationen als Umgebungsvariablen niemals Hardcode-Geheimnisse in Quelldateien:
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-----"
Cloud-API-Handelsschlüssel gegen Legacy-API Schlüssel
Coinbase gibt jetzt aus . Cloud-API-Handelsschlüssel Diese verwenden einen EC-Privatschlüssel für die JWT-Authentifizierung und haben das ältere HMAC API-Schlüsselformat ersetzt. Stellen Sie sicher, dass Sie beim Einrichten Ihrer Bot-Anmeldeinformationen einen Cloud API Trading Key und keinen Legacy Key ?? erstellen.
Schritt 1: Makro-Signale aus FXMacroData abrufen
Die vier Makroserien verankern das BTC-Regime-Modell: Kurs der USD- Ich weiß . Inflation des KPI- Das ist ... 10-Jahres-Inflationsrate für die BrückennutzungUnd ... Spotpreis für GoldZusammen beschreiben sie das Liquiditätsumfeld, das Inflationsregime und die Nachfrage nach Hard Assets.
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}")
Jeder Endpunkt gibt Daten in der Reihenfolge der jüngsten zuerst zurück. val Die Figur steht in der Schlagzeile und announcement_datetime trägt den Zeitstempel der Freisetzung der zweiten Stufe nützlich für die in Schritt 4 erfasste Planung. val ist der Spotpreis.
Die Daten werden in der Datenbank auf der Website der Kommission veröffentlicht.
Als die Fed Ende 2024 mit Zinssenkungen begann und die Breakeven-Inflation über 2,2% blieb, stieg BTC von ~$60.000 auf über $90.000.
Schritt 2: Erstellen Sie einen zusammengesetzten Makroscore
Statt auf einen einzigen Indikator zu reagieren, synthetisiert ein zusammengesetztes Score alle vier Signale in eine Richtung zwischen -1 (Risiko-off, BTC bearish) und +1 (Risk-on, BTC bullish). Jede Komponente trägt einen gewichteten Begriff dazu bei, je nachdem, ob ihre aktuelle Lesung BTC historisch unterstützt oder ablehnt.
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)
Anleitung zur Interpretation der Punkte
| Punktumfang | Makro-Regelung | Empfohlene Signal |
|---|---|---|
| +0,5 bis +1,0 | Risikopositionen anpassungsfähige Zinsen, moderate bis hohe Inflation | Akkumulieren / halten von BTC |
| +0,1 bis +0,5 | Ein wenig unterstützend gemischte Signale, Übergangsregelung | Position reduziert, Warten auf Bestätigung. |
| -0,1 bis +0,1 | Neutral kein starkes Regime-Signal | Flat / nicht mehr erhältlich |
| -1,0 bis -0,1 | Risikoabgrenzung hohe Zinsen, deflationäres oder stagflationärer Umfeld | Ausgang / Verringerung der Langzeitbelichtung |
Schritt 3: Verbindung mit der Coinbase Advanced Trade API
Der Beamte . coinbase-advanced-py Die Bibliothek wickelt Coinbase REST API und verarbeitet JWT Authentifizierung automatisch. RESTClient Sie können den Namen Ihres Cloud API Trading Key und den zugehörigen EC-Privatschlüssel verwenden.
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}")
Für die Erstprüfung Sandbox verwenden
Coinbase Advanced Trade bietet eine Sandbox-Umgebung an api-public.sandbox.pro.coinbase.com- Gehen Sie . base_url="https://api-public.sandbox.pro.coinbase.com" - Ich bin hier . RESTClient Die Daten werden in einem System mit einem System für die Berechnung der Daten über die Datenverarbeitung und die Datenübertragung in einem Netzwerk mit einem Netzwerkplatz für die Datenberechnung und -übertragbarkeit erfasst.
Schritt 4: Planung um Makro-Veröffentlichungsereignisse
Eine der leistungsstärksten Funktionen von FXMacroData für den Algo-Handel ist der Endpunkt des Release-Kalenders.
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()}")
Mit dem genauen Zeitstempel für die Veröffentlichung können Sie eine Nachveröffentlichungssignal-Aktualisierung planen, die es der ersten Preisreaktion ermöglicht, sich vor dem Neuschätzen und Handel zu begleichen:
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)
Schritt 5: Größe der Positionen und Auftragserteilung auf Coinbase
Coinbase Advanced Trade-Orders funktionieren anders als Binance: Kaufen Die Befehle geben eine quote_size (USD-Menge auszugeben), während Verkaufen Die Befehle geben eine base_size Die nachstehende Größenfunktion skaliert die USD-Zuteilung mit der absoluten Größe des Makroscore höhere Überzeugung rechtfertigt eine größere Zuteilung, begrenzt auf ein konfigurierbares Maximum.
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 Preis Illustrativ 2024
Der Makro-Score überstieg im ersten Quartal 2024 über +0,3, da die Fed sich stabil hielt und die Breakeven-Inflation stieg. BTC lief in den folgenden Monaten von ~ $ 40k auf $ 70k, bevor sich der Score zurückzog, da die Zinssenkungserwartungen vollständig in Rechnung gestellt wurden.
Schritt 6: Zusammenstellen der gesamten Strategie-Schleife
Jetzt bringen Sie alle Teile zusammen in eine einzige . run_strategy() Funktion. Bei jedem Aufruf holt es frische Makrodaten ab, berechnet die Punktzahl neu, erkennt eine Regimeänderung und geht entweder entsprechend ein oder aus.
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)
Schritt 7: Risikomanagement und betriebliche Überlegungen
Eine Makrosignalstrategie handelt selten Regimeänderungen, die durch FOMC, CPI und NFP-Drucke getrieben werden, produzieren typischerweise 610 umsetzbare Signale pro Jahr. Diese geringe Frequenz ist durch Design: Sie positionieren für mehrwöchige Richtungsbewegungen, nicht für Intraday-Rauschen. Jede Position birgt jedoch ein bedeutendes Risiko, daher sind disziplinierte Kontrollen essentiell.
✓ Tun
- Papierhandel in der Coinbase-Sandbox für mindestens zwei Wochen vor dem Start
- Maximale Zuweisung auf 20% des Kontos pro Handel
- Einstellen eines täglichen Abzugschaltwerks: Stoppen, wenn die Verluste innerhalb von 24 Stunden 5% übersteigen
- Log alle Ergebnisse, Handel und Konto-Snapshot in einer Datei für die Prüfung
- Verwenden Sie einzigartige
client_order_idUUIDs zur Verhinderung von doppelten Aufträgen beim erneuten Versuch
Vermeiden
- Eintritt in eine Position unmittelbar zum Zeitpunkt der Freigabe Warte 60 90 s bis die Liquidität normalisiert
- Übermäßige Anpassung von Punktewichtungen an einen einzelnen Zinszyklus
- Mehrfache Bot-Instanzen gleichzeitig auf demselben Konto ausführen
- Hardcoding-API-Schlüssel oder private Schlüssel im Quellcode oder in der Versionskontrolle
- Die Kosten für die Auftragsvergabe von Coinbase (0,050,60% Maker/taker) in den Gewinn- und Verlustberechnungen werden ignoriert
Alle Zeitstempel von FXMacroData einschließlich announcement_datetime In den Indikatorantworten und Release-Datumzeiten vom Kalenderendpunkt sind UTC. Halten Sie Ihre Planungslogik in UTC und konvertieren Sie nur für Anzeig Zwecke. Dies beseitigt die Sommerzeit-Unklarheit um US-Datenveröffentlichungen, die eine häufige Quelle von Planungsfehlern ist.
Grenzwerte für die Coinbase API
Coinbase Advanced Trade erzwingt Rate Limits pro Schlüssel (normalerweise 30 Anfragen/Sekunde). Die obige Strategie macht höchstens eine Handvoll API-Aufrufe pro Makro-Ereignis, gut innerhalb von Grenzen. Wenn Sie die Strategie auf Umfragepreise auf einem Timer erweitern, fügen Sie eine kleine time.sleep() zwischen den Anrufen, um sich von der Grenze fernzuhalten.
Erweiterung der Strategie
Das Rahmenwerk ist modular aufgebaut und es sind mehrere natürliche Erweiterungen zu untersuchen:
- Hinzufügen von COT-Positionsdaten Der CFTC COT-Endpunkt von FXMacroData bietet wöchentliche spekulative Positionierungen in USD-Futures.
/cot/usdund dem Makroscore einen Nettopositionsbegriff hinzufügen. - Mehrwährungsliquiditätsindex die Makro-Signale EUR, JPY und GBP neben USD einbeziehen.
- Brückungsgleichgeschwindigkeitssignal Anstelle des Niveaus der Breakeven-Inflation die 4-wöchige Veränderung der Inflation verwenden.
- Ausführung von Limitordern ersetzen
market_order_buy- Ich weiß .market_order_sellMitlimit_order_gtc_buy- Ich weiß .limit_order_gtc_sellSie müssen die aktuelle Bestellbuch mitclient.get_best_bid_askund sitzen Sie einen Tick in der besten Gebot / Fragen. - Clusterung des Release-Kalenders Fragen Sie die Veröffentlichungskalender Die Daten werden in einem Zeitraum von mindestens einem Monat nach der Anzeige der USD-Ereignisse erfasst und dann in einem Fenster mit mehreren hochinflüssigen Freisetzungen innerhalb von 48 Stunden ermittelt.
Zusammenfassung
Sie haben jetzt einen funktionierenden, auf Makro-Signale basierenden Bitcoin-Handelsbot, der mit Coinbase Advanced Trade verbunden ist. Die Strategie liest den Kurs des US-Dollar, den US-amerikanischen Verbraucherpreis, die Breakeven-Inflation und Gold von FXMacroData aus, um einen zusammengesetzten Regime-Score zu erstellen, planen sich um reale Makroankündigungsereignisse herum und leiten BTC-USD-Marktorders proportional zur Regimeüberzeugung ein.
Der Makro-Ansatz handelt selten und mit hoher Überzeugung , was genau das ist, was Regime-basierte Strategien von geräuschverfolgenden technischen Systemen unterscheidet.