Vì sao tối ưu tham số hay dẫn tới overfit

Tổ hợp tham số đứng đầu bảng trong mẫu có thể chính là tổ hợp sụp mạnh nhất ngoài mẫu. Bài này đo một ca như vậy rồi chỉ ra cơ chế đứng sau.

FinLens36 phút đọc

Một phép dò tham số chạy xong và in ra bảng xếp hạng. Dòng đầu bảng, tổ hợp thắng cuộc, cho lợi nhuận tổng +545.83% với profit factor 6.19 và vượt phép mua rồi giữ 224.88 điểm phần trăm. Ba con số, cái nào cũng đẹp.

Khoá đúng tổ hợp ấy lại, không sửa gì, rồi chạy trên đoạn dữ liệu sau đó, đoạn mà phép dò chưa từng nhìn thấy. Kết quả: −30.98%, trong khi cùng kỳ phép mua rồi giữ cho +15.41%, và tỷ số Sharpe của chiến lược là −0.57.

Chuyện này tự nó chưa lạ. Phần đáng nói nằm ở chỗ khác: tổ hợp đẹp nhất trong mẫu chính là tổ hợp sụp mạnh nhất ngoài mẫu. Không phải một tổ hợp bất kỳ trong bảng, mà đúng cái tổ hợp mà phép tối ưu đã chọn ra và đặt lên dòng đầu.

Bài này không nói bộ tham số nào tốt, và cũng không nói tối ưu tham số là việc không nên làm. Nó trả lời một câu hẹp hơn nhưng khó chịu hơn: vì sao thứ hạng trong mẫu lại có thể không mang thông tin gì, và đôi khi còn mang thông tin ngược dấu. Bài dành cho người đã tự chạy backtest, đã thấy một bảng xếp hạng tham số, và đang cân nhắc tin vào dòng đầu tiên của nó.

Bài không đưa ra tín hiệu mua bán, không dự báo giá của bất kỳ mã nào, và mọi con số backtest trong bài chỉ được dùng để chứng minh một cách hỏng.

Hai đường cong vẽ qua cùng một đám điểm dữ liệu, đường thứ nhất gấp khúc đi xuyên qua đúng mọi điểm, đường thứ hai trơn và đi giữa đám điểm, phía bên phải xuất hiện thêm vài điểm mới mà đường gấp khúc trượt xa còn đường trơn vẫn bám gần

Đường đi qua đúng mọi điểm cũ là đường tệ nhất với những điểm mới. Nguồn: FinLens tổng hợp.

Phép tối ưu tham số thật ra đang làm gì

Bốn thứ người chạy tự chọn, không thứ nào do dữ liệu quyết định

Một lượt tối ưu tham số gồm bốn phần, và cả bốn đều là lựa chọn của con người:

  1. Họ quy tắc. Giao cắt hai đường trung bình động, giá cắt một đường trung bình, ngưỡng của một chỉ báo dao động, hoặc một tổ hợp nhiều điều kiện.
  2. Lưới tham số. Mỗi tham số nhận bao nhiêu giá trị, từ đâu tới đâu, bước nhảy bao nhiêu.
  3. Hàm mục tiêu. Xếp hạng theo lợi nhuận tổng, theo hệ số lãi trên lỗ, theo tỷ số Sharpe, hay theo lợi nhuận chia cho mức sụt giảm sâu nhất. Bốn hàm mục tiêu này thường xuyên xếp hạng khác nhau trên cùng một lưới.
  4. Cửa sổ dữ liệu. Bắt đầu từ ngày nào, kết thúc ngày nào.

Không lựa chọn nào trong bốn cái đó được dữ liệu quyết định hộ. Chúng được người chạy đặt vào trước khi có kết quả, và mỗi lần đổi một trong bốn là một lần thử mới.

Chỗ khó chịu: phép tối ưu không có cách nào nói "không bộ nào dùng được"

Đây là tính chất quan trọng nhất của phép tối ưu và cũng là thứ ít được nói ra nhất.

Phép tối ưu lấy giá trị lớn nhất của một tập số. Lấy giá trị lớn nhất thì luôn ra một con số, và con số đó luôn cao hơn trung vị của chính tập ấy. Điều này đúng ngay cả khi mọi phần tử trong tập được sinh ra hoàn toàn ngẫu nhiên và không phần tử nào chứa thông tin gì.

Nghĩa là: sự tồn tại của một bộ tham số đứng đầu bảng không phải bằng chứng rằng quy tắc gốc có giá trị. Đó là một tính chất của phép lấy cực đại, không phải một phát hiện về thị trường. Bảng xếp hạng sẽ trông y hệt như vậy nếu ta thay chuỗi giá thật bằng một chuỗi số ngẫu nhiên: vẫn có dòng đầu, vẫn có tổ hợp thắng cuộc, vẫn có khoảng cách rõ ràng giữa dòng đầu và dòng cuối.

Từ đó rút ra định nghĩa dùng trong cả bài này. Một bộ tham số bị coi là overfit khi phần lớn ưu thế của nó trên đoạn dữ liệu dùng để chọn nó đến từ những chi tiết không lặp lại ở đoạn dữ liệu khác. Định nghĩa này không nói gì tới độ phức tạp. Một quy tắc chỉ có hai tham số vẫn overfit được, nếu hai tham số ấy được chọn bằng cách thử hàng nghìn cặp rồi giữ lại cặp cao nhất.

Thí nghiệm trục: khoá bộ tốt nhất rồi cho nó chạy tiếp

Thiết kế

Thí nghiệm chỉ có ba bước và cố ý không có bước nào thứ tư:

  1. Chạy phép tối ưu trên đoạn dữ liệu thứ nhất, gọi là kỳ trong mẫu. Nhận về một bảng xếp hạng gồm 15 tổ hợp của một chiến lược giao cắt trung bình động.
  2. Lấy tổ hợp đứng đầu, ở đây là tổ hợp có cửa sổ N = 150, rồi khoá lại. Không tinh chỉnh, không đổi hàm mục tiêu, không thêm bộ lọc.
  3. Chạy đúng tổ hợp đã khoá trên đoạn dữ liệu tiếp theo, gọi là kỳ ngoài mẫu, và so với phép mua rồi giữ chính mã đó trong đúng kỳ ấy.

Mã dùng cho thí nghiệm là HPG, một mã ngành thép trên HOSE. Nó có mặt ở đây với vai trò một điểm dữ liệu để chạy phép tính, không phải vì có gì đáng nói về doanh nghiệp.

Kết quả, cả hai kỳ trong cùng một bảng

KỳLợi nhuận chiến lượcMua và giữ cùng kỳVượt mua-giữChỉ số kèm theo
Trong mẫu+545.83%+320.95%+224.88 đptProfit factor 6.19
Ngoài mẫu−30.98%+15.41%−46.39 đptTỷ số Sharpe −0.57

Hai chỗ cần khai rõ về chính bảng này. Cột mua và giữ của kỳ trong mẫu được suy ra bằng phép trừ từ khoảng vượt 224.88 điểm phần trăm, chứ không phải một con số đo riêng. Và cột vượt mua-giữ của kỳ ngoài mẫu cũng là phép trừ: −30.98 trừ 15.41 ra −46.39.

Bảng này cố tình in cả hai kỳ cạnh nhau. Tách chúng ra thành hai mục khác nhau là cách trình bày làm mất hẳn vế thứ hai, và vế thứ hai mới là nội dung.

Khoảng vượt phép mua và giữ của cùng một tổ hợp tham số, hai kỳ
-50050100150200250điểm phần trămTrong mẫu: 224.88 điểm phần trămNgoài mẫu: -46.39 điểm phần trămTrong mẫuNgoài mẫu
Khoảng vượt phép mua và giữ của cùng một tổ hợp tham số, hai kỳ. Đơn vị điểm phần trăm.
MốcVượt mua-giữ (điểm phần trăm)
Trong mẫu224.88
Ngoài mẫu-46.39

HPG, tổ hợp giao cắt trung bình động có cửa sổ N = 150, là tổ hợp đứng đầu bảng xếp hạng của kỳ trong mẫu. Chốt số liệu 04/09/2026. Cả hai cột đều là hiệu giữa lợi nhuận chiến lược và lợi nhuận phép mua rồi giữ trong cùng kỳ. Đây là mô phỏng quá khứ có phí và trượt giá giả định, không phải kết quả giao dịch thật. Nguồn: HOSE, FinLens tổng hợp.

Con số thứ hai, và nó mạnh hơn con số thứ nhất

Nếu chỉ có một dòng sụp thì còn giải thích được bằng may rủi. Nhưng bảng gốc có 15 dòng, và khi chấm cả hai kỳ thì kết quả là: 0 trên 15 tổ hợp vượt được phép mua rồi giữ ở CẢ HAI kỳ.

Không phải "tổ hợp đứng đầu gặp xui". Không tổ hợp nào trong bảng sống sót qua cả hai đoạn. Bảng xếp hạng trong mẫu, xét như một công cụ để chọn, đã không chọn ra được gì.

Và mệnh đề đắt nhất: trong lượt chạy này, tổ hợp được xếp hạng cao nhất trong mẫu lại là tổ hợp có mức suy giảm mạnh nhất khi ra ngoài mẫu. Thứ hạng trong mẫu ở đây không chỉ vô dụng, nó còn chỉ ngược.

Bảng này chứng minh cái gì và không chứng minh cái gì

Nó chứng minh rằng một thứ hạng trong mẫu không tự động mang sang kỳ khác, và trong ít nhất một ca đo được thì nó mang sang ngược dấu. Nó không chứng minh rằng phép tối ưu luôn đảo thứ hạng, cũng không chứng minh rằng mọi chiến lược giao cắt trung bình động đều hỏng. Đây là một mã, một họ quy tắc, một cách chia kỳ. Thứ nó làm được là dời gánh nặng chứng minh: ai muốn dùng thứ hạng trong mẫu như một căn cứ thì phải tự chỉ ra vì sao thứ hạng ấy bền, chứ không được mặc định là bền.

Một chi tiết về chi phí phải nói ngay ở đây

Mức trượt giá mặc định của công cụ backtest là 0.10% một vòng, và toàn bộ lượt thu thập đầu tiên chạy ở mức đó. Nhưng lưới bước giá đặt một sàn vật lý cao hơn hẳn, khác nhau theo từng mã: với HPG ở mức giá 21,700 đ ngày 04/09/2026 và bước giá 50 đ trên HOSE, sàn một vòng là 0.2304%, tức gấp khoảng 2.3 lần mức mặc định.

Bảng sàn trượt giá đầy đủ cho mười mã và toàn bộ hệ quả của nó nằm ở bài chi phí giao dịch ăn mòn lợi nhuận thế nào. Chỗ liên quan tới bài này chỉ là một câu: con số trong mẫu đã đẹp sẵn còn được đẹp thêm bởi một tham số đặt thấp hơn sàn vật lý, nên nó lại càng không phải thứ để đọc như một kết quả.

Phần phân bố độ trễ của chính bộ số HPG N = 150 này thuộc về bài chỉ báo trễ và chỉ báo dẫn. Bài đó trả lời câu hỏi độ trễ phân bố thế nào; bài này trả lời câu hỏi vì sao bộ tham số ấy được chọn ra và vì sao việc được chọn ra không nói lên điều gì.

Số bậc tự do: mỗi tham số thêm vào là một chiều để dò

Số ô lưới tăng theo hàm mũ

Lấy một lưới tham số rất bình thường, loại mà ai cũng có thể dựng trong vài phút. Cửa sổ nhanh nhận 8 giá trị, cửa sổ chậm nhận 10 giá trị, và giữ điều kiện cửa sổ nhanh phải nhỏ hơn cửa sổ chậm. Số cặp hợp lệ là 69.

Rồi thêm tham số. Mỗi lần thêm là nhân, không phải cộng:

Số tham số quétTham số vừa thêmSố ô lướiSố ô trông đẹp thuần do ngẫu nhiên, nếu q = 5%
2cửa sổ nhanh và cửa sổ chậm693.45
3ngưỡng cắt lỗ, 5 giá trị34517.25
4kiểu làm trơn (SMA, EMA, Wilder), 3 giá trị1,03551.75
5số phiên xác nhận (0, 1, 2, 3), 4 giá trị4,140207

Cột cuối cần một giả định được nói thẳng: gọi q là xác suất một bộ tham số hoàn toàn vô dụng vẫn vượt được ngưỡng đánh giá thuần do may rủi. Con số q không đo được từ dữ liệu, nó phụ thuộc vào ngưỡng ta đặt và vào độ nhiễu của chính chuỗi. Lấy q = 5% chỉ là một mức để có số mà tính. Với q = 5%, số ô trông đẹp mà thực chất chỉ là may rủi bằng đúng 5% số ô, tức 207 ô trong lưới cuối cùng.

Hai trăm lẻ bảy bộ tham số trông đẹp, không bộ nào chứa thông tin gì. Và phép tối ưu sẽ trả về bộ đẹp nhất trong số đó.

Xác suất tìm được ít nhất một bộ đẹp thuần do may rủi

Cùng giả định q = 5% và coi các lần thử là độc lập, xác suất có ít nhất một bộ vượt ngưỡng thuần do may rủi sau K lần thử là 1 − (1 − q)^K:

Xác suất có ít nhất một bộ tham số vô dụng vượt ngưỡng thuần do may rủi
020406080100%K = 1: 5 %K = 5: 22.62 %K = 10: 40.13 %K = 20: 64.15 %K = 30: 78.54 %K = 50: 92.31 %K = 100: 99.41 %K = 1K = 5K = 10K = 20K = 30K = 50K = 100
Xác suất có ít nhất một bộ tham số vô dụng vượt ngưỡng thuần do may rủi. Đơn vị %.
MốcXác suất (%)
K = 15
K = 522.62
K = 1040.13
K = 2064.15
K = 3078.54
K = 5092.31
K = 10099.41

Phép tính thuần tuý theo công thức 1 − (1 − q) mũ K, với giả định mỗi lần thử độc lập và mỗi bộ tham số vô dụng có xác suất q = 5% vượt ngưỡng do may rủi. Con số q là giả định để có số mà tính, không phải một đại lượng đo được. Trục ngang là số lần thử K. Nguồn: FinLens tổng hợp.

Ở K = 20 thì xác suất đã là 64.15%, tức khả năng cao hơn không. Ở K = 100 thì gần như chắc chắn. Với lưới 4,140 ô ở bảng trên, câu hỏi "có tìm được bộ nào trông đẹp không" không còn là câu hỏi nữa.

Hai điều chỉnh phải nói, và chúng đi ngược nhau

Công thức trên giả định các lần thử độc lập, và trong một lưới tham số thì điều đó sai theo hướng làm công thức nói quá. Hai ô cạnh nhau, ví dụ cửa sổ 20 và cửa sổ 21, sinh ra hai chuỗi tín hiệu chồng lấn gần như hoàn toàn. Số phép thử thực sự độc lập nhỏ hơn hẳn số ô lưới, nên xác suất thật thấp hơn con số vừa tính.

Nhưng có một hướng ngược lại, và nó thường lớn hơn: số ô lưới chỉ đếm phần được ghi lại. Trước khi dừng ở lưới cuối cùng, người chạy còn thử những thứ không ai ghi vào báo cáo. Đổi họ quy tắc. Đổi hàm mục tiêu từ lợi nhuận tổng sang Sharpe rồi lại đổi về. Đổi cửa sổ dữ liệu vì đoạn đầu trông bất thường. Đổi mã vì mã đầu tiên không cho kết quả nào đáng nhìn. Mỗi lần đổi là một lần thử, và toàn bộ những lần đó nằm ngoài mọi bảng xếp hạng.

Con số đáng lo không phải số ô trong lưới cuối cùng. Nó là tổng số thứ đã thử trước khi có kết quả được báo cáo, và gần như không ai ghi lại con số ấy.

Ba khối cạnh nhau minh hoạ không gian tham số nở ra, khối thứ nhất là một hàng ô đơn, khối thứ hai là một lưới ô vuông hai chiều, khối thứ ba là một khối hộp ba chiều gồm rất nhiều ô nhỏ, mỗi khối có một ô được tô đậm để chỉ ô cho kết quả cao nhất

Thêm một tham số là nhân số ô lên, không phải cộng thêm. Nguồn: FinLens tổng hợp.

Con số không ai ghi lại: ca 30 cấu hình trong chính đợt viết này

Có một ví dụ sống ngay trong loạt bài này, và nó đáng kể ra vì nó là chuyện thật chứ không phải giả định.

Bài backtest là gì và đọc kết quả thế nào cần một cặp cấu hình để minh hoạ luận điểm trung tâm của nó: hai cấu hình trên cùng một mã, cùng cửa sổ, cùng phí, cho lợi nhuận tổng gần bằng nhau nhưng mức sụt giảm sâu nhất chênh nhau hơn 31 điểm phần trăm. Cặp ấy tồn tại, số liệu có thật, và bài đó in đầy đủ.

Nhưng để tìm ra cặp đó, người thu thập dữ liệu đã phải quét 30 cấu hình.

Ba điều đáng rút ra từ chuyện này:

Thứ nhất, ba mươi là một con số bình thường tới mức chẳng ai nghĩ tới việc ghi lại. Quét 30 cấu hình là một buổi chiều làm việc. Nó không phải hành vi khai thác dữ liệu quá đà, nó là cách người ta vẫn làm.

Thứ hai, đặt 30 vào biểu đồ ở trên thì con số là 78.54%. Với giả định q = 5%, quét 30 lần cho xác suất 78.54% có ít nhất một cấu hình trông đẹp thuần do may rủi. Ai quét 30 lần rồi báo cáo cấu hình đẹp nhất thì cái được báo cáo phần lớn là hệ quả của việc quét 30 lần, chứ không phải của thị trường.

Thứ ba, chính bài kia đã làm đúng cách xử lý. Nó viết con số 30 ra giấy, và nó in kèm rằng cả hai cấu hình trong cặp minh hoạ đều thua phép mua rồi giữ hơn 335 điểm phần trăm, nên bảng ấy không đọc thành lời khen được. Một cặp số tìm được sau 30 lần quét vẫn dùng được để minh hoạ một cơ chế, miễn là con số 30 đi kèm và miễn là không ai đọc nó thành một kết quả.

Ranh giới ở đây rất mảnh nhưng rất rõ. Dùng kết quả dò tìm để chỉ ra một cách hỏng thì được, vì cách hỏng đó chỉ cần tồn tại một lần là đủ chứng minh. Dùng kết quả dò tìm để nêu ưu điểm thì không, vì ưu điểm đòi hỏi tính lặp lại, mà lặp lại thì chính con số 30 đã phủ định.

Đọc phân bố của TOÀN BỘ các bộ tham số, không chỉ bộ đứng đầu

Đây là phần ít được dạy nhất, và cũng là phần rẻ nhất để làm: dữ liệu đã có sẵn ngay trong lượt chạy, chỉ là không ai in ra.

Mọi báo cáo tối ưu đều đưa bộ đứng đầu. Rất ít báo cáo đưa phân bố kết quả của toàn bộ các ô lưới. Nhưng bộ đứng đầu một mình không đọc được, y như một con số không đọc được nếu không biết nó đứng cạnh cái gì.

Bốn thứ cần nhìn trong phân bố

Một: khoảng cách từ bộ tốt nhất tới trung vị, đo bằng độ phân tán của chính phân bố ấy. Nếu bộ tốt nhất chỉ nhỉnh hơn trung vị chừng một độ lệch chuẩn thì nó gần như chắc chắn chỉ là đỉnh của nhiễu: lấy cực đại của vài nghìn số ngẫu nhiên thì cũng ra một giá trị nhỉnh hơn trung vị đúng chừng đó. Nếu nó tách hẳn ra nhiều lần độ phân tán thì tình huống khác, tuy vẫn chưa phải bằng chứng.

Hai: hình dạng vùng quanh bộ tốt nhất. Có hai kiểu rất khác nhau mà bảng xếp hạng không phân biệt được.

Đỉnh nhọnCao nguyên
Ô ngay cạnh bộ tốt nhấttụt hẳn xuốnggần bằng
Đọc thế nàobộ tốt nhất khai thác một đặc điểm rất hẹp của đoạn dữ liệu nàyquy tắc ít nhạy với tham số ở vùng đó
Khi tham số lệch một nấc lúc chạy thậtkết quả đổi hoàn toànkết quả gần như không đổi

Một đỉnh nhọn là dấu hiệu xấu gần như không có ngoại lệ, vì thị trường không có lý do gì để phân biệt cửa sổ 47 với cửa sổ 48.

Ba: tỷ lệ các ô cho kết quả dương, và tỷ lệ các ô vượt được phép mua rồi giữ. Nếu đa số lưới nằm dưới phép mua rồi giữ thì cái đứng đầu bảng đang là ngoại lệ của chính lưới nó, và ngoại lệ thì cần lời giải thích riêng chứ không được hưởng uy tín của cả lưới.

Bốn: bộ tốt nhất có nằm ở rìa lưới không. Nếu nó rơi đúng vào giá trị lớn nhất hoặc nhỏ nhất mà lưới cho phép, nghĩa là điểm cực đại thật có thể nằm ngoài lưới, và cái ta đang cầm chỉ là điểm cực đại của một cái hộp do ta tự dựng.

Hai biểu đồ phân bố đặt cạnh nhau, mỗi biểu đồ là một dãy cột biểu diễn số lượng bộ tham số theo mức kết quả, biểu đồ bên trái có cột cao nhất nằm sát ngay đám đông ở giữa, biểu đồ bên phải có một cột đứng tách hẳn về phía phải cách xa đám đông, mỗi biểu đồ đều có một vạch đánh dấu vị trí trung vị

Cùng một bộ đứng đầu, hai phân bố, hai mức tin cậy khác hẳn nhau. Nguồn: FinLens tổng hợp.

Phép đọc này chỉ hạ được độ tin cậy, không nâng được

Cần nói thẳng giới hạn, vì đây là chỗ dễ đọc quá tay nhất.

Một cao nguyên rộng, một khoảng cách lớn tới trung vị và một tỷ lệ ô dương cao không biến kết quả trong mẫu thành bằng chứng. Cả bốn dấu hiệu trên đều đo trên đúng đoạn dữ liệu đã dùng để chọn, nên chúng vẫn nằm trọn trong mẫu. Một quy tắc overfit hoàn toàn có thể tạo ra một cao nguyên đẹp, nếu đoạn dữ liệu ấy có một đặc điểm kéo dài đủ lâu.

Phép đọc phân bố có công dụng đúng một chiều: nó loại nhanh những kết quả không đáng nhìn tiếp. Bộ tốt nhất sát trung vị, hoặc đứng trên một đỉnh nhọn, thì dừng ở đó, khỏi cần chạy ngoài mẫu. Còn khi phân bố trông khá thì việc duy nhất nó cho phép là chạy tiếp bước kiểm chứng ngoài mẫu, không hơn.

Và ở Việt Nam, "cao nguyên" có thể là ảo

Có một cái bẫy riêng cho thị trường này. Lưới bước giá làm nhiều giá trị tham số danh nghĩa khác nhau thực thi ra cùng một quy tắc.

Ví dụ cụ thể: một ngưỡng cắt lỗ đặt ở 3.0%, 3.2% và 3.4% trên một cổ phiếu HNX giá 13,200 đ, nơi một bước giá bằng 0.7576% thị giá, sẽ rơi vào cùng một khoảng giữa hai mức giá hợp lệ trong phần lớn trường hợp và sinh ra cùng một lệnh thoát. Ba ô lưới, một quy tắc. Cơ chế lưới bước giá dựng ở bài hỗ trợ và kháng cự bản chất là gì, và hệ quả cho bài này là: một vùng phẳng trong phân bố tham số có thể chỉ là dấu vết của lưới giá, không phải dấu hiệu quy tắc ổn định.

Phép kiểm rất nhanh: đổi ngưỡng từ đơn vị phần trăm sang đơn vị bước giá. Nếu ba ô "khác nhau" quy về cùng một số bước giá thì chúng không phải ba phép thử.

Chuỗi thời gian không được chia ngẫu nhiên

Trong học máy nói chung, cách chia dữ liệu mặc định là trộn ngẫu nhiên rồi cắt ra tập huấn luyện và tập kiểm tra. Với chuỗi giá, cách đó hỏng vì bốn lý do chồng lên nhau.

Một: rò rỉ qua cửa sổ của chính chỉ báo. Giá trị của một đường trung bình động 150 phiên tại ngày t được tính từ 150 phiên trước t. Nếu ngày t rơi vào tập kiểm tra còn phần lớn 150 phiên kia nằm trong tập huấn luyện, thì điểm kiểm tra ấy được dựng từ chính dữ liệu huấn luyện. Cửa sổ càng dài thì lượng rò rỉ càng lớn, và tham số cửa sổ lại thường là thứ đang được tối ưu.

Hai: các phiên liền nhau không độc lập. Giá đóng cửa hôm nay và hôm qua tương quan rất cao. Trộn ngẫu nhiên đặt một phiên vào tập kiểm tra trong khi hai phiên kề nó nằm trong tập huấn luyện, và mô hình chỉ cần nội suy giữa hai hàng xóm là "đoán đúng". Kết quả kiểm tra đẹp lên vì một lý do không liên quan gì tới khả năng dự báo.

Ba: chế độ thị trường đi thành khối. Một giai đoạn biến động mạnh kéo dài vài tháng, một giai đoạn đi ngang kéo dài cả năm. Trộn ngẫu nhiên rải mỗi khối sang cả hai phía, nên tập kiểm tra luôn chứa những mẫu rất giống mẫu trong tập huấn luyện. Câu hỏi "quy tắc này sống được sang một chế độ chưa từng thấy không" không còn được hỏi nữa.

Bốn, và đây là lý do nặng nhất: nó mô phỏng một tình huống không tồn tại. Người dùng một quy tắc luôn đứng ở mép phải của chuỗi, với toàn bộ quá khứ ở bên trái và không một phiên nào ở bên phải. Phép chia ngẫu nhiên tạo ra một người biết trước một phần tương lai rồi hỏi người đó về phần còn lại. Không ai bao giờ ở vị trí đó.

Cách chia đúng, và chỗ nó vẫn bị phá

Nguyên tắc thì đơn giản: chia theo thời gian, kỳ trong mẫu ở trước, kỳ ngoài mẫu ở sau, và giữ một khoảng đệm giữa hai kỳ ít nhất bằng cửa sổ dài nhất trong lưới tham số. Khoảng đệm ấy tồn tại chính vì lý do thứ nhất ở trên: không có nó thì những phiên đầu của kỳ ngoài mẫu vẫn đang được tính từ dữ liệu trong mẫu.

Nhưng chỗ hay bị phá nhất không nằm ở phép chia. Nó nằm ở đây:

Kỳ ngoài mẫu dùng được đúng một lần

Ngay khi đã nhìn kết quả ngoài mẫu rồi quay lại đổi quy tắc, đổi lưới, đổi hàm mục tiêu hay đổi cửa sổ, đoạn dữ liệu đó đã tham gia vào việc chọn. Nó trở thành dữ liệu trong mẫu, dù không ai sửa một dòng lệnh nào và dù phép chia vẫn còn nguyên trên giấy. Lần chạy thứ hai trên cùng đoạn ấy không còn là kiểm chứng độc lập. Cách duy nhất giữ cho nó còn nghĩa là ghi lại toàn bộ quy tắc và lưới trước khi chạy, rồi chấp nhận kết quả dù nó ra sao.

Đây cũng là phiên bản của một cái bẫy đã gặp ở bài khung thời gian và tính nhất quán: vấn đề không nằm ở công cụ mà nằm ở thứ tự ra quyết định. Chọn trước rồi đo là một phép đo. Đo trước rồi chọn là một câu trả lời.

Và mốc chia có thể rơi vào một chỗ không do thị trường quyết định

Chia theo thời gian thì phải chọn một mốc, và ở Việt Nam mốc ấy dễ rơi vào một chỗ mà chuỗi đổi bản chất vì lý do hành chính.

Chuỗi giá có thể bị gãy vì diện hạn chế giao dịch, vì đình chỉ, hoặc vì mã chuyển nơi giao dịch, và mọi cơ chế đó nằm ở bài xu hướng và cấu trúc giá. Riêng chuyện chuyển sàn đáng nhắc lại vì nó có hạn cụ thể: toàn bộ cổ phiếu niêm yết trên HNX phải chuyển sang HOSE chậm nhất 31/12/2026. Khi một mã chuyển, biên độ đổi, bước giá đổi, phiên khớp lệnh định kỳ mở cửa xuất hiện. Cỗ máy sinh ra chuỗi giá đổi trong đúng một đêm, và trên đồ thị không có gì đánh dấu chỗ đó.

Hệ quả cho phép chia: một kỳ ngoài mẫu vắt qua mốc chuyển sàn không phải là "cùng một quy tắc chạy trên dữ liệu mới", nó là quy tắc chạy trên một cỗ máy khác. Kết quả xấu đi ở đó không nói được gì về việc quy tắc có overfit hay không.

Hai cách chia một chuỗi thời gian đặt trên dưới nhau, cách phía trên cắt chuỗi thành hai đoạn liền mạch với một khoảng đệm ở giữa và ghi rõ đoạn trước là trong mẫu đoạn sau là ngoài mẫu, cách phía dưới rải các phiên trong mẫu và ngoài mẫu xen kẽ nhau khắp chuỗi, kèm một mũi tên chỉ vào một phiên ngoài mẫu bị kẹp giữa hai phiên trong mẫu

Cắt theo thời gian và trộn ngẫu nhiên không phải hai lựa chọn ngang nhau. Nguồn: FinLens tổng hợp.

Bảy chỗ thị trường Việt Nam làm phép dò tìm này tệ hơn

Phần trên đúng với mọi thị trường. Bảy mục dưới đây thì không, và chúng đều làm cùng một việc: khiến số phép thử thực sự độc lập ít hơn ta tưởng, hoặc khiến hàm mục tiêu đo sai thứ nó tưởng đang đo.

Một: lưới bước giá gộp các ô tham số lại với nhau. Đã nói ở trên. Nhiều giá trị danh nghĩa khác nhau thực thi ra cùng một quy tắc, nên một lưới 4,140 ô có thể chỉ chứa vài trăm quy tắc thật sự khác nhau. Điều này làm giảm số phép thử độc lập, nhưng đồng thời làm hỏng cách đọc "cao nguyên".

Hai: biên độ dao động cắt cụt mọi ngưỡng lớn. Biên độ một phiên trên HOSE là ±7%. Mọi ngưỡng cắt lỗ hay chốt lãi đặt từ 7% trở lên đều không thể chạm tới trong cùng phiên phát tín hiệu, nên chúng đổ dồn thành cùng một hành vi: thoát ở phiên sau. Trong lưới tham số, các giá trị 8%, 10% và 15% vì thế không phải ba phép thử khác nhau theo cách người dựng lưới tưởng. Cơ chế cắt cụt nằm ở bài đọc nến Nhật.

Ba: sàn trượt giá khác nhau theo từng mã, và phép tối ưu bị lệch theo tần suất. Đây là mục nặng nhất. Một tham số trượt giá chung cho mọi mã đặt thấp hơn sàn vật lý sẽ ưu ái có hệ thống những bộ tham số giao dịch nhiều, vì chi phí bị đặt thiếu tỷ lệ với số lệnh. Nghĩa là phép tối ưu không chỉ chọn ra một bộ tham số may mắn, nó còn chọn theo một chiều biết trước: về phía các bộ nhanh hơn. Trên lượt chạy lại 40 cấu hình khi thay tham số trượt giá bằng sàn của từng mã, cả 40 trên 40 cấu hình đều xấu đi, không cấu hình nào tốt lên, và mức bào mòn tỷ lệ với số lệnh chứ không tỷ lệ với chất lượng tín hiệu. Toàn bộ số liệu ở bài chi phí giao dịch ăn mòn lợi nhuận thế nào.

Bốn: một phần khối lượng không đi qua sổ lệnh. Bộ tham số nào có điều kiện dựa trên khối lượng, kiểu "khối lượng vượt bao nhiêu lần trung bình n phiên", đang tối ưu một ngưỡng trên một chuỗi trộn hai thứ khác bản chất: phần khớp trong sổ lệnh và phần thoả thuận. Chi tiết ở bài khối lượng giao dịch nói gì. Với bài này, hệ quả là ngưỡng tối ưu tìm được có thể chỉ đang bắt đúng vài phiên có giao dịch thoả thuận lớn trong đoạn dữ liệu đó.

Năm: khoảng trống giá giả trên chuỗi chưa điều chỉnh. Vào ngày giao dịch không hưởng quyền, giá tham chiếu bị điều chỉnh theo giá trị quyền, và trên chuỗi thô bước nhảy hành chính ấy trông hệt một khoảng trống do thị trường tạo ra. Một phép dò ngưỡng cắt lỗ chạy trên chuỗi thô sẽ tìm thấy rằng vài ngưỡng nhất định "hoạt động tốt", trong khi thứ chúng đang bắt chỉ là độ lớn của các đợt chia cổ tức trong đúng đoạn đó. Cơ chế đầy đủ ở bài xu hướng và cấu trúc giá.

Sáu: kỳ nghỉ Tết làm cửa sổ n phiên trải dài hơn bình thường. Mọi cửa sổ chỉ báo đếm phiên, không đếm thời gian. Một cửa sổ 20 phiên vắt qua Tết Nguyên đán trải trên một khoảng thời gian dài hơn hẳn một cửa sổ 20 phiên giữa năm. Hai chỗ hỏng đi kèm. Thứ nhất, tham số n không còn là một cái núm điều chỉnh tốc độ thuần nhất, vì số lần cửa sổ vắt qua Tết phụ thuộc vào chính n. Thứ hai, trong một cửa sổ dữ liệu 5 năm chỉ có khoảng 5 cái Tết, nên bất kỳ ưu thế nào của một bộ tham số phát sinh từ cách nó ứng xử quanh Tết đều đang được khớp trên 5 quan sát.

Bảy: chu kỳ T+2 đặt trần cứng lên tần suất. Một vòng mua bán trên thị trường cơ sở cần tối thiểu ba phiên, nên với khoảng 248 phiên mỗi năm thì trần cơ học chừng 82 vòng, và trần thật còn thấp hơn. Phép tối ưu không biết cái trần đó: nó sẵn sàng xếp hạng cao một bộ tham số sinh ra 200 vòng một năm, thứ không thực hiện được. Cấu trúc T+2 và bảng bào mòn theo số vòng nằm ở bài khung thời gian và tính nhất quán, còn đường đi của một lệnh nằm ở bài một lệnh mua đi qua những khâu nào.

Công cụ này mất tác dụng khi nào

Phép tối ưu tham số, và mọi bảng xếp hạng sinh ra từ nó, mất tác dụng ở chín chỗ dưới đây. Mỗi mục ứng với một cơ chế cụ thể đã nêu ở trên, không phải một cảnh báo chung.

Khi số phép thử không được ghi lại. Không có con số K thì không tính được xác suất may rủi, và không tính được thì bảng xếp hạng không diễn giải được. Đây là chỗ hỏng phổ biến nhất và cũng dễ sửa nhất.

Khi kỳ ngoài mẫu đã bị nhìn quá một lần. Nhìn kết quả rồi sửa quy tắc là đã chuyển đoạn dữ liệu ấy sang phía trong mẫu. Sau lần đó, không còn kỳ ngoài mẫu nào nữa cho tới khi thị trường sinh thêm dữ liệu mới.

Khi bộ tốt nhất đứng trên một đỉnh nhọn. Ô lưới ngay cạnh cho kết quả khác hẳn nghĩa là kết quả đang phụ thuộc vào một chi tiết rất hẹp của đoạn dữ liệu, và thị trường không có lý do gì phân biệt cửa sổ 47 với cửa sổ 48.

Khi bộ tốt nhất nằm ở rìa lưới. Cực đại thật có thể ở ngoài hộp, nên cái đang cầm là cực đại của cái hộp chứ không phải của quy tắc.

Khi tham số chi phí đặt thấp hơn sàn vật lý của chính mã đó. Lúc đó thứ hạng bị lệch có hệ thống về phía các bộ giao dịch nhiều, và độ lệch ấy tỷ lệ với số lệnh chứ không tỷ lệ với chất lượng tín hiệu.

Khi lưới tham số mịn hơn lưới bước giá. Các ô cạnh nhau thực thi ra cùng một quy tắc, nên chúng không phải các phép thử độc lập và một cao nguyên trong phân bố có thể chỉ là dấu vết của lưới giá.

Khi ngưỡng phần trăm vượt biên độ dao động. Mọi ngưỡng từ ±7% trở lên trên HOSE đổ dồn thành cùng một hành vi trong phiên, nên chúng không phân biệt được bằng dữ liệu trong phiên.

Khi cửa sổ dữ liệu chứa một mốc đổi cỗ máy. Chuyển sàn, đổi diện giao dịch, đình chỉ dài. Kết quả xấu đi sau mốc ấy không nói được gì về overfit, và kết quả tốt lên cũng vậy.

Khi số quan sát của thứ đang được khớp quá nhỏ. Năm cái Tết trong năm năm, hoặc năm lệnh trong mười năm như ca ở bài backtest. Một tỷ lệ thắng 60% tính trên 5 lệnh là 3 trên 5, và không mang ý nghĩa thống kê nào.

Những chỗ bài này cố ý không khẳng định

Không khẳng định rằng tối ưu tham số là việc vô ích. Bài chỉ khẳng định rằng kết quả của nó không đọc được nếu thiếu số phép thử, phân bố toàn lưới và một kỳ ngoài mẫu chưa bị nhìn.

Không khẳng định rằng phép tối ưu luôn đảo thứ hạng. Ca HPG N = 150 là một ca đo được. Một ca đủ để bác bỏ mệnh đề "thứ hạng trong mẫu luôn mang sang được", không đủ để dựng mệnh đề ngược lại.

Không khẳng định con số q = 5%. Đó là giả định đặt vào để có số mà tính. Giá trị thật phụ thuộc vào ngưỡng đánh giá, vào độ nhiễu của chuỗi và vào mức chồng lấn giữa các ô lưới, và bài này không đo nó.

Không khẳng định lưới 69, 345, 1,035 và 4,140 ô là lưới của bất kỳ ai. Đó là một lưới dựng ra để đếm, chọn các giá trị tròn cho dễ theo dõi.

Không khẳng định rằng đọc phân bố sẽ cứu được một kết quả. Nó chỉ loại nhanh những kết quả không đáng nhìn tiếp. Chiều ngược lại không tồn tại.

Không khẳng định gì về tham số trượt giá của riêng lượt chạy N = 150. Bài biết mức mặc định của công cụ là 0.10% một vòng và biết sàn vật lý của HPG là 0.2304%, nhưng không khẳng định lượt chạy cụ thể ấy dùng mức nào. Điều biết chắc là hướng: áp sàn thật thì kết quả chỉ có thể xấu đi.

Không khẳng định rằng bảy chỗ đặc thù Việt Nam là danh sách đầy đủ. Chúng là bảy chỗ đo được hoặc suy được từ quy định hiện hành.

Không khẳng định điều gì về triển vọng của bất kỳ mã nào xuất hiện trong bài. HPG có mặt vì nó là một mã có đủ dữ liệu để chạy phép tính, và mọi mã khác cùng đặc điểm sẽ cho cùng cấu trúc lập luận.

Bảy câu hỏi trước khi tin một bộ tham số đã tối ưu

Bảy câu dưới đây trả lời được bằng thông tin đã nằm sẵn trong lượt chạy, không cần thêm dữ liệu và không cần dự báo gì.

Một: tôi đã thử tổng cộng bao nhiêu thứ trước khi ra con số này? Đếm cả những lần đổi họ quy tắc, đổi hàm mục tiêu, đổi cửa sổ dữ liệu và đổi mã. Nếu không đếm được thì con số K không tồn tại, và mọi phần còn lại không diễn giải được.

Hai: bộ tốt nhất cách trung vị của cả lưới bao xa, tính theo độ phân tán của chính lưới ấy? Nhỉnh hơn một chút thì dừng lại ở đây.

Ba: các ô ngay cạnh bộ tốt nhất cho kết quả thế nào? Tụt hẳn là đỉnh nhọn. Bộ tốt nhất có nằm ở rìa lưới không?

Bốn: bao nhiêu phần trăm số ô trong lưới vượt được phép mua rồi giữ? Nếu rất ít thì cái đứng đầu bảng đang là ngoại lệ của chính lưới nó.

Năm: kỳ ngoài mẫu này tôi đã nhìn lần thứ mấy? Lần thứ hai trở đi thì nó không còn là kỳ ngoài mẫu.

Sáu: tham số trượt giá tôi đang dùng có cao hơn một bước giá chia cho thị giá của chính mã đó không? Thấp hơn thì bảng xếp hạng đang lệch về phía các bộ giao dịch nhiều, và mức lệch tỷ lệ với số lệnh.

Bảy: bộ tham số này sinh ra bao nhiêu vòng mua bán mỗi năm, và con số đó có nằm dưới trần cơ học của T+2 không? Vượt trần thì kết quả đang mô tả một chiến lược không thực hiện được trên thị trường cơ sở.

Trả lời xong bảy câu, việc còn lại không phải là chọn ra một bộ tham số. Việc còn lại là ghi cả bảy câu trả lời xuống cùng với quy tắc và lưới, trước khi chạy bất cứ thứ gì trên đoạn dữ liệu tiếp theo. Ghi lại không làm phép đo chính xác hơn, nó chỉ giữ cho phép đo còn là phép đo.

Đọc tiếp gì

Bài này khép lại chuỗi "Chỉ báo kỹ thuật". Năm bài trước dựng từng viên gạch: đường trung bình động cho ba công thức làm trơn và chỗ độ trễ sinh ra, chỉ báo RSIchỉ báo MACD cho hai họ chỉ báo dựng trên phép làm trơn ấy, Bollinger Bands cho dải dựa trên độ lệch chuẩn, rồi chỉ báo trễ và chỉ báo dẫn cho phân bố độ trễ đo trên 94 điểm xoay.

Bốn thứ bài này cố ý để lại cho chỗ khác, mỗi thứ có một bài riêng. Cách đọc một bảng kết quả mô phỏng, kể cả những cột hay bị bỏ qua, nằm ở backtest là gì và đọc kết quả thế nào. Hai loại sai lệch làm hỏng dữ liệu trước khi phép tối ưu kịp chạy, tức tập mã thiếu những mã đã rời sàn và những chỗ thông tin tương lai lọt vào quá khứ, nằm ở sai lệch sống sót và nhìn trước. Bảng sàn trượt giá của từng mã, thứ đã được nhắc ba lần trong bài này, nằm ở chi phí giao dịch ăn mòn lợi nhuận thế nào. Và phép tính nối tỷ lệ thắng với tỷ lệ lãi trên lỗ, thứ trả lời câu hỏi một chuỗi lệnh có kỳ vọng dương hay không, nằm ở kỳ vọng toán học của một hệ thống.

Một câu tóm tắt cho cả sáu bài của chuỗi này: mọi chỉ báo đều là một phép lọc trên cùng một chuỗi giá, phép lọc nào cũng có tham số, và tham số nào cũng có thể được chọn theo cách làm cho quá khứ đẹp lên mà không làm tương lai rõ hơn chút nào.

Nội dung trong bài mang tính chia sẻ kiến thức, không phải khuyến nghị mua bán chứng khoán và không phải tư vấn đầu tư. Các con số backtest trích từ mô phỏng trên dữ liệu lịch sử có phí và trượt giá giả định, chốt số liệu 04/09/2026, và chúng được đưa vào bài chỉ để chứng minh một cách hỏng chứ không để mô tả ưu điểm của bất kỳ chiến lược nào. Kết quả mô phỏng quá khứ không phải kết quả giao dịch thật và không nói lên điều gì về kết quả tương lai. Lưới tham số 69, 345, 1,035 và 4,140 ô là lưới giả định dựng ra để đếm số bậc tự do. Xác suất trong biểu đồ là phép tính thuần tuý trên một giả định được nêu rõ, không phải một đại lượng đo được. Quy tắc về biên độ, bước giá và chu kỳ thanh toán trích từ quy định hiện hành của HOSE, HNX và VSDC.

Câu hỏi thường gặp

Overfit trong tối ưu tham số nghĩa là gì?

Nghĩa là phần lớn ưu thế mà một bộ tham số thể hiện trên đoạn dữ liệu dùng để chọn nó đến từ những chi tiết không lặp lại ở đoạn dữ liệu khác. Nó không phải chuyện mô hình quá phức tạp hay quá nhiều dòng lệnh. Một quy tắc chỉ có hai tham số vẫn overfit được, nếu hai tham số đó được chọn bằng cách thử hàng nghìn cặp rồi giữ cặp cho kết quả cao nhất.

Vì sao phép tối ưu luôn trả về một bộ tham số trông đẹp?

Vì nó lấy giá trị lớn nhất. Lấy giá trị lớn nhất của một tập số thì luôn ra một con số, và con số đó luôn cao hơn trung vị của chính tập ấy, kể cả khi mọi phần tử trong tập đều sinh ra hoàn toàn ngẫu nhiên. Phép tối ưu không có cơ chế nào để trả lời rằng không bộ nào dùng được, nên sự tồn tại của một bộ đứng đầu bảng không phải bằng chứng về bất cứ điều gì.

Vì sao dữ liệu chuỗi thời gian không được chia ngẫu nhiên thành tập huấn luyện và tập kiểm tra?

Có bốn lý do chồng lên nhau. Chỉ báo tại một phiên được tính từ n phiên liền trước nên nếu phiên đó rơi vào tập kiểm tra còn n phiên trước nó nằm trong tập huấn luyện thì giá trị kiểm tra được dựng từ chính dữ liệu huấn luyện. Các phiên liền nhau không độc lập. Các chế độ thị trường đi thành khối nên trộn ngẫu nhiên sẽ rải mỗi chế độ sang cả hai phía. Và câu hỏi thật luôn là quy tắc có sống được sang một quãng thời gian chưa từng thấy hay không, mà phép chia ngẫu nhiên thì không hỏi câu đó.

Đọc phân bố kết quả của toàn bộ các bộ tham số để làm gì?

Để biết bộ đứng đầu cách phần còn lại bao xa. Nếu bộ tốt nhất chỉ nhỉnh hơn trung vị một chút so với độ phân tán của chính phân bố ấy thì nó nhiều khả năng chỉ là đỉnh của nhiễu. Nếu nó tách hẳn ra và vùng tham số quanh nó cũng cho kết quả tương tự thì tình huống khác, tuy vẫn chưa phải bằng chứng. Phép đọc này chỉ có thể hạ độ tin cậy xuống, không bao giờ nâng một kết quả trong mẫu lên thành bằng chứng.

Kỳ dữ liệu ngoài mẫu dùng được mấy lần?

Đúng một lần. Ngay khi đã nhìn kết quả ngoài mẫu rồi quay lại sửa quy tắc hoặc đổi lưới tham số, đoạn dữ liệu đó đã tham gia vào việc chọn và nó trở thành dữ liệu trong mẫu. Lần chạy thứ hai trên cùng đoạn ấy không còn là kiểm chứng độc lập nữa, dù không ai sửa dòng lệnh nào.

Cập nhật lần cuối:

Đọc tiếp

Nội dung trong bài mang tính chia sẻ kiến thức, không phải khuyến nghị mua bán. Mọi quyết định đầu tư và rủi ro đi kèm thuộc về người đọc.