Implementation shortfall va DIY TCA: bajarish sizga aslida qancha tushishini o'lchash
Har bir institutsional desk o'zining tranzaksiya xarajatlarini tahlil qilish (TCA) quvuriga ega. Kripto-bot ishlatuvchilardan esa deyarli hech kim. Odatiy sozlash fill'larni loglaydi, komissiyalarni yig'adi va backtest PnL bilan live PnL o'rtasidagi farqni "slippage" deb ataydi — bu tushuntirilmagan yagona qoldiq bo'lib, u kechikish, spread, ta'sir (impact), noqulay tanlov (adverse selection) va qochib ketgan har bir bajarilmagan buyurtmani o'ziga singdiradi. Bitta raqam sifatida o'lchanadigan xarajatni tuzatib bo'lmaydi. Uni to'g'ri o'lchash mexanizmi 1988 yildan beri mavjud, u mulkiy (proprietary) emas, va o'z fill loglaringiz ustida bu taxminan 200 qator Python kodi. Ushbu maqola aynan shuni quradi.
Bu natija chiroyliroq dashboard emas. Sizning backtestingiz xarajat modelini o'z ichiga oladi — slippage konstantasi, fill ehtimoli, impact koeffitsienti — va undagi har bir parametr hozircha taxmindir. Live fill'lar ustidagi TCA — bu parametrlarni kalibrlash mumkin bo'lgan yagona haqiqiy asos. Ushbu tsiklning simulyatsiya tomonini biz Fill simulyatsiyasi: yopilish narxi fantaziyasidan navbatni hisobga oluvchi haqiqatgacha bo'lgan zinapoya maqolasida qurgan edik; bu maqola esa o'lchov tomonini quradi.
Qog'oz va haqiqat: Perold aslida nimani o'lchagan edi
Asosiy usul André Perold'ga tegishli (1988, "The Implementation Shortfall: Paper Versus Reality," Journal of Portfolio Management 14(3), 4–9). Ikkita portfelni parallel yuriting. Qog'oz portfeli har bir qarorni darhol, cheksiz hajmda, nol xarajat bilan, qaror qabul qilingan paytdagi narxda bajaradi. Haqiqiy portfel — sizning botingiz aslida nima qilgani: qisman fill'lar, kvotalarni ta'qib qilish, qolgan qismini bekor qilish, komissiyalar. Implementation shortfall — bu ularning daromadlari orasidagi farq.
Bu ta'rif muhim, chunki u nimani yashirishdan bosh tortadi. Komissiya hisoboti komissiyalarni ko'rsatadi. Fill va limit narxini solishtiruvchi hisobot esa umuman hech narsa ko'rsatmaydi (siz hech qachon limitingizdan yomonroq narxda fill olmaysiz — bu qurilishning o'zidan kelib chiqadi). Qog'oz portfeli esa siz uchun hamma narsani hisobga oladi: qaror va kelish o'rtasidagi drift, siz kesib o'tgan spread, siz keltirib chiqargan ta'sir va — bu juda muhim — narx qochib ketayotganda hech qachon bajarilmagan buyurtmalar. Wagner va Edwards (1993, "Best Execution," Financial Analysts Journal 49(1), 65–71) ko'rinadigan komissiyalarni aysbergning uchi deb atagan edi; aylanma (turnover) bo'lgan har qanday narsa uchun suv ostidagi qism ustunlik qiladi.
Belgilashni aniqlaymiz. Ota buyurtma: tomon (sotib olish/sotish), hajm . Qaror narxi — bu strategiyangiz signal ishga tushgan paytda ko'rgan mid narx. Fill'lar ko'rinishida keladi, jami bajarilgan miqdor . Gorizontda (ota buyurtma bajarilgan, bekor qilingan yoki muddati tugagan paytda) mid narx ga teng. Aniq komissiyalar . Valyuta ko'rinishidagi implementation shortfall:
qog'oz nominali ga bo'lish orqali bazis punktlariga normallashtiriladi. Musbat qiymat siz to'laganingizni bildiradi. Birinchi had — bu fill'laringiz qog'oz portfeliga nisbatan sizga qancha tushgani; ikkinchisi — Perold'ning imkoniyat xarajati — bajarilmagan qoldiq narx qochib ketgan qiymatda belgilanadi; uchinchisi esa birjangiz hisobotida ko'rsatiladigan yagona qismdir.
Bir konventsiya haqida eslatma: sanoatda "arrival price" (kelish narxi) deyiladi, va aksariyat aksiya TCA'sida arrival — bu buyurtma bozorga yetib borgan paytdagi mid narxni bildiradi. Bot uchun esa qaror vaqti va kelish vaqti sizning o'z ichki kechikishingiz hamda rate-limit navbatida kutish tufayli farqlanadi — bu haqiqiy, o'lchanadigan xarajat. Shuning uchun biz ikkala vaqt belgisini ham, ikkala narxni ham saqlaymiz va dekompozitsiyaga ularni ajratishga imkon beramiz.
Dekompozitsiya: kechikish, ta'sir, vaqtlash, imkoniyat, komissiyalar
Bitta IS raqami sizga ijro qimmatga tushayotganini aytadi. Lekin nima uchun ekanini aytmaydi, turli komponentlar uchun yechimlar esa butunlay boshqa-boshqa — kechikish xarajati va ta'sir xarajatini bir xil o'zgartirish bilan hal qilib bo'lmaydi. Robert Kissell'ning kengaytirilgan implementation shortfall usuli (Kissell, 2006, "The Expanded Implementation Shortfall: Understanding Transaction Cost Components," Journal of Trading 1(3), 6–16; to'liq kitob shaklida The Science of Algorithmic Trading and Portfolio Management, Academic Press, 2013 da ishlab chiqilgan) jamini komponentlarga ajratadi, har biri buyurtma hayot siklining alohida bosqichiga tegishli. Amaliyotchi versiyasi, arrival mid dan foydalanib (birinchi birja tasdig'idagi mid narx):
Bu tenglik Perold ta'rifiga aniq qaytadi — hadlarni ochsangiz, qisqarib ketadi. Har bir qismning o'z egasi bor:
Kechikish xarajati : signal ishga tushishi bilan birinchi bola buyurtmangiz birjada faol bo'lishi orasidagi narx drifti. Bu sizning infratuzilmangiz — serializatsiya, tarmoq, rate-limit navbatlari, xavf tekshiruvlari. Agar signalingiz haqiqiy qisqa gorizontli alfaga ega bo'lsa, kechikish xarajati u birinchi bo'lib oqib chiqadigan joy; barqaror musbat o'rtacha qiymat bozor siz yetib kelmasdan oldin sizning foydangizga harakatlanishini bildiradi — bu yemirilayotgan momentum-alfa yoki xuddi shu signalni savdo qilayotgan tezroq raqib.
Savdo xarajati : fill'laringiz kelishga (arrival) nisbatan qancha to'lagani — kesib o'tilgan spread, bozor ta'siri va jadval ichi drifti qo'shilib. Bu ijro algoritmining baholash varaqasi, va aynan ijro tadqiqotlari modellashtiradigan miqdor. Almgren, Thum, Hauptmann va Li (2005, "Direct Estimation of Equity Market Impact," Risk 18(7), 58–62) buni Citigroup deski orqali o'tgan taxminan 700,000 AQSh aksiya buyurtmalari ustida (2001-yil dekabr — 2003-yil iyun) o'lchagan va savdo xarajati kunlik volatillik va ishtirok darajasiga qarab masshtablanishini aniqlagan — vaqtinchalik ta'sir savdo tezligiga nisbatan darajali qonun bo'yicha, ko'rsatkichi taxminan 3/5 ga yaqin, doimiy ta'sir esa hajmga deyarli chiziqli. Kalibrlashda biz ularning funksional shaklidan qayta foydalanamiz.
Vaqtlash xavfi: bu o'rtacha dekompozitsiyada had emas, balki uning atrofidagi dispersiya. Ota buyurtmani vaqt bo'yicha yoyish kutilayotgan ta'sirni kamaytiradi, ammo sizni volatillikka duchor qiladi; qolgan pozitsiyasi bo'lgan jadval uchun xarajatning standart og'ishi ko'rinishida masshtablanadi. Bu aynan Almgren–Chriss freymvorki optimallashtiradigan murosa. TCA hisobotingizda bu ota buyurtmalar bo'yicha IS ning tarqalishi sifatida namoyon bo'ladi — har bir o'rtacha qiymat yonida standart og'ishni ko'rsating, aks holda barcha e'tibor o'rtachaga, barcha pulingiz esa dumga (tail) ketadi.
Imkoniyat xarajati : bajarilmagan miqdor yakuniy narxda belgilanadi. Passiv strategiyalar uchun bu odatda eng katta va eng kam tekshiriladigan komponent, va u butun freymvorkni halol qiladigan had — buni tuzoqlar bo'limida batafsilroq ko'rib chiqamiz, chunki uni tashlab qo'yish TCA orqali o'zini-o'zi aldashning eng keng tarqalgan usulidir.
Komissiyalar : aniq qism. Kriptoda komissiyalarni chegirmalardan keyin loglang (VIP darajalar, fill vaqtidagi narxda konvertatsiya qilingan token qaytimlari) va maker qaytimlarini ishorasi bilan saqlang — manfiy komissiya shovqin emas, bu ma'lumot.
Amaliy misol
10 BTC sotib olamiz (). Signal da ishga tushadi; qog'oz nominali $600,000. Birinchi bola buyurtma mid narxda tasdiqlanadi. Keyingi ikki daqiqada 8 BTC VWAP 60,072 da fill bo'ladi; narx uzoqlashib bormoqda, algoritm o'z limitiga rioya qiladi, va qolgan 2 BTC mid narxda bekor qilinadi. Aralash komissiyalar bajarilgan nominalning 2.5 bazis punkti.
| Komponent | Formula | USD | qog'oz nominalining bps'i |
|---|---|---|---|
| Kechikish | 120 | 2.0 | |
| Savdo xarajati | 480 | 8.0 | |
| Imkoniyat | 456 | 7.6 | |
| Komissiyalar | 120 | 2.0 | |
| Jami IS | 1,176 | 19.6 |
Birja hisobotida $120 ko'rsatiladi. Qarorni amalga oshirishning haqiqiy narxi esa $1,176 bo'ldi — o'n barobar farq, bunda ikkita eng katta komponent komissiyaga asoslangan hisobda ko'rinmas edi. Uning taxminan 40% i hech qachon savdo qilinmagan miqdordan kelib chiqdi. Faqat fill'larni tahlil qiladigan TCA hisoboti bu ota buyurtmani 8 bps deb baholab, "yaxshi" deb hisoblagan bo'lardi.

Markout'lar: noqulay tanlovni narxlash
Implementation shortfall ota buyurtmani baholaydi. U alohida fill'lar sifati haqida hech narsa aytmaydi — aniqrog'i, siz sistematik ravishda sizdan ko'proq narsa biladigan kontragentlar bilan savdo qilyapsizmi yo'qmi. Bu markout'lar orqali o'lchanadi: har bir fill'ni undan keyingi belgilangan gorizontdagi mid narxga nisbatan belgilang.
bu yerda — vaqtidagi fill narxi, esa vaqtidagi mid narx. Bu fill'ning gorizontdagi bir birlik uchun mark-to-market PnL'i, va da uning aniq anatomiyasi bor: maker fill yarim spreddan boshlanadi (siz bid narxida sotib oldingiz, mid undan yuqorida); taker fill yarim spreddan boshlanadi. o'sishi bilan nima bo'lishi savdoning axborot mazmunini ko'rsatadi:
- soniya snayperlik (sniping) va eskirgan kvotalarni "terib olish"ni ajratib beradi. Agar maker fill'laringiz bajarilgandan bir soniya o'tib allaqachon zararda bo'lsa, demak tezroq ishtirokchilar sizning kvotalaringizni ular noto'g'ri narxlangan paytda uradi — sizning kvota yangilash sikllingiz ularning trigger sikllaridan sekinroq. Bu markout latentlik diagnostikasi, strategiya diagnostikasi emas.
- soniya klassik noqulay tanlovni (adverse selection) o'lchaydi: fill'lardan keyin narx siz o'tgan tomon bo'ylab davom etadi. Market meyker uchun bu spread egallashi yengib o'tishi kerak bo'lgan xarajat; aksiya mikrostrukturasida buni realized spread deyishadi va SEC Rule 605 hisobotida 5 daqiqalik gorizontda institutsionallashtirilgan. Kripto tezroq harakatlanadi; 10–60 soniya bunga ekvivalent diapazon.
- soniya fill'lar mikrostruktura gorizontidan tashqarida sizga qarshi momentum tashiydimi-yo'qmi buni ko'rsatadi — taker strategiyalar uchun, signalingizning 60 soniyadagi alfasi kirish uchun to'lagan spred-plyus-ta'sirdan oshadimi. bps dan boshlanib, hech qachon nolni kesib o'tmaydigan taker markout egri chizig'i — bu alfasi to'lay olmaydigan kirishlar uchun to'laydigan strategiyadir.
Maker/taker assimetriyasi — bu ikkita egri chiziqdagi passiv savdoning butun iqtisodiyoti. bps dan (yarim spred) boshlanib, 60 soniyada bps gacha pasayadigan maker egri chizig'i shuni aytadi: siz spredni egallaysiz, lekin undan ko'prog'ini qaytarib berasiz, va hech qanday rebate darajasi buni tuzatmaydi. Xuddi shu egri chiziq bps da barqarorlashsa, bu kvota beruvchi dvigatel o'zini oqlayapti degani. Bu, shuningdek, sodda touch-fill backtestlar aynan e'tiborsiz qoldiradigan narsa — narx sizning limitingizga tegib o'tganida sizni fill qiladigan simulyator fill bo'lish noto'g'ri bo'lish bilan bog'liqligini e'tiborsiz qoldiradi, shuning uchun fill-simulyatsiya zinapoyasining navbatni hisobga oluvchi pog'onasi o'lchangan markout'larni taxmin emas, balki kirish ma'lumoti sifatida talab qiladi.

Hisoblash — bu o'zingizning mid narx oqimingiz ustidagi merge_asof:
import pandas as pd
def markouts(fills: pd.DataFrame, mids: pd.DataFrame,
horizons=("1s", "10s", "60s")) -> pd.DataFrame:
"""fills: [ts, price, qty, side, liquidity]; mids: [ts, mid].
Both UTC-indexed and sorted. Mid stream must be from YOUR captured
feed, not candles reconstructed later."""
fills = fills.sort_values("ts").reset_index(drop=True)
mids = mids.sort_values("ts")
out = fills.copy()
for h in horizons:
probe = fills[["ts"]].copy()
probe["ts"] = probe["ts"] + pd.Timedelta(h)
m = pd.merge_asof(probe, mids, on="ts", direction="backward")
out[f"mo_{h}"] = (fills["side"] * (m["mid"].values - fills["price"])
/ fills["price"] * 1e4)
return out
def markout_report(mo: pd.DataFrame) -> pd.DataFrame:
"""Qty-weighted markouts by liquidity flag. Weighting matters:
a 0.001 BTC fill and a 2 BTC fill are not equal evidence."""
cols = [c for c in mo.columns if c.startswith("mo_")]
def agg(g):
w = g["qty"] / g["qty"].sum()
return pd.Series({c: (g[c] * w).sum() for c in cols}
| {"n": len(g), "qty": g["qty"].sum()})
return mo.groupby("liquidity").apply(agg)
Hisobotni yanada nozikroq kesib ko'ring — belgi (symbol), kunning soati va kvotaning mid narxdan masofasi bo'yicha. Maker strategiyasi uchun eng foydali kesim — bu fill vaqtidagi navbat pozitsiyasi bo'yicha markout: yangi navbatning boshida turgan fill'lar, sizni yutib o'tgan (swept) darajadagi fill'lardan butunlay boshqacha narxlanadi.
Quvur: nimani loglash kerak
TCA log qatlamida o'ladi, matematika qatlamida emas. Yuqoridagi matematika ko'pchilik botlar tashlab yuboradigan raqamlarni talab qiladi, va ularning hech birini keyinchalik birja tarixidan qayta tiklab bo'lmaydi. Muzokara qilib bo'lmaydigan narsalar:
- Qaror mid narxi, o'z feedingizdan, signal vaqtida. Birja sham (candle) yopilishi emas, keyingi qayta tiklash emas. Benchmark — "strategiyam qaror qabul qilgan paytda ishongan narx" — buni faqat o'sha paytdagi jarayoningiz biladi.
- Ikkala vaqt belgisi: qaror vaqti va birinchi tasdiq vaqti, aks holda kechikish xarajati o'lchab bo'lmaydigan bo'lib qoladi va sezdirmasdan savdo xarajatiga qo'shilib ketadi.
- Har bir fill birja vaqt belgisi, komissiya va maker/taker belgisi bilan — sizning lokal qabul qilish vaqtingiz o'zingizning kiruvchi kechikishingiz bilan ifloslangan.
- Bekor qilingan va muddati o'tgan ota buyurtmalar, hammasi kabi loglangan. Nol fill'li ota buyurtmalar jadvaldagi eng qimmat qatorlardir.
- Doimiy mid narx oqimi (yoki L1 oqimi) 100–250ms granularlikda, markout'larni hisoblash uchun yetarlicha uzoq saqlangan. Agar siz fill simulyatori uchun order book'larni allaqachon yozib olayotgan bo'lsangiz, bu bepul.
Ikkita tekis jadval yetarli:
PARENTS = {
"parent_id": "str",
"strategy": "str",
"symbol": "str",
"venue": "str",
"algo": "str", # twap | pov | sniper | quote | ...
"side": "int8", # +1 buy, -1 sell
"qty": "float64", # parent size, base units
"limit_px": "float64", # NaN for unconstrained
"decision_ts": "datetime64[ns, UTC]",
"decision_mid": "float64", # mid your feed showed at decision_ts
"arrival_ts": "datetime64[ns, UTC]", # first exchange ack
"arrival_mid": "float64",
"end_ts": "datetime64[ns, UTC]", # filled / cancelled / expired
"terminal_mid": "float64",
"mkt_volume": "float64", # market volume over [arrival_ts, end_ts]
"sigma_bps": "float64", # realized vol estimate at decision time
}
FILLS = {
"parent_id": "str",
"ts": "datetime64[ns, UTC]", # exchange timestamp
"price": "float64",
"qty": "float64",
"fee": "float64", # quote ccy, post-discount, signed
"liquidity": "str", # maker | taker
"venue": "str",
}
Atributsiya funksiyasi dekompozitsiyaning to'g'ridan-to'g'ri transkripsiyasi:
import numpy as np
def is_decomposition(p: pd.Series, fills: pd.DataFrame) -> dict:
"""Expanded implementation shortfall for one parent, bps of paper
notional. Sign convention: positive = cost."""
s, X = p["side"], p["qty"]
paper = X * p["decision_mid"]
x = fills["qty"].sum()
delay = s * X * (p["arrival_mid"] - p["decision_mid"])
trade = s * ((fills["price"] - p["arrival_mid"]) * fills["qty"]).sum()
oppty = s * (X - x) * (p["terminal_mid"] - p["arrival_mid"])
fees = fills["fee"].sum()
bps = lambda v: 1e4 * v / paper
return {
"parent_id": p["parent_id"],
"delay_bps": bps(delay), "trade_bps": bps(trade),
"oppty_bps": bps(oppty), "fees_bps": bps(fees),
"is_bps": bps(delay + trade + oppty + fees),
"fill_ratio": x / X,
"participation": x / max(p["mkt_volume"], x),
}
def tca_table(parents: pd.DataFrame, fills: pd.DataFrame) -> pd.DataFrame:
fg = dict(tuple(fills.groupby("parent_id")))
empty = fills.iloc[0:0]
rows = [is_decomposition(p, fg.get(p["parent_id"], empty))
for _, p in parents.iterrows()]
return parents.merge(pd.DataFrame(rows), on="parent_id")
Va atributsiya so'rovlari — bu TCA hisobdorlik bo'lishdan to'xtab, tadqiqotga aylanadigan joy:
tca = tca_table(parents, fills)
def wavg(g: pd.DataFrame, col: str) -> float:
w = g["qty"] * g["decision_mid"] # notional weights
return (g[col] * w).sum() / w.sum()
comp = ["delay_bps", "trade_bps", "oppty_bps", "fees_bps", "is_bps"]
by_strat = tca.groupby("strategy").apply(
lambda g: pd.Series({c: wavg(g, c) for c in comp}
| {"is_std": g["is_bps"].std(), "n": len(g)}))
done = tca[tca["fill_ratio"] > 0.99]
done["pov_bin"] = pd.qcut(done["participation"], 6)
impact_curve = done.groupby("pov_bin").apply(lambda g: wavg(g, "trade_bps"))
tca["hour"] = tca["arrival_ts"].dt.hour
by_hour = tca.groupby("hour").apply(lambda g: wavg(g, "is_bps"))
by_venue = tca.groupby("venue").apply(
lambda g: pd.Series({"is_bps": wavg(g, "is_bps"),
"is_std": g["is_bps"].std(),
"fill_ratio": g["fill_ratio"].mean(), "n": len(g)}))
4-so'rov — bu smart order router optimallashtiradigan kirish jadvali — har bir venue bo'yicha TCA'siz marshrutlash komissiya jadvali bo'yicha marshrutlash, ya'ni eng kichik xarajat komponenti bo'yicha marshrutlash degani (Kriptoda smart order routing aynan shu jadvalni boshlang'ich nuqta sifatida oladi). Markout moduli bilan birga, bu va'da qilingan ~200 qator.
Tsiklni yopish: backtest xarajat modelini kalibrlash
Mana bu yerda quvur o'zini oqlaydi. Backtestingiz raqamlarni da'vo qiladi: slippage_bps = 5, fill ehtimoli egri chizig'i, ta'sir koeffitsienti. Ularning har biri live ijro haqidagi da'vo, TCA jadvali esa live ijroning o'zi. Tsikl: TCA bilan o'lchash, xarajat modelini moslashtirish, moslashtirilgan model bilan backtestni ishga tushirish, savdo qilish, qayta o'lchash.

Taker xarajati uchun o'zingiz yangi funksional shakl o'ylab topish o'rniga Almgren va boshq. (2005) dan qarzga oling. Ularning natijasi — xarajat kunlik volatillikka va ishtirok darajasining darajasiga proporsional — ikkita parametrli model beradi:
bunda aksiya bahosi dastlabki qiymat sifatida. Uni xom ota buyurtmalarda emas, guruhlangan (binned) o'rtachalarda moslashtiring — alohida ota buyurtma xarajatlari shovqin bilan boshqariladi (bu vaqtlash xavfi hadi), va xom ma'lumotlar ustidagi log-log regressiya xursandchilik bilan shovqinga moslashadi:
done = tca[(tca["fill_ratio"] > 0.99) & (tca["participation"] > 0)]
done["norm_cost"] = done["trade_bps"] / done["sigma_bps"]
bins = done.groupby(pd.qcut(done["participation"], 8)).agg(
pov=("participation", "mean"), cost=("norm_cost", "mean"))
bins = bins[bins["cost"] > 0] # can't log a negative bin
b, log_a = np.polyfit(np.log(bins["pov"]), np.log(bins["cost"]), 1)
def taker_cost_bps(participation, sigma_bps, a=np.exp(log_a), b=b):
return a * sigma_bps * participation ** b
Keyin xato chegaralari haqida halol bo'ling. Almgren jamoasi 700,000 buyurtmaga ega bo'lsa-da, vaqtinchalik ta'sir ko'rsatkichini deb hisobot qilgan; 2,000 ta ota buyurtmasi bo'lgan bot esa har bir belgi (symbol) uchun ni erkin baholashga haqli emas. Amaliy rejim: bo'yicha normallashtirgandan keyin belgilar bo'yicha birlashtiring, ni 0.6 ga qattiq torting (yoki uni butunlay qat'iylashtirib, faqat ni moslashtiring), va har oyda qayta moslashtiring. Agar sizning moslashtirilgan ingiz o'sib ketsa, izingiz kattalashgan yoki bozor yupqalashgan — har qanday holatda ham backtest buni bilishi kerak edi.
Maker strategiyalar uchun kalibrlash maqsadlari boshqacha va boshqa ikkita moduldan keladi:
- Fill ehtimoli: fill simulyatorining navbat modeli har bir (spread-masofa, navbat-pozitsiya) katak uchun ni bashorat qiladi; ota buyurtma logingiz esa har bir katak uchun haqiqiy fill nisbatlarini beradi. Kelishmovchilik — bu grid havolasi biriktirilgan simulyator xatosi.
- Noqulay tanlov: simulyatorning bilvosita "fill'lar almashtiriladi" degan taxminini o'lchangan markout jadvali bilan almashtiring — masofada, soatda simulyatsiya qilingan maker fill o'lchangan ni darhol mark-to-market chegirma sifatida oladi. Aynan shu bitta o'zgarish — sarob ko'radigan maker backtest bilan kuzatib boradigan backtest o'rtasidagi farqdir; bu fill-simulyatsiya maqolasida belgilangan yetishmayotgan kalibrlash kirishi edi.
- Xarajat tarqalishi: backtestga IS ning o'rtachasini emas, uning taqsimotini bering. Faqat o'rtachani siljitadigan xarajat modeli vaqtlash xavfi yaratadigan drawdown'larni takrorlay olmaydi; hatto har bir ota buyurtma bo'yicha IS'ga moslashtirilgan lognormal taqsimot ham doimiy qiymatdan yaxshiroq ishlaydi.
To'liq slippage-egri chiziq muolajasi — funksional shakllar, rejimga bog'liqlik, darajali qonun qachon buziladi — bu alohida maqola: Backtestlar uchun slippage egri chiziqlari va xarajat modellari. Bu yerdagi asosiy fikr — arxitektura: o'sha maqoladagi modellarni ushbu maqoladagi jadvallarsiz moslashtirib bo'lmaydi.
Tuzoqlar
TCA adabiyoti o'nlab yillar davomida mavjud, uni "aldash" usullari ham shunday. Uchta muvaffaqiyatsizlik rejimi o'z-o'zini aldashning ko'pchiligini tashkil qiladi.
Benchmark bilan o'ynash. Kelish narxidan (arrival price) boshqa har qanday benchmarkni "quchoqlab" olish mumkin. Klassik misol — VWAP: interval VWAP'ga nisbatan baholanadigan algoritm uni bir bazis punkt ichida kuzatib borishi mumkin, shu bilan birga pozitsiya kelishga nisbatan yigirmata qon yo'qotayotgan bo'ladi, chunki benchmark siz siljitayotgan narx bilan birga drift qiladi — va sezilarli ishtirok darajasida sizning o'z print'laringiz o'zi VWAP hisoblanadi, shuning uchun uni kuzatish o'z-o'zini baholaydigan uy vazifasidir. Biz benchmark siyosatini TWAP vs VWAP vs POV maqolasida yorib ko'rsatgan edik; TCA tomonidagi qoida esa soddaroq: benchmarklar savdodan oldin tanlanadi, va IS-versus-arrival har doim hisoblanadi, hatto scheduler o'zining scheduling benchmarkiga nisbatan baholansa ham. Nozikroq varianti — arrival bilan o'ynash: agar decision_ts ni belgilaydigan komponent qisqa muddatli momentumni ko'ra olsa, u "qarorlar" vaqtini kechikish hadini yaxshiroq ko'rsatish uchun sozlashi mumkin. Qaror vaqt belgilari signal qatlamiga tegishli, ular har qanday ijro mantig'i ishlashidan oldin loglanadi.
Faqat bajarilganlar tahlilidagi survivorship bias (omon qolganlar noto'g'ri xulosasi). Xarajat tahlilingizni faqat fill'larga bog'lang, va passiv ijro bepul ko'rinadi. Aniqroq aytganda: 100 ta passiv sotib olish ota buyurtmasi, mid narxdan bir tik pastda. Oltmishtasi bajariladi va — passiv bo'lgani uchun — o'rtacha kelishdan 3 bps yaxshiroq narxlarda bajariladi: o'lchangan "xarajat" bps, faxrlanadigan hisobot. Bajarilmagan qirqtasi esa aynan narx uzoqlashib ketgan buyurtmalar edi; ularni bekor qilishda 25 bps noqulay deb belgilang, va halol raqam bps bo'ladi. Faqat-fill hisoboti va haqiqiy hisobot 11 bps ga va ishorasiga ko'ra ham farq qiladi. Bu chekka holat emas — bu passiv savdoning mexanizmi: bajarilish narx siz orqali o'tishi bilan bog'liq, va bu aynan touch-fill backtestlarni fantaziyaga aylantiradigan bir xil shartlanish. Imkoniyat xarajati IS ning ixtiyoriy nafislashi emas; bu butun o'lchovni tanlov ta'siridan himoya qiladigan haddir. Xuddi shu og'ishning taker varianti ham bor: o'tkazib yuborilgan IOC buyurtmalari, rate limit yoki xavf tekshiruvlari tomonidan rad etilgan buyurtmalar — agar o'tkazib yuborishlar loglanmasa, o'tkazib yuborish xarajati o'lchanmaydi, va u aynan strategiyangiz savdoni eng ko'p xohlagan tez bozorlarda eng katta bo'ladi.
Turli xil oyoqqa otish (foot-gun), qisqacha: birja sham'laridan qayta tiklangan arrival mid narxlar (feedingiz va sham aynan muhim paytda kelishmaydi); notional og'irliklarsiz har bir ota buyurtma bo'yicha bps'larni o'rtachalash (mingta chang fill bitta haqiqiy buyurtmani ovoz bilan bosib ketadi); chegirmagacha loglangan komissiyalar; fill'dan boshqa venue'dan olingan markout mid narxlar (venue'lararo bazis noqulay tanlov niqobida); va perp'larda funding to'planishining ijro oynasiga oqib kirishiga yo'l qo'yish — funding xarajat, lekin ijro xarajati emas, va ularni aralashtirish ikkala tahlilni ham zaharlaydi.
Bu hafta nima qilish kerak
Botingizga ikkita log jadvalini qo'shing — yuqoridagi sxema loyiha emas, ustunlar ro'yxati. Hech narsani orqaga to'ldirmang (backfill): ikki haftalik halol loglar bir yillik qayta tiklashdan yaxshiroq. Dekompozitsiyani va uchta markout gorizontini ishga tushiring. Qaysi komponent ustunlik qilishini bilib olasiz (deyarli hech qachon komissiyalar emas), passiv fill'laringiz o'z spred egallashidan tashqari noqulay tanlanganmi-yo'qmi, va backtestingizning xarajat konstantasi o'lchangan egri chiziqdan qanchalik uzoqda turgani. Keyin moslashtirilgan egri chiziqni simulyatorga qaytarib ulang va aynan shu strategiyani ishga tushirishni sizga aytgan backtestni qayta ishga tushiring. Perold'ning qog'oz portfeli, o'ttiz sakkiz yildan keyin ham, hali ham sizning haqiqiy portfelingiz ega bo'lgan yagona halol raqibdir.
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.