Tutorial/Crear una alerta de tipo de cambio en Python con USD/IDR

Crear una alerta de tipo de cambio en Python con USD/IDR

Crea un monitor con la biblioteca estándar de Python que avise una vez al superar un umbral, guarde su estado y respete la frescura y los límites de la API.

ERexchangerate.dev·Sep 8, 2026·8 min de lectura

Una alerta debe comparar cada observación efectiva nueva con la anterior, no cada consulta HTTP con la consulta anterior. La primera observación crea una base, los datos antiguos y los errores no cambian el estado, y solo un cruce válido produce un aviso.

Key points
Usa sources["IDR"] y effective_at["IDR"] para juzgar el dato de IDR. Los campos globales son un resumen conservador de todas las monedas solicitadas.
La primera observación válida solo crea una base. Tras un cruce, desarma la alerta y vuelve a armarla únicamente cuando una observación válida posterior regrese por debajo del umbral.
Escribe el JSON en un archivo temporal, usa modo 0600 y reemplaza el archivo con os.replace. Así una interrupción no deja una base incompleta.
Usa un timeout de diez segundos, conserva la clave en EXCHANGERATE_API_KEY y espera al menos 60 segundos entre consultas. En 429 conserva el estado y respeta Retry-After.
Descarga el script completo, configura el umbral y la ruta de estado fuera del control de versiones. Solo imprime en la consola; no envía mensajes externos.

Modela la observación por moneda

Usa sources["IDR"] y effective_at["IDR"] para juzgar el dato de IDR. Los campos globales son un resumen conservador de todas las monedas solicitadas.

python · observation modelcopy
from decimal import Decimal

def idr_observation(payload: dict) -> dict:
    return {
        "rate": Decimal(str(payload["rates"]["IDR"])),
        "source": payload["sources"]["IDR"],
        "effective_at": payload["effective_at"]["IDR"],
        "market_session": payload["market_session"],
    }

Define la política de cruce

La primera observación válida solo crea una base. Tras un cruce, desarma la alerta y vuelve a armarla únicamente cuando una observación válida posterior regrese por debajo del umbral.

SituaciónCambio de estadoAviso
Primera observación válidaGuardar baseNo
Movimiento menor al umbralarmed=trueNo
Cruce con alerta armadaarmed=falseUno
Dato repetido/antiguo o errorConservar estadoNo

Guarda el estado de forma segura

Escribe el JSON en un archivo temporal, usa modo 0600 y reemplaza el archivo con os.replace. Así una interrupción no deja una base incompleta.

python · atomic state writecopy
import json
import os
import tempfile
from pathlib import Path

def save_state(path: Path, state: dict) -> None:
    path.parent.mkdir(parents=True, exist_ok=True)
    fd, temporary = tempfile.mkstemp(prefix=f".{path.name}.", dir=path.parent, text=True)
    try:
        os.fchmod(fd, 0o600)
        with os.fdopen(fd, "w") as handle:
            json.dump(state, handle, sort_keys=True)
            handle.write("\n")
        os.replace(temporary, path)
    except Exception:
        try:
            os.unlink(temporary)
        except OSError:
            pass
        raise

Limita red y cuota

Usa un timeout de diez segundos, conserva la clave en EXCHANGERATE_API_KEY y espera al menos 60 segundos entre consultas. En 429 conserva el estado y respeta Retry-After. El valor predeterminado de cinco minutos consume unas 8.640 llamadas en 30 días; un intervalo de 60 segundos consume unas 43.200 y puede superar la cuota compartida.

Los errores no pueden crear alertas falsas
Usa un timeout de diez segundos, conserva la clave en EXCHANGERATE_API_KEY y espera al menos 60 segundos entre consultas. En 429 conserva el estado y respeta Retry-After.

Ejecuta el monitor completo

Descarga el script completo, configura el umbral y la ruta de estado fuera del control de versiones. Solo imprime en la consola; no envía mensajes externos. La edad máxima predeterminada es una hora. Configura FX_ALERT_MAX_AGE_SECONDS si aceptas una referencia diaria o un mercado cerrado. python-exchange-rate-alerts.py

shell · run itcopy
chmod 700 python-exchange-rate-alerts.py
export EXCHANGERATE_API_KEY="your-key"
export FX_ALERT_THRESHOLD_PCT="1.0"
export FX_ALERT_POLL_SECONDS="300"
export FX_ALERT_STATE_PATH="$HOME/.local/state/fx-alert.json"
python3 python-exchange-rate-alerts.py

Prueba la política sin esperar al mercado

Prueba la primera observación, un movimiento menor, un cruce, una marca temporal repetida, datos antiguos, el rearme y un segundo cruce mediante un mock de red.

ER
exchangerate.dev
Guías de integración para desarrolladores.

Sigue leyendo

TutorialCómo obtener tipos de cambio en PythonLeer ReferenceLeer source y market_sessionLeer GuideHistorial de FX en una llamadaLeer
Más ComparacionesFixer vs exchangerate.devOpen Exchange Rates vs exchangerate.devCurrencylayer vs exchangerate.dev
AprenderReading source and market_session in your pipelineIndicative vs executable FX rates: what a rates API actually gives youECB reference rates, explained
Tasas en VivoEUR/USDGBP/USDUSD/JPY