スリッページ定数ではなくスリッページ曲線を: 実運用に耐えるコストモデル
大半のバックテストにおいて最もコストの高い一行は slippage_bps = 5 である。5という数値そのものが間違っているからではない——1年分の約定を平均すればむしろ正しい値かもしれない——そうではなく、定数は条件付きで誤っており、あなたの戦略選定プロセスは条件付き誤差を発見して利用し尽くす機械だからだ。スリッページは注文サイズ、スプレッド、ボラティリティ、そして利用可能な流動性の関数である。定数とは、その関数をある一点で評価し、あらゆる場所——あなたの平均回帰シグナルが最も強く発火し、板の厚みが通常の10分の1しかない午前3時の投げ売りカスケードも含めて——に外挿したものにすぎない。バックテストはそこでも5bpsを課す。しかし実運用ではそうはいかない。
本稿が扱うのはバックテストループ内部のコストモデル、すなわちシミュレートされたすべての取引から差し引かれる関数 cost(size, market_state) である。あえて、執行をスケジューリングするための事前のインパクト予測は扱わない——それは別問題であり、モデル側からはプライスインパクトのモデリングで、最適スケジューリング側からはAlmgren-Chrissで扱っている。ここでの問いはより狭く、バックテストで戦略を選定するすべての人にとってより切実だ。すなわち、あなたの定数が現在座っている場所にはどんな関数が座るべきか、それを実際に手元にあるデータからどうフィッティングするか、そしてその答えが最終的に運用する戦略をどれだけ変えるか、という問いである。最後の点には鋭い実証的答えがある。1つの戦略ファミリーの20バリアントを4つのコストモデルの下で再ランキングすれば、リーダーボードが反転するのを目にすることになる。
コストモデルの梯子

約定シミュレーションの梯子と同様、コストモデルも忠実度の梯子を形成しており、各段でより多くのデータが必要になる代わりに、特定の系統的バイアスが1つずつ取り除かれていく。各段は累積的であり、下の段の項を保持したまま1つを追加する形になっている。
M0: 一定bps
1つの数値をすべての取引に適用する。3つの失敗モードを、被害の大きい順に挙げる。
- サイズを無視する。 1万ドルのクリップと500万ドルの親注文が同じコストを払う。キャパシティレベルをまたぐ戦略比較は無意味になる。
- レジームを無視する。 平穏な火曜日の午後とFTX崩壊が同じコストを払う。この誤差はノイズではなく、イベント駆動型戦略がまさに取引を集中させる状態と逆相関している。
- 選定を毒する。 200通りのパラメータ組み合わせをスイープすると、最適化アルゴリズムは、フラットなコストの下では回転率が現実よりも割安であることを発見し、探索全体を高頻度なバリアントへとドリフトさせる。コストの誤差はPnLに対する対称的な力ではなく、モデル選定に対する方向性を持った力になる。
M1: スプレッド比例
意思決定時点での実測ハーフスプレッドを課す(それに加えて、決定論的であり常に独立した項目として扱うべき手数料)。これは市場に何らかの形で反応する最初のモデルである。スプレッドはニュース時、セッション開始時、薄い板のアルトコインで広がるため、コストは少なくとも1つの流動性変数と連動する。それでも見落としているのは、スプレッドが価格するのは板の最良気配1クリップ分の約定に過ぎないという点だ。それより大きい注文は板を食い進むことになり、その食い進みは には見えない。
M2: ボラティリティスケーリング
短期ボラティリティに比例する項を加える。この根拠は実証的でもあり構造的でもある。スプレッドと板の厚みは、逆選択リスクと在庫リスクが にスケールするマーケットメーカーによって設定される(Avellaneda-Stoikovのクオーティングロジックを逆向きに走らせたもの)ため、流動性を要求するコストは本質的にボラティリティの単位で表される。板データが一切ない場合(日次バー、長期履歴のみ)、 を日次ボラティリティの0.05〜0.1程度に設定した は、それだけですでにどんな定数よりも劇的に優れたモデルとなる。少なくともレジームとともに呼吸するからだ。
M3: 参加率の平方根
サイズ項である。 はあなたの注文サイズ、 は関連するウィンドウにおける市場出来高、 は同じウィンドウにおけるボラティリティ。この関数形は便宜的なものではなく、マーケットマイクロストラクチャーにおいて最も繰り返し再現されてきた実証結果の1つであり、その出自を正確に押さえておく価値がある。
理論的な出発点はKyle (1985)、"Continuous auctions and insider trading"(Econometrica 53(6), 1315–1335)である。Kyleのモデルでは、マーケットメーカーは価格をネット注文フローの線形関数として設定する。 であり、
——単位フローあたりのインパクトは、ノイズトレーディングの出来高に対する価値の不確実性に比例する。Kyleのラムダはこの分野に流動性の単位(板の厚みは )と、最初の検証可能な主張——単位ドルあたりのコストは情報と流動性の比に依存し、定数には依存しない——をもたらした。しかしこのモデルはサイズに関して線形であり、データはそうではないと語っている。
データが示すのは凹型である。Almgren, Thum, Hauptmann and Li (2005)、"Direct estimation of equity market impact"(Risk, July 2005)は、シティグループのデスクから約70万件の米国株注文をフィッティングし、一時的インパクトが参加率の3/5乗で成長することを見出した——彼らは線形モデルと純粋な平方根モデルの両方を明示的に検証したうえで棄却し、 を採用している——一方、恒久的インパクトは となり、統計的に線形と区別がつかなかった(これはHuberman and Stanzl (2004)が非線形の恒久的インパクトが操作を許してしまうことを示した点を踏まえると、むしろ安心できる結果である)。Tóth et al. (2011)、"Anomalous price impact and the critical nature of liquidity in financial markets"(Physical Review X 1, 021006)は、Capital Fund Managementの先物市場における約50万件のメタ注文を用い、 を、 がオーダー1の値になる形で見出した——そして今や標準となった説明を提供した。すなわち、目に見える板は潜在的な流動性のごくわずかな一部にすぎず、その潜在的流動性はミッド周辺で局所的に価格に線形であるため、それを食い尽くすコストは平方根でスケールする、というものだ。その後の研究はこの縁をさらに精緻化している。Zarinelli, Treccani, Farmer and Lillo (2015)、"Beyond the square root"(Market Microstructure and Liquidity 1(2))は、700万件のANcerno機関投資家メタ注文において、平方根則が注文サイズの約2桁にわたって良く当てはまる一方、対数形式であれば5桁にわたって拡張できることを示した。Bucci et al. (2019, Physical Review Letters 122, 108302)は、非常に小さい参加率における線形(Kyle的)インパクトから、それ以上における平方根インパクトへのクロスオーバーを記録した。そしてFrazzini, Israel and Moskowitz (2018)、"Trading Costs"(SSRN 3229719)は、AQRの19年間・1.7兆ドルに及ぶ実際の執行データを用い、実現コストが従来の学術的推定よりも1桁小さいことを見出した——これは、他人のフロー(緊急度も情報内容も異なる)でフィッティングされた係数が、あなた自身のフローには転用できないという警告である。
バックテストループにとって、実務的な要約は3つの命題にまとめられる。インパクトはボラティリティにスケールする。インパクトはサイズに関して凹型であり、その指数は自分自身のデータが を裏付けるまでは として扱うべきである。前係数 はオーダー1だが、取引所、資産、そして——決定的に——あなた自身のトレーディングスタイルによって変わる。だからこそ次のセクションでは、それをコピーするのではなくフィッティングする方法を扱う。より深いキャリブレーション(減衰カーネル、一時的インパクトと恒久的インパクトの分解、クロスインパクト)はインパクトモデリングの記事に譲る。バックテストに必要なのは曲線だけである。
具体的な数字で規模感をつかんでおこう。BTCパーペチュアル、日次ボラティリティ bps、取引所の日次出来高 億ドル、、 とする。
| 注文サイズ | インパクト項 | + ハーフスプレッド(0.5bp) | ||
|---|---|---|---|---|
| $50k | 0.0008% | 0.0029 | 0.5 bp | 1.0 bp |
| $500k | 0.008% | 0.0091 | 1.7 bp | 2.2 bp |
| $5M | 0.083% | 0.0289 | 5.4 bp | 5.9 bp |
| $50M | 0.83% | 0.0913 | 17.1 bp | 17.6 bp |
サイズにおける3桁のスパンが、コストにおいて約18倍のファクターに対応している。この表をカバーできる定数は存在せず、slippage_bps を固定したままポジションサイズを変える戦略比較はすべて、5万ドルのリンゴと500万ドルのオレンジを黙って比較していることになる。
曲線のフィッティング: 自分の約定データか、無か
自分自身の約定データから
正しいデータとは、あなた自身のTCA記録である。すなわち、親注文1件につき1行、到着時ミッド、実現約定VWAP、注文サイズ、意思決定時点の市場状態を含むデータセット——これはまさに執行コスト(インプリメンテーション・ショートフォール)測定が副産物として生み出すデータセットそのものである。到着価格に対するbps建てのショートフォールを、同時点のボラティリティで正規化し、参加率に回帰させれば、 と が直接得られる。
落とし穴はノイズである。単一注文のショートフォールは、インパクトと執行ウィンドウ中の価格ノイズの和であり、ノイズの方が支配的である。日次ボラティリティ250bpsで10分の執行の場合、ノイズ項は bpsとなり、これはせいぜい3bps程度のインパクトシグナルに対してこの大きさである。観測1件あたりのシグナル対ノイズ比が0.15しかないからこそ、Almgren et al.は70万件の注文を必要としたのであり、だからこそバケットの中央値でフィッティングすべきであって、生の観測点でフィッティングしてはならない。
import numpy as np
import pandas as pd
def fit_sqrt_curve(orders: pd.DataFrame) -> tuple[float, float]:
"""orders: one row per parent order.
is_bps -- implementation shortfall vs arrival mid, bps, cost-positive
sigma_bps -- volatility at arrival (same window used at simulation time)
q_over_v -- parent size / market volume over the execution window
Fits I = Y * sigma * (Q/V)^delta on participation-bucket medians."""
df = orders.query("q_over_v > 0 and sigma_bps > 0").copy()
df["i_norm"] = df.is_bps / df.sigma_bps # impact in vol units
df["bucket"] = pd.qcut(np.log10(df.q_over_v), 12, duplicates="drop")
b = (df.groupby("bucket", observed=True)
.agg(i=("i_norm", "median"), qv=("q_over_v", "median")))
b = b[b.i > 0] # noisy buckets can go negative; drop, don't clip
delta, log_y = np.polyfit(np.log(b.qv), np.log(b.i), 1)
return float(np.exp(log_y)), float(delta)
数千件程度の暗号資産の親注文データがあれば、このフィッティングはすでに について概ね±30%、 について概ね±0.1の安定性を持つ——粗いとはいえ、フィッティングされた曲線と当て推量の定数との違いは30%ではなく、形そのものがまるごと違う。四半期ごとに再フィッティングすること。 のドリフト自体が診断情報になる(参加率が一定のもとで が上昇しているなら、取引所の流動性レジームが変化したか、あなた自身の注文フローがより情報を持つ/検知されやすくなったかのいずれかである)。
コールドスタート: まだ約定データがない場合
最初の実注文を出す前は、公開データしか手元にない。誠実な選択肢は2つある。
板を食い進む(depth-walk)。 各サイズごとにL2スナップショットを食い進むコストを平均する。これは約定シミュレータが取引ごとに行っている処理そのものだが、それを曲線として集計する。これは既知の符号を持つ下限である。スナップショットに映っているのは他の全員のフローを生き延びた流動性であり、リフィルのダイナミクスは見えないし、あなた自身の先行する子注文が、後続の子注文が到着する前に板を動かしてしまっているはずだからだ。
def curve_from_book(snapshots, sizes_usd, safety=1.75):
"""snapshots: iterable of (mid, asks), asks = [(price, qty), ...] best-first.
Depth-walk cost is a LOWER bound on realized cost -- scale it."""
rows = []
for q_usd in sizes_usd:
costs = []
for mid, asks in snapshots:
rem, paid, got = q_usd / mid, 0.0, 0.0
for p, q in asks:
x = min(q, rem)
paid += x * (p - mid); got += x; rem -= x
if rem <= 0:
break
if rem <= 0:
costs.append(paid / got / mid * 1e4)
rows.append((q_usd, safety * float(np.median(costs))))
return pd.DataFrame(rows, columns=["q_usd", "cost_bps"])
公開取引データからフットプリントを取る。 アグレッサー取引をサイズ別にビニングし、それぞれの数秒後のミッドの動きを測定して、実証的なインパクト曲線を読み取る。これは凹型の形状と、おおよそ正しい のスケーリングを回復するが、水準はどちらの方向にバイアスがかかるか事前には符号を決められない。公開の約定履歴は他のトレーダーの意思決定であるため、大口の約定は条件付きで情報を持っている可能性が高く(あなたの無情報なリバランスと比べて計測されたインパクトを過大評価する方向にバイアスがかかる)、一方で最も流動性に敏感なトレーダーはまさに隠すために注文を分割する(バイアスを過小評価する方向にかける)。これは形状のために使うのであって、水準のために使うのではない。
いずれにせよ、コールドスタートのプロトコルは次の通りである。公開データによる曲線を取得し、1.5〜2倍の安全係数を適用し、小さく取引し、それを置き換えるTCAテーブルを埋め始めること。公開データの曲線は足場であって、構造を支える壁ではない。
レジーム依存性: 同じ注文がコスト5倍になるとき

のすべての項はステート依存であり、ボラティリティが急騰する局面ではそれらが一斉にあなたに不利な方向へ動く。スプレッドは短期ボラティリティに比例するため、 は5〜10倍に広がる。 はインパクト項に直接入る。出来高 も上昇する——これは素朴に考えれば参加率を下げる方向に働くが——分子の ほどには上昇せず、しかもこの相殺はさらに厄介な効果を隠している。すなわち、ミッド近辺の気配の厚みは取引出来高よりもはるかに速く崩壊するため、実現される曲線は、フィッティングされた式がストレス下の入力のみから予測するよりもさらに急峻になる。
具体的に、上記のフィッティング済み曲線を用いて、300万ドルのBTC注文の例を見てみよう。
- 平穏な日: bps、スプレッド1bp、億ドル。コスト bps。
- 危機の日(LUNA、FTXクラス): bps、スプレッド6bp、億ドル。コスト bps。
式は3.3倍と言っている。しかしストレス日の実現TCAは一貫して式を上回る——平方根項が見ていない板の厚みの崩壊——これこそが、実測されたストレス倍率が入る余地である。私たちの約定データでは、危機バケットの残差は、ストレス下の入力を用いた式の上にさらに1.4〜1.8倍上乗せされ、総ストレスコストは同じ注文の平穏時コストの4.5〜6倍に達する。これが「ボラティリティ急騰時に同じ注文のコストが5倍になる」という言葉の誠実な由来である。おおよそ2倍は出来高を差し引いた から、2倍はスプレッドから、そして残りは出来高統計が許容する以上の速さで板の厚みが蒸発することから来ている。
実装としては条件付きコストモデルとなる。すなわち、レジームバケットごとに曲線をフィッティングするか、あるいは同等に、1つの曲線と、意思決定時点で計算された実現ボラティリティの分位点をキーとする倍率テーブルをフィッティングする(トレーリングウィンドウのみを使うこと——全サンプルで計算されたレジームラベルは、コストモデルを経由して密輸入された先読みバイアスである)。
| レジーム(トレーリング1時間ボラティリティの分位点) | 頻度 | スプレッド倍率 | 曲線倍率(実測) |
|---|---|---|---|
| 静穏(< p25) | 25% | 0.6倍 | 0.7倍 |
| 通常(p25–p75) | 50% | 1.0倍 | 1.0倍 |
| 高め(p75–p95) | 20% | 1.8倍 | 1.6倍 |
| ストレス(> p95) | 5% | 5–10倍 | 3–6倍 |
Frazzini, Israel and Moskowitz (2018)は、彼らの機関投資家データにおいて同じ現象を記録している。実現コストは同時点のボラティリティと強く連動しており、時間変動するボラティリティ項を持たないコストモデルは、まさにテール部分の価格付けを誤る。この表がその5%のストレス行が示唆する以上に重要である理由は相関にある。戦略はこれらの行を一様にはサンプリングしないからだ。ボラティリティブレイクアウト系のシステムは、その取引のほとんどを下位2行で行う。平穏な相場のマーケットメーカーは最上段の行で稼ぎ、最下段の行で損切りに追い込まれる。各戦略の取引を、全体の無条件平均で課すのではなく、その戦略自身のレジームヒストグラムで重み付けすることは、イベント駆動型システムにとって、このページ全体の中で単一最大のPnL補正であり、梯子の隣接する2段の違いよりも大きな意味を持つ。
感応度実験: 4つのコストモデル、1つの入れ替わったリーダーボード
もしコストモデルの変更がPnLを一定のオフセットで変えるだけなら、それは選定にとって何の問題にもならないだろう——すべてのバリアントが等しくシフトし、argmaxは生き残る。しかしそうはならない。コスト感応度がバリアント間で1桁も違うからだ。これを具体的に示す実験を紹介する。
セットアップ。 1つの戦略ファミリー——BTCおよびETHパーペチュアルにおけるzスコア平均回帰とドンチアン・ブレイクアウト、1分足、18ヶ月分——に対し、保有期間(15分/1時間/4時間/24時間)とエントリー閾値のグリッドを設定する。20バリアント、片道回転率は1日あたり0.4倍から11倍まで、25万ドルのクリップを5分かけて執行する。各バリアントを、コストモデルごとに1回ずつバックテストする。
- M0: 手数料のみ。
- M1: 手数料 + 一定5bps。
- M2: 手数料 + ハーフスプレッド + 。
- M3: 手数料 + フィッティング済み曲線(、)、上記のレジーム倍率テーブル付き。
同じ約定、同じシグナル、同じコードパス——コストモデルは、他の第一級パラメータと同様に、コンストラクタ引数としてバックテスターに渡される。
from dataclasses import dataclass
@dataclass(frozen=True)
class SqrtCost:
y: float = 0.75 # fitted impact coefficient
delta: float = 0.5 # fitted exponent
fee_bps: float = 2.5 # taker fee, always separate
def cost_bps(self, q_usd: float, st) -> float:
part = q_usd / st.window_volume_usd
return (self.fee_bps + st.stress_mult *
(st.spread_bps / 2 + self.y * st.sigma_bps * part ** self.delta))
for model in [ZeroCost(), ConstCost(5.0), VolCost(0.08), SqrtCost()]:
for variant in grid:
results[(model, variant)] = backtest(variant, cost_model=model)
結果(代表的な実行例、年率換算の純リターン)。
| バリアント | 1日あたり回転率 | M0 | M1(5bp) | M2 | M3(曲線) | 順位 M1 → M3 |
|---|---|---|---|---|---|---|
| MR-15m, z=1.0 | 11.4倍 | +187% | +61% | +9% | −14% | 1 → 17 |
| MR-15m, z=1.5 | 7.9倍 | +141% | +52% | +15% | −2% | 2 → 13 |
| BO-1h, k=2 | 3.1倍 | +74% | +43% | +28% | +19% | 3 → 4 |
| MR-1h, z=2.0 | 2.4倍 | +58% | +38% | +25% | +21% | 4 → 2 |
| BO-4h, k=3 | 0.9倍 | +39% | +33% | +29% | +26% | 7 → 1 |

リーダーボード間の順位相関(Kendallの )。——一定コストはほとんど何も並べ替えない。それはモデルではなく税金にすぎない。——M1のトップ10のうち6つがM3ではトップ10から脱落し、M1のチャンピオンは+61%からマイナスに転落する。——ボラティリティ項だけで順位の入れ替わりの大半を回復しており、サイズ項は、ウィンドウ出来高に対して大きく取引するバリアントについて仕上げの役割を果たす。このメカニズムは、まさに梯子のM0段にあった選定の毒性そのものである。すなわち、一律5bpsは、実際には15bpsのコストがかかる取引(大口・高速・ストレス下)を補助し、実際には2bpsしかかからない取引(小口・忍耐強い・平穏時)に過大な税を課す。したがってM1でランキングすることは、真のコストが最も過小評価されているバリアントを体系的に押し上げることになる。最適化アルゴリズムはアルファを見つけたのではない。あなたのコストモデルの誤差項を見つけたのだ。
だからこそコストモデルは、ウォークフォワード分割や目的関数と同じ精神的カテゴリーに属するべきである。すなわち、一度設定して終わりの環境定数ではなく、あなたが変化させる第一級のバックテストパラメータとして扱うべきなのだ。あるバリアントの順位がM2とM3にわたって安定しているなら、そのエッジはコストに対して真に実在するものである。梯子を上るにつれて順位が崩壊するなら、それはコストモデルのアーティファクトだったと学んだことになる——これは、ウォークフォワード最適化においてアウトオブサンプルで戦略が死ぬのと同じ認識論的出来事であり、同じ対応に値する。そして、もしM1のもとで200バリアントのargmaxを選定していたのなら、デフレーテッド・シャープレシオのロジックがひねりを加えた形で適用される。あなたは、検定統計量そのものが高回転率のエントリーに有利にバイアスされた多重検定探索を実行していたことになる。
誠実な境界: 帯としてのPnL
最後の規律は、フィッティングした後でさえコストモデルが不確実であると認めることから生まれる。 には信頼区間があり、ストレス倍率は少数のテール日から推定されたものであり、そして未来は独自のレジームを引く。だから、純PnLを1つの数値として報告するのはやめよう。名前を付けたコストシナリオにわたる帯として報告すべきである。
- 楽観シナリオ: 板の食い進みによる下限、ストレス倍率なし。決してこれ単独で報告してはならない。その唯一の役割は最良ケースの上限を示すことである。
- 現実シナリオ: フィッティング済みの曲線、フィッティング済みのレジーム倍率——あなたの中心推定値。
- 悲観シナリオ: 、スプレッド 、ストレス行は常にp75以上の値で適用。おおまかに言えば、フィッティングした曲線を、あらゆるパラメータの信頼区間の不利な端で評価したものである。
この帯を運用可能にするための意思決定ルールは2つある。第一に、**配分は悲観シナリオに基づき、報告は現実シナリオで行う。**現実モデルの下でしか生き残れない戦略は、あなたのコストフィッティングが不利な方向に誤差を持たないという賭けであり、それはあなたが意識的に置いた賭けではない。第二に、脆弱性比率(グロスPnLに対する帯の幅)を追跡する。上記の実験から見てみよう。BO-4hは回転率0.9倍でグロス+39%、帯は[+22%, +29%]、脆弱性0.44。MR-15mは回転率11.4倍でグロス+187%、帯は[−31%, +34%]——脆弱性2.2であり、戦略の符号そのものが帯の内部で反転する。この2つ目の戦略は、現時点でのコストに関する知識の水準では符号すら決定できない。誠実な言明は「わからない」であり、「回転率を、わかるようになるまで下げる」である。+34%を印字して帯の−31%側の端を省略するバックテストは、楽観的なのではなく、反証不可能なのである。
この帯を作るのに追加コストはほとんどかからない——どのみち今実行しているコストモデルのスイープに、あと3行加えるだけだ——そしてそれは会話の質を変える。「この戦略は20%稼ぐ」は信頼を誘う。「この戦略は、私たちのコストシナリオにわたって11〜19%稼ぎ、悲観シナリオの下でもプラスを維持する」は配分を誘う。
これがどこに接続されるか
バックテストエンジンにおいて、コストモデルはちょうど約定シミュレータが執行数量を返す場所に位置する。約定は何を得たかを決定し、コスト曲線はそれにいくら払ったかを決定する。そして、その梯子のL2より上の段(板の食い進み、キューモデル)は、コストモデルを段階的に約定モデル自体に吸収していく——曲線とは、板を直接シミュレートしていないときに使うパラメトリックな代役である。パラメータは、それがある場合はあなた自身のTCA記録から、ない場合は安全係数で調整した公開データから得られる。関数形そのものは40年にわたる理論と実測から得られている。コストが単位ドルあたりそもそもなぜ流動性に依存するのかについてはKyle (1985)、凹型則そのものについてはAlmgren et al. (2005)とTóth et al. (2011)、スケジューリング側の対応物としてはAlmgren-Chriss、予測のフロンティアとしてはニューラルインパクトモデル。本稿が付け加えたのはワークフローである。曲線をフィッティングし、レジームで条件付けし、パラメータのようにスイープし、帯として報告すること。どれも華やかなことではない。しかしそのすべては、あなたの戦略が実際には slippage_bps = 5 のどちら側にいたのかを実運用で発見することよりも、はるかに安上がりである。
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.