Probability of Backtest Overfitting: Tìm Kiếm Của Bạn Có Đánh Bại Được Một Lần Tung Đồng Xu?
Bài viết thuộc series "Backtest Không Ảo Tưởng".
📄 Bài viết này đã phát triển thành một bài báo nghiên cứu. Mọi con số dưới đây đến từ một script tất định duy nhất xây dựng ground truth có kiểm soát — các tìm kiếm không-lợi-thế, các tìm kiếm với lợi thế được cài đặt, và một lưới tham số trung bình động thực tế trên một random walk — sau đó chạy Combinatorially Symmetric Cross-Validation (CSCV) để ước lượng Probability of Backtest Overfitting dựa trên đó, đo trực tiếp mức độ quy trình lựa chọn khái quát hóa tốt đến đâu. Đọc bài báo trực tuyến (phiên bản tương tác + PDF) tại pbo-search.marketmaker.cc, mã nguồn và dữ liệu tại github.com/suenot/pbo-search.
Deflated Sharpe Ratio đưa kẻ thắng cuộc của bạn ra xét xử: cho rằng bạn đã tìm kiếm qua N cấu hình, liệu Sharpe này có vượt quá những gì may mắn có thể mua được không? Bài viết này đưa một thứ khác ra xét xử — hành động lựa chọn. Bạn đã chạy một lưới, giữ lại ô tốt nhất, rồi tiếp tục. Nhưng bản thân sự lựa chọn đó có đáng tin cậy không? Nếu bạn chạy lại toàn bộ phép chia in-sample/out-of-sample theo một cách khác, liệu cùng một cấu hình đó có còn đứng đầu — hay bạn chỉ vừa phong vương cho kẻ may mắn nhất trong một trăm đồng xu?
Probability of Backtest Overfitting (PBO), được giới thiệu bởi Bailey, Borwein, López de Prado & Zhu (2017), trả lời chính xác câu hỏi đó, và nó làm điều này bằng một con số mà hầu hết mọi người đọc sai ngay từ cái nhìn đầu tiên. Đây là câu quan trọng nhất trong toàn bộ bài viết này, vì vậy hãy đọc nó hai lần:
Null của PBO là 0.5, không phải 1. Một tìm kiếm không có kỹ năng out-of-sample nào sẽ có điểm PBO ≈ 0.5. Một nửa không phải là "overfit một nửa" — một nửa là overfit hoàn toàn, một lần tung đồng xu. Bạn muốn PBO gần không.
Đó chính là điều khiến ai cũng vấp ngã. Chúng ta được huấn luyện để đọc xác suất so với một null của "không có gì," và với overfitting, bản năng của chúng ta nói rằng cách đọc "vô tội" là 0. Không phải vậy. PBO là xác suất mà cấu hình bạn chọn là tốt nhất in-sample rơi vào nửa dưới của toàn bộ tập hợp out-of-sample. Nếu tìm kiếm của bạn thực sự chẳng học được điều gì có thể khái quát hóa, thì kẻ thắng cuộc in-sample, out-of-sample, có khả năng nằm ở bất kỳ đâu trong bảng xếp hạng — vì vậy nó rơi vào nửa dưới khoảng một nửa số lần. PBO ≈ 0.5 nghĩa là quy trình lựa chọn của bạn là một lần tung đồng xu. PBO ≈ 0 nghĩa là kẻ thắng cuộc in-sample vẫn đáng tin cậy giữ vị trí thắng cuộc out-of-sample — sự lựa chọn đáng tin cậy. Mọi thứ dưới đây được xây dựng để biến sự thật hiệu chuẩn duy nhất đó thành cụ thể, trên dữ liệu nơi chúng ta biết ground truth.
| Chế độ (200 cấu hình, T = 1000, S = 16) | Đó là gì | Sharpe in-sample của kẻ thắng cuộc | Sharpe out-of-sample | PBO | Phán quyết |
|---|---|---|---|---|---|
| Trường không-lợi-thế (200 chiến lược nhiễu iid) | may mắn thuần túy, không có lợi thế ở bất kỳ đâu | 1.98 | 0.06 | 0.476 | overfit — một lần tung đồng xu |
| Lợi thế được cài đặt (20 cấu hình mang Sharpe hàng năm 2.38) | kỹ năng thực sự, vững chắc | 3.73 | 2.34 | 0.001 | đáng tin cậy |
| Lưới MA-crossover trên một random walk thuần túy (170 cấu hình) | một ảo ảnh hấp dẫn | 0.97 | 0.04 | 0.463 | overfit — một lần tung đồng xu |
Các tỷ lệ Sharpe được hàng năm hóa ×√252. Cả ba hàng đều lấy trung bình Sharpe của chiến lược được chọn trên 60 ma trận Monte-Carlo — so sánh ngang hàng, vì vậy lưới overfit được chấm điểm theo cùng cách như null và lợi thế được cài đặt. Trên nền tảng đã lấy trung bình này, Sharpe in-sample được chọn của lưới (0.97) thực ra thấp hơn con số 1.98 đã bị thổi phồng của null, Sharpe out-of-sample của nó là một con số dương nhẹ 0.04, và PBO của nó (0.463) nằm ngay dưới ½ — không thể phân biệt về mặt thống kê với null. Các con số kịch tính trên một ma trận đơn lẻ (Sharpe in-sample tốt nhất-trong-lưới 2.33 sụp đổ xuống trung vị out-of-sample −0.22, PBO 0.573) thuộc về một seed random-walk đại diện và xuất hiện, được gắn nhãn rõ ràng, trong Màn 4. Mọi con số đều có thể truy vết về file kết quả.
Ba chế độ, một bài học. Một tìm kiếm không-lợi-thế nằm ngay tại ranh giới tung đồng xu 0.5 dù nhiễu là iid (PBO 0.476) hay được khoác lên hình hài một lưới trung bình động thực sự (PBO 0.463) — hai cái này không thể phân biệt về mặt thống kê, và cả hai đều là bằng chứng buộc tội. Một lợi thế thực sự kéo PBO xuống 0.001. Lấy trung bình trên các ma trận, kẻ thắng cuộc được chọn của lưới không có gì nổi bật — một Sharpe in-sample 0.97, thấp hơn con số 1.98 đã bị thổi phồng của null — và bản thân điều đó chính là chẩn đoán trung thực: một tìm kiếm không-lợi-thế đọc y hệt như null. Kịch tính nằm ở phần đuôi. Trên một ma trận random-walk đại diện (Màn 4), ô tốt nhất của lưới ghi nhận Sharpe in-sample 2.33 — về cơ bản bằng với Sharpe out-of-sample 2.34 của lợi thế được cài đặt, một trận hòa gay cấn — vậy mà out-of-sample nó rơi vào nửa dưới cũng thường xuyên như rơi vào nửa trên. Khoảng cách đó giữa một backtest lộng lẫy và một lựa chọn vô giá trị là vô hình trong chính Sharpe của kẻ thắng cuộc và chỉ trở nên hữu hình khi bạn chấm điểm quy trình. Đó chính là điều PBO làm.
Màn 1 — Quy trình bị xét xử: CSCV thực sự làm gì

DSR mang tính tham số (parametric): nó mô hình hóa phân phối của Sharpe lớn nhất dưới một null và khử lạm phát ý nghĩa thống kê của kẻ thắng cuộc một cách giải tích. CSCV là câu trả lời phi tham số (non-parametric) cho cùng vấn đề thiên lệch lựa chọn — thay vì mô hình hóa giá trị lớn nhất, nó lấy mẫu lại phép chia train/test theo mọi cách có thể và quan sát, một cách thực nghiệm, liệu kẻ thắng cuộc in-sample có tiếp tục thắng hay không. Không có giả định phân phối, không cần đếm "số lần thử hiệu quả." Chỉ đơn giản là: lựa chọn đó có khái quát hóa được không?
Hãy bắt đầu với nguyên liệu thô. Bạn đã backtest N = 200 cấu hình của một lớp chiến lược trên T = 1000 quan sát đồng bộ. Xếp chồng chuỗi lợi nhuận của mỗi cấu hình thành một cột và bạn có được một ma trận hiệu suất M kích thước T × N — 1,000 hàng thời gian, 200 cột chiến lược. Đây là đầu vào duy nhất mà CSCV cần.
Bây giờ là cách xây dựng, trong bốn bước:
- Chia thời gian thành
S = 16khối rời nhau có độ dài bằng nhau (T/Shàng mỗi khối). Các khối giữ nguyên cấu trúc thời gian cục bộ — một lựa chọn thiết kế trở nên quan trọng ngay khi lợi nhuận có trí nhớ (memory). - Chọn mọi cách để dùng nửa số khối để huấn luyện và nửa còn lại để kiểm tra. Với
S = 16, đó là tất cảC(16, 8) = 12,870cách để chọn 8 trong 16 khối làm tập huấn luyện; 8 khối còn lại là tập kiểm tra. Đây chính là nguồn gốc của cụm từ "đối xứng tổ hợp" (combinatorially symmetric): mỗi lượt chia có một ảnh phản chiếu (hoán đổi train và test), vì vậy phương pháp này sử dụng dữ liệu của bạn một cách đối xứng thay vì chỉ một lát cắt quá khứ→tương lai đặc quyền duy nhất mà một walk-forward đơn lẻ trao cho bạn. - Trên mỗi lượt chia, xếp hạng toàn bộ 200 cấu hình theo Sharpe in-sample và chọn ra kẻ thắng cuộc
n*. Sau đó tìm xem chính cấu hìnhn*đó xếp hạng out-of-sample như thế nào, trên 8 khối được giữ lại. - Ghi lại thứ hạng out-of-sample tương đối của kẻ thắng cuộc và chuyển nó thành một logit. PBO là tỷ lệ trong số 12,870 lượt chia mà logit đó ≤ 0.
Việc liệt kê này nhỏ gọn đến mức gần như không đáng viết ra:
from itertools import combinations
combos = list(combinations(range(S), S // 2)) # C(16, 8) = 12,870 splits
Với mỗi lượt chia, gọi là thứ hạng out-of-sample của kẻ thắng cuộc in-sample trong số cấu hình (hạng 1 = tệ nhất, = tốt nhất). Chuẩn hóa nó thành một thứ hạng tương đối , lấy logit của nó, và tích hợp trên toàn bộ các lượt chia:
Logit chỉ là một cây thước đo tiện lợi. nghĩa là kẻ thắng cuộc rơi vào nửa trên out-of-sample (thứ hạng tương đối trên ½) — tính nhất quán in-sample/out-of-sample, tốt. nghĩa là nó rơi vào đúng hoặc dưới trung vị out-of-sample — lựa chọn in-sample đã không khái quát hóa trên lượt chia đó. PBO là tỷ lệ các lượt chia mà kẻ thắng cuộc in-sample không đánh bại được trung vị out-of-sample. Toàn bộ ma trận quyết định nó: với M và S cho trước, PBO là tất định (deterministic) — không có seed lấy mẫu lại, tất cả 12,870 lượt chia đều được liệt kê đầy đủ.
Trong code, một khi bạn đã có Sharpe in-sample và out-of-sample của mọi cấu hình trên mọi lượt chia (các ma trận R_tr và R_te, mỗi cái 12,870 × 200), trái tim của bộ ước lượng chỉ gói gọn trong sáu dòng:
n_star = R_tr.argmax(axis=1) # in-sample winner, per split
oos_sh = R_te[rows, n_star] # that winner's OWN out-of-sample Sharpe
rank = (R_te <= oos_sh[:, None]).sum(axis=1) # its OOS rank among N configs, 1..N
omega = np.clip(rank / (N + 1.0), 1e-6, 1 - 1e-6) # relative OOS rank in (0,1)
lambdas = np.log(omega / (1.0 - omega)) # logit
pbo = float(np.mean(lambdas <= 0.0)) # fraction of splits with lambda <= 0
Hãy để ý những gì không có ở đây: không có p-value, không có ngưỡng trên Sharpe của kẻ thắng cuộc, không có mô hình phân phối null. PBO không bao giờ hỏi liệu kẻ thắng cuộc có tốt hay không. Nó hỏi liệu việc chọn ra cái tốt nhất in-sample có phải là một quyết định sống sót được khi tiếp xúc với dữ liệu giữ lại (held-out) hay không. Đó là một thuộc tính của tìm kiếm của bạn, không phải của chiến lược của bạn — đó chính xác là lý do tại sao nó bắt được những thứ mà thống kê riêng của kẻ thắng cuộc không thể.
Màn 2 — Hiệu chuẩn là toàn bộ lập luận: null là 0.5

Một công cụ chẩn đoán mà bạn không thể hiệu chuẩn được chỉ là một lời đồn. Vì vậy, trước khi tin tưởng PBO trên bất kỳ điều gì thực tế, hãy xác định chắc chắn hai điểm mốc trên dữ liệu nơi câu trả lời đã biết trước: một trường không có lợi thế ở bất kỳ đâu, và một trường có lợi thế thực sự. Nếu PBO không rơi gần 0.5 ở trường hợp đầu và gần 0 ở trường hợp thứ hai, nó vô giá trị.
Điểm mốc null. Xây dựng M từ 200 cột nhiễu Normal độc lập, không drift, không lợi thế — Sharpe thực đúng bằng 0 cho mọi cấu hình — và chạy CSCV. Lấy trung bình trên 60 ma trận như vậy. Chiến lược được chọn (tốt-nhất-in-sample) ghi nhận trung bình Sharpe in-sample hàng năm 1.98. Đó không phải là một con số nhỏ; đó chính là cùng sự thổi phồng do lựa chọn mà bài viết về DSR đã đo được — cái tốt nhất trong số 200 cột nhiễu trông giống một chiến lược đáng được cấp vốn. Out-of-sample, chính kẻ thắng cuộc đó mang lại một Sharpe hàng năm 0.06. Nó gần như trả lại toàn bộ những gì đã kiếm được. Và phán quyết về quy trình:
Đó chính là lần tung đồng xu, được đo lường. Trên 12,870 lượt chia, kẻ thắng cuộc in-sample có khả năng rơi xuống dưới trung vị out-of-sample cũng nhiều như rơi lên trên nó — 0.476, thấp hơn ½ một chút xíu, không thể phân biệt với 0.5 khi xét đến độ phân tán Monte-Carlo. Chẩn đoán đồng hành cũng đồng ý: xác suất mà Sharpe out-of-sample của chiến lược được chọn là âm là 0.475 — chọn cái tốt nhất in-sample từ nhiễu thuần túy và nó thua lỗ out-of-sample khoảng một nửa số lần. Không có kỹ năng nào trong sự lựa chọn bởi vì không có kỹ năng nào để tìm ra, và PBO báo cáo chính xác điều đó: 0.5 là ranh giới overfitting, và nhiễu thuần túy nằm ngay trên đó.
Tại sao lại là 0.5 mà không phải 1? Bởi vì dưới một null thực sự, cả 200 cột đều có thể hoán đổi cho nhau (exchangeable) — về mặt thống kê là các lần rút mẫu có thể thay thế lẫn nhau từ cùng một quá trình nhiễu. Kẻ thắng cuộc in-sample chỉ đặc biệt trong phạm vi in-sample; out-of-sample nó chỉ là một cột khác, có khả năng xếp hạng ở bất kỳ đâu như nhau. Vì vậy thứ hạng out-of-sample tương đối của nó phân phối đều trên , logit đối xứng quanh 0, và tỷ lệ với hội tụ về ½. Một PBO bằng 1 sẽ tệ hơn một lần tung đồng xu — nó có nghĩa là thành công in-sample dự đoán một cách đáng tin cậy sự thất bại out-of-sample, điều này đòi hỏi một cơ chế phản-bền-vững (anti-persistence) chủ động, không chỉ đơn thuần là thiếu vắng lợi thế (thêm về điều này trong phần ghi chú trung thực).
Điểm mốc lợi thế. Bây giờ hãy xây dựng một trường nơi 20 trong số 200 cấu hình mang một lợi thế thực sự, được cài đặt — một Sharpe trên mỗi quan sát là 0.15, hàng năm hóa thành 2.38 (suy ra: ) — và để 180 cấu hình còn lại là nhiễu. Chạy CSCV giống hệt. Câu chuyện đảo ngược hoàn toàn:
| Sharpe in-sample (hàng năm) | Sharpe out-of-sample (hàng năm) | PBO | P(thua lỗ OOS) | |
|---|---|---|---|---|
| Null (0 lợi thế) | 1.98 | 0.06 | 0.476 | 0.475 |
| Lợi thế được cài đặt (Sharpe 2.38) | 3.73 | 2.34 | 0.001 | 0.0006 |
Kẻ thắng cuộc của lợi thế được cài đặt ghi nhận Sharpe in-sample hàng năm 3.73 — bị thổi phồng bởi sự lựa chọn, như thường lệ — nhưng lần này nó giữ lại được một out-of-sample 2.34, và PBO sụp đổ xuống 0.001. Trên tất cả 12,870 lượt chia, kẻ thắng cuộc in-sample rơi vào nửa dưới out-of-sample về cơ bản là không bao giờ. Xác suất của một khoản thua lỗ out-of-sample giảm xuống 0.0006. Đây chính là hình hài của một quy trình lựa chọn đáng tin cậy: dù bạn cắt train và test theo cách nào, cùng một loại cấu hình vẫn tiếp tục thắng, bởi vì có một hiệu ứng thực sự, vững chắc ở đó để tìm kiếm khóa vào. Hai điểm mốc — 0.476 trên nhiễu, 0.001 trên một lợi thế thực sự — chính là sự hiệu chuẩn. PBO hoạt động.
Màn 3 — Một nhiệt kế liên tục, không phải một bài kiểm định có/không

Hai điểm mốc chứng minh PBO có thể phân biệt nhiễu với lợi thế. Nhưng thuộc tính sâu sắc hơn là nó làm điều này một cách mượt mà. Quét lợi thế được cài đặt từ không có gì đến mạnh và PBO không nhảy vọt từ 0.5 xuống 0 — nó trượt xuống theo một đường dốc đơn điệu, và Sharpe out-of-sample của chiến lược được chọn tăng lên để gặp nó, từng bước một:
| Sharpe thực được cài đặt (hàng năm) | PBO | Sharpe OOS của chiến lược được chọn (hàng năm) |
|---|---|---|
| 0.00 | 0.52 | −0.05 |
| 0.48 | 0.44 | 0.19 |
| 0.95 | 0.21 | 0.81 |
| 1.59 | 0.03 | 1.65 |
| 2.38 | 0.001 | 2.48 |
| 3.17 | 0.00 | 3.29 |
Hãy đọc hai cột dữ liệu cùng nhau. Tại lợi thế thực bằng không, PBO là 0.52 và chiến lược được chọn kiếm được −0.05 out-of-sample — lần tung đồng xu, lại một lần nữa, và một kẻ thắng cuộc thua lỗ. Thêm một chút lợi thế mong manh (hàng năm 0.48) và PBO giảm nhẹ xuống 0.44. Đến một Sharpe thực hàng năm 0.95 — một lợi thế thực sự khiêm tốn, đáng tin — PBO đã là 0.21 và Sharpe out-of-sample đã leo lên 0.81. Tại 1.59 nó là 0.03; tại 2.38, 0.001; tại 3.17, về cơ bản là 0.00, với chiến lược được chọn mang theo một 3.29 out-of-sample. PBO giảm đơn điệu khi lợi thế thực tăng lên, và hiệu suất out-of-sample của kẻ thắng cuộc tăng lên đồng bộ — cả hai chính là cùng một sự thật được nhìn từ hai phía.
Đây chính là thuộc tính khiến PBO có thể sử dụng được trong thực tế: nó là một nhiệt kế overfitting liên tục, không phải một cảnh báo nhị phân. Một PBO bằng 0.21 không chỉ nói "không overfit" — nó nói rằng sự lựa chọn của bạn có kỹ năng out-of-sample một phần: kẻ thắng cuộc in-sample đánh bại trung vị out-of-sample 79% số lần, nhưng lợi thế đủ mỏng để một phần năm số lượt chia vẫn chôn vùi nó. Bạn có thể quan sát con số này di chuyển khi bạn làm mạnh thêm tín hiệu, thu hẹp vũ trụ chiến lược, hoặc cắt tỉa lưới của mình, và biết hướng nào là trung thực. Quy tắc ngón tay cái của chính bài báo — bác bỏ khi PBO vượt quá 0.05 — tự nhiên xuất hiện từ đường dốc này: dưới Sharpe hàng năm ~1.5 tìm kiếm chưa vượt qua được nó; trên ~1.6 thì đã vượt qua. Nhưng bản thân đường dốc mang tính thông tin nhiều hơn bất kỳ ngưỡng cắt đơn lẻ nào, bởi vì nó cho bạn biết không chỉ liệu bạn có overfit hay không mà còn gần một lần tung đồng xu đến mức nào.
Màn 4 — Cái bẫy thực tế: một backtest đẹp đẽ, được chứng nhận là vô giá trị

Null nhiễu-iid là trung thực nhưng dễ bị gạt bỏ — "chiến lược của tôi không phải là các cột Normal ngẫu nhiên." Vì vậy đây là cái bẫy dưới hình dạng mà những người thực hành thực sự bước vào. Hãy lấy một giao cắt trung bình động (moving-average crossover), quy tắc được backtest nhiều nhất trên thế giới: mua khi một MA nhanh cắt lên trên một MA chậm, đứng ngoài trong các trường hợp khác. Đưa nó vào lưới — 10 độ dài nhanh 17 độ dài chậm, giữ lại các cặp nhanh-dưới-chậm hợp lệ, cho K = 170 cấu hình. Bây giờ hãy chạy lưới đó trên một chuỗi với lợi thế bằng không đã được chứng minh: một random walk thuần túy. Không có gì để tìm thấy cả. Một crossover không thể dự đoán một random walk. Chúng ta biết câu trả lời là "không có chiến lược nào."
Lưới không biết điều đó. Nó trao cho bạn một kẻ thắng cuộc, và kẻ thắng cuộc đó hấp dẫn:
| Chẩn đoán (một ma trận random-walk đại diện, seed 3000, K = 170, S = 16) | Giá trị |
|---|---|
| Sharpe in-sample tốt nhất (hàng năm) | 2.33 |
| PBO | 0.573 |
| Sharpe out-of-sample trung vị (hàng năm) | −0.22 |
| Xác suất của một khoản thua lỗ out-of-sample | 0.63 |
| Độ dốc suy giảm out-of-sample so với in-sample | −0.92 |
| Logit trung vị | −0.25 |
Đây là một ma trận đơn lẻ với seed cố định. Lấy trung bình trên 60 ma trận random-walk độc lập, chính những chẩn đoán này đọc được PBO 0.463 ± 0.223, một Sharpe in-sample được chọn là 0.97 suy giảm xuống 0.04, và P(thua lỗ OOS) 0.47 — không thể phân biệt về mặt thống kê với null. Con số 0.573 của seed 3000 là một lần rút mẫu nằm ở phía cao của dải null ~0.5 — nhiễu lấy mẫu quanh giá trị tung-đồng-xu, nằm hoàn toàn bên trong độ phân tán ±0.223 giữa các ma trận — và câu chuyện giống hệt nhau dù theo cách nào.
Một Sharpe in-sample hàng năm 2.33 trên một giao cắt trung bình động là kiểu kết quả sẽ kết thúc trong một bản pitch deck gọi vốn. Nó về cơ bản bằng với Sharpe out-of-sample của lợi thế thực sự-được-cài-đặt của chúng ta từ Màn 2 (2.34 — một trận hòa gay cấn). Nếu bạn dừng lại ở backtest, bạn sẽ cấp vốn cho nó. CSCV từ chối. PBO là một lần tung đồng xu ở đây: 0.463 trung bình trên 60 ma trận, 0.573 trên riêng ma trận này — cả hai đều nói rằng tìm kiếm không có kỹ năng out-of-sample. Đừng đọc quá mức con số 0.573: nó nằm cao hơn ½ 0.073, nhiễu lấy mẫu quanh null 0.5 và nằm hoàn toàn bên trong dải ±0.223 giữa các ma trận; một PBO thực sự trên 0.5 — nơi thành công in-sample sẽ chủ động dự đoán thất bại out-of-sample — cần một cấu trúc phản-bền-vững hoặc chi phí giao dịch mà random walk này không chứa (xem phần ghi chú trung thực). Trên ma trận này, logit trung vị −0.25 đặt kẻ thắng cuộc in-sample trung vị ở một thứ hạng out-of-sample tương đối khoảng 0.44 (suy ra: ) — xấp xỉ thứ 75 trong số 170 (suy ra: ), ngay dưới mức giữa của toàn bộ trường mà nó lẽ ra phải dẫn đầu. Sharpe out-of-sample trung vị của kẻ thắng cuộc đó là −0.22 — âm — và nó chịu một khoản thua lỗ out-of-sample 63% số lần. Một Sharpe backtest 2.33 với kỳ vọng out-of-sample là thua lỗ: chính là định nghĩa của một ảo ảnh.
Độ dốc suy giảm −0.92 là con dao thứ hai. Hồi quy Sharpe out-of-sample của kẻ thắng cuộc được chọn trên mỗi lượt chia theo Sharpe in-sample của nó; độ dốc âm rất dốc — cấu hình càng trông tốt in-sample thì nó càng làm tệ out-of-sample. Đây chính là dấu vân tay của overfitting trên một chuỗi có trí nhớ: crossover bám vào các mô hình thoáng qua trong các khối huấn luyện mà, vì là các tạo tác (artifact) của một random walk, đảo ngược lại out-of-sample. Một điểm tinh tế đáng nói ra để bạn không đọc quá mức độ dốc: một độ dốc âm tự nó không phải là một phán quyết. Ngay cả chế độ lợi-thế-thực-sự từ Màn 2 cũng có một độ dốc suy giảm âm (−0.52) — hồi quy về giá trị trung bình luôn kéo giá trị lớn nhất được chọn xuống một chút out-of-sample. Điều phân biệt ảo ảnh với lợi thế thực không phải là việc độ dốc âm mà là nơi kẻ thắng cuộc rơi vào: lợi thế thực vẫn ở gần đỉnh (PBO 0.001) trong khi trả lại một chút; ảo ảnh nằm trên ranh giới tung đồng xu (PBO 0.463 trung bình, 0.573 trên seed này), kẻ thắng cuộc của nó không có khả năng nằm trên trung vị out-of-sample nhiều hơn là nằm dưới nó. Đọc độ dốc để biết mức độ co rút; đọc PBO để biết liệu nó có còn khái quát hóa hay không. Ảo ảnh thất bại ở cả hai.
Đây chính là lý do tại sao PBO xứng đáng có chỗ đứng bên cạnh một backtest thô. Sharpe in-sample 2.33 không phải là một lời nói dối — chiến lược thực sự đã kiếm được nó, in-sample, trên random walk đó. Đó là sự lựa chọn, được khoác lên một quy tắc quen thuộc trên một lưới trông có vẻ thực tế, và không có lượng thời gian nhìn chằm chằm vào đường cong tài sản (equity curve) nào có thể tiết lộ điều đó. Chỉ chấm điểm quy trình mới làm được.
Màn 5 — PBO và DSR: hai câu hỏi trung thực, một cao nguyên

PBO và Deflated Sharpe Ratio là hai nửa của cùng một bài kiểm tra trung thực, và chúng không dư thừa lẫn nhau — chúng thẩm vấn những đối tượng khác nhau:
| Deflated Sharpe Ratio (DSR) | Probability of Backtest Overfitting (PBO) | |
|---|---|---|
| Đối tượng bị xét xử | kẻ thắng cuộc | quy trình lựa chọn |
| Câu hỏi | Sharpe này có vượt quá những gì may mắn mua được qua N lần thử không? | việc chọn ra cái tốt nhất in-sample có khái quát hóa out-of-sample không? |
| Phương pháp | tham số — khử lạm phát ngưỡng ý nghĩa | phi tham số — lấy mẫu lại tất cả C(S, S/2) lượt chia train/test |
| Giá trị null | DSR ≈ 0.5 (kẻ thắng cuộc chỉ vừa khớp với trần nhiễu) | PBO ≈ 0.5 (kẻ thắng cuộc là một lần tung đồng xu out-of-sample) |
| Bạn muốn | DSR gần 1 | PBO gần 0 |
| Cần biết số lần thử N? | có — và các lưới tương quan khiến N trở nên mơ hồ | không — việc lấy mẫu lại theo lượt chia xử lý sự phụ thuộc một cách tự nhiên |
Chúng thậm chí có thể bất đồng với nhau, và sự bất đồng đó mang tính chẩn đoán. DSR có thể bị đánh lừa bởi một lưới tương quan dẫn đến khử lạm phát quá mức (cái bẫy mà toàn bộ màn cuối của bài viết về DSR nói đến — 640 ô tương quan không phải là 640 lần thử độc lập, và đưa số đếm thô vào sẽ thổi phồng quá mức trần nhiễu). PBO không bao giờ đếm số lần thử; nó lấy mẫu lại ma trận lợi nhuận thực tế, vì vậy tương quan của lưới đã được tích hợp sẵn vào các lượt chia một cách miễn phí. Ngược lại, PBO cho bạn biết quy trình có khái quát hóa hay không nhưng không cho biết liệu kẻ thắng cuộc có vượt qua một ngưỡng lợi nhuận tối thiểu (hurdle rate) hay không — một tìm kiếm có thể có PBO thấp và vẫn chọn ra thứ gì đó mà Sharpe out-of-sample của nó, dù đáng tin cậy ở trên trung vị của toàn trường, lại quá nhỏ để giao dịch. DSR định giá kẻ thắng cuộc; PBO định giá quy trình. Hãy chạy cả hai.

Có một trực giác hình học nằm bên dưới tất cả những điều này, và đó là điều hữu ích nhất để mang theo. Một lợi thế thực sự là một cao nguyên; overfitting là một đỉnh nhọn. Khi một hiệu ứng thực sự chi phối lưới của bạn, các cấu hình tốt tụ lại thành cụm — fast=3/slow=55 hoạt động tốt, và các cấu hình lân cận nó cũng vậy, bởi vì tất cả chúng đều đang lấy mẫu cùng một tín hiệu nền bên dưới. Cao nguyên đó vững chắc trước việc lấy mẫu lại: dù bạn huấn luyện trên 8 trong 16 khối nào, kẻ thắng cuộc in-sample vẫn được rút ra từ cùng một vùng rộng lớn, và vùng đó vẫn đứng đầu out-of-sample. Nhiều lượt chia đồng ý → PBO thấp. Khi overfitting chi phối lưới của bạn, "kẻ thắng cuộc" là một đỉnh nhọn cô độc — một ô tình cờ khớp với nhiễu của các khối huấn luyện, bị bao quanh bởi các cấu hình lân cận tầm thường. Đỉnh nhọn đó dễ vỡ: một lượt chia train/test khác sẽ phong vương cho một đỉnh nhọn cô độc khác, và không có cái nào trong số chúng sống sót đến tập kiểm tra. Các lượt chia bất đồng → PBO ≈ 0.5. Đây chính là bài học mà nghiên cứu plateau-analysis của chúng tôi đạt đến từ phía bản đồ tham số; PBO, trên thực tế, chính là sự phân biệt cao-nguyên-so-với-đỉnh-nhọn được đo lường trên mọi lượt lấy mẫu lại đối xứng của dữ liệu của bạn cùng một lúc.
Điều này cũng giải thích tại sao CSCV vượt trội hơn phép chia walk-forward mặc định mà người thực hành hay dùng. Walk-forward cho bạn một lát cắt quá khứ→tương lai duy nhất và một phán quyết duy nhất; CSCV cho bạn 12,870 lát cắt đối xứng và hỏi liệu kẻ thắng cuộc có sống sót qua tất cả chúng hay không. Một đỉnh nhọn có thể sống sót qua một lát cắt tùy ý nhờ may mắn; nó không thể sống sót qua 12,870 lát cắt. (Combinatorial Purged Cross-Validation, CPCV, của López de Prado mở rộng chính xác ý tưởng này với việc purging và embargoing để tiêu diệt sự rò rỉ nhãn (label-leakage) mà việc lấy mẫu lại thông thường có thể mắc phải dưới sự phụ thuộc tuần tự — nấc thang tiếp theo tự nhiên một khi các nhãn của bạn chồng lấp lên nhau.) Cùng một lời cảnh báo mang tính cấu trúc xuyên suốt toàn bộ series: chỉ số bạn tối ưu hóa lén lút chọn ra chiến lược của bạn (thiết kế hàm mục tiêu), một rò rỉ một-nến sản xuất ra một Sharpe 15 từ nhiễu (look-ahead bias), một tìm kiếm multiple-testing sản xuất ra một Sharpe 1.63 từ nhiễu (DSR) — và ở đây, một quy trình lựa chọn được lấy mẫu lại sản xuất ra một kẻ thắng cuộc vô giá trị mà chỉ PBO mới có thể phơi bày.
Ghi Chú Trung Thực
Bốn lưu ý, được nói thẳng thắn, bởi vì một nghiên cứu có kiểm soát chỉ giành được kết luận của nó bằng cách nêu rõ giới hạn của mình.
- Các quá trình tạo dữ liệu là tổng hợp (synthetic) — một cách có chủ đích. Nhiễu Normal iid cho null, một trường Sharpe-được-cài-đặt cho lượt quét lợi thế, và một lưới trung bình động trên một random walk thuần túy cho cái bẫy. Không cái nào là một tuyên bố về tính thực tế của thị trường; mỗi cái được chọn vì ground truth có kiểm soát. Chúng ta chỉ có thể chứng minh PBO đọc 0.5 trên "không có kỹ năng" và 0 trên "kỹ năng thực sự" bằng cách tạo ra dữ liệu nơi chúng ta biết cái nào là cái nào. Lợi nhuận thực có đuôi béo, tự tương quan, và non-stationary; điều được giao ở đây là công cụ chẩn đoán đã hiệu chuẩn, không phải một chiến lược.
- Null của PBO là 0.5, và đó là một tính năng, không phải một sự kỳ quặc. Hãy nói rõ điều này mỗi khi bạn báo cáo một PBO, bởi vì nếu không một nửa số độc giả của bạn sẽ coi 0.5 là "an toàn một nửa." Một tìm kiếm không-có-kỹ-năng-out-of-sample nằm ở mức 0.5; một lợi thế thực sự đẩy nó xuống 0. Không có cách đọc "vô tội" nào cho PBO ≈ 0.5 cả — đó là phán quyết overfit hoàn toàn.
- PBO > 0.5 là một vùng "nghịch lý" mà chúng tôi không ép buộc. Một PBO một cách hệ thống trên 0.5 nghĩa là thành công in-sample chủ động dự đoán thất bại out-of-sample — các cấu hình tệ-nhất-IS trở thành tốt-nhất-OOS. Điều đó đòi hỏi một cấu trúc phản-bền-vững hoặc chi phí giao dịch, không chỉ đơn thuần là thiếu vắng lợi thế. Các tìm kiếm overfit của chúng tôi nằm ngay tại ≈ 0.5 (0.476 cho nhiễu iid; 0.463 trung bình cho lưới MA; 0.573 trên một seed ở phía cao, nằm trong dải Monte-Carlo ±0.14–0.22 trên 60 ma trận), điều này đã có nghĩa là "không có kỹ năng out-of-sample." Chúng tôi không tạo ra vùng nghịch lý; chúng tôi chỉ cho thấy rằng overfitting đưa bạn đến đúng trên ranh giới tung đồng xu, điều đó đã đủ để buộc tội rồi.
- PBO là tất định với ma trận cho trước; chỉ có ma trận mới là ngẫu nhiên. Với
MvàS = 16cố định, tất cảC(16, 8) = 12,870lượt chia đều được liệt kê đầy đủ — không có seed bootstrap và không có phương sai lấy mẫu trong chính PBO. Độ phân tán mà chúng tôi báo cáo (±0.137 trên null, ±0.223 trên lưới MA) là phương sai trên 60 ma trận Monte-Carlo, không phải bên trong bộ ước lượng. Sharpe ở mỗi phía được ước lượng trên khoảng 500 quan sát — 496 sau khi cắt bớt khối CSCV, vìT = 1000chia thành 16 khối bằng nhau để lại 992 hàng sử dụng được, chia thành hai nửa 496; bởi vì Sharpe bất biến với thứ tự (order-invariant), thứ tự hàng bên trong một tập train hay test không quan trọng (nó sẽ quan trọng, đối với các chỉ số phụ thuộc đường đi (path-dependent) như tỷ lệ lợi nhuận/drawdown).
Điểm Chính
- PBO chấm điểm quy trình lựa chọn, không phải kẻ thắng cuộc — và null của nó là 0.5. Đó là xác suất mà cấu hình bạn chọn là tốt nhất in-sample rơi vào nửa dưới out-of-sample. PBO ≈ 0.5 là một lần tung đồng xu (overfit hoàn toàn); PBO ≈ 0 là một sự lựa chọn đáng tin cậy. Bạn muốn nó gần không, và bạn phải nói to điều đó ra, bởi vì 0.5 đọc như "an toàn" đối với một con mắt chưa được huấn luyện và có nghĩa hoàn toàn ngược lại.
- Hiệu chuẩn chứng minh nó hoạt động. Trên 200 chiến lược không-lợi-thế iid, Sharpe in-sample hàng năm tốt nhất 1.98 sụp đổ xuống 0.06 out-of-sample và PBO = 0.476 — nhiễu nằm trên ranh giới tung đồng xu, thua lỗ out-of-sample 47.5% số lần. Cài đặt một lợi thế thực sự (Sharpe hàng năm 2.38) và con số in-sample 3.73 sống sót đến một out-of-sample 2.34 trong khi PBO giảm xuống 0.001. Hai điểm mốc, một công cụ chẩn đoán đã hiệu chuẩn.
- PBO là một nhiệt kế liên tục. Quét lợi thế được cài đặt và PBO giảm đơn điệu — 0.52 → 0.44 → 0.21 → 0.03 → 0.001 → 0.00 tại các Sharpe thực hàng năm 0.00 / 0.48 / 0.95 / 1.59 / 2.38 / 3.17 — cùng với Sharpe out-of-sample của chiến lược được chọn tăng lên đồng bộ (−0.05 lên đến 3.29). Nó đo lường bạn gần một lần tung đồng xu đến mức nào, không chỉ đơn thuần là có/không.
- Cái bẫy thực tế chính là trọng tâm của toàn bộ vấn đề. Một lưới trung bình động 170-cấu-hình trên một random walk thuần túy trung bình cho một Sharpe in-sample được chọn chỉ 0.97 suy giảm xuống 0.04, với PBO 0.463 — không thể phân biệt về mặt thống kê với null, một tìm kiếm không-lợi-thế đọc y hệt như null. Trên một ma trận đại diện, ảo ảnh hiện lên rõ ràng: một Sharpe in-sample tốt nhất 2.33 (một con số dành cho pitch deck), một Sharpe out-of-sample trung vị −0.22, một 63% khả năng thua lỗ out-of-sample, PBO 0.573, và một độ dốc suy giảm dốc đứng −0.92. Một backtest đẹp đẽ với kỳ vọng out-of-sample âm, vô hình trước mọi thống kê được in cạnh kẻ thắng cuộc và chỉ hữu hình khi bạn chấm điểm quy trình.
- Kết hợp PBO với Deflated Sharpe Ratio. DSR định giá kẻ thắng cuộc (Sharpe này có vượt quá may mắn không, với N lần thử cho trước?); PBO định giá quy trình (sự lựa chọn có khái quát hóa không?). DSR cần một số lần thử và có thể bị đánh lừa bởi các lưới tương quan; PBO lấy mẫu lại ma trận và không bao giờ đếm số lần thử. Một lợi thế thực sự là một cao nguyên rộng mà nhiều lượt chia đồng ý (PBO thấp); một đỉnh nhọn cô độc in-sample là overfit (các lượt chia bất đồng, PBO ≈ 0.5). Hãy chạy cả hai, và đọc cao nguyên.
Kẻ thắng cuộc của một tìm kiếm có tội cho đến khi được chứng minh vô tội — và PBO thẩm vấn chéo chính bản thân tìm kiếm, không phải bằng chứng ngoại phạm mà nó trao cho bạn. Nó bỏ qua việc kẻ thắng cuộc trông tốt đến đâu in-sample và chỉ hỏi liệu việc chọn ra nó có phải là một quyết định sống sót được khi bị cắt lại theo 12,870 cách hay không. Khi nó không sống sót — khi Sharpe 2.33 lộng lẫy của bạn hóa ra lại rơi vào nửa dưới out-of-sample cũng thường xuyên như không — bạn chưa tìm thấy một chiến lược nào cả. Bạn đã tìm thấy đồng xu may mắn nhất, và PBO chính là con số bắt được nó đang lật.
Thí nghiệm đầy đủ — bộ khung hiệu chuẩn null, lượt quét nhiệt kế lợi thế được cài đặt, cái bẫy lưới random-walk, và mọi con số trong bài viết này có thể tái tạo được từ một script tất định duy nhất — nằm trong bài báo đồng hành tại pbo-search.marketmaker.cc, với mã nguồn và dữ liệu tại github.com/suenot/pbo-search.
Tác Giả
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.