Por qué los datos macro impulsan Bitcoin
Bitcoin se negocia menos como una acción tecnológica y más como un activo macro. No paga dividendos, no reporta ganancias y no tiene un modelo de flujo de efectivo para anclar su valor. En su lugar, BTC se mueve con las condiciones de liquidez global, las expectativas de tasas de interés reales y la fortaleza del dólar las mismas fuerzas que impulsan el EUR/USD y el AUD/JPY. Eso significa que el kit de herramientas macro construido para los operadores de divisas se aplica directamente a Bitcoin.
Cuando la Fed alivia, la liquidez del dólar inunda los mercados de riesgo y BTC tiende a liderar la carga. Cuando el IPC sorprende al alza, las narrativas de devaluación monetaria empujan el capital a activos duros. Cuando la inflación de equilibrio aumenta, los rendimientos reales se comprimen y el oro se eleva junto con BTC. Cada una de estas señales se observa de antemano a través de los puntos finales del indicador de FXMacroData timestamped al segundo y disponible a través del API REST limpio.
Esta guía construye un robot de trading algorítmico basado en señales macro para BTC-USD en Coinbase Advanced Trade es una empresa de comercio electrónico.Al final tendrás una estrategia de Python que funcione:
- Extrae datos sobre el tipo de interés de política monetaria en dólares, la inflación, la tasa de equilibrio y el oro de FXMacroData
- Combina estos datos en una puntuación compuesta de los regímenes macro
- Programación de ejecución alrededor de las macros de alto impacto a través del calendario de liberación de FXMacroData
- Envía órdenes de mercado BTC-USD en Coinbase utilizando el oficial
coinbase-advanced-pyEl SDK
Tesión central
Los cambios de régimen macro ciclos de recorte de tasas, pivotes de inflación, reversiones de tendencia del dólar crean vientos de cola direccionales de varias semanas para Bitcoin.
Los requisitos previos
Antes de comenzar, asegúrese de tener listos los siguientes:
- Python 3.10+ todos los fragmentos utilizan una sintaxis de escritura moderna
- La clave de la API de FXMacroData inscribirse en / suscribirse y toma tu llave del tablero de la cuenta
- Cuenta de comercio avanzado de Coinbase con un saldo en dólares crear un Clave de comercio de API en la nube (nombre de clave API + clave privada CE) en el Plataforma para desarrolladores Consola con Comercio permisos habilitados
- Paquetes de Python¿ Qué ?
requests¿ Qué ?coinbase-advanced-py¿ Qué ?pandas¿ Qué ?schedule
pip install requests coinbase-advanced-py pandas schedule
Almacene sus credenciales como variables de entorno nunca secretos de código duro en archivos fuente:
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-----"
Claves de comercio de API en la nube vs Claves API heredadas
Coinbase ahora emite Claves de comercio de API en la nube A través de su consola de la Plataforma de Desarrolladores. Estos utilizan una clave privada EC para la autenticación JWT y han reemplazado el formato de clave HMAC API anterior. Asegúrese de crear una clave de negociación de API Cloud no una clave heredada al configurar sus credenciales de bot.
Paso 1: Obtener señales de macro de FXMacroData
Cuatro series macro anclan el modelo de régimen de BTC: Tipo de interés de política en USD¿ Qué ? Inflación del IPC, el Tasa de inflación de equilibrio a 10 años, y precio al contado del oroJuntos describen el entorno de liquidez, el régimen de inflación y el sentimiento de demanda de activos duros.
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}")
Cada punto final devuelve datos ordenados primero por el más reciente. val Tiene la figura principal y announcement_datetime lleva la marca de tiempo de liberación de segundo nivel útil para la programación contemplada en el paso 4. val es el precio al contado.
El régimen de entrada de la señal macro 20242025
Values ilustrativas. A medida que la Fed comenzó a reducir las tasas a finales de 2024 y la inflación de equilibrio se mantuvo por encima del 2.2%, BTC se recuperó de ~ $ 60k a más de $ 90k.
Paso 2: Construye una puntuación macro compuesta
En lugar de reaccionar a un solo indicador, una puntuación compuesta sintetiza las cuatro señales en un número direccional entre -1 (riesgo, BTC bajista) y +1 (riesgu, BTC alcista).
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)
Guía de interpretación de las puntuaciones
| Rango de puntuación | Macrorregimen | Sugiere una señal |
|---|---|---|
| +0,5 a +1,0 | Riesgo tasas acomodativas, inflación de moderada a alta | Acumular / mantener BTC largo |
| +0,1 a +0,5 | Se trata de una señal de apoyo leve de señales mixtas, régimen de transición. | Posición reducida, espera confirmación. |
| -0,1 a +0,1 | Neutral sin señal de régimen fuerte | Descatalogado / fuera de mercado |
| -1,0 a -0,1 | El riesgo de reducción tasas elevadas, entorno deflacionario o estagflacionario | Salida / Reducción de la exposición prolongada |
Paso 3: Conectar a la API de comercio avanzado de Coinbase
El oficial . coinbase-advanced-py La biblioteca envuelve la API REST de Coinbase y maneja la autenticación JWT automáticamente. RESTClient utilizando su nombre de clave de negociación de la API de la nube y la clave privada CE asociada.
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}")
Utilice la caja de arena para las pruebas iniciales
Coinbase Advanced Trade ofrece un entorno de caja de arena en api-public.sandbox.pro.coinbase.com- ¿ Qué pasa ? base_url="https://api-public.sandbox.pro.coinbase.com" ¿ Qué ? RESTClient para probar la lógica de los pedidos sin arriesgar fondos reales.
Paso 4: Programe los eventos de liberación de macros
Una de las características más potentes de FXMacroData para el comercio de algo es el punto final del calendario de lanzamiento. En lugar de hacer una encuesta en un temporizador fijo, consulta el tiempo de lanzado programado exacto para cualquier indicador y activa la actualización de la señal precisamente cuando se imprimen nuevos datos.
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()}")
Con la marca de tiempo exacta de liberación, puede programar una actualización de la señal posterior a la liberación permitiendo que la reacción inicial del precio se establezca antes de volver a calificar y operar:
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)
Paso 5: Posiciones de tamaño y envío de órdenes en Coinbase
Las órdenes de comercio avanzado de Coinbase funcionan de manera diferente a las de Binance: comprar Las órdenes especifican un quote_size (USD cantidad a gastar), mientras que Vender Las órdenes especifican un base_size La función de dimensionamiento a continuación escala la asignación en USD con la magnitud absoluta del puntaje macro una convicción más alta justifica una asignación más grande, limitada a un máximo configurable.
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
El valor de las acciones de la entidad es el valor de la inversión de la empresa.
Prueba retrospectiva ilustrativa. El puntaje macro cruzó por encima de +0.3 en el primer trimestre de 2024 ya que la Fed se mantuvo estable y la inflación de equilibrio aumentó. BTC pasó de ~ $ 40k a $ 70k en los meses siguientes antes de que el puntaje se retirara a medida que las expectativas de recorte de tasas se fijaron completamente.
Paso 6: Ensambla el ciclo completo de la estrategia
Ahora juntemos todas las piezas en una sola . run_strategy() En cada llamada, se buscan nuevos datos macro, se recalcula la puntuación, se detecta un cambio de régimen y se ingresa o se sale en consecuencia.
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)
Paso 7: Gestión de riesgos y consideraciones operativas
Una estrategia de señales macro se negocia con poca frecuencia cambios de régimen impulsados por las impresiones del FOMC, IPC y NFP generalmente producen 610 señales procesables por año. Esa baja frecuencia es por diseño: usted está posicionando para movimientos direccionales de varias semanas, no ruido intradiario. Pero cada posición conlleva un riesgo significativo, por lo que los controles disciplinados son esenciales.
✓ Hacer
- Comercio de papel en la caja de arena de Coinbase durante al menos dos semanas antes de su puesta en marcha
- La asignación máxima al 20% de la cuenta por operación
- Configurar un interruptor de desactivación diaria: detenerse si las pérdidas exceden el 5% en 24 h
- Registre cada puntaje, comercio y instantánea de cuenta en un archivo para la auditoría
- Utilice el nombre único .
client_order_idUUID para evitar órdenes duplicadas en el nuevo intento
Evite las
- Entrar en una posición inmediatamente en el momento de la liberación esperar 6090 s hasta que la liquidez se normalice
- Peso de puntuación demasiado ajustado a un ciclo de tipo único
- Ejecutar varias instancias de bot simultáneamente en la misma cuenta
- Claves de API o claves privadas de codificación dura en el código fuente o el control de versiones
- Ignorar las comisiones de pedido de Coinbase (0,050,60% creador/tomador) en los cálculos de P&L
Todas las marcas de tiempo de FXMacroData incluyendo announcement_datetime En las respuestas de indicadores y las fechas de lanzamiento desde el punto final del calendario son UTC. Mantenga su lógica de programación en UTC en todo momento y convierta solo para fines de visualización. Esto elimina la ambigüedad de la hora de verano en torno a las publicaciones de datos de los Estados Unidos, que es una fuente común de errores de programa.
Límites de las tasas de API de Coinbase
Coinbase Advanced Trade impone límites de tasa por clave (normalmente 30 solicitudes / segundo). La estrategia anterior hace como máximo un puñado de llamadas de API por evento macro, dentro de los límites. Si se extiende la estrategia a los precios de encuesta en un temporizador, añadir un pequeño time.sleep() entre llamadas para mantenerse alejado del límite.
Ampliación de la estrategia
El marco es modular, y vale la pena explorar varias extensiones naturales a continuación:
- Añadir datos de posicionamiento de COT El punto final CFTC COT de FXMacroData proporciona posicionamiento especulativo semanal en futuros en USD. El posicionamento en USD extremo ha sido históricamente un viento favorable para BTC.
/cot/usdy añadir un término de posicionamiento neto a la puntuación macro. - Indice de liquidez en varias monedas incorporar las señales macro del EUR, JPY y GBP junto con el USD. Cuando varios bancos centrales del G10 están aliviando simultáneamente, las condiciones de liquidez global son más favorables para los activos de riesgo como el BTC.
- Señales de velocidad de equilibrio en lugar del nivel de inflación de equilibrio, utilizar la tasa de cambio de 4 semanas.
- Ejecución de órdenes de límite sustituir
market_order_buy- ¿ Qué ?market_order_sellconlimit_order_gtc_buy- ¿ Qué ?limit_order_gtc_sellPara evitar el pago de la totalidad del margen de compra.client.get_best_bid_asky sentarse un tick dentro de la mejor oferta / pedir. - Clustering de calendario de lanzamiento consulta el calendario de liberación para todos los eventos USD un mes fuera e identificar las ventanas donde múltiples liberaciones de alto impacto se agrupan dentro de las 48 horas.
Resumen de las actividades
Ahora tiene un bot de negociación de Bitcoin basado en señales macro que funciona conectado a Coinbase Advanced Trade. La estrategia lee la tasa de política del USD, el IPC, la inflación de equilibrio y el oro de FXMacroData para construir una puntuación compuesta del régimen, se programa en torno a eventos de anuncio macro del mundo real y presenta órdenes de mercado BTC-USD proporcionales a la convicción del régimen.
El enfoque macro se opera con poca frecuencia y con una alta convicción , que es precisamente lo que separa las estrategias basadas en el régimen de los sistemas técnicos que persiguen el ruido.