مسیر Quant Developer · بخش ۲: اقتصاد و ریسک Market Making · درس ۵
Fair Value و قیمتگذاری
ارزش منصفانه چیست، چرا آخرین قیمت معامله و حتی Mid Price تخمین کاملی از آن نیستند، و بازارساز چطور قیمتهایش را دور Fair Value میچیند.
۱. سؤال اول بازارساز: «همین الان این دارایی چقدر میارزد؟»
در چهار درس اول دیدیم بازار چطور کار میکند: دفتر سفارش، صف، Maker و Taker، و جریان سفارشها. از این درس وارد بخش دوم مسیر میشویم: اقتصاد Market Making؛ یعنی چرا یک استراتژی پول درمیآورد یا پول از دست میدهد.
همهچیز از یک عدد شروع میشود: Fair Value یا ارزش منصفانه. Fair Value بهترین تخمین تو از قیمتی است که دارایی «باید» همین الان با آن معامله شود؛ به زبان دقیقتر، انتظار تو از قیمت در آینده نزدیک با توجه به همه اطلاعاتی که داری. این عدد را هیچجا نمیبینی. باید آن را تخمین بزنی.
چرا اینقدر مهم است؟ چون هر سفارش بازارساز در واقع یک شرط نسبت به Fair Value است:
اگر Fair Value واقعاً 100,000 باشد و تو در 99,990 بخری، بهطور متوسط ۱۰ دلار به ازای هر بیتکوین جلو هستی. اما اگر Fair Value در واقع 99,980 بوده و تو خبر نداشتی، همان خرید ۱۰ دلار زیان انتظاری دارد. پس کیفیت تخمین Fair Value مستقیماً روی سود و زیان مینشیند. در درس اول هم دیدیم «Pricing Engine» اولین جزء منطقی سیستم بعد از دریافت داده است.
برای تخمین Fair Value سه کاندیدای ساده داریم: آخرین قیمت معامله، Mid Price و Microprice. هر سه را روی همان دفتر سفارش درس اول بررسی میکنیم:
۲. آخرین قیمت معامله: عددی که همه میبینند
Last Price یا آخرین قیمت معامله همان عددی است که روی نمودارها و صفحه اول اپلیکیشن صرافی میبینی. ساده و در دسترس است، ولی برای قیمتگذاری انتخاب بدی است.
فرض کن دفتر سفارش بالا هیچ تغییری نکند و فقط چهار معامله کوچک پشت سر هم انجام شود:
| معامله | سمت Taker | قیمت معامله (Last Price) | Mid Price |
|---|---|---|---|
| ۱ | فروش (به Bid میخورد) | 99,990 | 100,000 |
| ۲ | خرید (از Ask برمیدارد) | 100,010 | 100,000 |
| ۳ | خرید | 100,010 | 100,000 |
| ۴ | فروش | 99,990 | 100,000 |
آخرین قیمت مدام ۲۰ دلار بالا و پایین میپرد، در حالی که هیچ اطلاع تازهای درباره ارزش دارایی وارد بازار نشده است. فقط Taker گاهی خریدار بوده و گاهی فروشنده. به این پدیده Bid-Ask Bounce میگویند. یکی از نتایجش این است که تغییرات پیاپی Last Price همبستگی منفی دارند؛ Richard Roll در سال ۱۹۸۴ از همین همبستگی منفی برای تخمین Spread فقط از روی قیمت معاملات استفاده کرد.
دو مشکل دیگر هم هست:
- کهنگی: در بازار کممعامله، آخرین معامله ممکن است چند دقیقه پیش انجام شده باشد و دیگر چیزی درباره وضعیت فعلی نگوید.
- معاملات بزرگ: در درس سوم دیدیم یک خرید Market به حجم 1 BTC آخرین تکهاش را در 100,030 پر کرد. آن عدد یک لحظه Last Price است، ولی فقط نشان میدهد یک نفر عجله داشت.
۳. Mid Price: بهتر، ولی کور نسبت به حجم
Mid Price را در درس دوم دیدیم: میانگین Best Bid و Best Ask. نسبت به Last Price سه مزیت دارد: از هر دو طرف دفتر استفاده میکند، با هر تغییر دفتر بهروز میشود (نه فقط با معامله)، و Bid-Ask Bounce ندارد. در جدول بالا Mid در تمام مدت 100,000 ماند.
ضعف Mid این است که حجم را نمیبیند. دو دفتر سفارش را مقایسه کن که هر دو Best Bid برابر 99,990 و Best Ask برابر 100,010 دارند:
| حجم Best Bid | حجم Best Ask | Mid | |
|---|---|---|---|
| دفتر A (دفتر درس ۱) | 0.4 | 0.3 | 100,000 |
| دفتر B | 5.0 | 0.05 | 100,000 |
در دفتر B فقط 0.05 BTC در 100,010 مانده است. کافی است یک خریدار کوچک بیاید تا این سطح تمام شود و Best Ask به 100,020 برسد؛ در حالی که برای پایین بردن Best Bid باید ۵ بیتکوین فروش بیاید. احتمال اینکه قدم بعدی قیمت رو به بالا باشد خیلی بیشتر است. Mid هر دو دفتر را یکسان میبیند.
۴. Microprice: وزن دادن به حجم
راه ساده برای دیدن این عدم توازن، Order Book Imbalance است: چه سهمی از حجم بالای دفتر در سمت خرید است؟
با این عدد، میانگین وزنی Bid و Ask را میسازیم. به این تخمین Microprice (یا Size-Weighted Mid) میگویند:
به وزنها دقت کن: حجم سمت خرید به قیمت فروش وزن میدهد. منطقش همان شهود دفتر B است: هرچه صف خرید سنگینتر باشد، قیمت به سمت Ask نزدیکتر است. یک شکل معادل که خواندنش راحتتر است:
برای دفتر درس ۱: حجم Bid برابر 0.4 و حجم Ask برابر 0.3 است؛ پس I = 0.4 / 0.7 ≈ 0.571 و:
برای دفتر B، I = 5 / 5.05 ≈ 0.990 و Microprice ≈ 100,009.80؛ یعنی تقریباً روی Ask.
- Last Price (اگر آخرین Taker خریدار بود)
- 100,010
- Mid Price
- 100,000
- Order Book Imbalance
- 0.571
- Microprice
- 100,001.43
Microprice هم بیعیب نیست:
- فقط سطح اول را میبیند. نسخههای کاملتر چند سطح دفتر را با وزن کمتر وارد میکنند.
- فریبپذیر است. سفارش بزرگی که فقط برای نمایش ثبت و بعد لغو میشود (Spoofing) میتواند Imbalance را جابهجا کند.
- رابطه حجم و حرکت قیمت ثابت نیست. اینکه Imbalance واقعاً حرکت بعدی را پیشبینی کند، یک فرض است که باید روی داده آزموده شود.
در عمل Fair Value اغلب ترکیبی از چند منبع است: Microprice، قیمت همان دارایی در بازارهای دیگر، قیمت قرارداد آتی (درس ۲۲ و ۲۳) و جریان معاملات اخیر (درس ۴). ولی اسکلت همه آنها همین است: یک عدد که از Mid «هوشمندتر» باشد.
۵. قیمتگذاری دور Fair Value
وقتی Fair Value را داری، سادهترین قاعده قیمتگذاری این است که با فاصله مساوی دو طرفش قیمت بدهی:
با Microprice دفتر درس ۱ و نیماسپرد ۱۰ دلار:
این قیمتها روی شبکه قیمت مجاز نیستند. با Tick Size فرضی ۱ دلار (همان فرض کد درس ۳) باید گرد شوند. قاعده محافظهکارانه این است که همیشه به نفع خودت گرد کنی: Bid رو به پایین و Ask رو به بالا. نتیجه: خرید در 99,991 و فروش در 100,012.
حالا ببین چه شد:
- خرید ما در 99,991 بالاتر از Best Bid فعلی (99,990) است؛ پس Best Bid جدید و نفر اول صف میشویم (همان «راه میانبر» درس ۳).
- فروش ما در 100,012 پشت Best Ask (100,010) مینشیند و احتمال پر شدنش کمتر است.
یعنی همان تمایل کوچک Microprice به سمت بالا، ما را در خرید تهاجمیتر و در فروش محتاطتر کرد. این دقیقاً رفتاری است که میخواهیم: اگر احتمال بالا رفتن قیمت بیشتر است، ترجیح میدهیم بخریم تا بفروشیم.
دو محافظ همیشه لازم است:
- عبور نکردن از طرف مقابل. اگر Fair Value ناگهان جهش کند، ممکن است Bid محاسبهشده به Best Ask برسد یا از آن بگذرد. در این حالت سفارش Taker میشود یا با Post-Only رد میشود (درس ۳). سیستم باید این حالت را تشخیص دهد، نه اینکه کورکورانه سفارش بفرستد.
- تازه بودن Fair Value. اگر Fair Value با تأخیر بهروز شود، قیمتهایت به یک عدد کهنه گره خوردهاند و معاملهگرهای سریعتر دقیقاً همانها را برمیدارند. این موضوع درس ۸ است.
۶. در کد: Mid، Microprice و قیمتگذاری
اول همان محاسبههای بالا:
import math
def mid(bid, ask):
return (bid + ask) / 2
def microprice(bid, ask, bid_size, ask_size):
"""Size-weighted mid: leans toward the side with LESS size."""
imbalance = bid_size / (bid_size + ask_size)
return imbalance * ask + (1 - imbalance) * bid
def quotes(fair_value, half_spread, tick=1):
"""Quote around fair value; round bid down and ask up to the tick grid."""
bid = math.floor((fair_value - half_spread) / tick) * tick
ask = math.ceil((fair_value + half_spread) / tick) * tick
return bid, ask
# Top of the lesson-1 book: 99,990 x 0.4 | 100,010 x 0.3
fv = microprice(99_990, 100_010, 0.4, 0.3)
print(mid(99_990, 100_010)) # 100000.0
print(round(fv, 2)) # 100001.43
print(quotes(fv, 10)) # (99991, 100012)
حالا یک آزمایش کوچک: یک دنیای ساختگی میسازیم که در آن «ارزش واقعی» را میدانیم، و میسنجیم هر تخمین چقدر از آن دور است.
import numpy as np
rng = np.random.default_rng(7)
n = 10_000
# Hidden "true" value: a random walk around 100,000 (synthetic, not real data)
value = 100_000 + np.cumsum(rng.normal(0, 3, n))
# Book on a 10-USDT grid with a 20-USDT spread that contains the true value
bid = np.round(value / 10) * 10 - 10
ask = bid + 20
# Assumption of this toy world: the closer value is to the ask,
# the heavier the bid queue (size imbalance carries information)
pos = (value - bid) / 20 # 0.25 .. 0.75
bid_size = np.clip(pos + rng.normal(0, 0.1, n), 0.05, None)
ask_size = np.clip(1 - pos + rng.normal(0, 0.1, n), 0.05, None)
mid = (bid + ask) / 2
imb = bid_size / (bid_size + ask_size)
micro = imb * ask + (1 - imb) * bid
# Each trade hits the bid or lifts the ask at random
last = np.where(rng.random(n) < 0.5, bid, ask)
for name, est in [("last", last), ("mid", mid), ("micro", micro)]:
rmse = np.sqrt(np.mean((est - value) ** 2))
print(f"{name:6s} RMSE vs true value: {rmse:5.2f} USDT")
خروجی:
last RMSE vs true value: 10.41 USDT
mid RMSE vs true value: 2.88 USDT
micro RMSE vs true value: 1.52 USDT
RMSE یا ریشه میانگین مربع خطا، فاصله معمول هر تخمین از ارزش واقعی است. خطای Last Price تقریباً برابر نیماسپرد (۱۰ دلار) است؛ یعنی Bid-Ask Bounce بر آن غالب است. Mid خطا را به حدود ۲.۹ دلار میرساند و Microprice تقریباً نصف آن.
۷. تمرین این درس
گزینه مناسب هر سؤال را انتخاب کن و در پایان نتیجه را ببین.
درس بعدی
در درس ششم سراغ اولین ریسک واقعی بازارساز میرویم: Inventory Risk. وقتی فقط یک طرف سفارشهایت پر میشود و موجودی جمع میکنی، هر حرکت قیمت مستقیماً سود و زیانت را جابهجا میکند. خواهیم دید چطور با Skew کردن همین قیمتهای دور Fair Value، موجودی را کنترل کنیم.
این مطلب صرفاً آموزشی است و توصیه خرید، فروش یا سرمایهگذاری نیست.