VPS لروبوتات التداول: ما الذي يهم فعلاً؟
اكتشف ما يحتاجه روبوت التداول فعلاً: إعادة التشغيل عبر systemd، ضبط الساعة، حماية مفاتيح API، نبضات الحياة، وحدود زمن الاستجابة الواقعية.
ما الذي يحتاجه روبوت التداول من VPS
يُقيَّم VPS المخصّص لروبوتات التداول وفق أربعة أمور: هل تعود العملية إلى العمل بعد توقفها، وهل الساعة مضبوطة، وهل يصعب سرقة مفاتيح API (واجهة برمجة التطبيقات)، وهل تعرف عند توقفها. تأتي السرعة الخام في مرتبة متأخرة بالنسبة إلى روبوت للاستخدام الفردي، لأن الجزء الأبطأ في مسار طلبك هو الوسيط والمسافة إليه، وليس المضيف الذي يشغّل Python.
هذا دليل هندسي. لا يتضمن أي جزء منه نصيحة مالية، ولا يناقش أي استراتيجية.
الاستمرارية تعتمد على انضباط إعادة التشغيل، لا على رقم في صفحة مبيعات
تختلف التزامات الاستمرارية المعلنة. تحدد AWS نسبة لا تقل عن 99.5 بالمئة لمثيل EC2 واحد، ونسبة 99.99 بالمئة لعمليات النشر المؤهلة عبر عدة مناطق توافر. تغطي هذه الالتزامات توافر البنية التحتية، لا سلامة bot لديك. قد يتوقف bot بسبب استثناء غير معالَج، أو websocket لا يعيد الاتصال مطلقاً، أو قاتل OOM (نفاد الذاكرة)، بينما يظل الخادم قيد التشغيل طوال الوقت. لذلك، السؤال المفيد هو: ماذا يحدث خلال الثواني العشر التالية لخروج العملية؟
شغّل bot كخدمة systemd، ودع نظام init يتولى إعادة التشغيل. ينفّذ ملف الوحدة ذلك.
[Unit]
Description=Trading bot
After=network-online.target
Wants=network-online.target
StartLimitIntervalSec=0
[Service]
Type=simple
User=bot
WorkingDirectory=/opt/tradingbot
EnvironmentFile=/etc/tradingbot/api.env
ExecStart=/opt/tradingbot/venv/bin/python -m tradingbot
Restart=always
RestartSec=10
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
ReadWritePaths=/var/lib/tradingbot
[Install]
WantedBy=multi-user.targetStartLimitIntervalSec=0 هو السطر الذي يغفل عنه كثيرون. تسمح الإعدادات الافتراضية لمجرى systemd ببدء التشغيل 5 مرات خلال 10 ثوانٍ، ويشمل ذلك البدء الأول وعمليات البدء اليدوية؛ ويمكن لإعدادات المدير تجاوز هذه القيم الافتراضية. عند بلوغ الحد، تتوقف محاولات إعادة التشغيل التلقائية، لكن يمكن بدء الوحدة يدوياً أو بواسطة timer أو socket بعد انقضاء الفاصل الزمني. يؤدي ضبط القيمة على 0 إلى تعطيل حد المعدل، ولذلك يواصل bot الذي يدخل في حلقة تعطل محاولاته بدلاً من التوقف بصمت. RestartSec=10 يمنع هذه الحلقة من إغراق exchange بمحاولات إعادة الاتصال.
تحقق من الملف قبل الوثوق به، ثم ابدأ الخدمة:
sudo systemd-analyze verify /etc/systemd/system/tradingbot.service
sudo systemctl daemon-reload
sudo systemctl enable --now tradingbot
systemctl status tradingbotenable هو الجزء الذي يبقى بعد إعادة التشغيل، وتؤدي تحديثات kernel إلى إعادة التشغيل. لمعرفة ما إذا كان bot يتوقف بصمت، اطلب من systemd عرض عداد إعادة التشغيل:
systemctl show tradingbot -p NRestarts
journalctl -u tradingbot --since "24 hours ago" | tail -50NRestarts=0 يحسب عدد مهام إعادة التشغيل التلقائية منذ آخر إعادة ضبط للعداد؛ ولا يثبت أن الأسبوع كان سليماً أو خالياً من الأعطال. تؤدي عمليات إعادة التشغيل اليدوية وsystemctl reset-failed إلى إعادة ضبط العداد، وقد يظل bot متوقفاً دون استجابة مع عرض القيمة 0. يحسب NRestarts=812 عدد 812 من مهام إعادة التشغيل، لا عدد عمليات إعادة الاتصال الناجحة بـexchange أو عمليات التداول، ولا يوضح وقت حدوثها. راجع journal لمعرفة التوقيت والسبب، بما في ذلك حالات الفشل التي تحدث قبل اتصال bot. يشرح تشغيل برنامج كخدمة systemd البنية الكاملة لملف الوحدة، بما في ذلك timers للمهام المجدولة مثل التقرير اليومي.
اضبط الساعة على UTC وتحقق من مزامنتها
تستخدم واجهات API الخاصة بالمنصات الزمنيات للتحقق من الطلبات الموقّعة؛ ويستخدم Binance Spot افتراضياً نافذة استقبال مدتها 5 ثوانٍ، ويرفض الزمنيات التي تسبق وقت الخادم بمقدار 1 ثانية على الأقل. تؤدي الساعة المنحرفة إلى أخطاء تبدو كأنها إخفاقات في المصادقة، لذلك قد يبدّل المستخدمون المفاتيح لساعات قبل التحقق من الوقت. في واجهات API المشابهة لـBinance، تكون الرسالة صريحة: Timestamp for this request was 1000ms ahead of the server's time.
اضبط الخادم على UTC. تؤدي المناطق الزمنية المحلية إلى قفزات مرتبطة بالتوقيت الصيفي في الأوقات المعروضة؛ أما Unix timestamps التي تستخدمها واجهات API فلا تقفز عند تغيير المنطقة الزمنية المعروضة.
sudo timedatectl set-timezone UTC
timedatectlيستخدم Ubuntu افتراضياً chrony ابتداءً من 25.10؛ ويمكن للتثبيتات الأقدم استخدام systemd-timesyncd، وهو عميل SNTP (بروتوكول وقت الشبكة البسيط). يضبط systemd-timesyncd الساعة، لكنه لا يستطيع الاستعلام من عدة خوادم في الوقت نفسه لاكتشاف مصدر وقت غير صحيح. استخدم chrony بدلاً منه:
sudo apt update && sudo apt install -y chrony
sudo systemctl enable --now chrony
chronyc tracking
chronyc sources -vالسطر الذي يجب قراءته من chronyc tracking هو System time، مثل System time : 0.000031415 seconds fast of NTP time. تشير القيمة الصغيرة إلى أن التصحيح المتبقي لساعة NTP الخاصة بـchrony صغير؛ تحقّق من المزامنة، ومن Root delay وRoot dispersion أيضاً قبل تقييم الدقة. إذا كانت القيمة Leap status : Not synchronised، فهذا يعني أن chrony غير متزامن، حتى إذا استجابَت الخوادم؛ فقد تُرفَض القياسات لأنها غير دقيقة بدرجة كافية. انتظر دقيقة، ثم تحقّق مرة أخرى قبل تعديل قواعد الجدار الناري.
أبقِ مفاتيح API خارج الأماكن التي تنسخها
مفتاح exchange مُسرَّب أخطر من مفتاح SSH مُسرَّب، لأن صلاحية السحب تحوّله فوراً إلى أموال. تغطي عادتان معظم المخاطر.
أولاً، لا تمنح مفتاح bot صلاحية السحب مطلقاً. وإذا كان exchange يدعم ذلك، فقيّد المفتاح بعنوان IP لخادمك. هذا هو الإجراء الوحيد الذي يجعل المفتاح المسروق عديم الفائدة تقريباً.
ثانياً، أبقِ السر خارج مجلد الشيفرة. كل ما يوجد داخل /opt/tradingbot ينتهي عاجلاً أو آجلاً في مستودع git أو أرشيف نسخة احتياطية. ضعه في ملف يملكه root ويقرأه systemd:
sudo install -d -m 750 -o root -g bot /etc/tradingbot
sudo install -m 640 -o root -g bot /dev/null /etc/tradingbot/api.env
sudo nano /etc/tradingbot/api.envيحتوي الملف على أسطر KEY=value عادية، من دون علامات اقتباس ومن دون export. يتيح النمط 640 للمالك root القراءة والكتابة، ويتيح لأعضاء المجموعة bot القراءة، من دون أي صلاحيات للمستخدمين الآخرين. تحقّق باستخدام sudo -u bot cat /etc/tradingbot/api.env، ثم باستخدام مستخدم غير مميّز خارج المجموعة bot، حيث يجب أن تفشل العملية مع Permission denied.
يجب ألا يعمل bot نفسه بصلاحيات root أو باستخدام مستخدم تسجيل الدخول الخاص بك. أنشئ حساب نظام مع shell nologin و/var/lib/tradingbot كمجلد home له، قبل بدء الخدمة أو إنشاء ملفات تملكها المجموعة bot:
sudo useradd --system --shell /usr/sbin/nologin --home-dir /var/lib/tradingbot --create-home botيوضح تشغيل الخدمات كمستخدم غير مميّز سبب كل خيار من هذه الخيارات، ومدى تأثير ProtectSystem=strict فعلياً. أما بقية الإعداد الأساسي للخادم، بما في ذلك مفاتيح SSH وجدار الحماية، فتوجد في الدقائق العشر الأولى على VPS جديد.
اكتشف توقف الخدمة قبل أن يكتشفه الوسيط
يقول systemctl status إن العملية قيد التشغيل. لكنه لا يقول إن bot ينفّذ أي شيء. فالعملية العالقة في حلقة إعادة محاولة للاتصال بـwebsocket متوقف تتجاوز فحوصات العملية في الوحدة السابقة.
استخدم heartbeat بدلاً من ذلك. يوفّر Uptime Kuma مراقبات push؛ إذ يتوقع أن يستدعي bot عنوان URL وفق جدول زمني، ويرسل تنبيهاً عندما يتوقف وصول الاستدعاءات. ضع الاستدعاء في نهاية الحلقة الرئيسية، بعد الجزء الذي يثبت أن bot يعمل، مثل القراءة الناجحة لبيانات السوق.
curl -fsS "http://monitor.example.com:3001/api/push/YOUR_TOKEN?status=up&msg=loop_ok"اضبط فترة المراقبة على ضعف مدة الحلقة تقريباً، حتى لا تؤدي التقلبات العادية في التوقيت إلى إرسال تنبيه. شغّل المراقب على خادم مختلف عن خادم bot، لأن المراقب الذي يتوقف مع الشيء الذي يراقبه لن يرسل أي تقرير. يوضّح مراقبة الحالة ذاتية الاستضافة باستخدام Uptime Kuma طريقة الإعداد.
أضف تنبيهاً للقرص أيضاً. سيملأ bot الذي يكتب سجلات مفصلة نظام الملفات الجذر خلال أسابيع، وعندما يمتلئ القرص تتوقف كتابة قاعدة البيانات، لا استدعاء الشبكة، لذلك تبدو الأعراض غير واضحة. يحافظ journalctl --vacuum-time=14d وسطر SystemMaxUse= في /etc/systemd/journald.conf على حجم journal ضمن حدود معقولة.
الجزء الصريح: زمن الاستجابة لا يعتمد في الغالب على خادمك
هنا يتوقف سوق منتجات VPS المخصّصة للتداول عن كونه تقنياً. تعرض الصفحات التسويقية أرقاماً أقل من ميلي ثانية، وتوحي بأن الخادم هو ما يفصل بينك وبين تنفيذ الأمر. لكن هذا لا ينطبق على كل روبوت تداول تجزئة تقريباً.
ينتقل أمرك من الروبوت إلى نقطة نهاية المنصة أو الوسيط عبر الإنترنت العام. وتتحكم المسافة الفعلية والربط بين مزود الخدمة لديك ومزود الخدمة لديهم في هذا المسار بدرجة كبيرة. ثم تضيف أنظمة الوسيط نفسها وقت الانتظار في قائمة المعالجة، وفحوص المخاطر، وحدود معدل الطلبات.
قِس ذلك بدلاً من التخمين. يعرض curl أزمنة الاتصال والوصول إلى أول بايت لنقطة نهاية فعلية:
curl -s -o /dev/null -w 'dns=%{time_namelookup}s connect=%{time_connect}s ttfb=%{time_starttransfer}s\n' \
https://api.kraken.com/0/public/Time
mtr -rwzc 100 api.kraken.comشغّل ذلك من خادم مرشح قبل الالتزام به. إذا كانت قيمة connect تساوي 0.180 ثانية، فهي تشمل تحليل DNS وإنشاء اتصال TCP؛ لكنها لا تحدد القارة التي يوجد فيها خادمك. وإذا كانت قيمة connect تساوي 0.004 ثانية وقيمة ttfb تساوي 0.140 ثانية، فإن الفرق يشمل إعداد TLS، وإرسال الطلب، وتأخيرات الشبكة، ومعالجة الخادم. يمكن أن يؤثر تغيير المضيف في بعض هذه المكونات، لذلك قارن القياسات من المواقع المرشحة.
فمتى يكون للمضيف أثر مهم؟ عندما يكون خادمك موجوداً داخل منشأة المنصة نفسها أو متصلاً بها عبر وصلة مباشرة، وتتنافس على موضعك في قائمة الانتظار؛ وهذا نشاط تجاري مختلف بميزانية مختلفة. ويكون مهماً أيضاً عندما تكون شيفرتك نفسها عنق الزجاجة: فالروبوت الذي يعيد حساب المؤشرات على كامل السجل في كل نبضة قد يستهلك 200 ميلي ثانية من وقت CPU في كل دورة، وهذا زمن استجابة فعلي يمكنك التحكم فيه مجاناً. حلّل أداء الدورة قبل أن تبحث عن خادم أسرع.
ما يهم في المضيف الذي تختاره هو الموقع الجغرافي، واستقرار الشبكة، وذاكرة كافية بحيث لا يتمكن OOM killer من التأثير في التشغيل. أضف ذاكرة إذا كنت تحتفظ بسجل النبضات في قاعدة بيانات محلية.
قائمة تحقق مختصرة قبل التشغيل الفعلي
- يطبع
systemctl is-enabled tradingbotالقيمةenabled، وتستمر الخدمة في العمل بعدsudo reboot. - يعرض
chronyc trackingحالة المزامنة، وانحرافاً في وقت النظام أقل من بضعة ميلي ثانية، مع بقاء تأخير الجذر والتشتت ضمن ميزانية التوقيت لديك. - يملك مفتاح API صلاحية التداول، ولا يملك صلاحية السحب، وتوجد قائمة سماح لعناوين IP إذا كانت المنصة توفرها.
- تؤدي إيقاف العملية باستخدام
sudo systemctl kill -s SIGKILL tradingbotإلى إعادتها بعد مهلةRestartSecووقت بدء التشغيل. - يرسل مراقب heartbeat تنبيهاً إليك بعد الفاصل الزمني المُعدّ، ويعيد المحاولة عندما توقف الروبوت عمداً.
- تكون السجلات محدودة الحجم، ويحتوي نظام الملفات الجذري على مساحة احتياطية في
df -h.
شغّل كل ذلك في بيئة الاختبار الخاصة بالمنصة أو في الوضع التجريبي لمدة أسبوع قبل استخدام أموال حقيقية. سيفشل كل عنصر أعلاه مرة واحدة على الأقل خلال ذلك الأسبوع، وهذا هو الغرض من الأسبوع.
FAQ
هل يحتاج روبوت التداول إلى خادم منخفض الكمون أو خادم bare metal؟
فقط إذا كنت تنافس مشاركين آليين آخرين في سرعة التنفيذ داخل المنصة نفسها، وهذا يعني عادةً استخدام colocation بدلاً من VPS عام. بالنسبة إلى روبوت التداول بالتجزئة، تتأثر مدة ذهاب الطلب وعودته أساساً بالموقع الجغرافي وبالمعالجة التي يجريها الوسيط نفسه. لذلك اختر خادماً قريباً من نقطة نهاية API، وقِس باستخدام curl وmtr قبل أن تدفع مقابل أي شيء أسرع.
ما مقدار RAM وCPU الذي يحتاج إليه روبوت التداول؟
تعتمد معظم الروبوتات ذات الاستراتيجية الواحدة على الشبكة، وتبقى في وضع الخمول بين الأحداث. تصبح الذاكرة العامل المحدِّد عندما تحتفظ بسجل tick داخل العملية أو تشغّل قاعدة بيانات محلية. لذلك راقب free -h والسجل بحثاً عن رسائل OOM kill بدلاً من التخمين.
لماذا ترفض واجهة API الخاصة بالمنصة طلباتي بسبب خطأ في الطابع الزمني؟
يقع الطابع الزمني للطلب خارج النافذة التي تقبلها المنصة. ويؤثر كل من انحراف الساعة وتأخر الطلبات. ثبّت chrony، وتحقق من أن chronyc tracking يعرض إزاحة صغيرة مقدارها System time وحالة leap متزامنة، وافحص أيضاً root delay وdispersion. يضمن ضبط الجهاز على UTC اتساق الأوقات المعروضة، لكنه لا يصحح انحراف الساعة. ولا يؤدي تدوير API key إلى إصلاح مشكلة الساعة.
كيف أمنع روبوتي من التوقف طوال الليل دون أن أعرف؟
شغّله باستخدام systemd مع Restart=always وStartLimitIntervalSec=0، لكي تستمر إعادة المحاولة عند حدوث حلقة تعطل بدلاً من بلوغ حد معدل بدء التشغيل. ثم أضف heartbeat يرسله الروبوت في نهاية كل حلقة ناجحة. تتولى إعادة التشغيل معالجة العملية. أما heartbeat فيكشف الحالة التي تكون فيها العملية حية لكنها عالقة.
هل يمكنني تشغيل الروبوت ونظام المراقبة على VPS نفسه؟
يمكنك ذلك، لكن نظام المراقبة سيعطيك معلومات مضللة في اليوم الذي تحتاج إليه فيه، لأن الانقطاع الذي يوقف الروبوت سيوقف نظام المراقبة معه. أبقِ التنبيهات على جهاز منفصل، ويفضل أن يكون لدى مزود أو في منطقة مختلفة، واستخدم خادم الروبوت للروبوت وسجلاته فقط.