Irregular Time in Tick Models: Continuous-Time Encodings vs. Plain Positional Embeddings
أشرطة الزمن هي ضغط اعتباطي يدمر توقيت الأحداث، وينبغي للنشاط أن يحدد حدود الشريط بدلا من ذلك — وقد عولجت هذه الحجة بالكامل، مع 17 نوعا من الأشرطة ومولدات عاملة، في أنواع الأشرطة وطرق التجميع للتداول الخوارزمي. يبدأ هذا المقال بخطوة بعدها، عند الجزء الذي لم يحله أحد: حتى بعد التحول إلى أشرطة tick أو الحجم أو عدم التوازن، يظل النموذج الذي تغذيه بها يفترض تباعدا منتظما. يتعامل nn.TransformerEncoder ذو التضمين الموضعي المتعلم مع الموضع 7 على أنه "الخانة السابعة"، سواء وصل ذلك tick بعد 200 ميكروثانية أو بعد 40 ثانية من الموضع 6. ويضيع زمن الوصول بين الأحداث — الشيء الذي صممت أشرطة النشاط للحفاظ عليه — مرة أخرى في طبقة الإدخال.
لذلك فإن سؤال هذا المقال ضيق وقابل للاختبار: كيف نخبر نموذج التسلسل بوقت حدوث tick فعليا، وهل يتفوق الحل المتقدم على الحل البديهي؟
الخلفية المفترضة

ما يلي متطلبات سبق أن غطتها هذه المدونة، ولن نعيد اشتقاق أي منها هنا:
- ضوضاء البنية الدقيقة وارتداد bid-ask. يشتق نموذج الانتشار الضمني لـ Roll التغاير التسلسلي السالب في عوائد tick من المبادئ الأولى وبوحدات السعر، مع توضيح خطأ التنفيذ الشائع: نمذجة فرق bid-ask بالتعلم الآلي.
- خصائص دفتر الأوامر. عدم توازن الدفتر، والسعر الوسطي الموزون، ونسبة العمق عبر المستويات 1-5، وضغط الدفتر، ونسبة الانتشار إلى tick موضحة في المقال نفسه؛ واشتقاقات OBI والوسط الموزون بالحجم — بما في ذلك التنبيه إلى أن الوسط الموزون ليس microprice الخاص بـ Stoikov — موجودة في DeepLOB: التعلم العميق على دفاتر الأوامر.
- تدفق الأوامر وشدة التداول. عدم توازن التداول وVPIN وlambda الخاصة بـ Kyle موجودة في مقال نمذجة الانتشار؛ أما الفاصل بين الأوامر وشدة الإثارة الذاتية لـ Hawkes كخصائص توقيت فموجودان في البصمة الرقمية: تحديد هوية المتداول. شدة
1/dtالبدائية التي اقترحتها هذه المسودة أصلا نسخة أضعف من صياغة Hawkes هناك. - عدم الاستقرارية خلال اليوم. نمط الحجم على شكل U، واتساع الانتشار في الفترات الهادئة، وترميز sin/cos لوقت اليوم مغطاة في مقال نمذجة الانتشار كخصائص لنظام السوق.
- التسميات. اصطلاحا التنعيم (متوسط المستقبل مقابل السعر الحالي، ومتوسط المستقبل مقابل المتوسط السابق)، والتقسيم إلى ثلاث فئات بعتبة ، وتحذير LOBFrame بشأن حساسية التسمية لـ و موجودة في مقال DeepLOB.
- عدم توازن الفئات. مع وجود منطقة ميتة تهيمن فئة FLAT، ولهذا يكون F1 بدلا من الدقة هو المقياس القابل للإبلاغ — في المقال نفسه.
- مدة ملء الشريط. الزمن الفعلي الذي يستغرقه شريط الحجم حتى يكتمل خاصية قابلة للاستخدام في نموذج tick؛ والمولدات التي تنتجها موجودة في أنواع الأشرطة وطرق التجميع.
من المهم التصريح بشيء بوضوح لأن النسخة الأصلية من هذه المسودة أخطأت فيه: الارتفاع في الدقة الاتجاهية من 50.0% إلى 50.5% ليس مربحا بالضرورة. النقطة المركزية لـ LOBFrame، التي يناقشها مقال DeepLOB، هي أن الحركة المتوقعة يجب أن تكون كبيرة بما يكفي لتجاوز الانتشار قبل أن تعني الدقة أي شيء، والنتيجة السلبية الصادقة في هذه المدونة توضح ما يحدث عند افتراض العكس.
خط الأساس

لنفترض مشفرا أساسيا من نوع CNN-Inception-LSTM بأسلوب DeepLOB؛ فالبنية، وأرقام FI-2010 Setup 2 الموثقة (F1 83.40 / الدقة 84.47 عند )، وتحفظات LOBFrame، وإعادة تنفيذ PyTorch العاملة كلها موجودة في DeepLOB: التعلم العميق على دفاتر الأوامر. لا يغير أي شيء أدناه ذلك المشفر — السؤال كله هو ما الذي يضاف إلى تمثيل الإدخال الخاص به.
ثلاث طرق لترميز الزمن غير المنتظم

الخيار A: delta_t كخاصية عادية
الإجابة البديهية. أضف (بعد تحويله لوغاريتميا وتوحيده بدرجة z) كعمود إضافي في متجه الخصائص، إلى جانب OFI وعدم توازن الدفتر، مع الإبقاء على التضمين الموضعي المتعلم المعتاد. لا يكلف ذلك شيئا، ويضيف بعد إدخال واحدا، وهو ما تفعله فعليا معظم نماذج tick في الإنتاج.
هذا هو الطرف الذي يجب أن يتفوق عليه كل اقتراح أكثر تعقيدا، وهو الطرف الذي تحذفه الأوراق التي تقترح بدائل أكثر تعقيدا.
الخيار B: الترميز الموضعي للزمن المستمر
استبدل التضمين الموضعي المتقطع بدالة جيبية للزمن المنقضي، عبر مقاييس زمنية قابلة للتعلم:
حيث إن معلمات للمقياس الزمني قابلة للتعلم، مهيأة بتوزيع لوغاريتمي من الميكروثانية إلى الثواني. والهدف هو أن يزن الانتباه الأحداث بحسب الصلة الزمنية بدلا من رقم الخانة — إذ ينبغي أن يكون الوصول إلى صفقة كبيرة حدثت قبل 200 ميكروثانية مختلفا عن الوصول إلى صفقة صغيرة حدثت قبل 50 ميلي ثانية.
الجزء القابل للتعلم هو المثير للاهتمام. إذا هيأت المقاييس الزمنية بتوزيع لوغاريتمي من 1 ميكروثانية إلى 10 ثوان ودربت النموذج، فإن المكان الذي تستقر فيه المقاييس الزمنية هو قياس بحد ذاته: فإذا انهارت نحو طرف الميلي ثانية، يخبرك النموذج بأن كل ما يتجاوز بضع ميلي ثوان قابل للتبادل، وهذه نتيجة عن السوق لا عن البنية.
import numpy as np
import torch
import torch.nn as nn
class ContinuousTimeEncoding(nn.Module):
"""Sinusoidal encoding for irregular inter-arrival times."""
def __init__(self, d_model: int, num_timescales: int = 64):
super().__init__()
log_timescales = torch.linspace(
np.log(1e-6), np.log(10.0), num_timescales
)
self.log_timescales = nn.Parameter(log_timescales)
self.proj = nn.Linear(num_timescales * 2, d_model)
def forward(self, delta_t: torch.Tensor) -> torch.Tensor:
"""
Args:
delta_t: (batch, seq_len) inter-arrival times in seconds
Returns:
(batch, seq_len, d_model) time encoding
"""
timescales = torch.exp(self.log_timescales) # (num_timescales,)
scaled = delta_t.unsqueeze(-1) / timescales.unsqueeze(0).unsqueeze(0)
encoding = torch.cat([torch.sin(scaled), torch.cos(scaled)], dim=-1)
return self.proj(encoding)
عند إدخاله في مشفر قياسي، يستبدل سطرا واحدا بالضبط — سطر إضافة التضمين الموضعي:
class TickTransformer(nn.Module):
def __init__(self, input_dim: int, d_model: int = 128,
nhead: int = 8, num_layers: int = 4, num_classes: int = 3):
super().__init__()
self.feature_proj = nn.Linear(input_dim, d_model)
self.time_encoding = ContinuousTimeEncoding(d_model)
encoder_layer = nn.TransformerEncoderLayer(
d_model=d_model, nhead=nhead,
dim_feedforward=d_model * 4,
dropout=0.1, batch_first=True
)
self.encoder = nn.TransformerEncoder(
encoder_layer, num_layers=num_layers
)
self.head = nn.Linear(d_model, num_classes)
def forward(self, features: torch.Tensor,
delta_t: torch.Tensor) -> torch.Tensor:
h = self.feature_proj(features) + self.time_encoding(delta_t)
h = self.encoder(h)
return self.head(h[:, -1, :])
أما الهيكل البرمجي الأساسي للمشفر فليس جديدا — فقد نُشر هيكل nn.TransformerEncoderLayer نفسه كبنية 2 في نمذجة الانتشار. الجديد هنا هو ContinuousTimeEncoding وحجة المقاييس الزمنية القابلة للتعلم فقط.
الخيار C: الحالة الكامنة المستمرة بين ticks (ODE-RNN)
الخيار الأكثر اتساقا مع المبادئ يعامل الحالة الكامنة كعملية زمن مستمر نمذجتها Neural ODE (Chen et al., 2018). بين ticks تتطور الحالة المخفية وفقا لمعادلة تفاضلية متعلمة:
عند وصول tick، تُحدّث الحالة باستخدام المشاهدة:
هذا هو إطار ODE-RNN. وهو يعالج التباعد غير المنتظم بنيويا بدلا من معاملته كخاصية إدخال: يدمج الحلال لمدة بالضبط بين الأحداث، من دون padding أو interpolation أو خطوة إعادة أخذ عينات تفقد المعلومات.
التكلفة حسابية. حلالات ODE تسلسلية ويصعب توازيها، ما يجعل هذا الطرف الأقل احتمالا للبقاء ضمن ميزانية الكمون — راجع انضباط الكمون الموضح في ضريبة IPC وسلم سرعة محرك الاختبار الخلفي لمعرفة كيفية قياس مثل هذه الادعاءات قبل طرحها. أدرج هنا باعتباره الحد الأعلى لما يمكن أن يقدمه نمذجة الزمن الصريح، لا باعتباره مرشحا للنشر.
الانتباه الموزون بالأحداث

فكرة ثانية مستقلة: ليست كل ticks متساوية في المعلومات. صفقة من 100 سهما عند bid أمر اعتيادي. أما صفقة تكتسح ثلاثة مستويات سعرية فهي تغير في النظام. يمكننا إدخال هذا الافتراض المسبق في الانتباه مباشرة. عرّف درجة أهمية الحدث:
حيث إن هو حجم الصفقة، و تغير السعر، و التقلب الأخير، و يشير إلى اكتساح متعدد المستويات. أضفها إلى logits الانتباه قبل softmax:
مع . يحتفظ النموذج بالقدرة على تعلم أنماط انتباه عشوائية، لكنه يبدأ بانحياز نحو الصفقات التي حركت السوق.
هذه صيغة مبتكرة. الشكل الوظيفي واختيار الحدود الثلاثة وsoftplus كلها تخمينات، ولا يوجد هنا ما يثبت أن الانحياز يساعد بدلا من أن يستهلك السعة فقط.
رؤوس الآفاق المتعددة

الآفاق المختلفة تفيد قرارات مختلفة، والمشفر المشترك ذو المخرجات المتعددة للآفاق يتفوق على نماذج منفصلة لكل أفق، كما أن loss المشترك يعمل كتنظيم — وقد نوقشت هذه الحجة، إلى جانب مخرجات الكميات وقابلية التفسير، في Temporal Fusion Transformer للتداول. الجزء الخاص بـ tick هو مجموعة الآفاق فقط: 1 و10 و50 و100 حدث بدلا من الأيام، ما يعني أن الآفاق تتداخل كثيرا في الزمن الفعلي أثناء الاندفاعات، وبالكاد تتداخل أثناء الفترات الهادئة — وهي تعقيدة لا تضطر أدبيات الآفاق اليومية إلى التعامل معها.
يجب قياس التنقية بالأحداث

تُغطى عملية التحقق walk-forward المنقاة من البداية إلى النهاية في التحسين Walk-Forward (المثبت، والمتدحرج، وCV التوافقي المنقى، وWFER، ومعدل التدهور)، كما تأتي دالة purged_walk_forward() العاملة مع فجوة تنقية وحظر صريحة في نمذجة الانتشار. ويقيس تصنيف انحياز النظر إلى المستقبل أثر التسربات من هذا النوع على Sharpe المبلغ عنه.
الشيء الخاص ببيانات tick هو أن ticks المتجاورة التي تفصلها ميلي ثوان قليلة تكاد تكون نسخا مكررة، لذا فإن فجوة تنقية مقاسة بـ الأيام بلا معنى عندما يضع اندفاع واحد 500 عينة شبه متطابقة داخل ثانية واحدة. يجب قياس الفجوة بـ الأحداث، والحجم الصحيح سؤال تجريبي عن بنية الاندفاع في أداتك، وليس ثابتا تنسخه من ورقة.
اختبار هذا الادعاء رخيص — امسح فجوة التنقية بالأحداث وارسم F1 للتحقق مقابلها. إذا انخفض F1 للتحقق مع اتساع الفجوة ثم استقر، فنقطة الاستقرار هي فجوتك؛ وإذا لم ينخفض أبدا، فلم يكن تسرب ticks المتجاورة هو المشكلة التي ظننتها.
التجربة التي تحسم الأمر

كل ما سبق بنية. لا شيء منه دليل. لن يتجاوز المقال معيار هذه المدونة حتى تُجرى الاختبارات التالية:
الإعداد. ثبّت مجموعة بيانات واحدة (صفقات BTC/USDT هي مجموعة البيانات المعتمدة)، ومشفرا واحدا، وتعريفا واحدا للتسمية، وتقسيما منقى واحدا. غيّر شيئا واحدا بالضبط.
الأطراف الثلاثة.
| الطرف | معلومات الزمن | الترميز الموضعي |
|---|---|---|
| A | كخاصية إدخال خام | تضمين موضعي متعلم بسيط |
| B | لا شيء، بخلاف الترميز | ContinuousTimeEncoding (مقاييس زمنية قابلة للتعلم) |
| C | كخاصية وترميز للزمن المستمر | ContinuousTimeEncoding |
ما يجب الإبلاغ عنه.
- F1 لكل فئة، وليس الدقة — تحت تسمية المنطقة الميتة تهيمن فئة FLAT، والدقة غير مفيدة للسبب نفسه الذي يذكره مقال DeepLOB.
- فترة ثقة من عمليات تشغيل متكررة ببذور مختلفة. لا يعني فرق F1 مقداره 0.4 نقطة بين الأطراف شيئا من دونها.
- المقاييس الزمنية الملائمة. اطبع
torch.exp(model.time_encoding.log_timescales)بعد التدريب. ومكان استقرارها هو الرقم الأكثر إثارة للاهتمام في التجربة، ولا يتطلب الحصول عليه سوى سطر واحد. - العتاد وتكلفة الزمن الفعلي لكل طرف، على أسلوب ضريبة IPC — مقاسة على عتاد معلن، وبالوسيط عبر N. إذا كلف الطرف B ثلاثة أضعاف زمن استدلال الطرف A مقابل جزء من نقطة F1، فهذه هي الإجابة.
أبلغ عن النتيجة السلبية إن وجدت. "لا يضيف ترميز الزمن المستمر شيئا مقارنة بإدخال كخاصية، على 30 يوما من ticks الخاصة بـ BTC" سيكون مقالا أكثر فائدة من استعراض ثلاث بنيات لم يقسها أحد. كما سيكون متسقا مع النتيجة العامة في هذه المدونة، وهي أن الحواف المبنية بعناية تميل إلى التبخر عند التحقق الصادق.
الوضع الحالي

السؤال غير المحسوم حقيقي: نماذج التسلسل التي تتلقى أحداثا متباعدة بشكل غير منتظم لا تزال ترمز الموضع بدلا من الزمن، كما أن تغطية المدونة الحالية — بما فيها مشفر Transformer في نمذجة الانتشار — تستخدم تضمينا موضعيا متعلما بسيطا. وترميزات الزمن المستمر والحالة الكامنة ODE-RNN والانتباه الموزون بالأحداث ثلاث طرق لإصلاح ذلك.
ما ينقص هو أي دليل على أن إصلاحه مهم. الطرق الثلاث كلها مواضيع حاليا وليست نتائج. والقياس الحاسم هو اختبار إزالة بثلاثة أطراف على مشفر ثابت وتقسيم منقى ثابت، مع الإبلاغ عن F1 لكل فئة بفترة ثقة والمقاييس الزمنية الملائمة — ولم يُجر هذا الاختبار بعد.
Authors
Trading-systems engineer
Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.