Algo-Trading de Bitcoin na Coinbase com Sinais Macroeconômicos FXMacroData banner image

Implementation

How-To Guides

Algo-Trading de Bitcoin na Coinbase com Sinais Macroeconômicos FXMacroData

Construa um bot de negociação de Bitcoin impulsionado por sinais macro em Python: obtenha dados de taxa de política USD, inflação, breakeven e ouro do FXMacroData, componha uma pontuação de regime, agende em torno das divulgações do FOMC e CPI, e envie ordens BTC-USD na Coinbase Advanced Trade automaticamente.

Também disponível em English

Por que os dados macro impulsionam o Bitcoin

O Bitcoin é mais parecido com um ativo macro, não é mais um ativa tecnológica, não paga dividendos, não registra lucros e não tem um modelo de fluxo de caixa para ancorar seu valor. Em vez disso, o BTC se move com as condições de liquidez global, as expectativas de taxa de juros reais e a força do dólar as mesmas forças que impulsionam o EUR/USD e o AUD/JPY. Isso significa que o kit de ferramentas macro criado para os traders de FX se aplica diretamente ao Bitcoin.

Quando o Fed alivia, o dólar inunda os mercados de risco e a liquidez do dólar tende a liderar a carga. Quando o IPC surpreende para cima, as narrativas de depreciação monetária empurram o capital para ativos duros. Quando a inflação de equilíbrio aumenta, os rendimentos reais se comprimem e o ouro se recupera ao lado do BTC. Cada um desses sinais é observado antecipadamente através dos endpoints do indicador do FXMacroData timestamped to the second e disponível através de uma API REST limpa.

Este guia constrói um robô de negociação algorítmica orientado por macro-sinal para BTC-USD em Coinbase Advanced Trade (Comércio Avançado da Coinbase)No final, você terá uma estratégia Python que:

  • Extrai dados sobre taxa de juro política, inflação, inflações de equilíbrio e ouro do FXMacroData
  • Combina-os numa pontuação composta do regime macro
  • Agendar a execução em torno de macros de alto impacto através do calendário de lançamento FXMacroData
  • Envia ordens de mercado BTC-USD na Coinbase usando o oficial coinbase-advanced-py SDK

Tese central

As mudanças de regime macro ciclos de corte de taxas, pivots de inflação, inversões de tendência do dólar criam ventos favoráveis direcionais de várias semanas para o Bitcoin.

Requisitos

Antes de começar, certifique-se de ter pronto o seguinte:

  • Python 3.10+ todos os snippets usam sintaxe de digitação moderna
  • Chave da API do FXMacroData Inscreva-se em / subscrever e pegue a chave do painel da conta
  • Conta de Comércio Avançado da Coinbase com um saldo em USD criando um Chave de negociação da API da nuvem (nome da chave API + chave privada CE) no Plataforma de Desenvolvedores Consola com Comércio permissões habilitadas
  • Pacotes Python- Não . requests- Não . coinbase-advanced-py- Não . pandas- Não . schedule
pip install requests coinbase-advanced-py pandas schedule

Armazenar suas credenciais como variáveis de ambiente nunca segredos de código rígido em arquivos de origem:

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-----"

Chaves de negociação de API em nuvem vs Chaves API legadas

A Coinbase já emite . Chaves de negociação da API da nuvem através do console da sua plataforma de desenvolvimento. Estes usam uma chave privada EC para autenticação JWT e substituíram o formato de chave HMAC API mais antigo. Certifique-se de criar uma chave de negociação da API Cloud não uma chave legada ao configurar as credenciais do seu bot.

Passo 1: Obter sinais de macro do FXMacroData

Quatro séries macro ancoram o modelo do regime BTC: Taxa de política do dólar- Não . Inflação do IPC- O quê ? Taxa de inflação de equilíbrio a 10 anosE ... preço spot do ouroJuntos, descrevem o ambiente de liquidez, o regime de inflação e o sentimento de demanda por ativos 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 ponto final retorna dados ordenados em primeiro lugar, sendo o mais recente. val É o título do livro e ... announcement_datetime A data de lançamento do produto deve ser indicada com o selo de lançar do segundo nível útil para a programação abrangida na etapa 4. val é o preço spot.

Regime de entrada de sinais macro 20242025

Como o Fed começou a cortar taxas no final de 2024 e a inflação de equilíbrio manteve-se acima de 2,2%, o BTC subiu de ~ $ 60k para acima de $ 90k.

Passo 2: Crie uma pontuação macro composta

Em vez de reagir a um único indicador, uma pontuação composta sintetiza todos os quatro sinais em um número direcional entre -1 (risco-off, BTC bearish) e +1 (risico-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)

Guia de interpretação de pontuação

Intervalo de pontuação Macro regime Sugestão de sinal
+0,5 a +1,0 Risco-a taxas de ajustamento, inflação moderada a elevada Acumular / manter BTC em longo prazo
+0,1 a +0,5 Aumentar ligeiramente sinais mistos, regime de transição Posição reduzida, aguardando confirmação.
-0,1 a +0,1 Neutro sem sinal de regime forte Flat / fora de circulação
-1,0 a -0,1 Risco de compensação taxas elevadas, ambiente deflacionário ou estagflacionário Sair / Reduzir a exposição prolongada

Passo 3: Conecte-se à API de Comércio Avançado da Coinbase

O oficial . coinbase-advanced-py biblioteca envolve a API REST da Coinbase e lida com a autenticação JWT automaticamente. RESTClient Utilizando o nome da sua chave de negociação da API da nuvem e a chave privada CE associada.

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}")

Utilize a caixa de areia para testes iniciais

A Coinbase Advanced Trade fornece um ambiente de sandbox em api-public.sandbox.pro.coinbase.comPassa . base_url="https://api-public.sandbox.pro.coinbase.com" Para ... RESTClient para testar a lógica de encomenda sem arriscar fundos reais.

Passo 4: Agendar em torno de eventos de Macro Release

Um dos recursos mais poderosos do FXMacroData para negociação de algo é o ponto final do calendário de lançamento. Em vez de pesquisar em um temporizador fixo, você consulta o tempo exato de lançar programado para qualquer indicador e aciona o atualização do sinal precisamente quando novos dados são impressos.

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()}")

Com o carimbo de lançamento exato, você pode agendar uma atualização de sinal pós-lançamento permitindo que a reação inicial do preço se estabeleça antes de re-pontuar e negociar:

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)

Passo 5: Tamanho das posições e envio de ordens na Coinbase

As ordens de comércio avançadas da Coinbase funcionam de forma diferente da Binance: comprar As ordens especificam um quote_size (dolar de dólares a gastar), enquanto vender As ordens especificam um base_size A função de dimensionamento abaixo escala a alocação em USD com a magnitude absoluta da pontuação macro maior convicção justifica uma alocação maior, limitada a um máximo configurável.

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

O preço do Macro Score vs BTC Illustrativo 2024

O resultado foi de +0,3 no primeiro trimestre de 2024, enquanto o Fed manteve-se estável e a inflação de equilíbrio aumentou.

Passo 6: Montar o ciclo completo da estratégia

Agora juntem todas as peças numa só . run_strategy() Função: em cada chamada, ele recupera dados de macro frescos, recalcula a pontuação, detecta uma mudança de regime e entra ou sai de acordo.

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)

Etapa 7: Gestão de riscos e considerações operacionais

Uma estratégia de sinais macro negocia com pouca frequência mudanças de regime impulsionadas por impressões do FOMC, do IPC e do NFP normalmente produzem 610 sinais acionáveis por ano. Essa baixa frequência é por design: você está posicionando para movimentos direcionais de várias semanas, não ruído intradiário. Mas cada posição carrega risco significativo, portanto, controles disciplinados são essenciais.

✓ Fazer

  • Negociação em papel na caixa de areia da Coinbase durante pelo menos duas semanas antes da entrada em funcionamento
  • Alteração do limite máximo de 20% da conta por transacção
  • Configurar um interruptor de desligamento diário: parar se as perdas excederem 5% em 24 h
  • Registre todos os resultados, negócios e instantâneos de conta em um arquivo para auditoria
  • Use o único client_order_id UUIDs para evitar ordens duplicadas na reatendimento

Evite

  • Entrar numa posição imediatamente no momento da liberação esperar 6090 s até que a liquidez se normalize
  • Peso de pontuação excessivamente ajustado a um ciclo de taxa única
  • Execução de várias instâncias de bot simultaneamente na mesma conta
  • Chaves de API de codificação rígida ou chaves privadas no código fonte ou no controlo de versões
  • Ignorar as taxas de encomenda da Coinbase (0,050,60% de fabricante/tomador) nos cálculos de lucro e lucro

Todos os carimbos de tempo do FXMacroData incluindo announcement_datetime em respostas de indicadores e datas de lançamento do ponto final do calendário são UTC. Mantenha sua lógica de agendamento em UTC durante todo e converta apenas para fins de exibição. Isso elimina a ambiguidade de economia de tempo em torno das versões de dados dos EUA, que é uma fonte comum de bugs de agendar.

Limite de taxa de API da Coinbase

A estratégia acima faz no máximo um punhado de chamadas de API por evento macro, bem dentro dos limites. time.sleep() Entre as chamadas para ficar longe do limite.

Extensão da Estratégia

O quadro é modular.

  • Adicionar dados de posicionamento COT O ponto final CFTC COT da FXMacroData fornece posicionamento especulativo semanal em futuros em USD. /cot/usd e adicionar um termo de posicionamento líquido à pontuação macro.
  • Índice de liquidez em várias moedas incorporar sinais macro EUR, JPY e GBP ao lado do USD. Quando vários bancos centrais do G10 estão a flexibilizar simultaneamente, as condições globais de liquidez são mais favoráveis para activos de risco como o BTC.
  • Signo de velocidade de equilíbrio em vez do nível de inflação de equilíbrio, utilizar a taxa de variação de 4 semanas.
  • Execução de ordens de limite substituir market_order_buy- Não .market_order_sell Com limit_order_gtc_buy- Não .limit_order_gtc_sell Para evitar o pagamento do spread total, procure o livro de pedidos atual com client.get_best_bid_ask e sentar um tique dentro da melhor oferta/pede.
  • Clustering de calendário de lançamento consulta do Calendário de lançamento Para todos os eventos USD, um mês para identificar as janelas em que várias libertações de alto impacto se agrupam dentro de 48 horas.

Resumo

Agora você tem um robô de negociação de Bitcoin operando com sinais macro conectado ao Coinbase Advanced Trade. A estratégia lê a taxa de política do USD, o IPC, a inflação de equilíbrio e o ouro da FXMacroData para construir uma pontuação composta do regime, agende-se em torno de eventos de anúncio macro do mundo real e envia ordens de mercado BTC-USD proporcionais à convicção do regime.

A abordagem macro opera com pouca frequência e com alta convicção , o que é precisamente o que separa as estratégias baseadas em regime de sistemas técnicos de busca de ruído.

Blogroll