Warum Makrodaten Bitcoin antreiben
Bitcoin ist kein Unternehmen. Es zahlt keine Dividenden, meldet keine Gewinne und hat keine Umsatzmultiplen, um eine Bewertung zu verankern. Stattdessen handelt BTC wie das risikoempfindlichste Vermögen auf dem Markt eine Hebelwettung auf globale Liquiditätsbedingungen, Dollarstärke und reale Zinserwartungen. Das bedeutet, dass das gleiche Makro-Toolkit, das von FX-Händlern zur Positionierung in EUR/USD oder AUD/JPY verwendet wird, direkt auf Bitcoin anwendet.
Wenn die Fed die Zinsen senkt, expandiert die Dollarliquidität und Risikovermögenswerte rally BTC führt in der Regel die Ladung. Wenn der CPI überrascht nach oben, Inflationssicherungs-Narrative wieder auftauchen. Wenn die realen Renditen zusammenbrechen, Narrative über Geldverwertung schieben Kapital in Hard-Asset-Alternativen. Jedes dieser Signale ist im Voraus über die Indikatorendpunkte von FXMacroData beobachtbar, zeitgestempelt bis zur Sekunde und über eine saubere REST API verfügbar.
Dieser Leitfaden führt Sie durch den Aufbau eines makrosignaldriven algorithmischen Handelsbots für BTC/USDT auf Binance.
- Zieht Echtzeit-Makro-Signale aus FXMacroData (Policy-Rate, Inflation, Breakeven-Ratio, Gold)
- Kombiniert sie zu einem zusammengesetzten Makroscore
- Planung der Ausführung bei Releases mit hoher Wirkung über den Release-Kalender
- Übermittelt Markt- und Limit-Orders auf Binance über das offizielle Python SDK
Kernthese
Makro-Regime-Ä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.9+ alle Snippets verwenden eine Standard-Syntax
- FXMacroData-API-Schlüssel melden Sie sich an /abonnieren Und holen Sie Ihren Schlüssel vom Armaturenbrett
- Binance-Konto mit einem USDT-Guthaben API-Schlüssel im Binance-Dashboard erstellen mit Ermöglichen des Spot- und Marginhandels überprüft
- Python-Pakete- Ich weiß .
requests- Ich weiß .python-binance- Ich weiß .pandas- Ich weiß .schedule
pip install requests python-binance pandas schedule
Speichern Sie Ihre API-Schlüssel als Umgebungsvariablen anstatt sie hart zu kodieren:
export FXMACRO_API_KEY="YOUR_FXMACRODATA_KEY"
export BINANCE_API_KEY="YOUR_BINANCE_KEY"
export BINANCE_SECRET_KEY="YOUR_BINANCE_SECRET"
Schritt 1: Makro-Signale aus FXMacroData abrufen
Vier Makroserien sind für ein BTC-Regime-Modell von zentraler Bedeutung: 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 Stimmung zur Flucht zu harten Vermögenswerten.
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")
# Each item: {"date": "2025-04-08", "val": 5.25, "announcement_datetime": "..."}
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 eine Liste zurück, die von neuesten bis ältesten geordnet ist. data[0] Die wichtigste Frage ist, ob die valfür Makroindikatoren val Die Figur steht in der Schlagzeile und announcement_datetime trägt den Zeitstempel für die Freigabe der zweiten Stufe, der für die Planung nützlich ist (in Schritt 4 erläutert).
Makro-Signal-Eingänge Aktuelles System
Als die Fed die Zinsen senkte und die Breakeven-Inflation stieg, bildete BTC einen mehrmonatigen Bullentrend.
Schritt 2: Erstellen Sie eine zusammengesetzte Makroscore
Statt auf einen einzigen Indikator zu reagieren, synthetisiert ein zusammengesetztes Score alle vier Signale in eine Richtungszahl zwischen -1 (vollständig risikoreich) und +1 (vollkommen risikorecht). Jede Komponente addiert oder subtrahiert Gewicht, je nachdem, ob die Lesung bullisch oder bärisch für Bitcoin ist.
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) ──────────────────────────
# Sub-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) ────────────────────────────
# CPI 2–4%: moderate inflation → neutral/slightly bullish
# CPI > 6%: high inflation → monetary debasement narrative → bullish
# CPI < 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 inflation expectations are re-anchoring → 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.6500 (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: Verbinden Sie sich mit Binance und holen Sie sich den BTC-Preis
Mit dem Makrosignal bereit, verbinden Sie sich mit Binance mit der offiziellen python-binance Der aktuelle Spotpreis wird immer vor der Bestellung abgeholt, um veraltete Referenzwerte zu vermeiden.
import os
from binance.client import Client
BINANCE_KEY = os.environ["BINANCE_API_KEY"]
BINANCE_SECRET = os.environ["BINANCE_SECRET_KEY"]
client = Client(BINANCE_KEY, BINANCE_SECRET)
# Verify connectivity
status = client.get_system_status()
print(f"Binance status: {status['msg']}") # → "normal"
# Latest BTC/USDT price
ticker = client.get_symbol_ticker(symbol="BTCUSDT")
btc_price = float(ticker["price"])
print(f"BTC/USDT spot: ${btc_price:,.2f}")
# Current USDT balance
account = client.get_account()
usdt_balance = next(
(float(b["free"]) for b in account["balances"] if b["asset"] == "USDT"),
0.0,
)
print(f"Available USDT: ${usdt_balance:,.2f}")
Papierhandel an erster Stelle
Binance bietet eine Testnet-Umgebung an testnet.binance.vision- Verwenden Sie ... Client(key, secret, testnet=True) Die Signallogik und -größen für mindestens zwei Wochen vor dem Start zu überprüfen.
Schritt 4: Planung um Makro-Veröffentlichungsereignisse
Eine der leistungsfähigsten Funktionen von FXMacroData für den algorithmischen Handel ist die Endpunkt des Release-KalendersAnstatt die Indikatoren auf einem festen Timer zu ermitteln, können Sie die genaue geplante Veröffentlichungszeit für jeden Indikator abfragen und Ihre Logik genau auslösen, wenn neue Daten landen.
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 release dates ordered ascending.
"""
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
# Find when the next FOMC policy rate decision is scheduled
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 release: {next_fomc.isoformat()} ({delta.days}d {delta.seconds // 3600}h away)")
else:
print("No upcoming policy_rate event found in calendar.")
# Find when the next CPI release is scheduled
next_cpi = get_next_release("usd", "inflation")
if next_cpi:
print(f"Next CPI release: {next_cpi.isoformat()}")
Mit dem genauen Zeitstempel für die Veröffentlichung können Sie eine Nachveröffentlichungssignal-Aktualisierung planen, die es dem Markt ermöglicht, den Druck für ein paar Minuten zu absorbieren, bevor Sie erneut bewerten und neu handeln:
def on_macro_release():
"""Called shortly after a scheduled macro release."""
print("Macro release fired — 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 settle slightly.
"""
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 library uses HH:MM:SS
schedule.every().day.at(fire_str).do(on_macro_release).tag(f"{currency}_{indicator}")
print(f"Scheduled signal 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
Die Positionsauswertung ist, wo die meisten algorithmischen Strategien Geld verlieren nicht in Signallogik. Die folgende Funktion misst den BTC-Handel als Bruchteil des verfügbaren Kapitals und skaliert mit der absoluten Größe des Makroscore. Eine Makroumgebung mit höherer Überzeugung (Score weiter von Null) rechtfertigt eine größere Allokation, aber nie mehr als ein konfigurierbares Maximum.
from binance.enums import SIDE_BUY, SIDE_SELL, ORDER_TYPE_MARKET, ORDER_TYPE_LIMIT
from binance.exceptions import BinanceAPIException
import math
def compute_quantity(
score: float,
usdt_balance: float,
btc_price: float,
max_position_pct: float = 0.20,
) -> float:
"""
Scale position size between 0 and max_position_pct of USDT balance.
Only trade when |score| > 0.30 to avoid noise-driven entries.
Returns BTC quantity rounded to Binance's minimum lot size (0.00001 BTC).
"""
if abs(score) < 0.30:
return 0.0
conviction = (abs(score) - 0.30) / 0.70 # 0.0 → 1.0
usdt_to_trade = usdt_balance * max_position_pct * conviction
btc_qty = usdt_to_trade / btc_price
return math.floor(btc_qty * 100_000) / 100_000 # 5 decimal places
def place_order(side: str, quantity: float, btc_price: float) -> dict | None:
"""
Submit a market order. For limit orders, pass a price to get_order_book
and sit 0.1% inside the spread.
"""
if quantity <= 0.0:
print("Quantity zero — no order placed.")
return None
try:
order = client.order_market(
symbol="BTCUSDT",
side=side,
quantity=quantity,
)
print(f"Order placed: {side} {quantity:.5f} BTC @ ~${btc_price:,.2f}")
return order
except BinanceAPIException as exc:
print(f"Binance order error: {exc.message}")
return None
Schritt 6: Zusammenstellen der gesamten Strategie-Schleife
Jetzt kombiniere jedes Stück zu einem einzigen . run_strategy() Funktion, die neue Makrodaten abruft, die Punktzahl berechnet, nach einer Regimeänderung sucht und entweder eine BTC-Position entsprechend eröffnet oder schließt.
import json
import pathlib
STATE_FILE = pathlib.Path("strategy_state.json")
def load_state() -> dict:
if STATE_FILE.exists():
return json.loads(STATE_FILE.read_text())
return {"position": 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. Fetch fresh 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)
print(f"Macro score: {score:+.4f} (prev: {state['last_score']:+.4f})")
# ── 3. Fetch current Binance position and price ───────────────
account = client.get_account()
btc_held = float(next(b["free"] for b in account["balances"] if b["asset"] == "BTC"))
usdt_held = float(next(b["free"] for b in account["balances"] if b["asset"] == "USDT"))
btc_price = float(client.get_symbol_ticker(symbol="BTCUSDT")["price"])
# ── 4. Regime change logic ─────────────────────────────────────
prev_score = state["last_score"]
was_long = prev_score >= 0.30
is_long_now = score >= 0.30
was_flat = abs(prev_score) < 0.30
is_flat_now = abs(score) < 0.30
if is_long_now and (was_flat or prev_score < 0):
# Enter or increase long
qty = compute_quantity(score, usdt_held, btc_price)
place_order(SIDE_BUY, qty, btc_price)
elif is_flat_now and was_long and btc_held > 0.0001:
# Exit long — macro regime has turned neutral
exit_qty = math.floor(btc_held * 100_000) / 100_000
place_order(SIDE_SELL, exit_qty, btc_price)
elif score < -0.30 and btc_held > 0.0001:
# Hard exit on bearish signal
exit_qty = math.floor(btc_held * 100_000) / 100_000
place_order(SIDE_SELL, exit_qty, btc_price)
print("BEARISH regime — full exit.")
# ── 5. Persist state ───────────────────────────────────────────
state["last_score"] = score
save_state(state)
# ── Run once immediately, then on each scheduled release ──────────────
run_strategy()
# Keep scheduler alive
while True:
schedule.run_pending()
time.sleep(10)
BTC/USDT vs Makro Score Simulierte 2024
Der Makro-Score überstieg Anfang 2024 über +0,3 und fiel mit dem Beginn der Bewegung von BTC von ~$40k auf $70k zusammen.
Schritt 7: Risikomanagement und betriebliche Überlegungen
Eine Makrosignalstrategie hat eine viel niedrigere Handelsfrequenz als ein reines technisches System Ein- und Ausstiege treten typischerweise bei etwa 68 wichtigen Indikatorveröffentlichungen pro Jahr auf. Diese niedrige Frequenz ist ein Merkmal, kein Fehler: Sie positionieren sich für mehrwöchige Regimeänderungen, nicht für Intraday-Rauschen.
✓ Tun
- Die Risikopositionen werden in der Tabelle 1 aufgeführt.
- Maximale Position auf 20% des Kontos pro Handel begrenzen
- Rückverfolgung von mindestens zwei Fed-Zinszyklen vor dem Start
- Log alle Trades und Scores in eine Datei für die Prüfung
- Verwenden Sie Binance Testnet für Trockenläufe zuerst
Vermeiden
- Nachfolgende Intraday-BTC-Bewegungen mit Makrosignalen
- Die Daten werden sofort nach der Datenfreigabe eingegeben (warten Sie 6090 Sekunden)
- Übermäßige Anpassung von Punktgewichten an einen einzelnen Zyklus
- Betrieb ohne täglichen Abzugsschalter
- Hard-Codierung von API-Schlüsseln in Quelldateien
Eine weitere Überlegung: BTC handelt rund um die Uhr, aber Makro-Events sind geplant. Die FOMC-, CPI- und NFP-Releases finden alle während der US-Marktzeiten statt. Ihr Planer sollte sich der Zeitzone bewusst sein verwendet UTC und konvertiert nur, wenn er den Endbenutzern angezeigt wird. announcement_datetime Das Feld ist immer UTC, so dass es einfach ist.
Erweiterung der Strategie
Hier sind natürliche Erweiterungen, die wir als nächstes erforschen:
- 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ährungs-Score die Makro-Signale von EUR, JPY und GBP zu integrieren, um einen globalen Liquiditätswert zu ermitteln.
- Brückungsverlauf Anstelle des Niveaus der Breakeven-Inflation die 4-wöchige Veränderung der Inflation verwenden.
- Integration des Release-Kalenders Fragen Sie die Veröffentlichungskalender für alle USD-Ereignisse, die einen Monat entfernt sind, sie nach dem Einflussgewicht gruppieren und Fenster identifizieren, in denen sich innerhalb von 48 Stunden mehrere hochwirksame Freisetzungen gruppieren das sind die Zeiträume, für die es sich zu positionieren lohnt.
Zusammenfassung
Sie haben jetzt einen funktionierenden, makrosignalgesteuerten Bitcoin-Handelsbot, der FXMacroData-Indikatordaten direkt mit der Ausführung von Binance verbindet. Die Strategie liest den Kurs des US-Dollar, den Preisindex, die Breakeven-Inflation und Gold, um einen zusammengesetzten Makroscore zu erstellen, planen sich um reale Ankündigungsereignisse herum und schlägt BTC/USDT-Orders proportional zur Regimeüberzeugung ein.
Der nächste Artikel dieser Serie behandelt die Rückprüfung dieses Rahmens anhand historischer Daten und die Kalibrierung der Punktzahlgewichte mit echten FXMacroData-Zeitreihen bis 2015.