Implementation shortfall dan DIY TCA: mengukur kos sebenar eksekusi anda
Setiap meja dagangan institusi mempunyai saluran paip transaction cost analysis. Hampir tiada sesiapa yang menjalankan bot kripto memilikinya. Persediaan tipikal mencatat fill, menjumlahkan yuran, dan memanggil perbezaan antara PnL backtest dengan PnL live sebagai "slippage" — satu residual tunggal yang tidak dijelaskan, yang menyerap latensi, spread, impact, adverse selection, dan setiap pesanan yang tidak terisi yang telah lari daripada harga. Anda tidak boleh membetulkan kos yang diukur sebagai satu nombor sahaja. Mekanisme untuk mengukurnya dengan betul telah wujud sejak 1988, ia bukan proprietari, dan ke atas log fill anda sendiri ia hanya kira-kira 200 baris Python. Artikel ini membina mekanisme tersebut.
Ganjarannya bukan dashboard yang lebih cantik. Backtest anda mengandungi model kos — pemalar slippage, kebarangkalian fill, pekali impact — dan setiap parameter di dalamnya pada masa ini hanyalah andaian. TCA ke atas fill live adalah satu-satunya ground truth yang boleh digunakan untuk menentukur parameter tersebut. Kami telah membina bahagian simulasi bagi gelung ini dalam Fill simulation: tangga dari fantasi harga penutup kepada realiti sedar-queue; artikel ini membina bahagian pengukuran.
Kertas berbanding realiti: apa yang Perold sebenarnya ukur
Helah asas ini dikaitkan dengan André Perold (1988, "The Implementation Shortfall: Paper Versus Reality," Journal of Portfolio Management 14(3), 4–9). Jalankan dua portfolio secara selari. Portfolio kertas melaksanakan setiap keputusan serta-merta, dalam saiz tanpa had, pada kos sifar, pada harga yang berlaku pada saat keputusan dibuat. Portfolio sebenar ialah apa yang bot anda benar-benar lakukan: fill separa, quote yang dikejar, baki yang dibatalkan, yuran. Implementation shortfall ialah perbezaan dalam pulangan kedua-duanya.
Definisi ini penting kerana apa yang ia enggan sembunyikan. Penyata yuran menunjukkan komisen. Laporan fill-berbanding-limit-price tidak menunjukkan apa-apa langsung (anda tidak pernah fill lebih teruk daripada limit anda — secara struktur memang begitu). Portfolio kertas mengenakan caj untuk segala-galanya: hanyutan antara keputusan dan ketibaan, spread yang anda silangi, impact yang anda cetuskan, dan — yang paling penting — pesanan yang tidak pernah terisi sementara harga terus lari. Wagner dan Edwards (1993, "Best Execution," Financial Analysts Journal 49(1), 65–71) menyebut yuran yang kelihatan sebagai hujung gunung ais; bagi apa-apa dengan turnover, bahagian yang tenggelam lebih mendominasi.
Tetapkan notasi. Satu pesanan induk (parent order): sisi (beli/jual), saiz . Harga keputusan ialah mid yang dilihat oleh strategi anda ketika isyarat dicetuskan. Fill tiba sebagai dengan jumlah kuantiti terisi . Pada horizon (induk selesai, dibatalkan, atau tamat masa), mid ialah . Yuran eksplisit ialah . Implementation shortfall dari segi matawang:
dinormalkan kepada basis points dengan membahagikannya dengan notional kertas . Positif bermakna anda membayar. Terma pertama ialah kos fill anda berbanding portfolio kertas; yang kedua ialah kos peluang Perold — baki yang tidak terisi ditanda pada harga yang ia terlepas; yang ketiga ialah satu-satunya bahagian yang diakui oleh penyata pertukaran anda.
Satu nota konvensyen: industri menyebut "arrival price," dan dalam kebanyakan TCA ekuiti, arrival bermaksud mid ketika pesanan sampai ke pasaran. Bagi sebuah bot, masa keputusan dan masa ketibaan berbeza disebabkan latensi dalaman anda sendiri ditambah baris gilir rate-limit — satu kos sebenar yang boleh diukur. Jadi kami mengekalkan kedua-dua cap masa dan kedua-dua harga, dan membiarkan penguraian memisahkannya.
Penguraian: delay, impact, timing, peluang, yuran
Satu nombor IS sahaja memberitahu anda bahawa eksekusi itu mahal. Ia tidak memberitahu anda sebabnya, dan pembetulan untuk komponen yang berbeza adalah sama sekali berbeza — anda tidak menyelesaikan kos delay dan kos impact dengan perubahan yang sama. Implementation shortfall yang diperluas oleh Robert Kissell (Kissell, 2006, "The Expanded Implementation Shortfall: Understanding Transaction Cost Components," Journal of Trading 1(3), 6–16; dikembangkan secara mendalam dalam The Science of Algorithmic Trading and Portfolio Management, Academic Press, 2013) menguraikan jumlah keseluruhan kepada komponen, setiap satu boleh dikaitkan dengan peringkat tersendiri dalam kitaran hayat pesanan. Versi praktikal, menggunakan arrival mid (mid pada pengesahan pertukaran pertama):
Identiti ini kembali tepat kepada definisi Perold — kembangkan terma-terma dan akan bersaling hapus. Setiap bahagian mempunyai pemilik tersendiri:
Kos delay : hanyutan harga antara isyarat dicetuskan dan child order pertama anda menjadi live di pertukaran. Ini adalah infrastruktur anda — serialisasi, rangkaian, baris gilir rate-limit, semakan risiko. Jika isyarat anda mempunyai alpha horizon-pendek yang sebenar, kos delay adalah tempat ia bocor terlebih dahulu; min yang secara konsisten positif menunjukkan pasaran bergerak ke arah anda sebelum anda tiba — alpha momentum yang mereput, atau seseorang yang lebih pantas mendagangkan isyarat yang sama.
Kos dagangan : apa yang fill anda bayar berbanding arrival — spread yang disilangi ditambah market impact ditambah hanyutan intra-jadual. Ini adalah kad laporan algoritma eksekusi, dan kuantiti yang sebenarnya dimodelkan oleh penyelidikan eksekusi. Almgren, Thum, Hauptmann dan Li (2005, "Direct Estimation of Equity Market Impact," Risk 18(7), 58–62) mengukurnya ke atas kira-kira 700,000 pesanan ekuiti AS daripada meja dagangan Citigroup (Disember 2001–Jun 2003) dan mendapati kos dagangan berskala mengikut volatiliti harian dan kadar penyertaan — impact sementara mengikut power law dalam kadar dagangan dengan eksponen hampir 3/5, impact kekal hampir linear dengan saiz. Kami akan menggunakan semula bentuk fungsian mereka apabila kami menentukur.
Risiko timing: bukan terma dalam penguraian min tetapi varians di sekelilingnya. Menyebarkan induk sepanjang masa mengurangkan impact jangkaan dan mendedahkan anda kepada volatiliti; bagi jadual dengan kedudukan baki , sisihan piawai kos berskala sebagai . Ini tepat sekali pertukaran (trade-off) yang dioptimumkan oleh kerangka kerja Almgren–Chriss. Dalam laporan TCA anda, ia muncul sebagai dispersi IS merentasi induk-induk — laporkan sisihan piawai di sebelah setiap min, atau min akan mengambil semua perhatian dan ekor (tails) akan mengambil semua wang anda.
Kos peluang : kuantiti yang tidak terisi ditanda pada harga terminal. Bagi strategi pasif, ini sering menjadi komponen terbesar dan paling kurang diperiksa, dan ia adalah terma yang menjadikan keseluruhan kerangka kerja ini jujur — lebih lanjut mengenai ini dalam bahagian perangkap, kerana mengabaikannya adalah cara paling biasa orang menipu diri sendiri dengan TCA.
Yuran : bahagian eksplisit. Dalam kripto, catat yuran selepas diskaun (tahap VIP, rebat token yang ditukar pada harga masa-fill) dan kekalkan rebat maker bertanda — yuran negatif adalah data, bukan bunyi bising.
Contoh berangka
Beli BTC. Isyarat dicetuskan dengan ; notional kertas $600,000. Child order pertama diakukan dengan mid . Sepanjang dua minit berikutnya, 8 BTC terisi pada VWAP 60,072; harga sedang trending menjauh, algo menghormati limitnya, dan baki 2 BTC dibatalkan dengan mid pada . Yuran gabungan 2.5 bps ke atas notional terisi.
| Komponen | Formula | USD | bps daripada kertas |
|---|---|---|---|
| Delay | 120 | 2.0 | |
| Kos dagangan | 480 | 8.0 | |
| Peluang | 456 | 7.6 | |
| Yuran | 120 | 2.0 | |
| Jumlah IS | 1,176 | 19.6 |
Penyata pertukaran menunjukkan $120. Kos sebenar untuk melaksanakan keputusan itu ialah $1,176 — faktor sepuluh, dengan dua komponen terbesar tidak kelihatan kepada perakaunan berasaskan yuran. Kira-kira 40% daripadanya datang daripada kuantiti yang tidak pernah didagangkan. Laporan TCA yang hanya menganalisis fill akan menilai induk ini sebagai 8 bps dan menganggapnya baik-baik sahaja.

Markouts: menilai adverse selection
Implementation shortfall menilai pesanan induk. Ia tidak memberitahu apa-apa tentang kualiti fill individu — khususnya, sama ada anda secara sistematik berdagang dengan pihak lawan yang mengetahui sesuatu yang anda tidak tahu. Itu diukur melalui markouts: tanda setiap fill kepada mid pada horizon tetap selepas ia berlaku.
di mana ialah harga fill pada masa dan ialah mid pada masa . Ini adalah PnL mark-to-market per unit bagi fill pada horizon , dan ia mempunyai anatomi yang bersih pada : fill maker bermula pada separuh-spread (anda membeli pada bid, mid berada di atas anda); fill taker bermula pada separuh-spread. Apa yang berlaku apabila berkembang ialah kandungan maklumat dagangan tersebut:
- s mengasingkan sniping dan pickoff quote-basi. Jika fill maker anda sudah berada dalam kerugian satu saat selepas terisi, peserta yang lebih pantas sedang memukul quote anda pada saat ia menjadi salah harga — gelung kemas kini quote anda lebih perlahan daripada gelung trigger mereka. Markout ini adalah diagnostik latensi, bukan diagnostik strategi.
- s mengukur adverse selection klasik: fill diikuti oleh pergerakan berterusan melalui harga anda. Bagi seorang market maker, ini adalah kos yang mesti diatasi oleh spread capture; mikrostruktur ekuiti memanggil kuantiti berkaitan ini realized spread, diinstitusikan dalam laporan SEC Rule 605 pada horizon 5 minit. Kripto bergerak lebih pantas; 10–60s adalah jalur yang setara.
- s memberitahu anda sama ada fill membawa momentum yang menentang anda melebihi horizon mikrostruktur — bagi strategi taker, sama ada alpha isyarat anda pada 60s melebihi spread-tambah-impact yang anda bayar untuk masuk. Lengkung markout taker yang bermula pada bps dan tidak pernah menyeberangi sifar adalah strategi yang membayar untuk kemasukan yang alpha-nya tidak mampu membiayai.
Ketidaksimetrian maker/taker adalah keseluruhan ekonomi dagangan pasif dalam dua lengkung. Lengkung maker yang bermula pada bps (separuh-spread) dan mereput kepada bps menjelang 60s bermakna: anda menangkap spread dan memberi balik lebih banyak, dan tiada tahap rebat yang membetulkan itu. Lengkung yang sama tetapi mendatar pada bps menunjukkan enjin quoting itu berbaloi. Ini juga tepat apa yang diandaikan oleh backtest touch-fill naif — sebuah simulator yang mengisi anda apabila harga menyentuh limit anda mengabaikan hakikat bahawa terisi berkorelasi dengan tersalah, itulah sebabnya anak tangga sedar-queue dalam tangga fill-simulation memerlukan markout terukur sebagai input dan bukan sebagai andaian.

Pengiraan adalah merge_asof ke atas strim mid 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)
Hiris laporan ini lebih lanjut mengikut simbol, jam dalam sehari, dan jarak quote daripada mid. Hirisan paling boleh diambil tindakan bagi strategi maker ialah markout-mengikut-kedudukan-queue-semasa-fill: fill di hadapan queue-segar mempunyai harga yang sangat berbeza daripada fill di mana tahap tersebut telah disapu melalui anda.
Saluran paip: apa yang perlu dicatat
TCA mati pada lapisan pencatatan, bukan lapisan matematik. Matematik di atas memerlukan nombor-nombor yang dibuang oleh kebanyakan bot, dan tiada satu pun daripadanya boleh dibina semula kemudian daripada sejarah pertukaran. Perkara yang tidak boleh dinegosiasi:
- Decision mid, daripada feed anda sendiri, pada masa keputusan. Bukan candle close pertukaran, bukan pembinaan semula kemudian. Penanda aras ialah "harga yang dipercayai oleh strategi saya ketika ia membuat keputusan" — hanya proses anda pada saat itu yang mengetahuinya.
- Kedua-dua cap masa: masa keputusan dan masa ack pertama, jika tidak kos delay tidak dapat diukur dan secara senyap bercampur dengan kos dagangan.
- Setiap fill dengan cap masa pertukaran, yuran, dan penanda maker/taker — masa terima tempatan anda tercemar oleh latensi masuk anda sendiri.
- Induk yang dibatalkan dan tamat tempoh, dicatat seperti segala-galanya yang lain. Induk dengan sifar fill adalah baris paling mahal dalam jadual.
- Strim mid berterusan (atau strim L1) pada kehalusan 100–250ms, disimpan cukup lama untuk mengira markout. Jika anda sudah merekod buku pesanan untuk simulator fill, ini adalah percuma.
Dua jadual rata sudah mencukupi:
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 daripada penguraian:
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 pertanyaan atribusi, iaitu tempat TCA berhenti menjadi perakaunan dan mula menjadi penyelidikan:
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)}))
Pertanyaan 4 ialah jadual input yang dioptimumkan oleh smart order router — routing tanpa TCA per-venue adalah routing mengikut jadual yuran, iaitu mengikut komponen kos yang paling kecil (Smart order routing dalam kripto mengambil jadual ini sebagai titik permulaannya). Bersama modul markout, ini adalah ~200 baris yang dijanjikan.
Menutup gelung: menentukur model kos backtest
Di sinilah saluran paip ini membuahkan hasil. Backtest anda menegaskan nombor-nombor: slippage_bps = 5, lengkung kebarangkalian fill, pekali impact. Setiap satu daripadanya adalah dakwaan tentang eksekusi live, dan jadual TCA adalah eksekusi live. Gelungnya: ukur dengan TCA, sesuaikan model kos, jalankan backtest dengan model yang disesuaikan, berdagang, ukur semula.

Bagi kos taker, pinjam bentuk fungsian daripada Almgren et al. (2005) dan bukannya mencipta yang baru. Hasil kajian mereka — kos berkadar dengan volatiliti harian didarab dengan kuasa kadar penyertaan — memberikan model dua-parameter:
dengan anggaran ekuiti sebagai prior. Sesuaikan pada min terbin, bukan induk mentah — kos induk individu didominasi oleh bunyi bising (itu adalah terma risiko-timing), dan regresi log-log ke atas data mentah akan dengan senang hati menyesuaikan bunyi bising 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
Kemudian bersikap jujur tentang jidar ralat (error bars). Pasukan Almgren mempunyai 700,000 pesanan dan masih melaporkan eksponen temporary-impact sebagai ; sebuah bot dengan 2,000 induk tidak layak menganggarkan secara bebas bagi setiap simbol. Rejim praktikal: kumpulkan merentasi simbol selepas menormalkan dengan , mengecutkan secara kuat ke arah 0.6 (atau hanya tetapkannya dan hanya sesuaikan ), dan sesuaikan semula setiap bulan. Jika yang disesuaikan anda hanyut ke atas, jejak (footprint) anda telah membesar atau pasaran telah menipis — dalam kedua-dua kes backtest perlu mengetahuinya.
Bagi strategi maker, sasaran penentukuran adalah berbeza dan datang daripada dua modul yang lain:
- Kebarangkalian fill: model queue simulator fill meramalkan bagi setiap sel (jarak-spread, kedudukan-queue); log induk anda menyediakan nisbah fill sebenar bagi setiap sel. Ketidaksepakatan adalah pepijat simulator dengan rujukan grid yang disertakan.
- Adverse selection: gantikan andaian tersirat simulator bahawa "fill boleh saling ditukar" dengan jadual markout yang diukur — fill maker simulasi pada jarak pada jam membawa yang diukur sebagai potongan mark-to-market segera. Satu perubahan ini adalah perbezaan antara backtest maker yang berhalusinasi dengan yang menjejaki realiti; ia adalah input penentukuran yang hilang yang dikenal pasti dalam artikel fill-simulation.
- Dispersi kos: masukkan taburan IS, bukan minnya, ke dalam backtest. Model kos yang hanya menganjak min tidak dapat menghasilkan semula drawdown yang dicipta oleh risiko timing; malah lognormal yang disesuaikan kepada IS per-induk mengatasi pemalar tetap.
Rawatan penuh lengkung slippage — bentuk fungsian, pelarasan mengikut rejim, bila power law itu gagal — adalah artikel tersendiri: Lengkung slippage dan model kos untuk backtest. Intinya di sini adalah seni bina: model dalam artikel tersebut tidak dapat disesuaikan tanpa jadual daripada artikel ini.
Perangkap
Literatur TCA telah berusia berdekad-dekad, begitu juga cara-cara untuk memanipulasinya. Tiga mod kegagalan menyumbang kepada kebanyakan penipuan diri sendiri.
Manipulasi penanda aras (benchmark gaming). Sebarang penanda aras selain harga arrival boleh "dipeluk" (hugged). Contoh klasik ialah VWAP: algoritma yang dinilai berbanding VWAP selang boleh menjejakinya dalam lingkungan satu basis point sementara kedudukan berdarah dua puluh berbanding arrival, kerana penanda aras itu hanyut bersama harga yang anda sendiri sedang tolak — dan pada penyertaan yang bermakna, cetakan (prints) anda sendiri adalah VWAP tersebut, jadi menjejakinya adalah kerja rumah yang menilai diri sendiri. Kami telah membedah politik penanda aras dalam TWAP vs VWAP vs POV; peraturan di sisi TCA lebih ringkas: penanda aras dipilih sebelum berdagang, dan IS-berbanding-arrival sentiasa dikira walaupun scheduler dinilai berbanding penanda aras penjadualannya sendiri. Variasi yang lebih halus ialah manipulasi arrival: jika komponen yang menetapkan decision_ts dapat melihat momentum jangka-pendek, ia boleh mengatur masa "keputusan" untuk mempercantikkan terma delay. Cap masa keputusan adalah milik lapisan isyarat, dicatat sebelum sebarang logik eksekusi dijalankan.
Survivorship bias dalam analisis fill-sahaja. Kondisikan analisis kos anda ke atas fill dan eksekusi pasif akan kelihatan percuma. Secara konkrit: 100 induk beli pasif, satu tick di bawah mid. Enam puluh terisi, dan — kerana pasif — terisi pada harga purata 3 bps lebih baik daripada arrival: "kos" terukur bps, sebuah laporan yang membanggakan. Empat puluh yang tidak pernah terisi adalah tepat yang mana harga naik menjauh; tandakan mereka 25 bps merugikan (adverse) pada pembatalan dan nombor jujurnya ialah bps. Laporan fill-sahaja dan laporan sebenar berbeza sebanyak 11 bps dan dari segi tanda. Ini bukan kes tepi — ia adalah mekanisme dagangan pasif itu sendiri: mendapat fill berkorelasi dengan harga melalui anda, iaitu pengkondisian yang sama yang menjadikan backtest touch-fill sebagai fantasi. Kos peluang bukan penambahbaikan pilihan bagi IS; ia adalah terma yang mempertahankan keseluruhan pengukuran daripada bias pemilihan. Bias yang sama mempunyai variasi taker: pesanan IOC yang terlepas, pesanan yang ditolak oleh rate limit atau semakan risiko — jika kegagalan tidak dicatat, kos daripada kegagalan tersebut tidak diukur, dan ia paling besar tepat dalam pasaran pantas di mana strategi anda paling mahukan dagangan tersebut.
Pelbagai jerat (foot-guns), secara ringkas: arrival mid yang dibina semula daripada candle pertukaran (feed anda dan candle tersebut tidak sepakat tepat pada saat ia penting); purata bps per-induk tanpa pemberat notional (seribu fill habuk mengatasi undi satu pesanan sebenar); yuran dicatat sebelum diskaun; markout mid diambil daripada venue yang berbeza daripada fill (asas silang-venue menyamar sebagai adverse selection); dan pada perps, membiarkan akruan funding bocor ke dalam tetingkap eksekusi — funding adalah satu kos, tetapi bukan kos eksekusi, dan mencampurkannya meracuni kedua-dua analisis.
Apa yang perlu dilakukan minggu ini
Tambah dua jadual log kepada bot anda — skema di atas adalah senarai lajur, bukan projek. Jangan backfill apa-apa; dua minggu log jujur mengatasi setahun pembinaan semula. Jalankan penguraian dan tiga horizon markout. Anda akan mempelajari komponen mana yang mendominasi (hampir tidak pernah yuran), sama ada fill pasif anda dipilih secara merugikan (adversely selected) melebihi spread capture-nya, dan sejauh mana pemalar kos backtest anda tersasar daripada lengkung terukur. Kemudian masukkan semula lengkung yang disesuaikan ke dalam simulator dan jalankan semula backtest yang mula-mula menyuruh anda menjalankan strategi ini. Portfolio kertas Perold, tiga puluh lapan tahun kemudian, masih menjadi satu-satunya lawan jujur yang dimiliki oleh portfolio sebenar anda.
Pengarang
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.