σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
uantCraft Academyالمسارات
Ctrl K
AO
+1.2k متعلّم
تسجيل الدخولانضم ↗
المسارات
AO
+1.2k متعلّم
تسجيل الدخول
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
مسار Python›الوحدة 9 · بيانات السوق وبنيته الدقيقة›الموضوع 9.2·~50 دمتقدم

اختلال تدفق الأوامر

الموضع في المسارالوحدة 9 من 11 · الموضوع 2 من 5
9.2 اختلال تدفق الأوامر
—درجة المختبر— / 100إجمالي XP—التتابع—

الضغط قبل أن يتحرك السعر

نادرًا ما يتحرك السعر وحده؛ فهو يتحرك لأن أوامر تصل وتسحب سيولة. والنظر إلى الصفقات وحدها يفوّت معظم القصة، فمعظم الحدث أوامر توضع وتُلغى في قمة الدفتر. واختلال تدفق الأوامر (OFI) يلخص كل تحديث لأفضل سعري الشراء والبيع في رقم واحد بإشارة: موجب حين يضيف المشترون أو يتراجع البائعون وسالب في الحالة المعاكسة. وعلى الآفاق القصيرة يتنبأ بتغيرات السعر التالية بدقة لافتة.

def book_imbalance(bid_size, ask_size):
    total = bid_size + ask_size
    if total == 0:
        return 0.0
    return (bid_size - ask_size) / total

print(book_imbalance(450, 200))        # 0.3846  more size on the bid: upward pressure
print(book_imbalance(100, 400))        # -0.6    sellers dominate
print(book_imbalance(0, 0))            # 0.0     an empty top does not divide by zero

تحديث واحد، رقم واحد

قارن بين سعرين متتاليين. في جانب الشراء: إذا ارتفع السعر أو بقي يُضاف حجمه الجديد؛ وإذا انخفض أو بقي يُطرح حجمه القديم (وعند بقاء السعر يتحقق الاثنان فيُحتسب تغير الحجم). وفي جانب البيع تنعكس الإشارات: سعر بيع أدنى أو مساوٍ يضيف ضغط بيع (- حجم البيع الجديد) وسعر أعلى أو مساوٍ يزيل القديم (+ حجم البيع القديم). والحدود الأربعة هي (b >= pb) * bs - (b <= pb) * pbs - (a <= pa) * as + (a >= pa) * pas حيث كل مقارنة 1 أو 0.

# The order-flow imbalance of one quote update, tried on four changes of the top of the book
def ofi_event(prev, cur):
    pb, pbs, pa, pas_ = prev
    b, bs, a, as_ = cur
    return (b >= pb) * bs - (b <= pb) * pbs - (a <= pa) * as_ + (a >= pa) * pas_

q0 = (99.5, 300, 100.0, 200)
print(ofi_event(q0, (99.5, 450, 100.0, 200)))     # 150   more size on the same bid
print(ofi_event(q0, (99.6, 100, 100.0, 200)))     # 100   a higher bid: the whole new size counts
print(ofi_event(q0, (99.4, 300, 100.0, 200)))     # -300  the bid price fell: the old size is gone
print(ofi_event(q0, (99.5, 300, 100.1, 200)))     # 200   the ask retreated: less selling pressure

سلسلة وما تفسره

تطبيق القاعدة على كل زوج متتالٍ من الأسعار يعطي سلسلة OFI. وعلى نافذة قصيرة، كثانية، اجمع الأحداث وقارنها بتغير السعر الوسطي: العلاقة قريبة من الخطية d_mid = slope * OFI. والميل يقول كم يحرك كل وحدة تدفق من السعر، ويصغر حين يكون الدفتر عميقًا. ويُضبط كخط مربعات صغرى يمر بالأصل: sum(ofi * dmid) / sum(ofi ** 2).

# A series of events from consecutive quotes, set beside the change of the mid price
import numpy as np

def ofi_event(prev, cur):
    pb, pbs, pa, pas_ = prev
    b, bs, a, as_ = cur
    return (b >= pb) * bs - (b <= pb) * pbs - (a <= pa) * as_ + (a >= pa) * pas_

quotes = [(99.5, 300, 100.0, 200), (99.5, 450, 100.0, 200), (99.6, 100, 100.0, 150), (99.6, 100, 100.1, 400)]
events = np.array([ofi_event(prev, cur) for prev, cur in zip(quotes, quotes[1:])], dtype=float)
print(events)                                                       # [150. 150. 150.]

mid = np.array([(q[0] + q[2]) / 2 for q in quotes])
dmid = np.diff(mid)
print(np.round(dmid, 3))                                            # the mid moved in the direction of the flow
# Recover the price impact of the flow with a slope through the origin
import numpy as np

def impact_slope(ofi, dmid):
    return float(np.sum(ofi * dmid) / np.sum(ofi ** 2))

rng = np.random.default_rng(1)
flow = rng.normal(0, 200, size=500)                                  # order-flow imbalance per second
price_change = 0.00005 * flow + rng.normal(0, 0.004, size=500)       # the mid moves with the flow, plus noise
print(round(impact_slope(flow, price_change), 6))                    # 5e-05, the true impact per unit of flow
تنبؤي لكنه ليس مالًا مجانيًايتنبأ OFI بحركات أصغر من الفارق، يتداول عليها السريعون أصلًا قبل التكاليف. وقيمته لمعظم الناس في التنفيذ: يقول هل تتمهل في أمر الشراء لأن الدفتر يميل لصالحك أم تستعجل لأن السعر على وشك الانطلاق. ويعتمد أيضًا على السوق: يختلف الميل بين الأسهم وأوقات اليوم.
  • اختلال الدفتر (bid - ask) / (bid + ask) بين -1 و+1؛ واحمِ الحالة الفارغة.
  • OFI لتحديث: (b >= pb) * bs - (b <= pb) * pbs - (a <= pa) * as + (a >= pa) * pas؛ والسلسلة تطبقه على كل زوج متتالٍ.
  • تغيرات السعر الوسطي قريبة من الخطية في OFI: slope = sum(ofi * dmid) / sum(ofi**2)؛ وهي إشارة قصيرة الأفق وأنفع ما تكون للتنفيذ.

التالي: الشيفرة غير المتزامنة مع asyncio، التعامل مع تدفقات بيانات كثيرة دون انتظار كل واحد.

المختبر: ما الذي يُقيَّم

  • قارن الجانبين باستخدام book_imbalance25 نقطة
  • قيّم تحديثًا واحدًا باستخدام ofi_event25 نقطة
  • تتبّع الضغط باستمرار باستخدام ofi_series25 نقطة
  • سعّر التدفق باستخدام impact_slope25 نقطة
المستكشف · lab-113-1
▾ lab-113-1
…
bash · داخل المتصفح
learner@quantcraft:~/lab-113-1$
لم يتم تحميل Python بعدPythonLn 1, Col 1Spaces: 4UTF-8

هل تريد إعادة ضبط هذا الموضوع؟

سيعود كل ما في lab-113-1 إلى الملفات الابتدائية وستُمسح الطرفية. ستفقد حلّك الحالي ولا يمكن التراجع عن ذلك.

سيُعاد ضبطه
  • main.py ← الشيفرة الابتدائية
  • سجل الطرفية ومخرجات الاختبارات
  • التغييرات غير المُرسلة
سيُحتفظ به
  • أفضل درجة في المختبر
  • نقاط XP والتتابع
  • تقدّم المحاضرة والملاحظات

سجّل الدخول لتشغيل الكود الخاص بك.

قراءة كل المحاضرات مجانية. أنشئ حسابًا أو سجّل الدخول لتشغيل الكود وتنفيذ الاختبارات وتسليم هذا المختبر.

  • بيئة تطوير داخل المتصفح مع طرفية bash — لا حاجة لتثبيت أي شيء
  • تصحيح فوري ونقاط خبرة ومكانك في المسار
إنشاء حسابتسجيل الدخول
أو
المتابعة عبر GitHub