Tutorial/สร้างการแจ้งเตือนอัตรา USD/IDR ด้วย Python

สร้างการแจ้งเตือนอัตรา USD/IDR ด้วย Python

สร้าง monitor ด้วย Python standard library ที่แจ้งเตือนครั้งเดียวเมื่อข้าม threshold เก็บ state อย่างปลอดภัย และเคารพ freshness กับโควตา API

ERexchangerate.dev·Sep 8, 2026·อ่าน 8 นาที

การแจ้งเตือนควรเทียบ observation ของ USD/IDR ที่มีผลใหม่กับ observation ก่อนหน้า ไม่ใช่เทียบเวลาที่ polling ครั้งก่อน ครั้งแรกสร้าง baseline ส่วนข้อมูลเก่าหรือ error ไม่เปลี่ยน state

Key points
ใช้ sources["IDR"] และ effective_at["IDR"] เพื่อประเมิน IDR ส่วน source รวมเป็นเพียงสรุปแบบ conservative
observation แรกเป็น baseline เท่านั้น หลังข้าม threshold ให้แจ้งครั้งเดียว และ arm ใหม่เมื่อ observation ที่ถูกต้องกลับมาต่ำกว่า threshold
เขียน JSON ลงไฟล์ชั่วคราว ตั้ง mode0600 แล้วใช้ os.replace เพื่อป้องกัน state เสียหาย
ใช้ timeout 10 วินาที เก็บคีย์ใน EXCHANGERATE_API_KEY และ polling ห่างอย่างน้อย60วินาที เมื่อ429 ให้เก็บ state และทำตาม Retry-After
ดาวน์โหลดสคริปต์เต็ม ตั้งค่า threshold และ state path นอก source control และแสดงผลใน console เท่านั้น

สร้างโมเดล observation

ใช้ sources["IDR"] และ effective_at["IDR"] เพื่อประเมิน IDR ส่วน source รวมเป็นเพียงสรุปแบบ conservative

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"],
    }

กำหนดนโยบายการข้าม threshold

observation แรกเป็น baseline เท่านั้น หลังข้าม threshold ให้แจ้งครั้งเดียว และ arm ใหม่เมื่อ observation ที่ถูกต้องกลับมาต่ำกว่า threshold

สถานการณ์การเปลี่ยน stateการแจ้งเตือน
observation ที่ถูกต้องครั้งแรกบันทึก baselineไม่
observation ต่ำกว่า thresholdarmed=trueไม่
ข้าม threshold ขณะ armedarmed=falseหนึ่งครั้ง
ข้อมูลซ้ำ/เก่าหรือ errorคง stateไม่

บันทึก state อย่างปลอดภัย

เขียน JSON ลงไฟล์ชั่วคราว ตั้ง mode0600 แล้วใช้ os.replace เพื่อป้องกัน state เสียหาย

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

จำกัด network และ quota

ใช้ timeout 10 วินาที เก็บคีย์ใน EXCHANGERATE_API_KEY และ polling ห่างอย่างน้อย60วินาที เมื่อ429 ให้เก็บ state และทำตาม Retry-After ค่าเริ่มต้นทุกห้านาทีใช้ประมาณ 8,640 calls ใน30วัน ส่วนทุก60วินาทีใช้ประมาณ43,200และอาจเกิน quota ร่วมรายเดือน

Error ต้องไม่สร้างการแจ้งเตือนปลอม
ใช้ timeout 10 วินาที เก็บคีย์ใน EXCHANGERATE_API_KEY และ polling ห่างอย่างน้อย60วินาที เมื่อ429 ให้เก็บ state และทำตาม Retry-After

รัน monitor

ดาวน์โหลดสคริปต์เต็ม ตั้งค่า threshold และ state path นอก source control และแสดงผลใน console เท่านั้น ค่าเริ่มต้นอายุข้อมูลสูงสุดคือหนึ่งชั่วโมง ตั้ง FX_ALERT_MAX_AGE_SECONDS หากยอมรับข้อมูลอ้างอิงรายวันหรือตลาดปิด 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

ทดสอบนโยบายโดยไม่ต้องรอตลาด

ทดสอบ baseline, crossing, timestamp ซ้ำ, ข้อมูลเก่า, rearm และ crossing ครั้งที่สองด้วย network mock

ER
exchangerate.dev
คู่มือการเชื่อมต่อสำหรับนักพัฒนา

อ่านต่อ

Tutorialดึงอัตราแลกเปลี่ยนใน Pythonอ่าน Referenceอ่าน source และ market_sessionอ่าน Guideประวัติ FX ในคำขอเดียวอ่าน
เปรียบเทียบเพิ่มเติมFixer vs exchangerate.devOpen Exchange Rates vs exchangerate.devCurrencylayer vs exchangerate.dev
เรียนรู้Reading source and market_session in your pipelineIndicative vs executable FX rates: what a rates API actually gives youECB reference rates, explained
อัตราสดEUR/USDGBP/USDUSD/JPY