Volver al blog

Cómo calcular la volatilidad de divisas: guía para desarrolladores

V
Vlado Grigirov
September 07, 2026
Currency API Exchange Rates Volatility Historical Data Python Risk Management

Saber cómo calcular la volatilidad de divisas es la diferencia entre una aplicación multidivisa que absorbe sin inmutarse un movimiento del 2% de un día para otro y otra que te despierta con una alerta a las 3 de la madrugada. La volatilidad es el número que te dice cuánto puede llegar a moverse un tipo de cambio, y casi todas las decisiones prácticas de un sistema que trabaja con divisas dependen de ella: cuánto tiempo sigue siendo válida una cotización, cuánto colchón añadir a un precio, cuándo cubrirse y cuándo lanzar una alerta.

Lo incómodo es que la mayoría de los tutoriales sobre el cálculo de la volatilidad se escribieron pensando en la renta variable. Dan por supuesto que hay un precio de cierre diario, un año bursátil de 252 días y una única cotización sin ambigüedades. El mercado de divisas no tiene nada de eso. Cotiza 24 horas al día, cinco días a la semana, en un mercado OTC descentralizado sin cierre oficial, y el "precio" de EUR/USD depende de en qué dirección lo cotices.

Esta guía recorre las matemáticas reales, las trampas propias del mercado de divisas y código funcional en Python y JavaScript que calcula la volatilidad realizada a partir de datos históricos de tipos de cambio.

Por qué la volatilidad de divisas importa ahora mismo

Septiembre de 2026 es un momento inusualmente bueno para pensar en la volatilidad, porque el mercado ha pasado casi todo el año en un régimen sospechosamente tranquilo... y luego dejó de estarlo por un momento.

Durante el verano, las divisas emergentes fueron menos volátiles que las del G7 durante cerca de 200 sesiones consecutivas, una racha que, según señaló Bloomberg, sería la más larga desde 2000 si se mantuviera. Las operaciones de carry trade financiadas en dólares encadenaron su mejor racha desde 2008, y se informó de que una popular cesta financiada en euros de real brasileño, peso colombiano y lira turca subía cerca de un 19% en lo que va de año: su mejor arranque desde 2005. Las estrategias de carry solo funcionan en mercados tranquilos, así que su rendimiento es en sí mismo una señal de volatilidad.

Después, a principios de septiembre, el yen se disparó más de un 2% frente al dólar en una sola sesión hasta tocar 155,28, su nivel más fuerte desde principios de agosto, mientras los operadores se posicionaban ante una nueva intervención del Ministerio de Finanzas de Japón. Aquello llegó tras una intervención conjunta de EE. UU. y Japón el 31 de julio y un récord de 11,73 billones de yenes (unos 73.000 millones de dólares) de intervención del MOF entre abril y mayo, después de que USD/JPY superara 160.

Ese contraste es toda la lección. La volatilidad media era baja. La volatilidad realizada en un día concreto fue enorme. Un sistema que dimensionara sus colchones de divisas a partir de una media anual móvil se habría equivocado de lleno justo el día en que importaba. Medir la volatilidad correctamente, y de forma continua, es lo que evita que eso ocurra.

Qué mide realmente la volatilidad de divisas

La volatilidad es la desviación típica de los retornos, expresada en términos anualizados. No es una previsión de dirección, ni es el tamaño de un movimiento. Es una medida de dispersión: hasta qué punto los retornos diarios de un par de divisas se reparten alrededor de su media.

Hay dos variantes que importan:

  • Volatilidad realizada (histórica): se calcula hacia atrás a partir de los tipos realmente observados. Es la que puedes calcular tú mismo desde una serie temporal y la que cubre esta guía.
  • Volatilidad implícita: se extrae de los precios de las opciones sobre divisas. Es la estimación del mercado a futuro. No puedes deducirla de los tipos al contado; necesitas un feed de datos de opciones.

Para la mayoría de los desarrolladores de aplicaciones (precios, facturación, cuadros de mando de tesorería, alertas de riesgo), la volatilidad realizada es suficiente y sale gratis si ya dispones de tipos históricos.

Una intuición rápida sobre las cifras: los pares principales como EUR/USD se han movido normalmente en una horquilla anualizada del 5% al 10% en periodos tranquilos y del 10% al 15% en momentos de tensión. Los pares emergentes suelen situarse dos o tres veces por encima. Esas bandas cambian con el tiempo, y precisamente por eso conviene medir en lugar de suponer.

La fórmula: retornos logarítmicos, desviación típica y anualización

El cálculo tiene tres pasos.

Paso 1: convierte los tipos en retornos logarítmicos.

r_t = ln(P_t / P_t-1)

Paso 2: calcula la desviación típica de esos retornos sobre la ventana que elijas (usa la desviación típica muestral, dividiendo entre n − 1).

Paso 3: anualiza multiplicando por la raíz cuadrada del número de observaciones por año.

annualised_volatility = stdev(r) * sqrt(N)

En conjunto:

σ_annual = stdev( ln(P_t / P_t-1) ) × √N

Por qué retornos logarítmicos y no variación porcentual

La variación porcentual simple es asimétrica: pasar de 1,10 a 1,20 es un +9,09%, pero el camino de vuelta de 1,20 a 1,10 es un −8,33%. Deberían ser iguales y de signo opuesto. Los retornos logarítmicos sí lo son: ln(1.20/1.10) y ln(1.10/1.20) solo se diferencian en el signo.

Esto importa mucho más en divisas que en renta variable por la inversión de la cotización. EUR/USD y USD/EUR describen el mismo mercado. Si calculas la volatilidad con variaciones porcentuales, obtienes dos respuestas ligeramente distintas según en qué dirección hayas cotizado el par, lo cual es obviamente incorrecto. Los retornos logarítmicos son simétricos ante la inversión: ln(1/x) = −ln(x), y la desviación típica ignora el signo. Mismo par, misma volatilidad, en cualquier dirección.

Los retornos logarítmicos también son aditivos en el tiempo, lo que hace trivial agregarlos a lo largo de varios días.

Por qué √N (y cuánto debe valer N en divisas)

La volatilidad escala con la raíz cuadrada del tiempo porque la varianza escala linealmente con el tiempo (bajo el supuesto estándar de paseo aleatorio). Para convertir la volatilidad diaria en anual, multiplica por √(days per year).

Los tutoriales de renta variable usan 252, el número aproximado de días de negociación de las bolsas estadounidenses. El mercado de divisas es distinto: funciona de forma continua desde el domingo por la tarde hasta el viernes por la tarde, es decir, unas 260 sesiones entre semana al año, menos un puñado de festivos de poca actividad. La mayoría de los proveedores de datos publican tipos todos los días laborables, incluidos aquellos en los que el mercado local de un país está cerrado.

La regla práctica: N debe coincidir con la frecuencia de muestreo de tus datos, no con una convención tomada prestada de otra clase de activo.

Frecuencia de los datosN (factor de anualización)
Diaria (días laborables, convención de divisas)260
Diaria (convención bursátil de 252 días)252
Semanal52
Mensual12
Horaria (24×5)~6.240
La diferencia entre 252 y 260 cambia tu resultado en torno a un 1,6% relativo: irrelevante para un cuadro de mando, relevante si comparas tu cifra con la de un proveedor. Elijas la que elijas, documéntala y mantenla constante.

Paso 1: consigue datos históricos de tipos de cambio limpios

La volatilidad solo es tan buena como la serie que hay debajo. Obtén una serie diaria con una sola llamada al endpoint /v1/timeseries:

curl -G "https://api.finexly.com/v1/timeseries" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d base=EUR \
  -d symbols=USD,JPY,GBP \
  -d start_date=2026-06-08 \
  -d end_date=2026-09-05

La respuesta es un mapa indexado por fecha:

{
  "success": true,
  "base": "EUR",
  "start_date": "2026-06-08",
  "end_date": "2026-09-05",
  "rates": {
    "2026-06-08": { "USD": 1.1421, "JPY": 178.62, "GBP": 0.8447 },
    "2026-06-09": { "USD": 1.1408, "JPY": 178.94, "GBP": 0.8451 }
  }
}

Una petición, una serie, sin bucle de paginación. La referencia completa de parámetros está en la documentación de la API de Finexly, y los patrones generales para trabajar con rangos de fechas los cubrimos en nuestra guía de la API de tipos de cambio históricos.

Cuatro problemas de datos exclusivos del mercado de divisas

Antes de fiarte del resultado, resuelve estos. Ninguno aparece en un tutorial de volatilidad de acciones, y los cuatro distorsionarán tu número.

1. No existe un cierre oficial. El mercado de divisas es descentralizado; nadie toca la campana. Cada proveedor toma su instantánea en un momento distinto: las 22:00 UTC, medianoche UTC, el fixing de referencia del BCE de las 14:15 CET o el fix WM/Reuters de las 4 de la tarde de Londres. Mezclar horas de instantánea dentro de una misma serie inyecta varianza artificial. Elige una convención y no la mezcles nunca. Si no sabes con seguridad qué hace tu proveedor, nuestra explicación sobre de dónde sacan los datos las API de tipos de cambio es un buen punto de partida.

2. Fines de semana y huecos. El mercado cierra el viernes por la tarde y reabre el domingo por la tarde. Un retorno de viernes a lunes cubre unas 65 horas de tiempo natural, pero en un cálculo ingenuo se trata como un solo "día". La mayoría de los profesionales lo aceptan y anualizan con recuentos de días laborables (el enfoque estándar), pero tienes que ser coherente. No rellenes hacia delante los tipos del fin de semana en la serie: una tirada de valores idénticos arrastrará tu desviación típica artificialmente a la baja.

3. Asimetría de la divisa base. Como se ha visto arriba, los retornos logarítmicos resuelven matemáticamente el problema de la inversión. Pero sigues teniendo que decidir en qué base estás midiendo el riesgo. La volatilidad de tu exposición en USD medida en EUR es una pregunta de negocio distinta de la del mismo par medido en USD, aunque el número salga idéntico. Sé explícito sobre el numerario.

4. Cruces triangulados. Si tu proveedor deriva, por ejemplo, SEK/NOK dividiendo SEK/USD entre NOK/USD, el resultado hereda el ruido de ambas patas y de cualquier desajuste temporal entre ellas. Los cruces sintéticos pueden mostrar una volatilidad sensiblemente mayor que la del mercado cotizado directamente. Nuestra guía sobre tipos de cambio cruzados explica cuándo la triangulación es segura y cuándo no.

Cuida también la precisión. Truncar los pares con JPY a dos decimales antes de calcular los retornos convierte los movimientos pequeños en ceros y sesga la volatilidad a la baja; consulta redondeo de divisas y decimales para la regla general. Guarda la precisión completa y redondea solo al mostrar.

Paso 2: calcula la volatilidad realizada en Python

Aquí tienes una implementación completa y con pocas dependencias. Usa requests y la biblioteca estándar; no hace falta pandas.

import math
import statistics
import requests

FX_DAYS_PER_YEAR = 260  # weekday sessions; use 252 for the equity convention


def fetch_series(base, symbol, start, end, api_key):
    url = "https://api.finexly.com/v1/timeseries"
    params = {
        "base": base,
        "symbols": symbol,
        "start_date": start,
        "end_date": end,
    }
    headers = {"Authorization": "Bearer " + api_key}
    response = requests.get(url, params=params, headers=headers, timeout=10)
    response.raise_for_status()
    return response.json()["rates"]


def log_returns(rates, symbol):
    """Ordered log returns from a date-keyed rates map."""
    dates = sorted(rates.keys())
    series = [rates[d][symbol] for d in dates]
    return [
        math.log(series[i] / series[i - 1])
        for i in range(1, len(series))
        if series[i] > 0 and series[i - 1] > 0
    ]


def annualised_volatility(returns, periods_per_year=FX_DAYS_PER_YEAR):
    if len(returns) < 2:
        raise ValueError("need at least two returns")
    return statistics.stdev(returns) * math.sqrt(periods_per_year)


rates = fetch_series("EUR", "USD", "2026-06-08", "2026-09-05", "YOUR_API_KEY")
returns = log_returns(rates, "USD")

vol = annualised_volatility(returns)
print("Observations:      {}".format(len(returns)))
print("Daily volatility:  {:.4%}".format(vol / math.sqrt(FX_DAYS_PER_YEAR)))
print("Annual volatility: {:.2%}".format(vol))

statistics.stdev es la desviación típica muestral (denominador n − 1), que es justo lo que quieres. Si te pasas a NumPy, recuerda que numpy.std usa por defecto la versión poblacional: pasa ddof=1 para que coincida.

Dos salvaguardas que merece la pena mantener en el código de producción: descarta los tipos no positivos antes de aplicar un logaritmo y niégate a devolver un número a partir de una ventana con demasiado pocas observaciones. Una volatilidad a 30 días calculada con nueve datos no es una volatilidad a 30 días.

Paso 3: el mismo cálculo en JavaScript

Aquí tampoco hace falta ninguna biblioteca numérica.

const FX_DAYS_PER_YEAR = 260;

async function fetchSeries(base, symbol, start, end, apiKey) {
  const url = new URL('https://api.finexly.com/v1/timeseries');
  url.searchParams.set('base', base);
  url.searchParams.set('symbols', symbol);
  url.searchParams.set('start_date', start);
  url.searchParams.set('end_date', end);

  const res = await fetch(url, {
    headers: { Authorization: `Bearer ${apiKey}` },
  });
  if (!res.ok) throw new Error(`Finexly returned ${res.status}`);
  const body = await res.json();
  return body.rates;
}

function logReturns(rates, symbol) {
  const dates = Object.keys(rates).sort();
  const series = dates.map((d) => rates[d][symbol]);
  const out = [];
  for (let i = 1; i < series.length; i += 1) {
    if (series[i] > 0 && series[i - 1] > 0) {
      out.push(Math.log(series[i] / series[i - 1]));
    }
  }
  return out;
}

function annualisedVolatility(returns, periodsPerYear = FX_DAYS_PER_YEAR) {
  if (returns.length < 2) throw new Error('need at least two returns');
  const mean = returns.reduce((a, b) => a + b, 0) / returns.length;
  const variance =
    returns.reduce((acc, r) => acc + (r - mean) ** 2, 0) / (returns.length - 1);
  return Math.sqrt(variance) * Math.sqrt(periodsPerYear);
}

const rates = await fetchSeries('EUR', 'USD', '2026-06-08', '2026-09-05', 'YOUR_API_KEY');
const vol = annualisedVolatility(logReturns(rates, 'USD'));
console.log(`Annualised volatility: ${(vol * 100).toFixed(2)}%`);

Fíjate en el denominador (returns.length - 1): la misma corrección de varianza muestral que en la versión de Python.

Volatilidad móvil y cómo detectar un cambio de régimen

Un único número sobre una ventana fija no te dice casi nada sobre cuándo se movió todo. La volatilidad móvil sí, y es la versión que de verdad quieres en un cuadro de mando.

def rolling_volatility(rates, symbol, window=30,
                       periods_per_year=FX_DAYS_PER_YEAR):
    dates = sorted(rates.keys())
    series = [rates[d][symbol] for d in dates]
    returns = [math.log(series[i] / series[i - 1]) for i in range(1, len(series))]
    return_dates = dates[1:]

    out = []
    for i in range(window - 1, len(returns)):
        chunk = returns[i - window + 1:i + 1]
        out.append((
            return_dates[i],
            statistics.stdev(chunk) * math.sqrt(periods_per_year),
        ))
    return out


for date, vol in rolling_volatility(rates, "USD", window=30)[-5:]:
    print("{}  {:.2%}".format(date, vol))

La elección de la ventana es un compromiso, no un dogma:

  • 10 días: muy reactiva, muy ruidosa. Buena para alertas, mala para fijar precios.
  • 30 días: la opción por defecto habitual. Reacciona en unas pocas sesiones sin dar bandazos.
  • 90 días: suave y estable. Buena para fijar ratios de cobertura y colchones de precio.

Una señal práctica de cambio de régimen es el ratio de volatilidad: divide la volatilidad a 10 días entre la de 90 días. Lecturas sostenidas por encima de aproximadamente 1,5 significan que la dispersión a corto plazo ha superado con claridad la línea base más larga. Aplicado a los pares con yen en torno a los episodios de intervención descritos antes, ese ratio se dispara mientras la cifra a 90 días apenas se mueve, que es exactamente la cuestión. Las ventanas largas esconden los eventos; las cortas los encuentran.

Si piensas ejecutar esto de forma continua sobre muchos pares, lee primero nuestras notas sobre caché y gestión de errores en API de divisas. Los tipos históricos diarios son inmutables una vez publicados, así que se pueden cachear indefinidamente: recalcula solo la ventana más reciente en lugar de volver a descargar un año de historia en cada carga de página. La página de planes de precios muestra dónde se sitúan los volúmenes de peticiones en cada nivel.

Cómo convertir un número de volatilidad en una decisión

Calcular la volatilidad es fácil. El valor está en usarla. Cuatro aplicaciones concretas:

  1. Ventanas de validez de las cotizaciones. El precio que muestras a un cliente es una opción corta que le has emitido. La deriva esperada a lo largo de un periodo de t días es aproximadamente σ_annual × √(t / 260). Con una volatilidad anualizada del 8%, una cotización de 24 horas conlleva en torno a un 0,5% de deriva esperada; con un 20%, más bien un 1,2%. Acorta el TTL cuando suba la volatilidad en vez de usar 15 minutos fijos para siempre.
  1. Colchones de precio. En lugar de fijar a fuego un margen de divisas del 2%, escálalo: buffer = k × σ_annual × √(settlement_days / 260). El colchón se ensancha automáticamente en regímenes de tensión y se estrecha cuando los mercados se calman, lo que te mantiene competitivo sin asumir riesgo oculto.
  1. Disparadores de cobertura. La exposición por sí sola no es riesgo; el riesgo es la exposición multiplicada por la volatilidad. Una exposición de 2 millones de dólares a un par con un 4% de volatilidad es un problema menor que 400.000 dólares en un par con un 30%. Ordena las decisiones de cobertura por exposure × σ, no por nocional. Nuestra guía sobre cobertura de divisas cubre los instrumentos; el número de volatilidad te dice qué merece uno.
  1. Detección de anomalías. Convierte cada nuevo movimiento diario en una puntuación z frente a la desviación típica de los últimos 30 días y lanza una alerta más allá de ±3. Esto detecta tanto eventos de mercado genuinos como datos defectuosos: un feed desactualizado o un cruce mal triangulado suele delatarse como un valor atípico inverosímil antes de que nadie lo note en un informe.

Para expresar estos movimientos en unidades de trader en lugar de porcentajes, consulta qué es un pip.

Errores habituales

  • Usar la variación porcentual en lugar de retornos logarítmicos. Introduce asimetría y hace que tu respuesta dependa de la dirección de la cotización.
  • Usar la desviación típica poblacional. numpy.std() sin ddof=1 infravalora la volatilidad, y mucho en ventanas cortas.
  • Rellenar hacia delante fines de semana y festivos. Los valores repetidos son días de retorno cero que arrastran mecánicamente la volatilidad hacia abajo.
  • Anualizar con la N equivocada. Datos semanales anualizados con 260 en lugar de 52 producen un número unas 2,2 veces mayor de lo debido.
  • Comparar volatilidades calculadas con horas de instantánea distintas. Dos proveedores, dos horas de fixing, dos números incomparables.
  • Dar una sola cifra anual y llamarla riesgo. La volatilidad se agrupa en racimos. Los meses tranquilos y las semanas violentas promedian en un número intermedio que no describe ninguno de los dos. Publica siempre una serie móvil junto al valor principal.
  • Suponer que baja volatilidad significa bajo riesgo. Los regímenes tranquilos y favorables al carry de 2026 lo fueron justo hasta que los titulares sobre la intervención movieron el yen un 2% en una sesión. Una volatilidad realizada baja describe el pasado reciente; no promete nada sobre la semana que viene.

Preguntas frecuentes

¿Cuál es un nivel de volatilidad normal para un par de divisas?

Los pares principales como EUR/USD y GBP/USD se han movido históricamente en torno al 5%-10% anualizado en condiciones tranquilas y al 10%-15% bajo tensión. Los pares emergentes suelen estar dos o tres veces por encima. En lugar de fiarte de reglas generales, calcula una volatilidad móvil a 90 días para los pares que te interesen y usa tu propia línea base: los niveles se mueven con el régimen.

¿Debo usar 252 o 260 días de negociación para anualizar la volatilidad de las divisas?

260 encaja mejor, porque el mercado de divisas cotiza todos los días laborables en lugar de seguir el calendario de una única bolsa. 252 es la convención bursátil y se usa mucho igualmente. La diferencia es de en torno a un 1,6% relativo, así que lo importante es elegir una, documentarla y aplicarla de forma coherente en todos los sitios donde compares números.

¿Puedo calcular la volatilidad implícita con una API de tipos de cambio?

No. La volatilidad implícita se despeja a partir de los precios de las opciones sobre divisas y requiere un feed de datos de opciones. Lo que sí puedes calcular a partir de una serie de tipos al contado o históricos es la volatilidad realizada. Para fijar precios, umbrales de cobertura y alertas en el código de tu aplicación, la volatilidad realizada suele ser la medida adecuada.

¿Cuántos datos históricos necesito?

Como mínimo, una observación más que la longitud de tu ventana, aunque eso da una estimación inestable. Como suelo práctico, usa 30 observaciones para una ventana de 30 días y descarga al menos un año de historia para poder comparar la lectura actual con una línea base más larga. El endpoint /v1/timeseries devuelve un rango de fechas arbitrario en una sola petición.

¿Por qué mi número de volatilidad difiere del de mi proveedor de datos?

Casi siempre es por una de estas cuatro causas: un factor de anualización distinto (252 frente a 260), desviación típica poblacional en lugar de muestral, una hora de instantánea distinta para el tipo diario, o retornos simples frente a logarítmicos. Comprueba esas cuatro antes de dar por hecho que los datos están mal.

¿La volatilidad predice en qué dirección se moverá una divisa?

No. La volatilidad mide dispersión, no dirección. Se espera que un par con un 20% de volatilidad anualizada se mueva mucho, pero el cálculo no dice nada sobre si sube o baja. Úsala para dimensionar el riesgo, no para tomar una posición.


¿Listo para calcular la volatilidad con datos en vivo? Consigue tu clave gratuita de la API de Finexly: sin tarjeta de crédito. Tendrás acceso a tipos en tiempo real e históricos de más de 170 divisas, con 1.000 peticiones gratuitas al mes y un endpoint /v1/timeseries que devuelve un rango de fechas completo en una sola llamada. Empieza con la API gratuita de tipos de cambio y amplía a medida que crezcan tus necesidades de datos.

Vlado Grigirov

Senior Currency Markets Analyst & Financial Strategist

Vlado Grigirov is a senior currency markets analyst and financial strategist with over 14 years of experience in foreign exchange markets, cross-border finance, and currency risk management. He has wo...

View full profile →