Skip to content
→ المدونة

تغذية حية لفوارق الأسعار بين المنصتين، دون الحاجة إلى خادم

dino.markets

ننشر التغذية المطابَقة عبر REST مجانًا، وهي طريقة جيدة للتحقق من المباريات المصطفة حاليًا بين Kalshi وPolymarket. لكنها طريقة سيئة لمراقبة فارق سعري وهو ينفتح فعليًا. تتأخر لقطة REST نحو دقيقتين عن اللحظة الحية، وقسنا كم يبقى الفارق بين المنصتين مفتوحًا قبل أن يُغلق: نحو 9.2 ثانية عند الوسيط. يُغلق 55% خلال 10 ثوانٍ، و96% خلال 30 ثانية. لا يمكن للقطة أُخذت قبل دقيقتين أن تُظهر لك شيئًا انفتح وأُغلق عشرات المرات منذ ذلك الحين.

مراقبة فارق وهو ينفتح لا تحتاج إلى خادم يجلس في مكان ما. تحتاج إلى اتصال مفتوح، وعلامة تبويب المتصفح يمكنها الاحتفاظ به بالكفاءة نفسها. إليك كيف تبني ذلك في ملف HTML واحد.

لماذا لا تستطيع اللقطة مجاراة الحدث

REST مناسبة لتصفح ما هو مطابَق والتأكد من وجود زوج، وتمنحك خطة Free ذلك. لكنها ليست بمستوى يصلح للتنفيذ. يأتي التأخر البالغ دقيقتين من طريقة عمل نقطة نهاية اللقطة المخزَّنة مؤقتًا، ولا نخطط لإزالته. إذا أردت رؤية فارق لحظة تشكّله، تحتاج إلى الدفق، والدفق يحتاج إلى تذكرة قصيرة الأجل قبل أن يتحدث إليك.

اسحب تذكرة باستدعاء curl واحد

لا يقبل الدفق مفتاح API الخاص بك مباشرة. تستبدله أولاً بتذكرة، ثم تتصل بالتذكرة بدلاً منه:

curl -X POST https://api.dino.markets/v1/stream/token \
  -H "Authorization: Bearer sk_live_..."

تحمل الاستجابة تذكرة صالحة لنحو 120 ثانية، وعنوان WebSocket الدقيق للاتصال به، والقنوات التي يستحقها مفتاحك. لا يلمس مفتاحك المقبس نفسه إطلاقًا.

افتح المقبس من ملف HTML واحد

وبيدك تذكرة، اتصل بالدفق. لا يمر أي مفتاح عبر هذا الاتصال الثاني، بل التذكرة فقط، في حقل data.t بإطار الاتصال:

<script>
async function mintTicket(apiKey) {
  const res = await fetch("https://api.dino.markets/v1/stream/token", {
    method: "POST",
    headers: { Authorization: `Bearer ${apiKey}` },
  });
  return await res.json();
}

function openStream(mint, onGap) {
  const ws = new WebSocket(mint.ws_url);
  ws.onopen = () => ws.send(JSON.stringify({ id: 1, connect: { data: { t: mint.ticket } } }));
  ws.onmessage = (e) => {
    // one WS frame can carry several newline-separated objects
    for (const line of e.data.split("\n")) {
      if (!line) continue;
      const msg = JSON.parse(line);
      if (Object.keys(msg).length === 0) { ws.send("{}"); continue; } // server ping, pong straight back
      if (msg.push?.pub?.data?.type === "price") onGap(msg.push.pub.data);
    }
  };
  return ws;
}
</script>

تستقبل onGap تحديث السعر مباشرة: id، وpriced_at، وspread_pts، وpotential_arb_pct (لا يُضبط إلا عندما تتقاطع المنصتان في مراجحة مؤكَّدة)، ومصفوفة outcomes تحمل سعر ask لكل من Kalshi وPolymarket على كل جانب. اكتب مباشرة إلى صف جدول من هناك. لا حاجة إلى أي إطار عمل، فقط وسم script ومتصفح.

احتفظ بهذا الملف على جهازك الخاص أثناء الاختبار. يستطيع أي شخص يعرض مصدره قراءة المفتاح المضمَّن فيه، لذا اقصر هذا النمط على صفحة تُشغّلها بنفسك بدلاً من صفحة تنشرها علنًا.

إعادة الاتصال بتذكرة جديدة

التذكرة أحادية الاستخدام وقصيرة الأجل عن قصد، لذا تحتاج الصفحة إلى إعادة الاتصال بتذكرة جديدة بدلاً من افتراض أن الاتصال الأول سيبقى إلى الأبد:

<script>
async function keepAlive(apiKey, onGap) {
  const mint = await mintTicket(apiKey);
  const ws = openStream(mint, onGap);
  ws.onclose = () => setTimeout(() => keepAlive(apiKey, onGap), 1000);
}
</script>

هذه هي الحلقة كاملة. في كل مرة يُغلق فيها المقبس، اسحب تذكرة جديدة وأعد الاتصال. معالجة الـping في openStream أعلاه مهمة هنا أيضًا: يتحقق الخادم من وجود عميل حي بين الحين والآخر، والصفحة التي لا تستجيب يُقطع اتصالها قبل وقت طويل من انتهاء صلاحية تذكرة الـ120 ثانية من تلقاء نفسها.

ما لا تستطيع علامة تبويب المتصفح فعله

يمنحك هذا جدولاً حيًا للفوارق طوال بقاء علامة التبويب مفتوحة، ولا شيء بعد ذلك. أغلق علامة التبويب ويختفي الاتصال، إلى جانب أي شيء لم تدوّنه في مكان آخر. لا يوجد سجل ترجع إليه، ولا شيء ينبّهك عندما تبتعد عن الشاشة. هذا مناسب للمراقبة. لكنه لا يمكن أن يعمل دون إشراف.

تلك مشكلة مختلفة: إبقاء مستهلك فعّالًا على مدار الساعة، على شيء لا يُغلق عندما تُبعد حاسوبك المحمول. نتناول ذلك تاليًا، في أين تُشغّل مستهلك دفق يبقى فعّالًا.

يفتح مفتاح Free هذا الاتصال بعينه فعلاً، على عيّنة صغيرة منسَّقة من الأسواق، لذا يعمل الكود أعلاه اليوم دون أي دفع. الدفق الكامل عبر كل رياضة متاح في Basic فأعلى. تشرح الوثائق تدفق الاتصال الكامل، بما في ذلك كيفية اشتقاق وصول قناتك من مستوى مفتاحك. هذه بيانات لمطورين لا نصيحة تداول أو مالية.

المزيد من المدونة