Làm sao biết kết quả của một hệ thống giao dịch là trung thực?
· #research-integrity #overfitting #backtesting #systematic-trading #quant-research
Người đọc không thể nhìn đường cong vốn mà biết được, vì một đường cong mượt thì dễ tạo ra. Thứ người đọc có thể kiểm tra là: tác giả có công bố những bài kiểm tra chống lại chính mình không, có nêu kích thước mẫu thực sự có giá trị thay vì con số đẹp mắt không, và có nói rõ tuyên bố nào của mình đã bị rút lại không. Một tác giả chưa từng rút lại điều gì thì hoặc là đang may mắn, hoặc là chưa hề soi kỹ.
MasterVP · Systematic Trading Journey
Bài viết của người sáng lập KenKem, một kỹ sư phần mềm hai mươi năm kinh nghiệm, từng giao dịch vàng bằng tay trước khi xây dựng hạ tầng nghiên cứu đứng sau MasterVP. Trong quy trình phát triển quant của mình, chính những kết quả khó chịu mới là thứ đáng công bố, bởi đó là phần mà người đọc không thể lấy được từ một trang bán hàng. Mọi con số dưới đây đều là kết quả backtest, mô phỏng hoặc đo đạc kiểm toán trên dữ liệu tick thật, có ghi ngày và có nhãn rõ ràng.
Một bài đánh giá công kích đã tìm thấy điều gì trong hệ thống của mình?
Hạ tầng nghiên cứu vững, còn cách báo cáo kết quả mới là điểm yếu.
Tháng 8 năm 2026 mình đặt hàng một bài kiểm toán từ góc nhìn bên ngoài dành cho Master Volume Profile. Đề bài không phải một bài đọc thiện chí, mà là một bài đánh giá đóng vai một quant bên ngoài đầy hoài nghi, được giao nhiệm vụ tìm ra phần yếu nhất của quy trình và nói thẳng, với yêu cầu mọi con số phải được tính lại từ chính kho mã nguồn chứ không trích lại từ các bản viết cũ của mình.
Kết luận chia làm hai nửa theo cách mình không ngờ tới. Về hạ tầng, người đánh giá nói rằng họ sẽ tuyển quy trình này: phân tách các lớp rõ ràng, một cổng chặn khớp lệnh cứng, và các kết quả âm được giữ lại và tra cứu được. Rồi tới nửa còn lại. Chỉ số bền vững mình dẫn đầu vốn không thể trượt. Bài kiểm tra có thể trượt thì đã trượt, và mình đã tự lý giải để đi qua nó. Kết luận không phải là lợi thế giao dịch này giả. Kết luận là bằng chứng hiện tại của mình không đủ để chứng minh nó không giả, trong khi tài liệu gửi nhà đầu tư lại mô tả như thể nó đủ.
Mình công bố những gì bài đánh giá tìm ra, thay vì chỉ công bố phần khen mình. Một bài đánh giá chỉ được trích khi nó đồng tình với mình thì chỉ là marketing với vài bước phụ.
Một bài kiểm tra độ bền có thể nào không bao giờ trượt được không?
Có, và bài kiểm tra của mình chính là như vậy.
Trong nhiều tháng mình dẫn đầu phần bằng chứng bằng Deflated Sharpe Ratio, chỉ số sinh ra để bắt những kết quả đến từ việc tìm kiếm quá nhiều. Nó đạt gần mức cao nhất trong thang đo, nên mình trích dẫn nó như bằng chứng mạnh nhất mình có.
Người kiểm toán không đọc kết luận, họ làm lại phép tính. Ngưỡng mà một kết quả phải vượt qua tăng theo độ phân tán của kết quả giữa các lần thử, và chỉ tăng theo logarit của số lần thử. Độ phân tán ghi nhận của mình chỉ bằng khoảng một phần tám chính kết quả đó. Ở mức phân tán ấy, cuộc tìm kiếm sẽ cần tới cỡ một trăm nghìn tỷ lần thử thì cổng kiểm duyệt mới có thể trượt. Nó không phải đang đạt. Nó không có khả năng làm gì khác ngoài đạt.
Tệ hơn, mình đã từng thu thập đúng bằng chứng xác nhận điều đó rồi đọc ngược nó. Một nghiên cứu trước đó cho thấy việc loại bỏ các lần thử trùng lặp chỉ làm chỉ số thay đổi một phần nghìn. Mình ghi nhận đó là sự ổn định. Thực ra đó là một cái kim không hề nhúc nhích.
Trong khi đó bài kiểm tra thực sự có khả năng phân biệt, xác suất quá khớp của backtest, lại cho kết quả trên một nửa ở tám trong chín ô, trên cả ba cấu hình đã phát hành. Kết quả đó nói rằng cấu hình mình chọn trong mẫu sẽ rơi xuống dưới trung vị ngoài mẫu với tần suất còn cao hơn cả tung đồng xu. Lý do mình bỏ qua nó là các cấu hình đã phát hành nằm ở nhóm phân vị cao ngoài mẫu, nhưng đó chỉ là ba lần rút từ đúng cái phân phối mà bài kiểm tra vừa tuyên bố là không đáng tin. Vấn đề chưa bao giờ là có nên phát hành hay không. Vấn đề là bài kiểm tra nào dẫn đầu phần bằng chứng, và mình đã đặt bài kiểm tra bão hòa lên trước.
Một mẫu giao dịch thực sự lớn tới đâu?
Nhỏ hơn số lệnh của nó, và thường nhỏ hơn cả một bậc độ lớn.
Mình từng trích dẫn con số 1.423 lệnh so với mức tối thiểu 192 lệnh theo lý thuyết, tức biên an toàn khoảng bảy lần. Bài kiểm toán đo lại chuỗi nghiên cứu một cách đàng hoàng. Trên 3.502 lệnh, phân phối có độ lệch 3,49 và độ nhọn vượt 19,5, hoàn toàn không giống đường cong chuẩn mà các mức tối thiểu kia giả định. Quy đổi sang mẫu hiệu dụng tương đương phân phối chuẩn, 3.502 lệnh chỉ đáng giá khoảng 326 quan sát.
Vậy biên an toàn thật là 326 so với 192, không phải 1.423 so với 192. Vẫn là một biên an toàn, nhưng không phải cái biên mình đã quảng bá. Đây đúng là kiểu sai lầm mình từng viết trong bài cần hỏi gì trước khi tin một backtest, chỉ khác ở chỗ lần này người cần đặt câu hỏi là chính mình.
Ba mươi lệnh gánh cả hệ thống thì điều đó nghĩa là gì?
Nghĩa là con số trung bình mềm hơn nhiều so với vẻ ngoài của nó.
Lấy chuỗi nghiên cứu, sắp xếp lại, rồi bỏ đi ba mươi lệnh tốt nhất trong 3.502 lệnh. Đó là 0,86% của mẫu, và nó khiến toàn bộ hệ thống chuyển sang âm. Riêng nhóm một phần trăm dẫn đầu đã chiếm nhiều hơn toàn bộ kết quả ròng, nghĩa là chín mươi chín phần trăm còn lại cộng lại là âm.
Đây không phải lỗi do mình tạo ra. Đó là hình dạng của giao dịch phá vỡ, nơi một số ít cú chạy lớn trả tiền cho một chuỗi dài các khoản lỗ nhỏ. Nhưng nó thay đổi giá trị của một hệ số lợi nhuận. Một tỷ số trích dẫn trên phân phối lệch đến vậy không phải là một thống kê đủ, còn mình thì đã trích dẫn nó như thể nó đủ.
Phần bằng chứng ngược lại phải nằm ở đây chứ không phải ở một chú thích cuối trang, vì chính bài kiểm toán yêu cầu như vậy. Một phép lấy mẫu lặp hai mươi nghìn lần trên cùng chuỗi dữ liệu cho thấy kết quả vẫn bền khi lấy mẫu lại chính mẫu đó. Thứ mà phép lấy mẫu lặp không làm được là nói về rủi ro thay đổi chế độ thị trường, bởi nó chỉ xáo lại đúng hai năm rưỡi đó và mặc định rằng hai năm rưỡi tiếp theo cũng chứa một lượng sự kiện đuôi tương đương. Phát biểu mình bảo vệ được thì hẹp hơn phát biểu cũ: lợi thế là có thật trong chế độ thị trường mình đã kiểm thử, nó được gánh bởi một số ít sự kiện, và việc nó có kéo dài hay không thì thực sự chưa được kiểm chứng.
Các bài kiểm tra tự động có bắt được lỗi làm đẹp kết quả không?
Chỉ khi nào người phát triển để chúng ở mức chặn cứng, và đó chính là toàn bộ ý nghĩa của chúng.
Bài kiểm tra mình dựa vào nhiều nhất lại là bài không hào nhoáng chút nào. Trước khi bất cứ thứ gì được phát hành, sản phẩm đã biên dịch phải chạy lại một phiên tham chiếu đã đóng băng, và từng lệnh phải khớp một đối một, khớp tới từng byte. Nó chứng minh giá trị ở bản 1.17, khi một lỗi lọt vào một trong các nhánh và lợi nhuận báo cáo cao hơn bản tham chiếu chứ không thấp hơn.
Nếu chỉ nhìn bằng mắt vào đường vốn, mình đã gật đầu và phát hành, bởi các con số dịch chuyển đúng hướng mình mong muốn. Bài kiểm tra khớp lệnh không quan tâm sai số chỉ về hướng nào. Nó đánh trượt bản dựng đó. Mình giữ nó ở mức chặn cứng thay vì chỉ cảnh báo, vì mình không tin chính mình sẽ bỏ qua nó một cách đúng đắn vào đúng thời điểm con số trông đẹp.
Cũng trong mùa kiểm toán đó, mình phát hiện sáu preset lỗi trong chính các cấu hình đã phát hành, trong đó có hai cấu hình năm phút ngừng giao dịch vào tháng 4 năm 2024 và không bao giờ chạy lại. Chúng không sập. Chúng lặng lẽ đứng ngoài, và điều đó trông giống sự thận trọng cho tới khi người ta đối chiếu với ngày tháng. Cả sáu preset đều bị gỡ bỏ, nên bản 1.18 ra mắt với ít sản phẩm hơn bản trước đó. Chuyện một trong những cài đặt bảo vệ ấy có thể khóa cứng một tài khoản lẽ ra vẫn hồi phục được thì mình viết ở bài vì sao bot giao dịch làm cháy tài khoản.
Mình đã dự đoán gì về hệ thống của chính mình và sai ở đâu?
Sai ở chỗ thực sự có bao nhiêu phần của nó là được khớp tham số.
Bài kiểm toán chỉ ra rằng mình có khoảng 180 tham số đầu vào của Expert Advisor và 336 nút điều chỉnh trong engine, đối chọi với khoảng 326 quan sát hiệu dụng, và gần như chưa tham số nào từng được tách ra kiểm tra một cách hệ thống. Mình dự đoán sẽ có dưới 25 tham số thực sự có ảnh hưởng, rồi chạy 436 lần phát lại trên ba nhánh đã phát hành để kiểm chứng.
Trong 231 khóa của engine, 82 khóa được một preset áp dụng, 49 khóa làm thay đổi lệnh nào được vào, và 33 khóa được phát hành ở một giá trị đã tinh chỉnh. Dự đoán của mình sai, và sai theo hướng bất lợi cho mình: 49, chứ không phải dưới 25. Tính ra là khoảng mười chín tới hai mươi quan sát hiệu dụng cho mỗi tham số được khớp, một tỷ lệ mỏng. Mẫu số trung thực là 33 chứ không phải con số 191 mà người đọc có thể suy ra từ danh sách tham số, và dự đoán bị bác bỏ thì được ghi nhận đúng là đã bị bác bỏ.
Việc đăng ký dự đoán trước khi chạy kiểm thử là lý do duy nhất giúp mình phân biệt được giữa việc mình đã đúng và việc mình tự thuyết phục rằng mình đã đúng sau khi thấy kết quả.
Vì sao 62 lệnh chạy thật vẫn chưa kết luận được điều gì?
Vì mẫu quá nhỏ để kết luận theo bất kỳ hướng nào.
Dòng tiền thật là một tài khoản prop firm chạy hệ thống năm phút, và tại thời điểm kiểm toán nó đã tạo ra 62 lệnh, giá trị t bằng âm 0,36. Đó không phải bằng chứng cho thấy hệ thống thất bại. Nó cũng không phải bằng chứng cho thấy hệ thống hoạt động. Nó là một phát biểu trung thực rằng chưa có gì được xác lập.
Khuyến nghị xếp hạng cao nhất của bài kiểm toán không phải chạy thêm một vòng quét tham số. Khuyến nghị là chạy các nhánh có khung thời gian chậm hơn ở mức khối lượng tối thiểu trong sáu tháng và thu thập lệnh khớp thật, bởi mọi thứ còn lại trong kho mã nguồn đều đang đo cùng một quãng hai năm rưỡi lịch sử. Một quy trình đã được kiểm chứng và một bài kiểm tra chạy thật chưa đủ tư cách kết luận là hai thứ khác nhau, và bất kỳ ai trình bày chúng như một thứ thì người đó đang bán một thứ gì đó.
Sau bài kiểm toán thì điều gì đã thay đổi?
Cổng phát hành, cấu trúc sổ ghi thí nghiệm, và thứ tự trình bày bằng chứng.
Một bài kiểm toán chỉ đẻ ra tài liệu mà không thay đổi dòng mã nào thì chỉ là một màn trình diễn. Một tháng sau bài kiểm toán này, cổng phát hành in ra một kết luận khác. Các bản ghi lock giờ đọc là "PBO-PASS/DSR-NONBINDING": khi ngưỡng kiểm tra nằm dưới ba mươi phần trăm của kết quả, Deflated Sharpe không còn được in là đạt nữa, nó được in là không ràng buộc, và bài kiểm tra có khả năng phân biệt sẽ dẫn đầu thay cho nó. Sổ ghi thí nghiệm được bổ sung các cột cho kích thước mẫu hiệu dụng, độ nhọn vượt, và kết quả ròng sau khi bỏ ba mươi lệnh tốt nhất, nên mọi bản lock sau này đều nêu các con số khó chịu bên cạnh các con số đẹp mà không cần ai phải hỏi.
Tính tới phiên bản 1.26, sổ ghi có 158 thí nghiệm khai báo trước: 52 bị bác bỏ thẳng, 5 bị dừng giữa chừng, 83 chỉ dừng ở mức nghiên cứu, và 11 đi tới quyết định khóa. Bài kiểm toán đếm được 137 vào tháng 8. Tỷ lệ khóa khoảng một trên mười bốn, với mọi thất bại đều được giữ lại và tra cứu được, chính là con số mình muốn thấy ở người khác, nên đó cũng là con số mình giữ lại cho mình.
Mình đã mất khá nhiều thời gian để xây dựng framework DQuants của riêng mình nhằm tăng tốc đáng kể toàn bộ quy trình phát triển, từ khâu kiểm chứng giả thuyết cho tới khâu triển khai. Nhưng phần mình sẽ bảo vệ mạnh nhất ở framework đó không phải tốc độ. Đó là việc nó khiến cho hành động lặng lẽ vứt bỏ một kết quả mình không thích trở nên rất tốn kém.
Câu hỏi thường gặp
Làm sao biết một backtest có trung thực không? Hãy tìm những gì tác giả công bố chống lại chính mình: một tháng tệ nhất được nêu tên, kích thước mẫu hiệu dụng đặt cạnh số lệnh danh nghĩa, một danh sách các ý tưởng đã bị bác bỏ, và ít nhất một tuyên bố mà tác giả đã rút lại. Một bản trình bày không có lần rút lại nào thường là chưa từng được kiểm toán, mà chỉ mới được viết ra.
Deflated Sharpe Ratio là gì và vì sao nó có thể gây hiểu lầm? Nó ước lượng xác suất một kết quả không phải do may mắn, có tính tới số cấu hình đã thử. Nó có thể bão hòa. Ngưỡng mà kết quả phải vượt qua tăng theo độ phân tán giữa các lần thử và chỉ tăng theo logarit của số lần thử, nên khi độ phân tán nhỏ so với chính kết quả thì không có độ rộng tìm kiếm thực tế nào làm nó trượt được. Trong trường hợp của mình, sẽ cần tới cỡ một trăm nghìn tỷ lần thử.
Xác suất quá khớp của backtest, hay PBO, là gì? Là bài kiểm tra chia dữ liệu nhiều lần, chọn cấu hình tốt nhất trên một nửa, rồi xem nó rơi vào đâu trên nửa còn lại. Trên một nửa nghĩa là cấu hình thắng trong mẫu lại kém hơn trung vị ngoài mẫu với tần suất cao hơn tung đồng xu. Kết quả của mình trên một nửa ở tám trong chín ô, và giờ mình dẫn đầu bằng chỉ số này thay vì bằng bài kiểm tra đã đạt.
Vì sao mẫu hiệu dụng lại nhỏ hơn số lệnh? Vì các công thức xác định mức mẫu tối thiểu giả định phân phối gần chuẩn, trong khi kết quả từng lệnh thì lệch và có đuôi dày. Chuỗi nghiên cứu của mình có độ lệch 3,49 và độ nhọn vượt 19,5, khiến 3.502 lệnh danh nghĩa chỉ còn tương đương khoảng 326 quan sát.
Một số ít lệnh tạo ra phần lớn lợi nhuận thì có phải vấn đề không? Tự thân nó không phải khiếm khuyết, vì hệ thống giao dịch phá vỡ vốn có hình dạng như vậy. Nhưng nó có nghĩa là các con số trung bình không đáng tin. Bỏ đi 30 lệnh tốt nhất trong 3.502 lệnh nghiên cứu, tức chưa tới một phần trăm mẫu, là toàn bộ chuỗi chuyển sang âm.
Kiểm tra khớp lệnh nên là cảnh báo hay chặn cứng? Chặn cứng. Ở bản 1.17, một lỗi khiến lợi nhuận báo cáo cao hơn bản tham chiếu chứ không thấp hơn, và cảnh báo đúng là thứ người ta dễ tự thuyết phục để bỏ qua khi con số dịch chuyển có lợi cho mình.
Cần bao nhiêu lệnh chạy thật thì kết quả mới có ý nghĩa? Nhiều hơn 62. Tại thời điểm kiểm toán, mẫu tiền thật là 62 lệnh giá trị t bằng âm 0,36, quá nhỏ để kết luận theo bất kỳ hướng nào. Yêu cầu về kích thước mẫu phụ thuộc vào phân phối, nên mẫu hiệu dụng mới là con số đáng hỏi.
Nên hỏi gì một người bán hệ thống giao dịch? Hãy hỏi bài kiểm tra nào trong phần bằng chứng của họ là bài có thể trượt, và chuyện gì đã xảy ra khi họ chạy nó. Hãy hỏi kích thước mẫu hiệu dụng, không phải số lệnh. Hãy hỏi họ đã rút lại điều gì. Các câu trả lời đó cho biết nhiều hơn bất kỳ đường cong nào.
Nếu người đọc muốn xem công việc này trở thành sản phẩm ra sao, MasterVP là phương pháp giao dịch trong ngày của riêng mình, xây trên lý thuyết volume profile vốn đã công khai. Nó được phát hành dưới dạng chỉ báo Master Volume Profiler trên TradingView và MetaTrader 5, thứ hiển thị cách đọc thị trường và để lệnh lại cho người dùng quyết định, và dưới dạng Master Volume Sniper trên chợ MQL5, một Expert Advisor thực thi đúng các quy tắc và cấu hình rủi ro mà người dùng thiết lập. Cả hai đều được ghi tài liệu kèm theo những điều kiện đi kèm ở trên, bởi chính những điều kiện đó mới là lý do phần còn lại đáng đọc.
Bài viết này được tổng hợp từ loạt bài tự kiểm toán trong nhật ký xây dựng MasterVP. Chỉ nhằm mục đích giáo dục. Không phải lời khuyên đầu tư. Các con số được trích dẫn là kết quả backtest, mô phỏng và kiểm toán trên dữ liệu tick thật, và hiệu suất trong quá khứ không đảm bảo kết quả trong tương lai. Mỗi trader vẫn chịu trách nhiệm cho cài đặt rủi ro và quyết định của chính mình.