Quant500 Academy

3. Configuración, credenciales y entornos separados

Nivel 7: Del cuaderno al proceso

Hay tres cosas distintas que la gente mete en el mismo saco: el código, que dice qué se hace; la configuración, que dice con qué parámetros; y las credenciales, que dicen quién eres. Mezclarlas es lo que convierte un error pequeño en una llamada al banco.

La configuración no se edita, se declara

Si para operar otra cartera hay que abrir un fichero y cambiar un número, el proyecto tiene un problema: cada operación distinta es una versión distinta del código, y ninguna queda registrada. La configuración debe llegar desde fuera, por argumentos de línea de comandos, por variables de entorno o por un fichero de configuración que el proceso lee al arrancar.

Un reparto que funciona bien en la práctica:

Hay una prueba rápida para saber si algo es configuración o es código: pregúntate si dos ejecuciones legítimas del mismo sistema podrían querer valores distintos. La ventana de la media móvil, no: forma parte de la estrategia y cambiarla es cambiar la estrategia. El capital asignado o el nombre del entorno, sí. Y una advertencia: la configuración no es un cajón de sastre. Si acabas metiendo condiciones dentro del fichero de parámetros, lo que estás haciendo es escribir código en un sitio donde nadie lo va a revisar ni a probar.

Fallar al arrancar es mejor que fallar a mitad

Leer la configuración es lo primero que hace el proceso, y debe hacerlo de forma que la ausencia de un valor lo mate ahí mismo, no cuarenta minutos después con media cartera montada.

# config.py
import os

def requerido(nombre):
    valor = os.environ.get(nombre)
    if not valor:
        raise RuntimeError('Falta la variable de entorno ' + nombre)
    return valor

# En el servidor, fuera del repositorio:
#   export BROKER_KEY='tu_clave_aqui'
#   export BROKER_SECRET='tu_secreto_aqui'
#   export ENTORNO='pruebas'
BROKER_KEY = requerido('BROKER_KEY')
BROKER_SECRET = requerido('BROKER_SECRET')
ENTORNO = requerido('ENTORNO')          # sin valor por defecto: a proposito

Ese detalle final es más importante de lo que parece. Un valor por defecto para el entorno es una trampa esperando su turno: el día que alguien olvide exportarlo, el proceso no fallará, hará algo. Y lo que haga dependerá de qué decidió el que escribió el valor por defecto meses atrás.

Credenciales: nunca en el repositorio, y si pasa, revocar

Una clave escrita en el código es una clave publicada. Los ficheros de credenciales viven fuera del proyecto o, si viven dentro, el fichero está listado en el fichero de exclusiones desde el primer día, junto con un ejemplo sin valores reales que sí se versiona.

Y esto hay que decirlo sin adornos: si una clave se sube por error, borrar el commit no arregla nada. El histórico ya se ha clonado, hay réplicas y cachés, y los repositorios públicos se rastrean con robots automáticos que encuentran secretos en cuestión de minutos. La única acción que sirve es entrar en el proveedor, revocar esa clave y emitir una nueva. Limpiar el historial viene después, y es higiene, no remedio. En 2016 Uber sufrió una brecha que expuso datos de unos 57 millones de usuarios y conductores: los atacantes entraron usando credenciales de almacenamiento que estaban en un repositorio de código privado de la empresa. Privado no significa seguro.

El accidente más común: apuntar al entorno equivocado

Pregunta a cualquiera que lleve tiempo operando y no te contará una estrategia que falló: te contará el día que ejecutó contra la cuenta real creyendo que era la de pruebas. Por eso el entorno no puede ser un comentario ni una costumbre, sino una barrera activa:

# guardas.py
CUENTAS = {
    'pruebas': 'https://sandbox.broker.example/v1',
    'real':    'https://api.broker.example/v1',
}

def resolver_destino(entorno, confirmar_real=False):
    if entorno not in CUENTAS:
        raise RuntimeError('Entorno desconocido: ' + str(entorno))
    if entorno == 'real' and not confirmar_real:
        raise RuntimeError('Operativa real sin confirmacion explicita: abortado')
    return CUENTAS[entorno]

Y en el punto de entrada, la confirmación se pide de forma que teclearla sea un acto consciente:

p.add_argument('--confirmar-real', action='store_true',
               help='Obligatorio para operar contra la cuenta real')
destino = resolver_destino(ENTORNO, args.confirmar_real)

La clave del diseño es que el valor por defecto de la bandera es falso y no existe ninguna forma de activarla sin escribirla. Si mañana alguien la convierte en un parámetro con valor por defecto verdadero para ahorrarse tecleo, la salvaguarda desaparece por completo aunque el código siga ahí.

Caso real: GitLab, 31 de enero de 2017

Un ingeniero de GitLab estaba resolviendo un incidente de replicación de la base de datos. Para rehacer la réplica había que vaciar un directorio de datos. Ejecutó el borrado, pero en la consola equivocada: la de producción. Cuando lo interrumpió, segundos después, quedaban unos pocos gigabytes de los cerca de trescientos que había.

Lo que convirtió el susto en incidente serio fue lo que vino después: de los cinco mecanismos de copia y recuperación que la empresa creía tener, ninguno funcionó como se esperaba. Se recuperó a partir de una instantánea tomada horas antes, y se perdieron alrededor de seis horas de datos de proyectos, incidencias y peticiones de cambio. GitLab publicó el postmortem completo y retransmitió la recuperación en directo, que es la parte admirable de la historia.

Traducido a operar una estrategia: la persona no se equivocó de comando, se equivocó de entorno. Es un fallo de diseño del sistema, no de atención. Un proceso que exige declarar el entorno y una bandera explícita para tocar lo real convierte ese descuido en un mensaje de error.

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.