Quant500 Academy

3. Autenticación: firmar cada petición con HMAC

Nivel 13: Conectar con Brokers Reales

Conectarse a una API de trading con Python consiste, típicamente, en usar la librería requests para hacer peticiones HTTP al endpoint de la API. Lo primero es obtener las credenciales (clave de API, secreto, y en algunos exchanges una passphrase) desde la plataforma. Consulta siempre la documentación oficial del bróker para los detalles concretos de endpoints, autenticación, límites de peticiones y formatos de datos.

En Coinbase Pro entras en la sección de API de tu cuenta y creas una nueva clave. Obtendrás tres valores: API key, API secret y API passphrase. Con ellos autenticas cada petición.

Como ya viste en niveles anteriores, esas credenciales nunca se escriben dentro del código. Se leen de variables de entorno, y el fichero que las define queda fuera del control de versiones:

import os
import time
import hmac
import hashlib
import base64
import json
import requests

# Definidas fuera del codigo, por ejemplo en un fichero .env que NO se sube a git:
#   export CB_API_KEY='tu_clave_aqui'
#   export CB_API_SECRET='tu_secreto_aqui'
#   export CB_API_PASS='tu_passphrase_aqui'
API_KEY = os.environ['CB_API_KEY']
API_SECRET = os.environ['CB_API_SECRET']
API_PASS = os.environ['CB_API_PASS']

Si la variable no existe, os.environ[...] lanza un KeyError y el programa muere al arrancar. Eso es exactamente lo que quieres: es mucho mejor fallar al inicio que descubrir a mitad de sesión que las credenciales estaban vacías.

Cómo funciona la firma

La clave secreta no viaja nunca por la red. Lo que viaja es una *firma*: un resumen criptográfico calculado con el secreto sobre los datos exactos de esta petición. El servidor, que conoce el mismo secreto, repite el cálculo y compara. Si coincide, la petición es auténtica y nadie la ha modificado por el camino.

# Marca de tiempo en segundos
timestamp = str(time.time())

method = 'POST'
request_path = '/orders'
body_json = json.dumps(body)

# El mensaje a firmar: timestamp + metodo + ruta + cuerpo, en este orden exacto
message = timestamp + method + request_path + body_json

# El secreto de Coinbase viene en base64: hay que decodificarlo antes de usarlo
hmac_key = base64.b64decode(API_SECRET)
signature = hmac.new(hmac_key, message.encode('utf-8'), hashlib.sha256)
signature_b64 = base64.b64encode(signature.digest()).decode('utf-8')

headers = {
    'CB-ACCESS-KEY': API_KEY,
    'CB-ACCESS-PASSPHRASE': API_PASS,
    'CB-ACCESS-SIGN': signature_b64,
    'CB-ACCESS-TIMESTAMP': timestamp,
    'Content-Type': 'application/json'
}

Hay tres detalles que provocan el 90% de los errores 401 de los principiantes:

Y una última medida que es puro sentido común operativo: al crear la clave, concédele solo permisos de consulta y de trading, nunca permiso de retirada de fondos, y restringe su uso a la IP de tu servidor si el exchange lo permite. Si algún día esa clave se filtra, la diferencia entre esos permisos y los completos es la diferencia entre un susto y una pérdida total.

El resto de Quant500

Lo que estás aprendiendo, aplicado al índice todos los días:

La cartera del modelo, cada semana en tu correo

Cada sábado, su semana en un minuto: cómo fue, lo mejor y lo peor, y qué directivos compraron con su dinero. Y el día que el modelo se rehace, qué entra y qué sale. Es una simulación, no un consejo. Como mucho un correo a la semana, sin publicidad y sin cuenta; te das de baja con un clic. Lo hace una persona: Pol Gracia.

Cartera modelo con resultados simulados, no una recomendación personalizada. Tu correo se usa solo para esto: privacidad.

Detrás de la Academia y del resto de Quant500 hay una sola persona: Pol Gracia Serrahima.