Mục lục
Trả lời ngắn: Recovery System trong EA là bộ điều phối đưa trạng thái vận hành từ mơ hồ về biết được sau khớp một phần, hết thời gian chờ (timeout), mất kết nối hoặc khởi động lại. Nó đối chiếu bằng chứng, giới hạn hành động và xác minh kết quả; không phải cơ chế mở thêm lệnh để gỡ lỗ.
Đọc xong, bạn sẽ hiểu: phục hồi vận hành khác chiến lược gỡ lỗ; vì sao phải đối chiếu trước khi thử lại; cách giữ khóa/ngân sách qua khởi động lại; và lúc phải chuyển cho người xử lý.
Lưu ý giáo dục: R17 và mọi đơn vị trong bài là dữ liệu giả để học kiến trúc, không phải công thức giao dịch hoặc lời khuyên đầu tư.
1. Recovery là phục hồi trạng thái, không đuổi theo khoản lỗ
a. Hai nghĩa không được trộn
Phục hồi trạng thái vận hành (operational recovery) là đưa EA từ trạng thái chưa rõ về một trạng thái có bằng chứng và người chịu trách nhiệm. Chiến lược gỡ lỗ lại tăng hoặc đổi phơi nhiễm với hy vọng bù khoản lỗ. Bài này chỉ nói nghĩa đầu.
Recovery không làm thời gian quay lại. Lần khớp đã xảy ra vẫn tồn tại; phí và trượt giá cũng vậy. Hành động sửa sau đó là một giao dịch mới với rủi ro riêng, không phải nút “undo”. Vì thế Martingale, mở rộng Grid, tăng DCA, khóa lỗ bằng Hedging hay thử lại vô hạn đều nằm ngoài phạm vi.
Hình dung bếp nhận đơn 10 món, đã giao 6 rồi mất phiếu. Việc đúng đầu tiên là đếm trên bàn còn thiếu 4, không nấu lại cả 10. Trong EA, con số “đã yêu cầu 10” không quan trọng bằng bằng chứng “đã khớp 6, còn 4”.
b. Khởi động lại là ranh giới sự cố
Sự cố (incident) là lúc trạng thái dự kiến và trạng thái quan sát không còn khớp hoặc không đủ bằng chứng để so. Terminal đóng, EA biên dịch lại, đổi tài khoản hay đổi tham số đều có thể làm chương trình được khởi tạo lại; OnDeinit() cung cấp mã lý do cho các trường hợp này. MQL5 OnDeinit
Sau khởi động lại, EA không được tiếp tục từ biến bộ nhớ như chưa có gì xảy ra. Nó phải nạp nhật ký bền, đọc tài khoản rồi đối chiếu. Biến toàn cục của terminal có thể lưu số qua phiên nhưng dùng chung; tên khóa phải gắn tài khoản, EA, mã giao dịch và phiên chạy. MQL5 GlobalVariableSet
2. Recovery Controller và demo R17
a. Từ ảnh sự cố đến trạng thái kết thúc
Luồng tối giản:
INCIDENT SNAPSHOT → EXPECTED/OBSERVED DIFF → RECONCILE → CLASSIFY → BOUNDED PLAN → UNIQUE RECOVERY INTENT → REQUEST → VERIFY → TERMINAL STATE
Trạng thái dự kiến (expected state) là điều sổ nói phải tồn tại. Trạng thái quan sát (observed state) là bằng chứng mới từ vị thế, lệnh đang hoạt động và lịch sử. Đối chiếu (reconciliation) là so hai phía trước mọi hành động.
PositionGetTicket() duyệt vị thế, nhưng tài liệu khuyên chọn lại ngay trước khi đọc để lấy dữ liệu mới. POSITION_IDENTIFIER giúp liên kết vòng đời; POSITION_VOLUME cho biết khối lượng hiện tại. MQL5 PositionGetTicket, MQL5 Position properties
Hình 1 — Recovery chỉ được hành động sau khi chênh lệch đã có bằng chứng và ngân sách còn cho phép.
b. R17: đã đóng 6, không được gửi lại 10
R17 bắt đầu với vị thế P17 đã xác nhận 10 U. Ý định đóng có khóa R17:P17:CLOSE:v1, yêu cầu 10 U, nhưng chỉ 6 U được xác nhận đóng. Sau đó terminal khởi động lại.
Ledger dự kiến khối lượng mở là 0 U; tài khoản thực tế còn 4 U. Chênh lệch là thực thi một phần (partial execution). Recovery chỉ được lập kế hoạch cho phần dư 4 U, không gửi lại toàn bộ 10 U.
| Step | Expected open | Observed open | Confirmed close | Budget | State |
|---|---|---|---|---|---|
| I0 | 0 U |
4 U |
6/10 U |
1 |
INCIDENT_DETECTED |
| R0 | 0 U |
4 U |
6/10 U |
1 |
RECONCILING |
| R1 | 0 U |
4 U |
6/10 U |
0 |
MANUAL_REVIEW_HALT |
Hàng khởi động lại nạp khóa v1, đọc vị thế, lệnh và lịch sử; nó không tạo yêu cầu mới. HistorySelect() lấy danh sách lệnh/lần khớp trong khoảng thời gian máy chủ để đối chiếu. MQL5 HistorySelect
Hình 2 — Phần đã khớp sáu đơn vị buộc recovery chỉ xử lý phần dư bốn đơn vị.
c. Timeout chưa nói thành công hay thất bại
Kế hoạch cho phép đúng một lần thử lại, với khóa mới R17:P17:CLOSE:v2 và lượng 4 U. Yêu cầu v2 hết thời gian chờ. Mã TRADE_RETCODE_TIMEOUT nói yêu cầu bị hủy theo timeout; vẫn phải kiểm tra sự kiện giao dịch, lệnh đang hoạt động, lịch sử và vị thế. MQL5 trade return codes
Sau đối chiếu đầy đủ, R17 không có lần đóng mới, không có lệnh đóng còn hoạt động và vị thế vẫn 4 U. Ngân sách từ 1 về 0, nên kết quả là MANUAL_REVIEW_HALT. Callback v2 lặp dùng cùng khóa, tạo zero yêu cầu thừa.
Hình 3 — Hết ngân sách mà phần dư còn tồn tại phải chuyển chủ cho manual review.
3. Chín lỗi và giới hạn
a. Lỗi làm recovery thành vòng lặp nguy hiểm
- Recovery = gỡ lỗ: biến kiểm soát sự cố thành tăng phơi nhiễm.
- Gửi lại cả lượng gốc: bỏ qua phần
6 Uđã khớp. - Timeout = thất bại: thử lại trước khi đối chiếu.
OrderSend=true= đã khớp: nhầm qua kiểm tra cấu trúc với thực thi.- Khởi động lại xóa trí nhớ: đặt lại khóa và ngân sách.
- Một quy tắc cho mọi lỗi: thị trường đóng và khối lượng sai bị xử lý giống nhau.
- Hành động bù = quay lui: che rủi ro của giao dịch mới.
- Bỏ can thiệp ngoài luồng: không phát hiện đóng tay, đổi tài khoản hoặc thiếu lịch sử.
- Còn chênh lệch vẫn RECOVERED: báo xanh khi phần dư còn mở.
OrderSend() trả true không chứng minh giao dịch đã thực thi; phải kiểm mã trả về và theo dõi sự kiện. Một yêu cầu có thể sinh nhiều transaction, và thứ tự chúng tới terminal không được đảm bảo. MQL5 OrderSend, MQL5 OnTradeTransaction
b. Phân loại trước khi hành động
Phân loại sự cố (classification) gắn bằng chứng với quy tắc của dự án:
WAIT_CONDITION: thị trường đóng, thiếu báo giá hoặc mất kết nối;REPLAN_ALLOWED: giá đổi/báo giá lại, nhưng chỉ sau ảnh chụp mới và còn ngân sách;HALT_CONFIG: khối lượng, mức dừng, kiểu khớp hoặc lệnh không hợp lệ;HALT_RISK: thiếu tiền, chạm giới hạn, vị thế đóng băng hoặc giao dịch bị tắt;RECONCILE_FIRST: timeout, đã đặt, khớp một phần, vị thế đã đóng hoặc có lệnh đóng.
Đây không phải bảng thử lại chung cho mọi nhà môi giới. Khoảng trống giá, trượt giá, phí, thanh khoản, quyền tài khoản và lịch sử thiếu vẫn có thể làm recovery dừng. Khi không chắc, câu trả lời đúng là UNKNOWN/HALT.
4. Recovery Contract trước khi viết code
a. Hai mươi câu hỏi
- ID/phiên bản sự cố? 2. Ai sở hữu? 3. Phạm vi nào? 4. Dự kiến lấy từ đâu?
- Quan sát lấy từ đâu? 6. ID ổn định nào? 7. Ảnh chụp lúc nào? 8. Ý định nào đã lưu?
- Lý do khởi động lại? 10. Mã trả về thuộc lớp nào? 11. Hành động nào được phép? 12. Hành động nào cấm?
- Ngân sách thử lại? 14. Điều kiện chờ? 15. Khóa duy nhất? 16. Khớp một phần xử lý ra sao?
- Có lệnh hoạt động không? 18. Điều bất biến xác minh là gì? 19. Trạng thái kết thúc? 20. Bàn giao/công tắc dừng ở đâu?
b. Trình tự fail-closed
Đóng băng ý định mới → nạp nhật ký → chọn lại vị thế → đọc lệnh/lịch sử → tính chênh lệch → phân loại → kiểm ngân sách/rủi ro → tạo khóa → gửi yêu cầu → nhận sự kiện → xác minh.
Chủ sở hữu mơ hồ, lịch sử thiếu, ảnh chụp cũ, tài khoản không khớp hoặc nhật ký không tin được đều trả UNKNOWN/HALT. Can thiệp tay phải được ghi như sự kiện mới; EA không tự nhận đó là kết quả recovery.
5. Recovery Ledger 15 phút
a. Cách làm
Dùng giấy hoặc Google Sheets; chưa mở MT5, kết nối tài khoản hay dùng tiền thật. Điền R17, tính phần dư 10 − 6 = 4 U, giữ ngân sách qua khởi động lại, rồi mô phỏng v2 timeout.
b. Mẫu đối chiếu
| Key | Event | Evidence | Extra request |
|---|---|---|---|
R17:P17:CLOSE:v1 |
partial | close 6 U, residual 4 U |
0 |
| restart | load + reconcile | residual 4 U |
0 |
R17:P17:CLOSE:v2 |
timeout | no close, no active order, residual 4 U |
1 |
| duplicate v2 | callback repeat | same key | 0 |
Kết quả phải là MANUAL_REVIEW_HALT: quan sát vẫn 4 U, ngân sách 0. Nếu gửi lại 10 U, đặt lại ngân sách khi khởi động lại hoặc đánh dấu RECOVERED, hãy quay lại mục 2.
6. Tổng kết: đối chiếu trước, hành động hữu hạn
a. Năm ý chính
- Recovery phục hồi trạng thái vận hành, không bảo đảm gỡ lỗ.
- Khớp một phần, timeout và khởi động lại đều cần đối chiếu.
- Khóa và ngân sách thử lại phải sống qua lần khởi tạo lại.
- Mỗi hành động cần bằng chứng hậu trạng thái.
- Hết ngân sách hoặc thiếu dữ liệu thì
MANUAL_REVIEW_HALT/UNKNOWN.
Bài trước là Basket Trading trong EA. Bài tiếp theo là Adaptive Position Sizing trong EA #18.
b. Câu hỏi tự kiểm tra
- Vì sao R17 chỉ được xử lý
4 U, không phải10 U? - Restart có được tạo ngay yêu cầu mới không?
- Timeout đã đủ kết luận thất bại chưa?
- Vì sao ngân sách
0dẫn tớiMANUAL_REVIEW_HALT?
c. Gợi ý đáp án
Xem gợi ý câu 1
Đã có bằng chứng đóng 6/10 U, nên chỉ còn phần dư 4 U. → xem mục 2.
Xem gợi ý câu 2
Không; phải nạp nhật ký và đối chiếu tài khoản/lịch sử trước. → xem mục 1 và 2.
Xem gợi ý câu 3
Chưa; timeout cần sự kiện, lệnh hoạt động, lịch sử và bằng chứng vị thế. → xem mục 2.
Xem gợi ý câu 4
Không còn quyền thử tự động trong contract, nên phải chuyển chủ. → xem mục 2 và 5.
d. Thuật ngữ cần nhớ
| Thuật ngữ | Giải thích ngắn |
|---|---|
| Sự cố | Chênh lệch trạng thái cần xử lý có kiểm soát. |
| Trạng thái dự kiến | Điều ledger nói phải tồn tại. |
| Trạng thái quan sát | Bằng chứng mới từ tài khoản và lịch sử. |
| Đối chiếu | So ý định, yêu cầu, vị thế và lịch sử. |
| Ngân sách thử lại | Số lần thử lại tối đa được phép. |
| Khóa duy nhất | ID ngăn tạo lại cùng hành động. |
| Thực thi một phần | Chỉ một phần yêu cầu có bằng chứng khớp. |
| Hành động bù | Hành động mới sửa chênh lệch, không quay ngược thời gian. |
| Trạng thái kết thúc | Điểm dừng có evidence và owner tiếp theo. |
e. Nguồn tham khảo
- MQL5 — OrderSend
- MQL5 — Trade return codes
- MQL5 — OnTradeTransaction
- MQL5 — PositionGetTicket
- MQL5 — Position properties
- MQL5 — HistorySelect
- MQL5 — OnDeinit
- MQL5 — GlobalVariableSet
Nội dung này phục vụ mục đích giáo dục, không phải lời khuyên đầu tư hoặc tín hiệu giao dịch. Recovery System không thể loại bỏ rủi ro thị trường, phí, trượt giá, mất kết nối hoặc lỗi thực thi.
Bài tiếp theo