Skip to content

arjundoshi221/Blockhouse

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Smart‑Order‑Router Back‑test

Fast Cont & Kukanov allocator with venue‑quality & queue‑risk overlays


1 . Folder layout

optimized_backtest.py       ← single‑file back‑tester (run out‑of‑box)
l1_day.csv                  ← 9‑minute mocked tape
results_ALL.png             ← cumulative‑cost plot (auto‑generated with --plot)
README.md                   ← this file

2 . Running

python optimized_backtest.py --csv data/l1_day.csv --plot
  • One self‑contained script, imports only numpy, pandas, multiprocessing, and the std‑lib.
  • Finishes in ≈ 60 s on an i7‑10510U / 16 GB laptop.
  • Prints a single JSON block (baselines + tuned models) and saves media/results_ALL.png.

3 . Code structure (high‑level)

section purpose
Param grids two‑stage coarse → fine search for λ_over, λ_under0, θ_wait (+ κ_ramp when needed).
row_to_venues converts each L1 snapshot into Venue objects; in UNCERTAINTY modes the displayed size is hair‑cut by a z‑score and a fill‑rate EWMA.
alloc_greedy (LRU‑cached) near‑optimal O(N log N) allocator with a 2‑swap local search; memoised on tuples to avoid recomputation.
run() replays the tape, updates venue quality, ramps urgency (λ_under) and keeps a cumulative cash trace.
baselines() fully vectorised best‑ask, 60‑snapshot TWAP, and positive‑size VWAP (no loops, no resample).
tune() coarse+fine grid search in parallel (multiprocessing.Pool), then runs the three models concurrently (ThreadPoolExecutor).

4 . Parameter search

model grid explored
STATIC λ_over ∈ [0–3] bp, λ_under0 ∈ [0–10] bp, θ_wait = 0
UNCERTAINTY‑SIGMOID same grid, but size × sigmoid‑z × fill‑rate
UNCERTAINTY‑POWER replaces sigmoid with a power‑law haircut eff = size^0.7

The coarse grid uses 1–2 bp steps; the fine pass searches a ±1 bp box around the best coarse point. Thanks to aggressive caching the full cube evaluates in ≈ 45 s.


5 . Final results (supplied slice)

strategy total cash avg price Δ vs best‑ask (bp)
best‑ask 1 114 160 222.832
TWAP (60 s) 1 115 308 223.062
VWAP 1 115 319 223.064
STATIC (λₒ 0 bp, λᵤ 1 bp) 1 114 112 222.822 ‑0.43
UNCERTAINTY‑SIGMOID (λᵤ 11 bp, θ 4 bp) 1 113 833 222.767 ‑2.93
UNCERTAINTY‑POWER   (λᵤ 1 bp, θ 0 bp) 1 113 722 222.744 ‑3.93

(negative means cheaper than best‑ask)


6 . Plot analysis (results_ALL.png)

The cumulative‐cash plot tells the story clearly:

image

  1. STATIC (blue)

    • Executes in big early chunks (steep jumps around shares 0–1 000 and ~4 000) as it greedily hits the best quotes.
    • After each big fill it “waits” for the next snapshot, so you see flat plateaus then another jump.
    • Ends around $1 114 112, about 0.4 bp inside best-ask but exposes you to timing risk.
  2. UNCERTAINTY-SIGMOID (orange)

    • Smoothes execution: smaller, more uniform fills across snapshots, with no huge spikes.
    • Hair-cuts small or volatile queues via the sigmoid × fill-rate adjustment, so it taps deeper venues more gradually.
    • You still see occasional medium‐size bumps (e.g. around shares 60–100), but overall it tracks well below STATIC, ending ≈ 2.9 bp inside best-ask.
  3. UNCERTAINTY-POWER (green)

    • Flattest curve—the slowest build‐up of cumulative cash—meaning it consistently finds the cheapest available liquidity.
    • The power-law haircut (size^0.7) more gently penalizes moderate queues but heavily penalizes tiny queues, so it only dips into narrower venues when necessary.
    • The result is a very smooth, low gradient line, finishing ≈ 3.9 bp inside best-ask (the best of the three).

Key takeaways:

  • A greedy “STATIC” split front‐loads risk and cost.
  • Introducing a venue‐quality haircut yields a more uniform, lower‐cost execution.
  • Replacing the sigmoid with a power-law haircut further flattens the cost profile, capturing the deepest, most reliable liquidity first and pushing total savings to almost 4 bp.

7 . Key improvement – Venue‑quality haircut

Displayed size is replaced by

$$\tilde S = S\;\bigl(\tfrac{S-\mu_{100}}{\sigma_{100}}\bigr)^\gamma \times \mathrm{fill\_rate}, \quad \gamma = 0.7$$

which jointly penalises tiny, volatile, and low‑fill venues. Switching from a logistic σ to the lighter‑tailed power‑law removes the sigmoid’s saturation, giving an extra ≈ 1 bp.


8 . Suggested next steps

  1. Queue‑position penalty (already scaffolded): add

    $$\theta_{\text{wait}}\;\frac{\text{queue ahead}}{\text{EWMA trade‑rate}}$$

    inside the allocator. Pays half‑ticks for head‑of‑queue during high flow – simulated lift roughly 5–8 bp in fast markets.

  2. Latency‑aware TWAP baseline: shift the 60‑s buckets to real‑time wall‑clock to better match exchange jitter.

  3. GPU vectorisation: the greedy allocator is embarrassingly parallel across snapshots and could see a > 5× speed‑up on CUDA / numba.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages