Overfitting và rủi ro tối ưu hóa quá mức trong xây dựng chiến lược giao dịch
Overfitting
Trong xây dựng chiến lược giao dịch, có một cái bẫy rất dễ gặp: backtest càng đẹp thì mình càng tin là chiến lược tốt. Đường lợi nhuận đi lên mượt, drawdown thấp, tỷ lệ thắng cao, lệnh thua ít, tham số nhìn có vẻ “chuẩn”. Nhưng đôi khi chiến lược đó không thật sự có lợi thế trên thị trường. Nó chỉ đang được chỉnh quá khớp với dữ liệu quá khứ. Đây chính là overfitting, hay trong trading thường gọi là tối ưu hóa quá mức.
Overfitting xảy ra khi một chiến lược học quá kỹ những đặc điểm ngẫu nhiên trong dữ liệu cũ, đến mức nó hoạt động rất tốt trên backtest nhưng lại kém khi gặp dữ liệu mới. Nói dễ hiểu hơn, thay vì học được quy luật thật của thị trường, chiến lược lại học thuộc lòng quá khứ. Nó nhớ quá kỹ từng đoạn tăng, từng đoạn giảm, từng nhiễu nhỏ, từng vùng giá đã xảy ra, rồi tạo ra một bộ điều kiện nhìn rất hay trong quá khứ nhưng không còn dùng được ngoài đời.

Backtest đẹp chưa chắc là chiến lược tốt
Một chiến lược giao dịch có thể bắt đầu rất đơn giản. Ví dụ mua khi giá vượt MA50, RSI trên 50, thanh khoản tăng hơn trung bình 20 phiên, và bán khi giá thủng MA20. Ban đầu chạy backtest thấy kết quả bình thường. Sau đó mình bắt đầu chỉnh: MA50 đổi thành MA47, RSI 50 đổi thành 53, thanh khoản tăng 1,5 lần đổi thành 1,72 lần, stoploss 7% đổi thành 6,3%, chốt lời 18% đổi thành 21%, thời gian nắm giữ 20 phiên đổi thành 17 phiên. Sau rất nhiều lần thử, cuối cùng tìm được bộ tham số cho kết quả rất đẹp.
Vấn đề là bộ tham số đó có thể đẹp không phải vì nó phản ánh một logic thị trường bền vững, mà vì nó vô tình khớp với dữ liệu đã xảy ra. Trong quá khứ, MA47 có thể tốt hơn MA50 chỉ vì một vài giao dịch. RSI 53 có thể tốt hơn RSI 50 chỉ vì tránh được vài lệnh thua cũ. Stoploss 6,3% có thể đẹp hơn 7% chỉ vì trong giai đoạn backtest có một số mã giảm đúng quanh vùng đó rồi hồi lại. Nhưng tương lai không có nghĩa vụ phải lặp lại đúng những con số này.
Đây là điểm nguy hiểm của overfitting. Nó không tạo ra một chiến lược nhìn tệ. Ngược lại, nó tạo ra một chiến lược nhìn rất thuyết phục. Chính vì nhìn quá đẹp nên người dùng càng dễ tin.
Tối ưu tham số không sai, sai là tối ưu đến mức mất ý nghĩa
Tối ưu tham số không phải lúc nào cũng xấu. Trong thực tế, mình vẫn cần kiểm tra xem chiến lược nhạy với tham số nào, vùng tham số nào hợp lý, stoploss bao nhiêu thì phù hợp với độ biến động của thị trường, thời gian nắm giữ bao lâu thì logic còn hiệu quả. Vấn đề nằm ở việc tối ưu quá kỹ để lấy kết quả đẹp nhất trong quá khứ.
Một chiến lược tốt thường không chỉ sống được tại một bộ tham số duy nhất. Nếu MA50 hoạt động tốt, thì MA45, MA55, MA60 cũng nên cho kết quả tương đối ổn. Nếu stoploss 7% là hợp lý, thì stoploss 6% hoặc 8% không nên làm chiến lược sụp hoàn toàn. Nếu chỉ cần thay tham số một chút mà kết quả từ rất đẹp chuyển sang rất tệ, đó là dấu hiệu chiến lược có thể đang bị fit quá mức.
Trong thực tế, nên nhìn vùng tham số thay vì nhìn một điểm tham số. Một hệ thống momentum nếu chỉ thắng khi dùng MA47 và RSI 53, nhưng thua khi dùng MA50 và RSI 55, thì rất đáng nghi. Còn nếu hệ thống hoạt động ổn trong một vùng rộng, ví dụ MA40–MA70, RSI 45–60, holding period 15–30 phiên, thì logic có thể đáng tin hơn. Thị trường thật luôn nhiễu, nên một chiến lược quá mong manh với tham số thường khó sống lâu.
Một ví dụ rất thực tế về overfitting
Giả sử mình có dữ liệu 5 năm của thị trường chứng khoán và muốn xây một chiến lược chọn cổ phiếu mạnh. Ban đầu mình định nghĩa đơn giản: chọn những cổ phiếu có lợi nhuận 60 phiên tốt hơn VN-Index, thanh khoản bình quân trên 20 tỷ/ngày, giá nằm trên MA50, sau đó nắm giữ 20 phiên. Kết quả backtest có lãi nhưng không quá ấn tượng.
Sau đó mình bắt đầu thêm điều kiện. Chỉ mua nếu RSI nằm trong khoảng 48–67. Chỉ mua nếu volume hôm nay lớn hơn 1,8 lần trung bình 17 phiên. Chỉ mua nếu giá cách đỉnh 52 tuần dưới 12%. Chỉ loại cổ phiếu nếu ATR lớn hơn 4,6%. Chỉ mua vào thứ Ba hoặc thứ Tư. Chỉ giữ đúng 13 phiên. Sau hàng trăm lần thử, backtest trở nên rất đẹp.
Nhưng nếu hỏi tại sao RSI phải là 48–67 chứ không phải 45–70, tại sao volume là 1,8 lần trung bình 17 phiên chứ không phải 2 lần trung bình 20 phiên, tại sao giữ 13 phiên chứ không phải 15 hoặc 20 phiên, thì rất khó trả lời bằng logic đầu tư. Khi một chiến lược có quá nhiều điều kiện quá cụ thể nhưng thiếu lý do kinh tế rõ ràng, đó là dấu hiệu rất mạnh của overfitting.
Nhiều khi những điều kiện đó chỉ giúp chiến lược né một vài lệnh thua trong quá khứ. Nhưng khi sang giai đoạn mới, thị trường không còn đi theo đúng cấu trúc cũ, bộ điều kiện tinh chỉnh quá mức sẽ mất tác dụng. Lúc đó nhà đầu tư mới nhận ra backtest đẹp không phải vì chiến lược mạnh, mà vì nó đã được “may đo” cho dữ liệu cũ.
Overfitting thường đến từ đâu?
Nguyên nhân đầu tiên là thử quá nhiều ý tưởng trên cùng một bộ dữ liệu. Nếu mình thử 100 chiến lược khác nhau, kiểu gì cũng có vài chiến lược thắng rất đẹp chỉ do may mắn. Đây là vấn đề data mining. Trong tài chính, dữ liệu thị trường rất nhiễu, nên nếu đào đủ lâu, mình sẽ tìm thấy một pattern nào đó nhìn có vẻ có ý nghĩa. Nhưng pattern đó có thể chỉ là ngẫu nhiên.
Nguyên nhân thứ hai là dùng quá nhiều tham số. Một chiến lược càng nhiều điều kiện, càng nhiều ngưỡng, càng nhiều bộ lọc, càng dễ khớp với quá khứ. Không phải cứ đơn giản là tốt, nhưng phức tạp mà không có logic rõ ràng thì rất nguy hiểm. Một hệ thống có 3–5 biến quan trọng, mỗi biến có lý do kinh tế, thường đáng tin hơn một hệ thống có 20 điều kiện nhưng chủ yếu được thêm vào để làm backtest đẹp hơn.
Nguyên nhân thứ ba là tối ưu dựa trên chỉ một giai đoạn thị trường. Ví dụ một chiến lược được xây trong giai đoạn thị trường tăng mạnh, thanh khoản dồi dào, cổ phiếu midcap/smallcap chạy tốt. Backtest đẹp trong giai đoạn đó không có nghĩa nó sẽ sống được khi thị trường đi ngang, thanh khoản giảm, dòng tiền co lại hoặc chỉ số bị kéo bởi vài trụ lớn. Nếu dữ liệu huấn luyện chỉ đại diện cho một môi trường thị trường, chiến lược dễ bị overfit vào môi trường đó.
Nguyên nhân thứ tư là bỏ qua chi phí giao dịch, trượt giá và thanh khoản. Một chiến lược tối ưu quá mức thường hay tăng số lần giao dịch để bắt nhiều nhịp nhỏ. Trên backtest, mỗi nhịp nhỏ đều có vẻ kiếm được tiền. Nhưng ngoài đời, phí, thuế, spread, trượt giá và khả năng khớp lệnh có thể ăn hết lợi nhuận. Khi thêm chi phí thật vào, chiến lược đẹp có thể trở nên rất bình thường.
Nguyên nhân thứ năm là dùng dữ liệu chưa sạch hoặc có bias. Nếu dữ liệu có look-ahead bias, survivorship bias, lỗi giá, lỗi volume, corporate actions chưa xử lý, thì quá trình tối ưu sẽ càng nguy hiểm. Vì mô hình không chỉ overfit với quá khứ, mà còn overfit với cả lỗi dữ liệu.
Vì sao overfitting đặc biệt nguy hiểm trong tài chính?
Trong nhiều lĩnh vực khác, dữ liệu có thể ổn định hơn. Nhưng thị trường tài chính luôn thay đổi. Hành vi nhà đầu tư thay đổi, thanh khoản thay đổi, lãi suất thay đổi, chính sách thay đổi, cấu trúc ngành thay đổi, mức độ tham gia của nhà đầu tư cá nhân/tổ chức thay đổi. Một quy luật từng hiệu quả trong giai đoạn này có thể yếu đi hoặc biến mất trong giai đoạn khác.
Thêm nữa, thị trường có rất nhiều nhiễu. Một cổ phiếu có thể tăng không phải vì tín hiệu kỹ thuật, mà vì tin đồn, kỳ vọng kết quả kinh doanh, dòng tiền ngành, quỹ cơ cấu, khối ngoại mua, hoặc đơn giản là tâm lý thị trường. Nếu chiến lược quá cố gắng giải thích từng biến động trong quá khứ, nó sẽ học cả những thứ không lặp lại.
Điểm nguy hiểm nhất là overfitting tạo ra sự tự tin giả. Nhà đầu tư nhìn backtest đẹp thì dễ tăng vốn, dùng margin, bỏ qua stoploss hoặc tin rằng hệ thống đã được kiểm chứng. Nhưng khi ra thị trường thật, hệ thống bắt đầu thua, nhà đầu tư lại nghĩ đó chỉ là giai đoạn drawdown bình thường. Càng tin vào backtest quá khớp, mình càng chậm nhận ra hệ thống không còn hiệu quả.
Out-of-sample test: kiểm tra ngoài dữ liệu tối ưu
Một trong những cách cơ bản nhất để giảm rủi ro overfitting là chia dữ liệu thành hai phần: in-sample và out-of-sample. In-sample là phần dùng để xây và tối ưu chiến lược. Out-of-sample là phần giữ lại để kiểm tra sau khi chiến lược đã hoàn thiện. Chiến lược không được “nhìn” vào dữ liệu out-of-sample trong quá trình thiết kế.
Ví dụ có dữ liệu từ 2016 đến 2025. Mình có thể dùng 2016–2021 để xây chiến lược, sau đó kiểm tra trên 2022–2025. Nếu chiến lược rất đẹp trong 2016–2021 nhưng sụp hoàn toàn trong 2022–2025, khả năng cao nó đã bị overfit. Nếu kết quả giảm đi nhưng vẫn còn hợp lý, drawdown vẫn chịu được, logic vẫn hoạt động, thì chiến lược đáng nghiên cứu tiếp.
Nhưng out-of-sample cũng phải dùng đúng. Nếu sau khi thấy kết quả out-of-sample xấu, mình lại quay về chỉnh tham số để làm đẹp cả out-of-sample, thì phần kiểm tra này đã bị “nhiễm bẩn”. Lúc đó out-of-sample không còn là dữ liệu ngoài mẫu nữa, mà trở thành một phần của quá trình tối ưu. Đây là lỗi rất thường gặp: người xây chiến lược nói có test ngoài mẫu, nhưng thực tế đã nhìn kết quả ngoài mẫu nhiều lần rồi chỉnh hệ thống theo nó.
Walk-forward test: người xây chiến lược nói có test ngoài mẫu, nhưng thực tế đã nhìn thực tế hơn một lần chia dữ liệu
Một phương pháp thực tế hơn là walk-forward testing. Thay vì chia dữ liệu một lần, mình mô phỏng quá trình ra quyết định theo thời gian. Ví dụ dùng dữ liệu 2016–2018 để tối ưu, giao dịch giả lập năm 2019; sau đó dùng 2017–2019 để tối ưu, giao dịch giả lập năm 2020; tiếp tục như vậy cho các năm sau.
Cách này gần với thực tế hơn, vì ngoài đời mình luôn dùng dữ liệu quá khứ để ra quyết định cho tương lai. Walk-forward giúp kiểm tra xem chiến lược có thích nghi được qua nhiều giai đoạn thị trường hay không. Một chiến lược tốt không cần năm nào cũng thắng, nhưng không nên chỉ sống được trong một giai đoạn duy nhất.
Walk-forward cũng giúp phát hiện tham số có ổn định không. Nếu mỗi lần tối ưu lại, tham số nhảy lung tung, lúc MA20, lúc MA100, lúc stoploss 3%, lúc stoploss 15%, thì có thể chiến lược không có cấu trúc ổn định. Ngược lại, nếu tham số tối ưu thay đổi trong một vùng hợp lý, đó là dấu hiệu tốt hơn.
Kiểm tra độ bền của tham số
Một chiến lược không nên phụ thuộc vào một con số quá chính xác. Vì vậy, cần kiểm tra độ bền của tham số. Thay vì chỉ báo cáo “tham số tốt nhất”, nên xem cả vùng xung quanh tham số đó.
Ví dụ chiến lược tốt nhất dùng MA50. Hãy kiểm tra MA40, MA45, MA55, MA60. Nếu kết quả vẫn ổn, chiến lược có thể đang bắt được logic momentum thật. Nếu chỉ MA50 thắng còn MA49 và MA51 thua nặng, đó là dấu hiệu quá khớp.
Tương tự với stoploss. Nếu stoploss 7% cho kết quả xuất sắc, nhưng 6% hoặc 8% làm chiến lược mất lợi nhuận, cần nghi ngờ. Thị trường không chính xác đến mức chỉ tôn trọng đúng 7%. Một chiến lược tốt thường có “vùng chịu đựng” nhất định với sai số tham số.
Có thể hiểu đơn giản: chiến lược tốt giống một cây cầu chắc, đi lệch một chút vẫn không rơi. Chiến lược overfit giống một sợi dây căng, chỉ cần lệch nhẹ là đứt.
Nên ưu tiên logic kinh tế hơn là kết quả tối ưu
Một cách rất tốt để chống overfitting là luôn hỏi: vì sao tín hiệu này có thể tạo ra lợi thế? Nếu không trả lời được bằng logic thị trường, đừng vội tin dù backtest đẹp.
Ví dụ momentum có logic: cổ phiếu mạnh có thể tiếp tục mạnh vì dòng tiền, kỳ vọng, quỹ mua vào, tâm lý đám đông và sự điều chỉnh chậm của thị trường với thông tin mới. Value có logic: tài sản bị định giá thấp có thể được thị trường định giá lại khi kỳ vọng thay đổi. Quality có logic: doanh nghiệp có ROE/ROIC cao, dòng tiền tốt, lợi thế cạnh tranh bền có thể tạo giá trị dài hạn. Low volatility có logic: nhà đầu tư thường trả giá quá cao cho cổ phiếu “hấp dẫn” và bỏ qua cổ phiếu ổn định.
Nhưng nếu một chiến lược nói rằng mua cổ phiếu khi RSI nằm từ 51,7 đến 54,2, volume lớn hơn 1,63 lần trung bình 18 phiên, và chỉ mua vào thứ Tư vì backtest đẹp nhất, thì cần hỏi logic nằm ở đâu. Không phải những điều kiện đó chắc chắn sai, nhưng nếu không có lý do thuyết phục, khả năng cao chúng chỉ đang fit quá khứ.
Backtest nên là công cụ kiểm chứng logic, không phải công cụ đào ngẫu nhiên để tìm kết quả đẹp.
Đơn giản không có nghĩa là kém
Nhiều người nghĩ chiến lược càng phức tạp càng chuyên nghiệp. Nhưng trong trading, phức tạp không đồng nghĩa với tốt hơn. Một hệ thống đơn giản nhưng có logic rõ, dữ liệu sạch, chi phí thực tế, kiểm tra ngoài mẫu ổn, đôi khi đáng tin hơn một mô hình nhiều lớp nhưng không giải thích được vì sao thắng.
Đơn giản cũng giúp dễ kiểm soát rủi ro. Khi chiến lược thua, mình biết nó thua vì yếu tố nào: momentum yếu, thị trường không có xu hướng, thanh khoản giảm, tín hiệu nhiễu hay chi phí cao. Còn một hệ thống quá phức tạp có thể rất khó hiểu. Khi nó thua, mình không biết nên sửa ở đâu, giữ tiếp hay dừng lại.
Điều này không có nghĩa Machine Learning hay mô hình phức tạp là vô dụng. Nhưng nếu dùng mô hình phức tạp, càng phải kiểm soát overfitting chặt hơn. Mô hình càng mạnh càng dễ học nhiễu nếu dữ liệu ít, feature nhiều, nhãn nhiễu và quá trình kiểm định không nghiêm túc.
Tối ưu quá nhiều chỉ tiêu cũng là một dạng overfitting
Một lỗi khác là tối ưu nhiều chỉ tiêu cùng lúc đến mức chiến lược trở nên “đẹp toàn diện” trên quá khứ. Vừa muốn CAGR cao nhất, Sharpe cao nhất, drawdown thấp nhất, win rate cao nhất, profit factor đẹp nhất, số lệnh đủ nhiều, thời gian hồi phục vốn ngắn nhất. Sau đó liên tục chỉnh điều kiện để mọi chỉ tiêu đều đẹp.
Nhưng ngoài đời, chiến lược nào cũng có đánh đổi. Chiến lược trend following thường có nhiều lệnh sai nhỏ và cần chịu drawdown. Chiến lược mean reversion có thể tỷ lệ thắng cao nhưng dễ gặp lỗ lớn khi thị trường gãy cấu trúc. Chiến lược momentum có thể tốt khi thị trường có dòng tiền nhưng kém khi thị trường đi ngang. Nếu một chiến lược trên backtest đẹp ở mọi góc độ, không có nhược điểm rõ ràng, đôi khi càng phải nghi ngờ.
Một hệ thống đáng tin thường có điểm mạnh và điểm yếu có thể giải thích được. Biết chiến lược kiếm tiền trong môi trường nào và mất tiền trong môi trường nào quan trọng hơn việc làm cho nó trông hoàn hảo trên dữ liệu cũ.
Cách giảm rủi ro overfitting khi xây chiến lược
Cách đầu tiên là giới hạn số lượng tham số. Mỗi điều kiện thêm vào phải có lý do rõ ràng. Nếu một bộ lọc chỉ được thêm vì nó làm backtest đẹp hơn nhưng không có logic, nên cân nhắc bỏ. Ít tham số hơn không đảm bảo thành công, nhưng giúp giảm nguy cơ chiến lược học thuộc quá khứ.
Cách thứ hai là chia dữ liệu theo thời gian và kiểm tra ngoài mẫu. Không trộn dữ liệu tương lai vào quá khứ. Không dùng random split như nhiều bài toán Machine Learning thông thường, vì dữ liệu tài chính có tính thời gian. Mình luôn phải mô phỏng đúng thực tế: dùng quá khứ để quyết định tương lai.
Cách thứ ba là kiểm tra độ nhạy tham số. Đừng chỉ nhìn bộ tốt nhất. Hãy nhìn vùng tham số xung quanh. Nếu chiến lược chỉ sống ở một điểm cực hẹp, rủi ro rất cao.
Cách thứ tư là thêm chi phí giao dịch, thuế, spread, slippage và giới hạn thanh khoản ngay từ đầu. Đừng để đến khi chiến lược đẹp rồi mới thêm chi phí, vì lúc đó mình rất dễ tiếc kết quả cũ và tìm cách hợp lý hóa.
Cách thứ năm là kiểm tra theo nhiều giai đoạn thị trường. Chiến lược hoạt động ra sao trong uptrend, downtrend, sideways, giai đoạn thanh khoản cao, giai đoạn thanh khoản thấp, giai đoạn thị trường bị kéo bởi trụ, giai đoạn midcap/smallcap dẫn dắt? Nếu chỉ thắng trong một môi trường duy nhất, cần biết rõ điều đó trước khi dùng.
Cách thứ sáu là paper trading hoặc chạy vốn nhỏ. Một chiến lược sau khi qua backtest và out-of-sample vẫn nên được forward test. Khi chạy thật với vốn nhỏ, nhiều vấn đề mới lộ ra: tín hiệu đến chậm, khó khớp lệnh, spread rộng, tâm lý không chịu được drawdown, dữ liệu cập nhật không ổn định, hoặc chiến lược giao dịch quá nhiều so với khả năng theo dõi.
Overfitting không chỉ xảy ra với hệ thống định lượng
Nhiều người nghĩ overfitting chỉ liên quan đến code, backtest hoặc Machine Learning. Thực ra nhà đầu tư phân tích thủ công cũng có thể bị overfit trong tư duy. Ví dụ nhìn lại một cổ phiếu đã tăng mạnh, rồi tìm ra rất nhiều lý do để giải thích vì sao “đáng lẽ phải mua”: chart đẹp, EPS tăng, ngành tốt, lãnh đạo mua vào, thanh khoản tăng, câu chuyện vĩ mô ủng hộ. Nhưng đó là phân tích sau khi kết quả đã xảy ra.
Nếu lấy quá khứ đã biết kết quả rồi chỉnh lại bộ tiêu chí để giải thích đúng cổ phiếu thắng, mình cũng đang overfit. Lần sau áp dụng bộ tiêu chí đó vào cổ phiếu mới chưa chắc hiệu quả. Đây là dạng overfitting rất đời thường: học nhầm bài học từ những ví dụ đã thành công, nhưng bỏ qua rất nhiều ví dụ có tín hiệu tương tự mà không tăng.
Vì vậy, dù dùng mô hình hay phân tích thủ công, vẫn cần tư duy kiểm định. Tiêu chí mua cổ phiếu có hoạt động trên nhiều trường hợp không? Có bao nhiêu mã thỏa điều kiện nhưng thất bại? Mình có đang chỉ nhìn người sống sót không? Có đang giải thích quá khứ quá hay nhưng không kiểm tra được tương lai không?
Kết luận
Overfitting là một trong những rủi ro lớn nhất khi xây dựng chiến lược giao dịch. Nó làm cho một hệ thống nhìn rất tốt trên quá khứ nhưng lại kém trong thực tế. Nguy hiểm hơn, nó tạo ra sự tự tin giả, khiến nhà đầu tư dễ tăng vốn, dùng margin hoặc bỏ qua rủi ro vì tin rằng chiến lược đã được kiểm chứng.
Một chiến lược đáng tin không phải là chiến lược có backtest đẹp nhất, mà là chiến lược có logic rõ ràng, dữ liệu sạch, ít phụ thuộc vào tham số quá cụ thể, chịu được kiểm tra ngoài mẫu, hoạt động ổn qua nhiều giai đoạn thị trường, và vẫn hợp lý sau khi tính chi phí giao dịch, thanh khoản và trượt giá.
Trong trading, mục tiêu không phải là tìm một bộ tham số hoàn hảo cho quá khứ. Mục tiêu là tìm một logic đủ bền để có cơ hội sống trong tương lai. Backtest chỉ là bước kiểm tra, không phải bằng chứng tuyệt đối. Nếu càng tối ưu thì chiến lược càng đẹp nhưng càng khó giải thích, đó không phải dấu hiệu chắc chắn của một edge mạnh. Đó có thể là dấu hiệu mình đang fit quá khứ quá kỹ.
