Eugen Soloviov
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.
Bài Viết
Kết Quả Phủ Định Trung Thực: Hàng Chục Nghìn Backtest, Năm Đồng Lớn, Không Có Edge Bền Vững
Phần đỉnh cao của mạch bài về tìm kiếm tham số và overfitting, và nó khép lại bằng một kết quả phủ định — kết quả đúng. Một tìm kiếm dual-timeframe trên một symbol duy nhất (ETHUSDT) tìm ra một cấu hình đạt +16.35% out-of-sample và +2.62% trên một holdout chưa hề bị động đến; Deflated Sharpe Ratio, sau khi tính đến ~37,000 lần thử, deflate nó về 0.00. Một lượt quét cross-instrument trên năm đồng lớn (ETH/BTC/SOL/BNB/XRP, mỗi đồng ~1.18M nến 1 phút), chọn theo trung vị out-of-sample, dập tắt nó vĩnh viễn: dual DSR 0.24 / PBO 0.264, triple DSR 0.14 / PBO 0.327 — cả hai đều fail các gate. Champion có lãi trên 1/5 symbol và lỗ trên các symbol còn lại. Đây chính là lý do bộ máy chống overfitting tồn tại: để ngăn bạn ship phần tốt nhất của nhiễu thành alpha.
Chứng Minh Không Có Look-Ahead Trong Backtest Đa Khung Thời Gian: Nhiễu Loạn Tương Lai, Chứng Minh Quá Khứ Không Thể Nhìn Thấy Nó
Các backtest đa khung thời gian để lộ dữ liệu tương lai qua một nến khung thời gian cao hơn đang hình thành, mà giá đóng cửa cuối cùng của nó chưa hề tồn tại. Bạn không thể chỉ đọc code để có được sự tin tưởng — bạn phải kiểm tra nó bằng thực nghiệm. Chúng tôi tái tạo chính xác quy tắc nến-đã-đóng (closed-bar) của bot live, sau đó chứng minh không có rò rỉ bằng một probe dịch chuyển tương lai: nhiễu loạn mọi nến tương lai và khẳng định mọi tín hiệu, mọi giao dịch trong quá khứ không đổi ở cấp độ bit. 25/25 kiểm tra parity đạt, và probe này thực sự có hiệu lực.
Khi Nào GPU Đáng Đồng Tiền: Roofline Của Sweep Tham Số, Nơi Con Số Tiêu Đề 167x Thực Ra Là 27x Thuật Toán Nhân 6.2x Phần Cứng
Lợi thế của GPU so với CPU tăng lên theo kích thước lô — 54.5x ở một combo mỗi lời gọi cho đến 359.6x ở 61 combo trên phép precompute chỉ báo đa khung thời gian của chúng tôi — bởi vì một sweep nhỏ không thể khấu hao chi phí khởi chạy kernel và truyền dữ liệu. Chúng tôi phân rã con số tiêu đề 167x thành một chiến thắng thuật toán 27x mà CPU cũng được hưởng và một chiến thắng phần cứng 6.2x, cho thấy lợi thế thực sự của GPU so với CPU tốt nhất chỉ là 3.2x với khung thời gian đơn và 6.2x với đa khung, và đưa ra một hướng dẫn quyết định về việc một sweep phải rộng đến mức nào trước khi đáng để đầu tư vào một GPU.
Cái bẫy độ chính xác GPU: Vì sao một backtest fp32 trên Apple Metal âm thầm trả về rác
GPU Metal của Apple không có float64. Chuyển một backtest được vector hóa sang nó một cách ngây thơ và thủ thuật WMA bằng prefix-sum đầy cám dỗ sẽ tràn fp32 — sai số tương đối lớn nhất 211× — vậy mà nó vẫn chạy và trả về những con số trông có vẻ hợp lý. Cách sửa không phải là thêm độ chính xác; đó là một công thức khác: tích chập cửa sổ trực tiếp, an toàn với fp32 tới 8×10⁻⁷ và nhanh hơn 55,9× so với numba đơn luồng. Cái bẫy, phép số học, và cách chứng minh bạn không rơi vào nó.
Cổng Fidelity: Backtest Từ Thô Đến Tinh Đánh Lừa Bạn Nhanh Hơn Trừ Khi Proxy Rẻ Xếp Hạng Giống Đánh Giá Đắt Tiền
Tìm kiếm đào sâu / đa fidelity (ASHA, successive halving, Hyperband) sàng lọc hàng nghìn cấu hình với chi phí rẻ và chỉ đưa những cấu hình sống sót lên đánh giá đầy đủ đắt đỏ. Đây là một cách tăng tốc thực sự — nhưng nó sụp đổ trong im lặng nếu xếp hạng ở fidelity thấp không khớp với xếp hạng ở fidelity cao. Chúng tôi đã đo tương quan thứ hạng theo fold: ở một fold, Spearman ρ có thể chỉ là 0.03 (xếp hạng gần như ngẫu nhiên), rồi tăng lên 0.43, 0.67, 0.78, 0.91 khi số fold tích lũy dần. Cách khắc phục là một cổng bắt buộc duy nhất — đo ρ(rẻ, đầy đủ) trước, rồi tự động nâng fidelity tối thiểu lên bậc đầu tiên có ρ ≥ 0.5.
Random vs Smart Search: Điểm giao thoa nằm ở chi phí đánh giá, không phải thuật toán
Khi một lần backtest rẻ, Sobol scrambled kém tinh vi thắng về thông lượng thô — các sampler thông minh (TPE, CMA-ES, ASHA) phải trả một khoản thuế ask/tell bằng Python khiến chúng chậm đi 20 lần, nên chúng đánh giá được ít điểm hơn hẳn ở cùng wall-clock và thua cuộc. Khiến mỗi lần đánh giá trở nên đắt đỏ (multi-TF + các fold walk-forward) và điểm giao thoa đảo chiều. Chúng tôi đo cả hai chế độ, và lý do vì sao độ trung thực xếp hạng theo fold (ρ@1 tăng từ 0.03→0.43) là điều kiện tiên quyết để việc cắt tỉa (pruning) mang lại hiệu quả.
Không gian tham số hai trục: Vì sao phần lớn phép quét của bạn nên gần như miễn phí
Không phải tham số nào cũng tốn chi phí tìm kiếm như nhau. Tham số của một chiến lược tách thành trục đắt (chỉ báo — phải tính lại trên toàn chuỗi giá) và trục rẻ (ngưỡng quyết định — một lượt duyệt O(n) trên tín hiệu đã tính sẵn). Vì chỉ báo bất biến với ngưỡng, bạn chỉ tính chúng một lần rồi quét hàng nghìn cấu hình ngưỡng ở tốc độ ~5,600 cfg/s — rẻ hơn khoảng 1,600 lần so với tính lại cho từng cấu hình. Một cách định giá lại lời nguyền số chiều.
Thuế Framework: Khi Thư Viện Backtest Của Bạn Chậm Hơn Cả Một Vòng Lặp Pandas Ngây Thơ
Chúng tôi đã đo hiệu năng tám engine backtest trên cùng một parameter sweep — 150 nghìn bar, 80 tổ hợp HMA-cross, số lệnh khớp chốt ở mức 2707. Hai trong số các framework event-driven phổ biến nhất lại chậm hơn một vòng lặp pandas viết tay, trong khi một engine vectorized/compiled chạy cùng khối lượng công việc đó nhanh hơn ~13.000 lần. Một nghiên cứu về chi phí phụ trội theo từng bar mà các thư viện phổ biến chưa từng được thiết kế để khấu hao.
Probability of Backtest Overfitting: Tìm Kiếm Của Bạn Có Đánh Bại Được Một Lần Tung Đồng Xu?
Deflated Sharpe Ratio định giá chiến lược thắng cuộc; PBO định giá tìm kiếm đã chọn ra nó. Combinatorially Symmetric Cross-Validation chạy C(16,8) = 12,870 lượt chia train/test trên một ma trận hiệu suất 1000x200 và hỏi: liệu kẻ thắng cuộc in-sample có rơi vào nửa dưới out-of-sample hay không? Cái bẫy mà hầu như ai cũng bỏ lỡ — null của PBO là 0.5, không phải 1. Trên 200 chiến lược không-lợi-thế, Sharpe hàng năm in-sample tốt nhất là 1.98 sụp đổ xuống 0.06 out-of-sample và PBO = 0.476: một lần tung đồng xu, overfit hoàn toàn. Cài đặt một lợi thế thực (Sharpe hàng năm 2.38) thì PBO giảm xuống 0.001, con số in-sample 3.73 sống sót đến out-of-sample 2.34. Một lưới trung bình động trên một random walk thuần túy cũng không có kỹ năng out-of-sample nào — PBO 0.463 trung bình trên 60 ma trận, không thể phân biệt về mặt thống kê với null — và trên một ma trận đại diện, ảo ảnh hiện lên rõ ràng: Sharpe in-sample tốt nhất 2.33 sụp đổ xuống trung vị out-of-sample -0.22, PBO 0.573, 63% xác suất thua lỗ.
Thuế IPC: Đặt Engine Backtest Sau Một Socket Và Mất 13% — Nhưng Gần Như Không Gì Trong Đó Là Do Socket
Chúng tôi đã port một kernel backtest numba theo từng dòng sang Rust và gọi nó qua ranh giới tiến trình theo bốn cách khác nhau, với một cổng tương đương xác nhận PnL giống hệt đến tận giao dịch cuối cùng. Truyền toàn bộ chuỗi giá 1.2 MB qua một Unix socket tốn ~2 ms — khoảng 0.1% công việc. Mã hóa JSON cùng payload đó tốn gấp 1348x so với byte thô, các lệnh gọi chatty theo từng combo truyền lại dữ liệu 80 lần, và một mẫu hình gọi theo từng nến sẽ phải trả 2.1 s IPC thuần túy trên một công việc 2.0 s. Ranh giới thì rẻ; thuế nằm ở cách bạn băng qua nó.
Deflated Sharpe Ratio: Có Bao Nhiêu Chiến Lược 'Thắng' Trong Backtest Của Bạn Sống Sót Qua Multiple Testing?
Một tìm kiếm tham số là một cỗ máy sản xuất may mắn. Trên nhiễu thuần túy — 1,000 chiến lược với lợi thế thực bằng không — Sharpe hàng năm tốt nhất trung bình đạt 1.63 và bài kiểm định ý nghĩa ngây thơ báo hiệu một phát hiện 100% số lần. Chúng tôi xây dựng ground truth có kiểm soát và chỉ ra rằng Deflated Sharpe Ratio, haircut Harvey-Liu, và White's Reality Check khôi phục sự trung thực: phát hiện sai giảm từ 1.000 xuống 0.001-0.057, các lợi thế thực sự trên trần nhiễu được giữ lại với sức mạnh phát hiện ~1 — và một cái bẫy thực sự (lưới tham số tương quan) nơi DSR thô khử lạm phát quá mức và phán quyết phải được đọc trên toàn bộ dải các ước lượng số lần thử hiệu quả, chứ không phải chỉ một.
Thiết Kế Hàm Mục Tiêu: Chỉ Số Bạn Tối Ưu Hóa Âm Thầm Chọn Chiến Lược Của Bạn
Để tìm kiếm chiến lược 'tốt nhất' bạn trước tiên phải định nghĩa 'tốt nhất' — và con số vô hướng đó âm thầm chọn ra người chiến thắng. Trên dữ liệu tổng hợp với lợi thế đã biết (600 seed, T=2000, 80 ngưỡng), một Sharpe per-trade ngây thơ tôn vinh một vé số: nó chọn một người chiến thắng có mức độ tiếp xúc dưới 5% trong 56% số seed và thoái hóa trong 57% — ở seed cực đoan nhất, 8 giao dịch đạt Sharpe in-sample 21.09 sụp đổ xuống 0.13 out-of-sample. Cách khắc phục trung thực gần như nhàm chán: đo trên toàn bộ dòng thời gian, thứ không bao giờ thoái hóa (out-of-sample 1.71). Một shrinkage theo số lượng giao dịch (conf_k) và một sàn tiếp xúc (exposure floor) có thể vá lại một chỉ số per-trade, nhưng ngay cả khi được sửa hoàn toàn chúng cũng chỉ khớp với Sharpe toàn dòng thời gian (1.70 so với 1.71) — không bao giờ vượt qua nó. Định luật Goodhart, trong một backtest, với ground truth có kiểm soát.