دوز مباشرة للمحتوى الرئيسي
دروس فالذكاء الاصطناعي

بنِي وشغّل صانع سوق Monad بلوك ببلوك باستعمال jev-trader

تعلّم كيفاش تثبّت jev-trader، وتشغّلو بأمان فـ وضعية التجربة، وتربط موديل Jev، وتفحص تغذيات HTTP وSSE ديالو، وتفسّر الكوتاسيونات والصفقات المنفّذة، وتفهم تحسينات الكمون اللي كتحافظ على دورة التداول ديالو داخل وقت البلوك ديال Monad، اللي كيقارب 300 ms.

بنِي وشغّل صانع سوق Monad بلوك ببلوك باستعمال jev-trader

شنو كيدير jev-trader

jev-trader هو بوت ديال التداول بلوك ببلوك لدفتر أوامر Kuru ديال MON-USDC فوق Monad. مع كل بلوك جديد، كيقرا دفتر الأوامر الحي، كيسول موديل واش يشري ولا يبيع، وكيصاوب نية ديال أمر محدود post-only فالجهة المختارة.

الثمن ديال الأمر كيتحدد بداخل QUOTE_INSIDE_TICKS تيكات من اللمسة الحالية. إلا كان السبريد ضيق بزاف، الثمن كيتحصر فاللمسة. البوت كيلغي الأوامر اللي كان حاطها من قبل وكيحط البديل فعملية Kuru وحدة باستعمال batchUpdate.

حيت الأمر post-only، راه معمول باش يبقى فدفتر الأوامر وما يتنفذش مباشرة. التنفيذ كيوقع ملي مشارك آخر كيحط أمر taker كيدوز الثمن ديالو. بهاد الطريقة، الاستراتيجية تقدر تربح السبريد بلا ما تخلصو، ولكن مخاطر التنفيذ، والمخزون، والغاز، والسوق باقية قائمة.

المميزات الرئيسية

  • قرار واحد مع كل بلوك ديال Monad: البوت كيعالج أحدث بلوك تقريبا كل 300 ms.
  • بيانات حية من دفتر أوامر Kuru: قارئ مخصص كيفك ترميز getL2Book وكيدمج AMM vault فدفتر الأوامر.
  • جوج اختيارات ديال الموديل: الموديل الوهمي الافتراضي كيستعمل قاعدة ديال الزخم، بينما MODEL=jev كيفعل موديل TypeSafe Jev.
  • سلوك آمن فالتجربة: بلا PRIVATE_KEY، البوت كيستعمل دفتر الأوامر الحقيقي وعمليات السوق الحقيقية، ولكن كيمحاكي الأوامر والتنفيذات ديالو.
  • تعويض الأوامر post-only: كل تحديث كيلغي الأوامر المعروفة اللي باقية فالدفتر وكيصيفط أمر post-only جديد فدفعة وحدة.
  • تتبع الوضعية والربح والخسارة: الأحداث كتعرض الوضعية، والنتائج المحققة وغير المحققة، وتكاليف الغاز، وعدد التنفيذات، ومجاميع أخرى.
  • المراقبة عبر HTTP وSSE: سيرفر صغير ديال Bun كيعرض آخر لقطة، حتى لـ 1,000 حدث تاريخي ديال البلوكات، وتدفق حي ديال الأحداث.
  • التأكيدات غير المتزامنة: المعاملات الحية كيتصيفطو فالمسار الرئيسي، بينما الإيصالات والفحوصات المرتبطة بها كيتعالجو من بعد.

بنية المشروع

شجرة المصدر كتفصل بين استقبال البلوكات، والوصول للسوق، وتقييم الموديل، ومنطق التداول، والمراقبة:

  • src/config.ts كيقرا إعدادات البيئة.
  • src/chain.ts كيتوصل بتحديثات WebSocket ديال newHeads، وكيستعمل polling كخطة احتياطية، وكيحتافظ غير بأحدث بلوك.
  • src/book.ts كيقرا وكيحلل دفتر الأوامر باستعمال eth_call وحدة.
  • src/market.ts كيتكلف بقراية دفتر Kuru، وإيداعات الهامش، والـ nonces المحلية، وتحديثات الدفعات، والتأكيدات غير المتزامنة.
  • src/model.ts كيعرف واجهة الموديل وكيقدم JevModel وMockModel.
  • src/trader.ts كيشغل حلقة التداول وكيحتافظ بتتبع الوضعيات والربح والخسارة.
  • src/server.ts كيقدم اللقطات، والتاريخ، وأحداث Server-Sent Events باستعمال Bun.serve.

التثبيت والإعداد

1. وجد ملف البيئة

من مجلد المستودع، نسخ إعدادات المثال:

cp .env.example .env

راجع ملف .env الناتج قبل ما تبدا التطبيق. أهم سلوك كيتحكم فيه وجود أو غياب PRIVATE_KEY.

خلي PRIVATE_KEY ما متعيّنش فالتشغيل الأول ديالك. التطبيق غادي يدير تجربة باستعمال بيانات السوق الحقيقية بلا ما يبث الأوامر ديالو.

2. ثبت الاعتماديات

المشروع كيستعمل Bun لتدبير الاعتماديات والتنفيذ:

bun install

3. شغل المتداول

bun run start

بالإعدادات الافتراضية، موديل الزخم الوهمي كيخدم كبديل للاستدلال. من بعد، السيرفر كيخلي حالة المتداول وتدفق الأحداث متاحين عبر نقاط HTTP.

اختيار موديل القرار

استعمل الموديل الوهمي الافتراضي

الموديل الافتراضي mock مناسب لتجريب المسار كامل بلا ما يتنادى Jev. كياخذ القرارات باستعمال قاعدة ديال الزخم، وكيخليك تتحقق من قراية دفتر الأوامر، والأوامر المحاكاة، والتنفيذات، والمحاسبة، وتدفق الأحداث.

فعل موديل Jev

باش تستعمل Jev، ضبط هاد القيم فـ .env:

MODEL=jev
TYPESAFE_AI_API_KEY=your_api_key

مع كل بلوك، كيتسول الموديل المختار على الحركة المتوقعة خلال HORIZON_BLOCKS. القيمة الافتراضية هي 100 بلوك، أو تقريبا 30 ثانية حسب README ديال المشروع.

القرار العادي كيكون يا إما buy يا إما sell. النتيجة hold ما كتمثلش استراتيجية ثالثة للموديل: كتبان غير ملي الموديل كيتأخر على الأجل المحدد ديال البلوك الحالي. فهاد الحالة، decision.late كتكون true وما كيتحط حتى أمر فداك البلوك.

التشغيل بأمان فmode ديال التجربة

ملي ما كتكونش PRIVATE_KEY مهيأة، jev-trader ما كيبعثش معاملات حية. ولكن كيبقى كيقرا دفتر Kuru الحقيقي وكيخرج قرارات حقيقية من الموديل.

الاقتباس المحاكى عندو status: "sim". كيبقى بلوك واحد وكيعتبر منفذا غير ملي طباعة حقيقية فالسوق كتدوز من الثمن ديالو. التنفيذ الناتج عندو simulated: true.

هاد الوضع مفيد باش تتحقق من:

  • واش تحديثات دفتر الأوامر كتوصل بشكل موثوق.
  • واش زمن استجابة الموديل كيبقى داخل الميزانية ديال البلوك.
  • شحال من مرة ممكن تتنفذ الاقتباسات.
  • كيفاش كتتبدل الوضعيات والربح والخسارة حسب قواعد المحاكاة.
  • واش لوحة المراقبة أو أي عميل SSE آخر كيتعامل مزيان مع كل نوع ديال الأحداث.

تفقد نقاط HTTP

كاينة نسخة منشورة للتجربة باستعمال الموديل الوهمي على https://jev-trader-production.up.railway.app.

قرا آخر لقطة

الـ root endpoint كيعطي الموديل اللي خدام دابا، والرصيد، وحالة التشغيل التجريبي، وآخر حدث ديال البلوك:

curl https://jev-trader-production.up.railway.app/

قرا التاريخ الأخير

الـ history endpoint كيرجع آخر 1,000 حدث ديال البلوكات:

curl https://jev-trader-production.up.railway.app/history

تبع بث SSE المباشر

استعمل curl -N باش تخلي الاتصال محلول وتبان الأحداث ملي كتوصل:

curl -N https://jev-trader-production.up.railway.app/events

البث كيرسل حدث snapshot ملي كيتاصل الكليان، ومن بعد حدث block على كل بلوك كيتعالج. إيصالات المعاملات المباشرة كتعطي تحديثات quote، والتنفيذات اللي كتكتاشف كتعطي أحداث fill.

فهم حدث ديال البلوك

حدث البلوك كيجمع حالة السوق، وقرار الموديل، والنية الجديدة ديال السعر، والسيولة الموجودة، ومعلومات على البوزيشن، والمجاميع التراكمية. هادا مثال مختصر:

{
  "block": 105488269,
  "mid": 0.022636,
  "bestBid": 0.022628,
  "bestAsk": 0.022644,
  "spreadBps": 7.07,
  "decision": {
    "action": "buy",
    "probabilities": { "buy": 0.77, "sell": 0.23, "hold": 0 },
    "upIn10": 0.77,
    "latencyMs": 81,
    "late": false
  },
  "quote": {
    "side": "buy",
    "price": 0.022629,
    "size": 200,
    "status": "sent",
    "capped": false
  }
}
  • mid وbestBid وbestAsk كيوصفو السوق اللي تلاحظ.
  • spreadBps كيعبر على السبريد الحالي بنقط الأساس.
  • decision.action هو الاتجاه اللي اختارو الموديل.
  • decision.probabilities كيبقي احتمالات الشراء والبيع ديال الموديل.
  • upIn10 كيساوي احتمال الشراء.
  • decision.latencyMs كيعطي مدة تقييم الموديل.
  • quote كيوصف الأمر اللي تحاول يتدار فهاد البلوك.
  • quote.cancel كيعرف الأوامر اللي كانت باقية واللي خاصها الإلغاء.
  • resting كيسجل الحجم المعروف ديال طلب الشراء والبيع من بعد التحديث.
  • position كيعطي الاتجاه، والحجم، وثمن الدخول، والنتائج غير المحققة.
  • totals كيجمع البلوكات، والقرارات، والأسعار، والتنفيذات، والتراجعات، والبلوكات المتأخرة، وكلفة الموديل، والغاز، وP&L.

سقف البوزيشن والتمويل

إلا منع سقف البوزيشن الجهة المطلوبة، ولا ما كانش المارجن المباشر كافي ليها، كيتحط السعر فالجهة المعاكسة. فهاد الحالة، quote.capped كتكون true. احتمالات الموديل الأصلية كتبقى بلا تغيير، وهادشي كيخلي المستهلكين يفرقو بين القرار ديال الموديل والجهة اللي تحط فيها السعر فعليا.

فهم تأكيدات الأسعار المباشرة

الإرسال المباشر كيتدار بلا انتظار للإيصال باش حلقة التداول ما تبقاش كتسنى. لذلك، حدث البلوك الأولي كيحتوي على نية فيها status: "sent".

gasMon المبلغ عليه كيتحسب بضرب حد الغاز فآخر رسم أساسي معروف زائد رسم الأولوية. المشروع كيوضح أن Monad كتخلص حد الغاز، وداكشي علاش كيتحسب هادا كالكلفة الحقيقية سواء نجحات المعاملة ولا تراجعات.

الإيصال كيوصل غالبا من بعد بلوك ولا جوج وكيعطي حدث مستقل ديال السعر:

event: quote
data: {
  "block": 105488269,
  "quote": {
    "status": "placed",
    "orderId": 100295812,
    "gasMon": 0.0357
  }
}

السعر المباشر يقدر يدوز لواحدة من هاد الحالات:

  • placed: المعاملة نجحات وفيها معرّف الأمر.
  • reverted: دفتر الأوامر تحرك وداز من الثمن المرسل قبل الإدراج، ولا الإلغاء المطلوب كان كيشير لأمر تعمّر من قبل.
  • lost: ما تلقاش حتى إيصال من بعد 10 بلوكات.

فهم أحداث التنفيذ

التنفيذات ما كتوقعش فمعاملة الوضع ديال البوت. كتوقع ملي أمر آخذ من متداول آخر كيضرب أمر باقٍ. البوت كيكشف Trade log المطابق بنفس عملية الاستطلاع ديال eth_getLogs اللي كتوفر معلومات السوق للموديل.

event: fill
data: {
  "block": 105488271,
  "fill": {
    "side": "buy",
    "size": 200,
    "price": 0.022629,
    "txHash": "0x…",
    "orderId": 100295812,
    "simulated": false
  }
}

txHash ديال التنفيذ كيرجع لمعاملة الآخذ. ملي كيتعالج تنفيذ، البث كيعكس حتى هو بيانات البوزيشن المحدثة، وP&L المحقق، ومجاميع التنفيذ التراكمية.

الانتقال للتداول المباشر

تحديد PRIVATE_KEY كيبدل التطبيق من السلوك التجريبي لإرسال المعاملات المباشرة. قبل ما تدير هادشي، تأكد من إعدادات البيئة، وتمويل المارجن، وحدود البوزيشن، وحجم الصفقة، ووضع السعر، وسقف الرسوم، وموثوقية RPC.

الوضع المباشر كيرسل أوامر Kuru حقيقية من نوع post-only وكيكلف غاز حقيقي. جرّب سير العمل كامل فالوضع التجريبي أولا، واستعمل حدود محافظة ملي تفعّل مفتاح ممول.

الإعدادات الرئيسية المرتبطة بالاستراتيجية اللي كيوصفها المشروع هي:

  • TRADE_SIZE_MON لحجم الأمر.
  • QUOTE_INSIDE_TICKS للوضع مقارنة مع أفضل سعر.
  • HORIZON_BLOCKS لأفق التنبؤ ديال الموديل.
  • MAX_FEE_GWEI لسقف رسوم المعاملة من النوع 2.
  • READ_RPC_URL لقراية دفتر الأوامر.
  • RPC_URL لإرسال المعاملات.

كيفاش البوت كيلتازم بمهلة 300 ms

المسار السريع مصمم بالضبط على جوج ديال الرحلات ذهابا وإيابا لـ RPC:

  1. واحد eth_call كيقرا دفتر الأوامر الحالي عبر READ_RPC_URL.
  2. واحد eth_sendRawTransaction كيرسل التحديث الموقع عبر RPC_URL وكيرجع ملي كتتقبل المعاملة.

هاد اللوب كيتفادى عن قصد بزاف ديال العمليات اللي تقدر تكون مكلفة:

  • ما كاينش eth_estimateGas لكل بلوك؛ حدّ الغاز كيتحط مسبقاً ولا كيتحسب مرة وحدة ملي كيبدا البرنامج.
  • ما كاينش eth_sendRawTransactionSync، اللي كيتسنى حتى كتتقترح المعاملة.
  • ما كاينش بحث على ثمن الغاز فالمسار السريع؛ المعاملات كتستعمل إعدادات رسوم ثابتة من النوع 2، برسوم أولوية ديال 2 gwei وسقف MAX_FEE_GWEI.
  • ما كاينش انتظار ديال الإيصال فحلقة اتخاذ القرار.
  • ما كايناش فحوصات داخلية للخزنة ولا للرسوم تقدر تأخر الطلب.

الـREADME كيشير لقياس تجريبي بنموذج وهمي فـdry-run بحوالي 18 ms p50 لقراية دفتر الأوامر، و100 ms p50 للّوب كاملة، وحوالي 80 ms محسوبة كوقت بديل الاستدلال الوهمي.

التحقق والقياس التجريبي

قيّس قارئ دفتر الأوامر المخصص

شغّل القياس المرفق باش تقارن القارئ المخصص مع الـSDK من ناحية الدقة والكمون:

bun run scripts/bench-read.ts

تحقق من ترميز المعاملات بلا اتصال

سكريبت الترميز التجريبي كيوقّع على عملية شراء وبيع بلا ما يبثّهم، ومن بعد كيتحقق باللي بيانات الاستدعاء اللي تولدات مطابقة للـSDK:

bun run scripts/dry-encode.ts

هادشي مفيد بزاف قبل تفعيل الوضع الحي، حيث وحدة السوق المحسنة للأداء كتستعمل بيانات استدعاء batchUpdate مرمّزة يدوياً.

نصائح متقدمة للتشغيل

  • راقب القرارات المتأخرة: تتبّع decision.late وtotals.lateBlocks. جواب متأخر من النموذج كيعني ما تحط حتى طلب فداك البلوك.
  • فرّق بين النية والتأكيد: ما تعتبرش status: "sent" طلباً موضوعاً. تسنّى الحدث اللاحق quote اللي فيه placed ولا reverted ولا lost.
  • تتبّع عروض الأسعار المحدودة بالسقف: ملي كتكون capped هي true، قارن الجانب المرسل مع احتمالات النموذج اللي بقات بلا تغيير باش تفهم علاش التنفيذ اختلف على الإشارة.
  • استعمل لقطة SSE: عملاء المراقبة الجدد خاصهم يبداو من أول حدث snapshot، ومن بعد يطبّقو تحديثات البلوكات وعروض الأسعار والتنفيذات اللي كتجي من بعد.
  • قيّس مساري RPC بجوج: القرايات البطيئة كتأخر القرارات، والإرسالات البطيئة كتنقص من احتمال يوصل عرض السعر قبل ما يتحرك السوق.
  • حسب حدود الغاز المؤداة: حتى المعاملة اللي رجعات بالخطأ تقدر تبقى عندها تكلفة مهمة، لذلك راقب gasMon وgasUsd ومجموع عمليات الرجوع، وما تقيّمش التنفيذات بوحدها.
  • تحقق باستعمال مخرجات التشغيل التجريبي: التنفيذات المحاكية كتَعتمد على صفقات حقيقية كتقطع ثمن الطلب، وهادشي كيخلي وضع التشغيل التجريبي أكثر واقعية من افتراض تنفيذ فوري، مع بقاء الفرق فموقعك الحقيقي فالطابور وطريقة التنفيذ.

الخلاصة

jev-trader كيجمع بين قارئ حي لدفتر Kuru، ونموذج قرار وهمي ولا Jev، وإرسال محسن لمعاملات Monad، وتدبير المراكز، وخدمة مراقبة SSE. بدا بلا PRIVATE_KEY، وعاين اللقطة وتدفق الأحداث، وقيّس المسار الحرج، وتحقق من الترميز قبل ما تفكر فالتنفيذ الحي. فالإنتاج، راقب التأكيدات، والبلوكات المتأخرة، والسقوف، وعمليات الرجوع، والمخزون، والربح والخسارة، وتكاليف الغاز مع بعضياتها.