رفتن به محتوای اصلی
سرفصل مسیر Quant Developer

مسیر Quant Developer · بخش ۲: اقتصاد و ریسک Market Making · درس ۶

Inventory Risk و Skew

وقتی فقط یک طرف سفارش‌های بازارساز پر می‌شود، موجودی جمع می‌شود و حرکت قیمت PnL را جابه‌جا می‌کند؛ Skew، اندازه نامتقارن و سقف موجودی این ریسک را کنترل می‌کنند.

سطح: متوسط۱۲ دقیقه مطالعه

۱. وقتی فقط یک طرف پر می‌شود

در درس اول گفتیم ممکن است سفارش خرید بازارساز پر شود ولی سفارش فروشش نه. در درس پنجم یاد گرفتیم قیمت‌ها را دور Fair Value بچینیم. حالا ببینیم وقتی این قیمت‌ها نامتوازن پر می‌شوند چه اتفاقی می‌افتد.

Inventory یا موجودی، مقدار دارایی‌ای است که بازارساز در هر لحظه در دست دارد. آن را با q نشان می‌دهیم: q مثبت یعنی دارایی خریده‌ای و نگه داشته‌ای (Long)، q منفی یعنی بیشتر فروخته‌ای تا خریده‌ای (Short). هر حرکت قیمت، سود و زیان موجودی را این‌طور تغییر می‌دهد:

ΔPnL = q × ΔP

یک سناریوی ساده با دفتر سفارش درس اول: بازار آرام‌آرام پایین می‌رود و فروشنده‌ها سه بار سفارش خرید تو را پر می‌کنند، هر بار 0.1 BTC. حالا q = 0.3 است. اگر قیمت ۱۰۰ دلار دیگر پایین برود:

ΔPnL = 0.3 × (−100) = −30 USDT

برای مقایسه، یک رفت‌وبرگشت کامل 0.1 BTC با Spread بیست‌دلاری، پیش از کارمزد ۲ دلار سود دارد (درس ۱). یعنی یک حرکت صددلاری کوچک، درآمد ۱۵ رفت‌وبرگشت را پاک می‌کند.

این ریسک با زمان و نوسان بزرگ می‌شود

اگر قیمت مثل یک گام تصادفی حرکت کند، انحراف معیار سود و زیان موجودی در افق زمانی t تقریباً این است:

σ(PnL) = |q| × σ × √t

که σ نوسان قیمت در هر واحد زمان است. با یک نوسان فرضی ۳۰ دلار در دقیقه و q = 0.3، نوسان PnL در یک دقیقه ۹ دلار و در یک ساعت حدود 0.3 × 30 × √60 ≈ 70 دلار است. بازارسازی که برای درآمد ۲ دلاری هر رفت‌وبرگشت کار می‌کند، نمی‌تواند چنین ریسکی را بی‌مدیریت رها کند. مفاهیم نوسان و انحراف معیار را در درس ۹ دقیق‌تر می‌سازیم.

۲. ایده Skew: قیمت‌ها را برخلاف موجودی جابه‌جا کن

اگر موجودی مثبت داری، می‌خواهی احتمال فروش بیشتر و احتمال خرید کمتر شود. راه ساده این است که هر دو قیمت را کمی پایین ببری. فروش ارزان‌تر جذاب‌تر می‌شود و خرید پایین‌تر کمتر پر می‌شود. به این کار Skew می‌گویند.

ابتدا یک قیمت مرجع شخصی می‌سازیم که به آن Reservation Price می‌گویند؛ قیمتی که با توجه به موجودی فعلی، برایت فرقی نمی‌کند بخری یا بفروشی:

r = Fair Value − k × q
Bid = r − h
Ask = r + h

h همان نیم‌اسپرد درس ۵ است و k ضریب Skew: به ازای هر بیت‌کوین موجودی، مرکز قیمت‌هایت چند دلار جابه‌جا شود. برای سادگی در این درس Fair Value را همان Mid دفتر درس ۱ یعنی 100,000 می‌گیریم، با h = 10 و k = 50 دلار به ازای هر BTC:

موجودی qReservation PriceBidAskاثر
صفر100,00099,990100,010متقارن، مثل درس ۱
0.2 (Long)99,99099,980100,000فروش داخل Spread و اول صف؛ خرید پشت 0.7 BTC در سطح دوم
0.2 (Short)100,010100,000100,020برعکس: خرید داخل Spread، فروش عقب‌تر
0.4 (Long)99,98099,97099,990فروش به Best Bid رسیده است؛ پایین را ببین

ردیف آخر یک حالت خرابی واقعی را نشان می‌دهد. Ask محاسبه‌شده 99,990 دقیقاً روی Best Bid بازار است؛ چنین سفارشی فوراً به‌عنوان Taker معامله می‌شود (یا اگر Post-Only باشد رد می‌شود، درس ۳). سیستم باید قیمت را محدود کند، مثلاً Ask را حداقل یک Tick بالای Best Bid، یعنی 99,991 بگذارد، یا آگاهانه تصمیم بگیرد که برای خروج از موجودی Taker شود.

۳. دو ابزار دیگر: اندازه نامتقارن و سقف موجودی

Skew فقط قیمت را جابه‌جا می‌کند. دو ابزار مکمل هم داریم:

اندازه نامتقارن (Asymmetric Sizing): وقتی Long هستی، حجم سفارش خرید را کوچک و حجم فروش را بزرگ کن. یک قاعده خطی ساده با اندازه پایه 0.1 BTC و سقف موجودی 0.5 BTC:

Bid Size = 0.1 × (1 − q / 0.5)
Ask Size = 0.1 × (1 + q / 0.5)

با q = 0.3، حجم خرید 0.04 و حجم فروش 0.16 BTC می‌شود. با q = 0.5 حجم خرید صفر است؛ یعنی قاعده اندازه، خودش سقف موجودی را هم اعمال می‌کند. (برای q منفی به همین شکل برعکس عمل می‌کند و در عمل باید حجم‌ها را به بازه مجاز و Lot Size محدود کرد.)

سقف موجودی (Inventory Limit): معمولاً دو لایه دارد:

لایهرفتارمثال فرضی
سقف نرمSkew و اندازه نامتقارن شدیدتر می‌شونداز 0.3 BTC به بالا
سقف سختسفارش سمتی که موجودی را بیشتر می‌کند اصلاً ثبت نمی‌شود0.5 BTC
خروج اضطراریموجودی با سفارش Taker یا ابزار دیگری کم می‌شودبالاتر از سقف سخت، مثلاً بعد از یک جهش قیمت

خروج با Taker یعنی Spread و کارمزد Taker می‌پردازی؛ هزینه‌اش را در درس ۷ حساب می‌کنیم. پوشش ریسک با ابزار دیگر (مثلاً قرارداد آتی) موضوع درس ۲۱ است و تعیین خود سقف بر اساس سرمایه موضوع درس ۲۴.

۴. شبیه‌سازی: با Skew و بدون Skew

حالا یک آزمایش کنترل‌شده. فرض‌های این دنیای ساختگی:

  • Mid یک گام تصادفی بدون روند است: هر گام (مثلاً یک ثانیه) با انحراف معیار ۲ دلار.
  • Fair Value همان Mid است و نیم‌اسپرد ۱۰ دلار.
  • احتمال پر شدن هر سفارش در هر گام با فاصله‌اش از Mid کم می‌شود: A × exp(−κ × δ) با A = 0.5 و κ = 0.1. سفارشی با فاصله ۱۰ دلار در هر گام حدود ۱۸٪ شانس پر شدن دارد.
  • هر سفارش دست‌کم ۱ دلار با Mid فاصله دارد؛ یعنی Skew هر قدر هم شدید باشد، از وسط Spread عبور نمی‌کند (همان محافظ بخش ۲).
  • هر پر شدن 0.1 BTC است. کارمزد صفر است و پر شدن‌ها هیچ اطلاعاتی درباره قیمت آینده ندارند (فرضی خوش‌بینانه).
  • ۵۰۰ مسیر مستقل، هر کدام ۳,۶۰۰ گام (یک ساعت ثانیه‌ای).
import numpy as np

def simulate(k, paths=500, steps=3_600, seed=42):
    """k = skew in USDT per 1 BTC of inventory. Returns inventory paths and final PnL."""
    rng = np.random.default_rng(seed)
    h, size, sigma = 10.0, 0.1, 2.0       # half spread, fill size (BTC), mid move per step
    A, kappa = 0.5, 0.1                   # fill prob = A * exp(-kappa * distance from mid)
    mid = np.full(paths, 100_000.0)
    q = np.zeros(paths)                   # inventory in BTC
    cash = np.zeros(paths)
    q_hist = np.empty((steps, paths))
    for t in range(steps):
        r = mid - k * q                   # skewed center of our quotes
        bid = np.minimum(r - h, mid - 1)  # never cross: stay at least 1 USDT from mid
        ask = np.maximum(r + h, mid + 1)
        buy = rng.random(paths) < A * np.exp(-kappa * (mid - bid))   # someone sells to us
        sell = rng.random(paths) < A * np.exp(-kappa * (ask - mid))  # someone buys from us
        q += size * (buy.astype(float) - sell)
        cash += size * (sell * ask - buy * bid)
        q_hist[t] = q
        mid += rng.normal(0, sigma, paths)
    pnl = cash + q * mid                  # mark-to-market at the final mid
    return q_hist, pnl

for k in (0, 50):
    q_hist, pnl = simulate(k)
    print(f"k={k:>2}: inventory std={q_hist[-1].std():.2f} BTC, "
          f"max |q|={np.abs(q_hist).max():.1f} BTC, "
          f"PnL mean={pnl.mean():.0f}, std={pnl.std():.0f} USDT")

خروجی:

k= 0: inventory std=3.34 BTC, max |q|=13.6 BTC, PnL mean=1316, std=274 USDT
k=50: inventory std=0.09 BTC, max |q|=0.5 BTC, PnL mean=1174, std=32 USDT
بیشترین موجودی بدون Skew
13.6 BTC
بیشترین موجودی با Skew (k = 50)
0.5 BTC
انحراف معیار PnL بدون Skew
274 USDT
انحراف معیار PnL با Skew
32 USDT

چطور این اعداد را بخوانیم:

  • بدون Skew، موجودی یک گام تصادفی است. هر پر شدن خرید یا فروش موجودی را 0.1 جابه‌جا می‌کند و هیچ نیرویی آن را به صفر برنمی‌گرداند. انحراف معیارش با جذر زمان رشد می‌کند و در بدترین مسیر به 13.6 BTC رسید؛ یعنی بیش از یک میلیون دلار ریسک جهت‌دار برای استراتژی‌ای که قرار بود از Spread درآمد داشته باشد.
  • با Skew، موجودی به صفر برمی‌گردد. در هیچ مسیری از 0.5 BTC بالاتر نرفت، بدون اینکه سقف سختی در کد باشد.
  • بها: میانگین PnL حدود ۱۱٪ کمتر شد (1,174 در برابر 1,316)، چون بخشی از معاملات نزدیک Fair Value انجام شد. در عوض پراکندگی PnL بیش از ۸ برابر کم شد. به ازای هر واحد ریسک، استراتژی با Skew بسیار بهتر است.

۵. از قاعده دستی تا مدل

در این درس k یک عدد ثابت و دستی بود. سؤال طبیعی این است: k «درست» چقدر است؟ مدل Avellaneda–Stoikov (۲۰۰۸) دقیقاً همین را رسمی می‌کند. در آن مدل Reservation Price این شکل را دارد:

r(s, q, t) = s − q × γ × σ² × (T − t)

که s قیمت میانی، γ ضریب ریسک‌گریزی، σ² واریانس قیمت و T − t زمان باقی‌مانده تا پایان افق است. یعنی همان k این درس، در آن مدل برابر γ × σ² × (T − t) است: هرچه بازار پرنوسان‌تر و تو ریسک‌گریزتر باشی، Skew شدیدتر است. فرض‌ها، Spread بهینه و محدودیت‌های این مدل را در درس ۱۱ کامل بررسی می‌کنیم و در درس ۱۲ نسخه‌ای با سقف موجودی (Guéant–Lehalle–Fernandez-Tapia) را می‌بینیم.

۶. تمرین این درس

گزینه مناسب هر سؤال را انتخاب کن و در پایان نتیجه را ببین.

سؤال ۱: بازارساز 0.3 BTC موجودی Long دارد و قیمت 50 دلار پایین می‌رود. اثر این حرکت روی PnL چیست؟
سؤال ۲: Fair Value برابر 100,000، k = 50 دلار به ازای هر BTC، نیم‌اسپرد 10 دلار و موجودی 0.3 BTC Short است. قیمت‌های خرید و فروش چه می‌شوند؟
سؤال ۳: بازارساز موجودی Long بزرگی دارد. Skew درست کدام است؟
سؤال ۴: در شبیه‌سازی، چرا میانگین PnL با Skew کمتر از حالت بدون Skew شد؟

درس بعدی

در این درس سود و زیان را فقط به‌صورت «نقد به‌علاوه موجودی ضرب در قیمت» حساب کردیم. در درس هفتم آن را دقیق باز می‌کنیم: Spread Capture، کارمزد و PnL؛ تفاوت سود ناخالص و خالص، تحقق‌یافته و تحقق‌نیافته، و اینکه چطور کل PnL را به سهم Spread، سهم موجودی و سهم کارمزد تجزیه کنیم.

این مطلب صرفاً آموزشی است و توصیه خرید، فروش یا سرمایه‌گذاری نیست.