Por qué los datos macro impulsan Bitcoin
Bitcoin no es una empresa. No paga dividendos, no reporta ganancias y no tiene múltiplos de ingresos para anclar una valoración. En su lugar, BTC se negocia como el activo más sensible al riesgo en el mercado una apuesta apalancada en las condiciones de liquidez global, la fortaleza del dólar y las expectativas de tasas de interés reales. Eso significa que el mismo conjunto de herramientas macro utilizado por los operadores de FX para posicionarse en EUR/USD o AUD/JPY se aplica directamente a Bitcoin.
Cuando la Fed reduce las tasas, la liquidez del dólar se expande y los activos de riesgo BTC generalmente lidera la carga. Cuando el IPC sorprende al alza, las narrativas de cobertura de inflación vuelven a surgir. Cuando los rendimientos reales colapsan, las narrativas sobre la devaluación monetaria empujan el capital a alternativas de activos duros. Cada una de estas señales se observa de antemano a través de los puntos finales de indicadores de FXMacroData, con sello de tiempo al segundo y disponible a través del API REST limpio.
Esta guía te muestra cómo construir un robot de trading algorítmico basado en señales macro para BTC/USDT en Binance.
- Extrae señales macro en tiempo real de FXMacroData (tipo de interés, inflación, tasa de equilibrio, oro)
- Los combina en una puntuación macro compuesta
- Programar la ejecución en torno a las liberaciones de alto impacto a través del calendario de liberación
- Envía órdenes de mercado y límite en Binance a través del SDK oficial de Python
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.9+ todos los fragmentos utilizan una sintaxis de escritura estándar
- La clave de la API de FXMacroData inscribirse en / suscribirse y toma tu llave del tablero de instrumentos
- Cuenta de Binance con un saldo de USDT financiado crear claves API en el panel de Binance con Habilitar el comercio al contado y el comercio de margen He comprobado
- Paquetes de Python¿ Qué ?
requests¿ Qué ?python-binance¿ Qué ?pandas¿ Qué ?schedule
pip install requests python-binance pandas schedule
Almacene sus claves de API como variables de entorno en lugar de codificarlas:
export FXMACRO_API_KEY="YOUR_FXMACRODATA_KEY"
export BINANCE_API_KEY="YOUR_BINANCE_KEY"
export BINANCE_SECRET_KEY="YOUR_BINANCE_SECRET"
Paso 1: Obtener señales de macro de FXMacroData
Cuatro series macro son fundamentales para un 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 fuga hacia 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")
# 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}")
Cada punto final devuelve una lista ordenada de más reciente a más antigua data[0] La clave para las materias primas es val; para los indicadores macro, val Tiene la figura principal y announcement_datetime lleva la marca de tiempo de liberación de segundo nivel útil para la programación (que se cubre en el paso 4).
Entrada de la señal macro Régimen actual
Valores ilustrativos basados en datos de 20242025. A medida que la Fed recortaba las tasas e incrementaba la inflación de punto de equilibrio, BTC formó una tendencia alcista de varios meses.
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 (totalmente riesgo-fuera) y +1 (total riesgo-en).
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)
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: Conecte a Binance y obtenga el precio de BTC
Con la señal macro lista, conecta con Binance usando el oficial python-binance Siempre busque el precio al contado actual antes de realizar una orden para evitar valores de referencia obsoletos.
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}")
El comercio de papel primero
Binance proporciona un entorno de prueba en testnet.binance.vision- ¿ Cómo ? Client(key, secret, testnet=True) Valida la lógica de la señal y el tamaño durante al menos dos semanas antes de cambiar a la vida.
Paso 4: Programe los eventos de liberación de macros
Una de las características más poderosas de FXMacroData para el comercio algorítmico es el punto final del calendario de liberaciónEn lugar de sondear los indicadores en un temporizador fijo, puede consultar el tiempo de lanzamiento programado exacto para cualquier indicador y disparar su lógica precisamente cuando aterriza 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 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()}")
Armado 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 el mercado absorba la impresión durante unos minutos antes de volver a puntuar y volver a operar:
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)
Paso 5: Posiciones de tamaño y envío de órdenes
El tamaño de posición es donde la mayoría de las estrategias algorítmicas pierden dinero no en la lógica de la señal. La función a continuación mide el comercio de BTC como una fracción del capital disponible, escalado con la magnitud absoluta de la puntuación macro. Un entorno macro de mayor convicción (puntuación más lejos de cero) justifica una asignación más grande, pero nunca más que un máximo configurable.
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
Paso 6: Ensambla el ciclo completo de la estrategia
Ahora combine cada pieza en una sola . run_strategy() Función que recupera nuevos datos macro, calcula el puntaje, verifica un cambio de régimen y abre o cierra una posición BTC en consecuencia.
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)
El valor de las transacciones de divisas de divisos de divisa de las divisas del mercado de divis asimismo se calcula en función de la situación de las operaciones de divisanzas de divisar de divisadas.
Prueba retrospectiva ilustrativa. La cruzada de la puntuación macro por encima de +0.3 a principios de 2024 coincidió con el comienzo del movimiento de BTC de ~ $ 40k a $ 70k. La puntuacion se retiró a medida que se fijaron las expectativas de recorte de tasas y la narrativa de activos duros se enfrió.
Paso 7: Gestión de riesgos y consideraciones operativas
Una estrategia de señal macro tiene una frecuencia de negociación mucho más baja que un sistema técnico puro las entradas y salidas generalmente ocurren alrededor de 68 lanzamientos de indicadores principales por año. Esa baja frecuencia es una característica, no un error: se está posicionando para cambios de régimen de varias semanas, no ruido intradiario. Sin embargo, también significa que cada posición conlleva más riesgo por operación, lo que hace que la gestión disciplinada del riesgo no sea negociable.
✓ Hacer
- Se aplicará un stop-loss del 0,5% al 2% por operación basado en el ATR
- Limita la posición máxima al 20% de la cuenta por operación
- Prueba posterior de al menos 2 ciclos de tipos de la Fed antes de su puesta en marcha
- Registre cada operación y puntuación en un archivo para la auditoría
- Utilice Binance testnet para las pruebas en seco primero
Evite las
- Perseguir movimientos intradiarios de BTC con señales macro
- Entrada inmediata en la liberación de datos (espera 6090 segundos)
- Peso de puntuación demasiado ajustado a un solo ciclo
- Funcionamiento sin interruptor de descenso diario
- Claves de API de codificación dura en archivos fuente
Una consideración adicional: BTC opera las 24 horas del día, los 7 días de la semana, pero los eventos macro están programados. Los lanzamientos de FOMC, CPI y NFP ocurren durante las horas de mercado de los Estados Unidos. Su programador debe estar consciente de la zona horaria utilice UTC en todo momento y convierta solo cuando se muestre a los usuarios finales. announcement_datetime El campo es siempre UTC, haciendo esto sencillo.
Ampliación de la estrategia
Este marco es intencionalmente modular.
- 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 corto es históricamente un viento de cola de BTC.
/cot/usdy añadir un término de posicionamiento neto a la puntuación macro. - Puntuación en varias monedas incorporar las señales macro del EUR, JPY y GBP para construir una puntuación global de liquidez.
- Velocidad de tendencia de equilibrio en lugar del nivel de inflación de equilibrio, utilizar la tasa de cambio de 4 semanas.
- Integración del calendario de lanzamiento consulta el calendario de liberación para todos los eventos de USD a un mes de distancia, agruparlos por peso de impacto e identificar las ventanas en las que se agrupen múltiples liberaciones de alto impacto en un plazo de 48 horas esos son los períodos que vale la pena posicionar.
Resumen de las actividades
Ahora tiene un bot de trading de Bitcoin basado en señales macro que conecta los datos del indicador FXMacroData directamente con la ejecución de Binance. La estrategia lee la tasa de política del USD, el IPC, la inflación de equilibrio y el oro para construir una puntuación macro compuesta, se programa en torno a eventos de anuncio del mundo real y los tamaños y presenta órdenes BTC/USDT proporcionalmente a la convicción del régimen.
El próximo artículo de esta serie cubre la prueba de retroceso de este marco contra datos históricos y calibración de los pesos de puntuación utilizando series temporales reales FXMacroData que se remontan a 2015.