يقارن التنبيه كل ملاحظة USD/IDR جديدة وفعالة بالملاحظة السابقة، لا بوقت الاستطلاع السابق. الملاحظة الأولى تنشئ خط أساس، ولا تغيّر الأخطاء أو البيانات القديمة الحالة.
- استخدم
sources["IDR"]وeffective_at["IDR"]للحكم على IDR. الحقل العام source ملخص محافظ لكل العملات المطلوبة. - الملاحظة الأولى خط أساس فقط. بعد التجاوز ينفذ التنبيه مرة ثم يتوقف، ولا يعود إلا بعد ملاحظة صالحة ترجع دون العتبة.
- اكتب JSON في ملف مؤقت، اضبط 0600، ثم استبدل الملف بـ
os.replaceحتى لا تترك المقاطعة حالة ناقصة. - استخدم مهلة عشر ثوانٍ، واحفظ المفتاح في
EXCHANGERATE_API_KEY. اجعل الفاصل 60 ثانية على الأقل، واحترمRetry-Afterبعد 429. - نزّل النص الكامل واضبط العتبة ومسار الحالة خارج التحكم بالإصدارات. الإخراج إلى وحدة التحكم المحلية فقط.
نمذجة الملاحظة لكل عملة
استخدم sources["IDR"] وeffective_at["IDR"] للحكم على IDR. الحقل العام source ملخص محافظ لكل العملات المطلوبة.
from decimal import Decimaldef 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"], }تعريف سياسة التجاوز
الملاحظة الأولى خط أساس فقط. بعد التجاوز ينفذ التنبيه مرة ثم يتوقف، ولا يعود إلا بعد ملاحظة صالحة ترجع دون العتبة.
| الحالة | تغيير الحالة | التنبيه |
|---|---|---|
| الملاحظة الصالحة الأولى | حفظ خط الأساس | لا |
| ملاحظة دون العتبة | armed=true | لا |
| تجاوز والإنذار مسلح | armed=false | مرة واحدة |
| ملاحظة مكررة/قديمة أو خطأ | حفظ الحالة | لا |
حفظ الحالة بأمان
اكتب JSON في ملف مؤقت، اضبط 0600، ثم استبدل الملف بـ os.replace حتى لا تترك المقاطعة حالة ناقصة.
import jsonimport osimport tempfilefrom pathlib import Pathdef 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تقييد الشبكة والحصة
استخدم مهلة عشر ثوانٍ، واحفظ المفتاح في EXCHANGERATE_API_KEY. اجعل الفاصل 60 ثانية على الأقل، واحترم Retry-After بعد 429. الفاصل الافتراضي خمس دقائق ويستهلك نحو 8,640 طلباً خلال 30 يوماً؛ أما 60 ثانية فتستهلك نحو 43,200 وقد تتجاوز الحصة المشتركة.
استخدم مهلة عشر ثوانٍ، واحفظ المفتاح في EXCHANGERATE_API_KEY. اجعل الفاصل 60 ثانية على الأقل، واحترم Retry-After بعد 429.
تشغيل المراقب الكامل
نزّل النص الكامل واضبط العتبة ومسار الحالة خارج التحكم بالإصدارات. الإخراج إلى وحدة التحكم المحلية فقط. الحد الافتراضي لعمر البيانات ساعة واحدة. اضبط FX_ALERT_MAX_AGE_SECONDS إذا كنت تقبل مرجعاً يومياً أو سوقاً مغلقاً. python-exchange-rate-alerts.py
chmod 700 python-exchange-rate-alerts.pyexport 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اختبار السياسة دون انتظار السوق
اختبر الملاحظة الأولى والتجاوز والبيانات القديمة وإعادة التسليح بواسطة محاكاة للشبكة.