Implementation shortfall dan TCA DIY: mengukur berapa sebenarnya biaya eksekusi Anda
Setiap desk institusional punya pipeline transaction cost analysis. Hampir tidak ada yang menjalankan bot crypto punya itu. Setup yang umum hanya mencatat fill, menjumlahkan fee, dan menyebut selisih antara PnL backtest dan PnL live sebagai "slippage" — satu residual tak terjelaskan yang menyerap latency, spread, impact, adverse selection, dan setiap order yang tidak terisi karena harga kabur. Anda tidak bisa memperbaiki biaya yang Anda ukur sebagai satu angka saja. Mesin untuk mengukurnya dengan benar sudah ada sejak 1988, bukan sesuatu yang proprietary, dan di atas log fill Anda sendiri hanya sekitar 200 baris Python. Artikel ini membangunnya.
Hasilnya bukan sekadar dashboard yang lebih cantik. Backtest Anda memuat model biaya — konstanta slippage, probabilitas fill, koefisien impact — dan setiap parameter di dalamnya saat ini cuma tebakan. TCA atas fill live adalah satu-satunya ground truth yang bisa dipakai mengkalibrasi parameter tersebut. Kita sudah membangun sisi simulasi dari loop ini di Fill simulation: the ladder from close-price fantasy to queue-aware reality; artikel ini membangun sisi pengukurannya.
Paper versus realita: apa yang sebenarnya diukur Perold
Trik fundamentalnya berasal dari André Perold (1988, "The Implementation Shortfall: Paper Versus Reality," Journal of Portfolio Management 14(3), 4–9). Jalankan dua portfolio secara paralel. Paper portfolio mengeksekusi setiap keputusan secara instan, dalam ukuran tak terbatas, tanpa biaya, pada harga yang berlaku saat momen keputusan diambil. Real portfolio adalah apa yang benar-benar dilakukan bot Anda: fill parsial, quote yang dikejar, sisa yang dibatalkan, fee. Implementation shortfall adalah selisih return keduanya.
Definisi ini penting karena apa yang ditolaknya untuk disembunyikan. Laporan fee menunjukkan komisi. Laporan fill-versus-limit-price tidak menunjukkan apa-apa (Anda tidak pernah fill lebih buruk dari limit Anda — secara konstruksi). Paper portfolio membebankan Anda untuk segalanya: drift antara keputusan dan arrival, spread yang Anda crossing, impact yang Anda timbulkan, dan — yang krusial — order yang tidak pernah terisi selagi harga kabur. Wagner dan Edwards (1993, "Best Execution," Financial Analysts Journal 49(1), 65–71) menyebut fee yang terlihat sebagai puncak gunung es; untuk apa pun dengan turnover, bagian yang tenggelam justru mendominasi.
Mari tetapkan notasi. Sebuah parent order: sisi (buy/sell), ukuran . Decision price adalah mid yang dilihat strategi Anda saat sinyal muncul. Fill datang sebagai dengan total kuantitas terisi . Pada horizon (parent selesai, dibatalkan, atau timeout), mid-nya adalah . Fee eksplisit adalah . Implementation shortfall dalam satuan mata uang:
dinormalisasi ke basis point dengan membaginya dengan notional paper . Nilai positif berarti Anda membayar. Suku pertama adalah berapa biaya fill Anda relatif terhadap paper portfolio; suku kedua adalah opportunity cost ala Perold — sisa yang tidak terisi, ditandai pada harga tempat ia kabur; suku ketiga adalah satu-satunya bagian yang diakui oleh laporan exchange Anda.
Satu catatan konvensi: industri menyebutnya "arrival price," dan di sebagian besar TCA ekuitas, arrival berarti mid saat order mencapai pasar. Untuk bot, waktu keputusan dan waktu arrival berbeda karena latency internal Anda sendiri plus antrean rate-limit — biaya yang nyata dan terukur. Jadi kita simpan kedua timestamp dan kedua harga, dan biarkan dekomposisi memisahkan keduanya.
Dekomposisi: delay, impact, timing, opportunity, fee
Satu angka IS saja memberitahu Anda bahwa eksekusi itu mahal. Ia tidak memberitahu mengapa, dan perbaikan untuk komponen yang berbeda sama sekali berbeda — Anda tidak menyelesaikan delay cost dan impact cost dengan perubahan yang sama. Expanded implementation shortfall dari Robert Kissell (Kissell, 2006, "The Expanded Implementation Shortfall: Understanding Transaction Cost Components," Journal of Trading 1(3), 6–16; dikembangkan lebih panjang di The Science of Algorithmic Trading and Portfolio Management, Academic Press, 2013) memecah total menjadi komponen-komponen, masing-masing dapat diatribusikan ke tahap berbeda dalam siklus hidup order. Versi praktisi, menggunakan arrival mid (mid pada acknowledgment exchange pertama):
Identitas ini secara persis teleskopis kembali ke definisi Perold — jabarkan suku-sukunya dan akan saling meniadakan. Setiap bagian punya pemilik yang berbeda:
Delay cost : drift harga antara sinyal muncul dan child order pertama Anda live di exchange. Ini adalah infrastruktur Anda — serialisasi, jaringan, antrean rate-limit, risk check. Jika sinyal Anda memiliki alpha jangka pendek yang genuin, delay cost adalah tempat pertama ia bocor; rata-rata yang konsisten positif menandakan pasar bergerak sesuai arah Anda sebelum Anda tiba — alpha momentum yang meluruh, atau ada orang lain yang lebih cepat men-trading sinyal yang sama.
Trading cost : berapa yang dibayar fill Anda relatif terhadap arrival — spread yang di-cross ditambah market impact ditambah drift intra-schedule. Ini adalah rapor dari algoritma eksekusi, dan kuantitas yang benar-benar dimodelkan oleh riset eksekusi. Almgren, Thum, Hauptmann dan Li (2005, "Direct Estimation of Equity Market Impact," Risk 18(7), 58–62) mengukurnya atas kurang lebih 700.000 order ekuitas AS dari desk Citigroup (Desember 2001–Juni 2003) dan menemukan trading cost berskala dengan volatilitas harian dan participation rate — temporary impact mengikuti power law pada trade rate dengan eksponen mendekati 3/5, permanent impact mendekati linear terhadap ukuran. Kita akan memakai ulang bentuk fungsional mereka saat mengkalibrasi.
Timing risk: bukan suku dalam dekomposisi rata-rata, melainkan varians di sekitarnya. Menyebarkan parent order sepanjang waktu mengurangi impact yang diharapkan tapi mengekspos Anda pada volatilitas; untuk schedule dengan posisi tersisa , standar deviasi biaya berskala sebagai . Ini persis trade-off yang dioptimasi oleh kerangka Almgren–Chriss. Dalam laporan TCA Anda, ini muncul sebagai dispersi IS antar parent order — laporkan standar deviasinya di samping setiap rata-rata, atau rata-rata akan menyita semua perhatian sementara ekornya akan menyita semua uang Anda.
Opportunity cost : kuantitas tak terisi yang ditandai pada harga terminal. Untuk strategi pasif, ini rutin menjadi komponen terbesar sekaligus paling jarang diperiksa, dan inilah suku yang membuat seluruh kerangka jujur — lebih lanjut di bagian jebakan, karena mengabaikannya adalah cara paling umum orang membohongi diri sendiri dengan TCA.
Fee : bagian eksplisit. Di crypto, catat fee setelah diskon (tier VIP, rebate token yang dikonversi pada harga saat fill) dan pertahankan tanda pada maker rebate — fee negatif adalah data, bukan noise.
Contoh kasus
Buy BTC. Sinyal muncul dengan ; notional paper $600.000. Child order pertama ter-ack dengan mid . Selama dua menit berikutnya, 8 BTC terisi pada VWAP 60.072; harga sedang trending menjauh, algo mematuhi limitnya, dan sisa 2 BTC dibatalkan dengan mid pada . Fee gabungan 2,5 bps dari notional yang terisi.
| Komponen | Formula | USD | bps dari paper |
|---|---|---|---|
| Delay | 120 | 2,0 | |
| Trading cost | 480 | 8,0 | |
| Opportunity | 456 | 7,6 | |
| Fee | 120 | 2,0 | |
| Total IS | 1.176 | 19,6 |
Laporan exchange menunjukkan $120. Biaya riil dari mengimplementasikan keputusan tersebut adalah $1.176 — sepuluh kali lipat, dengan dua komponen terbesar tidak terlihat oleh akuntansi berbasis fee. Kurang lebih 40% di antaranya berasal dari kuantitas yang tidak pernah ter-trading. Laporan TCA yang hanya menganalisis fill akan menilai parent order ini 8 bps dan menyebutnya baik-baik saja.

Markout: memberi harga pada adverse selection
Implementation shortfall menilai parent order. Ia tidak mengatakan apa pun tentang kualitas fill individual — secara spesifik, apakah Anda secara sistematis bertransaksi dengan counterparty yang tahu sesuatu yang tidak Anda ketahui. Itu diukur dengan markout: menandai setiap fill terhadap mid pada horizon tetap setelah kejadian tersebut.
di mana adalah harga fill pada waktu dan adalah mid pada waktu . Ini adalah PnL mark-to-market per unit dari fill pada horizon , dan ia memiliki anatomi yang jelas pada : fill maker dimulai pada setengah-spread (Anda beli di bid, mid berada di atas Anda); fill taker dimulai pada setengah-spread. Apa yang terjadi saat bertambah adalah kandungan informasi dari trade tersebut:
- s mengisolasi sniping dan pickoff quote basi. Jika fill maker Anda sudah rugi satu detik setelah terisi, partisipan yang lebih cepat sedang menghantam quote Anda tepat saat menjadi mispriced — loop update quote Anda lebih lambat dari loop trigger mereka. Markout ini adalah diagnostik latency, bukan diagnostik strategi.
- s mengukur adverse selection klasik: fill yang diikuti pergerakan berkelanjutan menembus harga Anda. Bagi market maker, ini adalah biaya yang harus dikalahkan oleh spread capture; mikrostruktur ekuitas menyebut kuantitas terkaitnya realized spread, dilembagakan dalam pelaporan SEC Rule 605 pada horizon 5 menit. Crypto bergerak lebih cepat; 10–60 detik adalah band yang setara.
- s memberitahu apakah fill membawa momentum yang melawan Anda melampaui horizon mikrostruktur — untuk strategi taker, apakah alpha sinyal Anda pada 60 detik melebihi spread-plus-impact yang Anda bayar untuk masuk. Kurva markout taker yang mulai di bps dan tidak pernah melewati nol adalah strategi yang membayar entry yang tidak sanggup dibiayai oleh alphanya.
Asimetri maker/taker adalah keseluruhan ekonomi trading pasif dalam dua kurva. Kurva maker yang mulai di bps (setengah-spread) dan meluruh ke bps pada 60 detik mengatakan: Anda menangkap spread tapi memberikan kembali lebih banyak, dan tidak ada tier rebate yang bisa memperbaikinya. Kurva yang sama tapi mengendap di bps mengatakan mesin quoting menghasilkan nilainya. Ini juga persis yang diasumsikan hilang oleh backtest touch-fill naif — simulator yang mengisi Anda setiap kali harga menyentuh limit Anda mengabaikan bahwa terisi berkorelasi dengan salah, itulah sebabnya anak tangga queue-aware pada tangga fill-simulation membutuhkan markout terukur sebagai input, bukan sebagai asumsi.

Komputasinya adalah sebuah merge_asof di atas mid stream Anda sendiri:
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)
Iris laporan lebih jauh berdasarkan simbol, jam dalam sehari, dan jarak quote dari mid. Irisan yang paling actionable untuk strategi maker adalah markout-per-posisi-antrean-saat-fill: fill di depan antrean segar berharga sangat berbeda dari fill di mana level tersebut tersapu melalui posisi Anda.
Pipeline: apa yang harus dicatat
TCA mati di lapisan logging, bukan di lapisan matematika. Matematika di atas membutuhkan angka-angka yang dibuang begitu saja oleh kebanyakan bot, dan tak satu pun bisa direkonstruksi kembali dari riwayat exchange. Hal-hal yang tidak bisa dinegosiasikan:
- Decision mid, dari feed Anda sendiri, pada saat sinyal. Bukan candle close exchange, bukan rekonstruksi belakangan. Benchmarknya adalah "harga yang diyakini strategi saya saat memutuskan" — hanya proses Anda pada momen itu yang tahu.
- Kedua timestamp: waktu keputusan dan waktu ack pertama, atau delay cost jadi tidak terukur dan diam-diam bercampur ke trading cost.
- Setiap fill dengan timestamp exchange, fee, dan flag maker/taker — waktu terima lokal Anda tercemar oleh latency inbound Anda sendiri.
- Parent order yang dibatalkan dan kedaluwarsa, dicatat seperti yang lain. Parent order dengan nol fill adalah baris paling mahal dalam tabel.
- Mid stream persisten (atau L1 stream) dengan granularitas 100–250ms, disimpan cukup lama untuk menghitung markout. Jika Anda sudah merekam order book untuk fill simulator, ini gratis.
Dua tabel flat sudah cukup:
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",
}
Fungsi atribusi adalah transkripsi langsung dari dekomposisi:
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")
Dan kueri atribusinya, tempat TCA berhenti menjadi akuntansi dan mulai menjadi riset:
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)}))
Kueri 4 adalah tabel input yang dioptimasi oleh smart order router — routing tanpa TCA per-venue adalah routing berdasarkan jadwal fee, yakni berdasarkan komponen biaya terkecil (Smart order routing di crypto mengambil tabel ini sebagai titik awalnya). Bersama modul markout, inilah sekitar 200 baris yang dijanjikan.
Menutup loop: mengkalibrasi model biaya backtest
Di sinilah pipeline membayar dirinya sendiri. Backtest Anda mengklaim angka-angka: slippage_bps = 5, kurva probabilitas fill, koefisien impact. Setiap satu di antaranya adalah klaim tentang eksekusi live, dan tabel TCA adalah eksekusi live. Loopnya: ukur dengan TCA, fit model biaya, jalankan backtest dengan model yang sudah di-fit, trading, ukur ulang.

Untuk biaya taker, pinjam bentuk fungsional dari Almgren dkk. (2005) alih-alih menciptakan sendiri. Hasil mereka — biaya proporsional terhadap volatilitas harian dikali pangkat dari participation rate — memberikan model dua parameter:
dengan estimasi ekuitas sebagai prior. Fit pada rata-rata yang di-bin, bukan parent order mentah — biaya parent order individual didominasi oleh noise (itulah suku timing-risk), dan regresi log-log pada data mentah akan dengan senang hati nge-fit noise tersebut:
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
Lalu jujurlah soal margin errornya. Tim Almgren punya 700.000 order dan tetap melaporkan eksponen temporary-impact sebagai ; bot dengan 2.000 parent order tidak berhak mengestimasi secara bebas per simbol. Rezim praktisnya: gabungkan lintas simbol setelah dinormalisasi dengan , tarik kuat-kuat ke arah 0,6 (atau tetapkan saja dan hanya fit ), dan fit ulang setiap bulan. Jika hasil fit Anda melayang naik, footprint Anda membesar atau pasar menipis — bagaimanapun juga backtest perlu tahu itu.
Untuk strategi maker, target kalibrasinya berbeda dan berasal dari dua modul lainnya:
- Probabilitas fill: model queue dari fill simulator memprediksi per sel (jarak-spread, posisi-antrean); log parent order Anda memberikan rasio fill riil per sel. Ketidaksesuaian adalah bug simulator dengan referensi grid yang menyertainya.
- Adverse selection: ganti asumsi implisit simulator bahwa "fill itu fungible" dengan tabel markout terukur — fill maker simulasi pada jarak di jam membawa yang terukur sebagai haircut mark-to-market langsung. Perubahan tunggal ini adalah selisih antara backtest maker yang berhalusinasi dan yang benar-benar melacak; ini adalah input kalibrasi yang hilang, yang ditandai di artikel fill-simulation.
- Dispersi biaya: masukkan distribusi IS, bukan rata-ratanya, ke dalam backtest. Model biaya yang hanya menggeser rata-rata tidak bisa mereproduksi drawdown yang diciptakan timing risk; bahkan lognormal yang di-fit ke IS per-parent-order mengalahkan konstanta.
Pembahasan lengkap kurva slippage — bentuk fungsional, pengkondisian rezim, kapan power law-nya rusak — adalah artikel tersendiri: Slippage curves and cost models for backtests. Poinnya di sini bersifat arsitektural: model-model di artikel itu tidak bisa di-fit tanpa tabel-tabel dari artikel ini.
Jebakan
Literatur TCA sudah berumur puluhan tahun, begitu pula cara-cara mengakalinya. Tiga mode kegagalan menjelaskan sebagian besar penipuan diri sendiri.
Benchmark gaming. Benchmark apa pun selain arrival price bisa "dipeluk" (di-hug). Contoh klasiknya adalah VWAP: algoritma yang dinilai terhadap interval VWAP bisa melacaknya dalam satu basis point sementara posisi berdarah dua puluh bps relatif terhadap arrival, karena benchmarknya melayang mengikuti harga yang justru sedang Anda dorong sendiri — dan pada participation yang signifikan, print Anda sendiri adalah VWAP-nya, sehingga melacaknya sama saja dengan menilai PR sendiri. Kita sudah membedah politik benchmark di TWAP vs VWAP vs POV; aturan di sisi TCA lebih sederhana: benchmark dipilih sebelum trading, dan IS-versus-arrival selalu dihitung meskipun sebuah scheduler dinilai terhadap benchmark schedulingnya sendiri. Varian yang lebih halus adalah arrival gaming: jika komponen yang menetapkan decision_ts bisa melihat momentum jangka pendek, ia bisa mengatur waktu "keputusan" untuk mempercantik suku delay. Timestamp keputusan adalah milik lapisan sinyal, dicatat sebelum logika eksekusi apa pun berjalan.
Survivorship bias dalam analisis filled-only. Kondisikan analisis biaya Anda hanya pada fill, dan eksekusi pasif akan terlihat gratis. Konkretnya: 100 parent order buy pasif, satu tick di bawah mid. Enam puluh terisi, dan — karena pasif — terisi pada harga rata-rata 3 bps lebih baik dari arrival: "biaya" terukur bps, laporan yang membanggakan. Empat puluh yang tidak pernah terisi justru yang harganya melambung menjauh; tandai itu 25 bps adverse saat dibatalkan, dan angka jujurnya adalah bps. Laporan filled-only dan laporan sebenarnya berbeda 11 bps dan berbeda tanda. Ini bukan kasus pinggiran — ini adalah mekanisme trading pasif itu sendiri: terisi berkorelasi dengan harga yang menembus posisi Anda, pengkondisian yang sama yang membuat backtest touch-fill jadi fantasi. Opportunity cost bukan penyempurnaan opsional dari IS; ia adalah suku yang mempertahankan seluruh pengukuran dari bias seleksi. Bias yang sama punya varian taker: order IOC yang meleset, order yang ditolak oleh rate limit atau risk check — jika yang meleset tidak dicatat, biaya dari melesetnya tidak terukur, dan itu paling besar justru di pasar cepat tempat strategi Anda paling ingin trading.
Berbagai jebakan lain, singkatnya: arrival mid yang direkonstruksi dari candle exchange (feed Anda dan candle tersebut berselisih tepat saat itu penting); merata-ratakan bps per-parent-order tanpa bobot notional (seribu fill remeh mengalahkan suara satu order sungguhan); fee dicatat pra-diskon; mid markout diambil dari venue yang berbeda dari fill-nya (basis lintas-venue menyamar sebagai adverse selection); dan pada perp, membiarkan akrual funding bocor ke jendela eksekusi — funding adalah biaya, tapi bukan biaya eksekusi, dan mencampurnya meracuni kedua analisis.
Yang harus dilakukan minggu ini
Tambahkan dua tabel log ke bot Anda — skema di atas adalah daftar kolom, bukan proyek. Jangan backfill apa pun; dua minggu log yang jujur mengalahkan setahun rekonstruksi. Jalankan dekomposisinya dan tiga horizon markout. Anda akan belajar komponen mana yang mendominasi (hampir tidak pernah fee), apakah fill pasif Anda mengalami adverse selection melebihi spread capture-nya, dan seberapa jauh konstanta biaya backtest Anda dari kurva terukur. Lalu sambungkan kurva hasil fit itu kembali ke simulator dan jalankan ulang backtest yang tadinya menyuruh Anda menjalankan strategi ini sejak awal. Paper portfolio Perold, tiga puluh delapan tahun kemudian, masih menjadi satu-satunya lawan jujur yang dimiliki portfolio riil Anda.
Penulis
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.