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ư, tín hiệu giao dịch hay thiết kế hoàn chỉnh cho EA dùng tiền thật.

Trả lời ngắn: EA Engine là bộ phận điều phối: nhận một sự kiện, đọc trạng thái hiện tại, kiểm điều kiện an toàn, gọi bước xử lý phù hợp rồi ghi lại kết quả. Nó chỉ điều phối thứ tự; chiến lược và giới hạn rủi ro nằm ở các phần khác.

Kết quả được ghi lại cũng không bảo đảm máy chủ đã thực hiện yêu cầu.

Đọc xong, bạn sẽ hiểu:

  • Engine khác signal strategy ở đâu.
  • Event queue và state machine phối hợp ra sao.
  • Guard/cooldown ngăn xử lý lặp như thế nào.
  • Cách trace một vòng engine trên giấy.

1. Engine là bộ điều phối, không phải chiến lược

a. Một trưởng ca, nhiều trạm

Trong bài trước, EA được nhìn như chuỗi event → read → check → action → log. Engine là phần đứng giữa để điều phối chuỗi đó. Nó biết event nào đang được xử lý, state hiện tại là gì, stage nào được phép chạy và sau đó state phải đổi ra sao.

Hãy hình dung một bếp có trạm nhận món, kiểm nguyên liệu, nấu và giao. Công thức món ăn giống strategy; trưởng ca điều phối phiếu giống engine. Công thức đúng nhưng hai đầu bếp cùng nấu một phiếu vẫn tạo món trùng. Trưởng ca tốt không làm món ngon thay công thức, nhưng giữ đúng thứ tự và tránh xung đột.

Hình 1 — Engine điều phối event và state; strategy chỉ là một phần được gọi.

b. Engine không phải “bộ não biết trade”

Signal module có thể nói điều kiện A/B đã đúng. Risk module có thể chặn vì spread hoặc exposure. Execution module có thể tạo request. Engine chỉ gọi các phần này theo contract.

Nếu strategy sai, engine chạy rất đều vẫn cho quyết định sai. Nếu execution không kiểm result, engine không thể tự đoán server đã khớp. Vì vậy, “engine mạnh” không phải claim lợi nhuận; nó chỉ mô tả cấu trúc vận hành dễ kiểm soát hơn.

c. Năm trách nhiệm cốt lõi

Một engine tối thiểu thường cần:

  • nhận và phân loại event;
  • đọc/cập nhật state;
  • kiểm guard trước stage;
  • chọn thứ tự signal → risk → execution → verify;
  • ghi transition và lỗi.

Phần cụ thể tùy EA. Có EA chỉ chạy một symbol; EA đa symbol phải có cơ chế cập nhật dữ liệu khác. Không lấy một sơ đồ làm chuẩn tuyệt đối.

2. Event queue, state và transition

a. Event queue không phải nhiều người cùng chạy

Event queue là hàng đợi event của một chương trình. Với NewTick, tài liệu MQL5 lưu ý: nếu event NewTick đã nằm trong queue hoặc đang xử lý, NewTick mới không được thêm tiếp. AutoTrading bị tắt cũng không làm OnTick() ngừng chạy; nó hạn chế việc gửi trade request. MQL5 Reference — OnTick

Điều này phá hai hiểu lầm:

  1. Mỗi biến động nhỏ không chắc tạo một lượt handler riêng.
  2. Handler chậm không “xử lý kỹ hơn”; nó có thể làm EA bỏ lỡ nhịp event mới.

Engine cần giữ handler gọn, tránh việc nặng không cần thiết và log thời gian xử lý khi độ trễ quan trọng.

b. State là bảng trạng thái hiện tại

State là tình trạng hiện tại của vòng engine. Ta dùng năm state demo:

  • IDLE: sẵn sàng nhận việc.
  • EVALUATING: đang đọc signal/risk.
  • ACTING: đang tạo hoặc theo dõi action.
  • COOLDOWN: chờ điều kiện reset.
  • SAFE: dừng có kiểm soát vì state không tin cậy.

Transition là việc chuyển từ state trước sang state sau. Mỗi transition phải có trigger và rule. Ví dụ:

IDLE + bar mới → EVALUATING

EVALUATING + signal false → COOLDOWN

COOLDOWN + timer hết → IDLE

Hình 2 — State machine làm rõ vòng nào được phép chuyển sang action.

c. Transition sai phải fail rõ

Nếu state là ACTING mà một tick mới cố đưa thẳng về EVALUATING, engine phải biết có cho phép hay không. Im lặng nhảy state làm log khó đọc và có thể tạo action trùng.

Một rule đơn giản:

Nếu transition không nằm trong bảng cho phép → SAFE + log

Đây không phải cách duy nhất, nhưng tốt hơn việc tiếp tục từ state mơ hồ.

3. Trace một vòng tick giả

a. Tick A trên bar mới

Giả sử engine đang IDLE, chưa xử lý bar 101.

  1. Tick A đến.
  2. Engine đọc bar id 101.
  3. Guard kiểm 101 != last_processed_bar.
  4. State chuyển IDLE → EVALUATING.
  5. Signal giả là false.
  6. Engine không gọi execution, ghi NO_SIGNAL.
  7. State chuyển EVALUATING → COOLDOWN.

Guard là điều kiện chặn xử lý lặp hoặc sai state. Nó không đánh giá thị trường; nó bảo vệ quy trình.

b. Tick B vẫn thuộc bar 101

Tick B đến ngay sau đó. State đang COOLDOWN, bar vẫn 101. Guard thấy bar đã xử lý nên action là SKIP_DUPLICATE. Engine giữ COOLDOWN.

Hình 3 — Guard giữ cùng một bar khỏi bị xử lý như hai cơ hội mới.

Cooldown là state chờ có điều kiện sau action hoặc evaluation. Nó có thể kết thúc khi bar mới xuất hiện, timer hết hoặc transaction hoàn tất. Cooldown không phải sleep() tùy tiện; ngủ trong handler có thể chặn queue.

c. Action cần ID và kết quả

Nếu signal true và risk pass, state có thể chuyển EVALUATING → ACTING. Engine tạo action_id, gọi execution rồi chờ/đọc result. Khi hoàn tất, lưu last_action_id, state mới và log.

Nếu cùng event được thử lại, idempotency là đặc tính giúp request lặp không tạo tác động ngoài ý muốn. Một action_id đã thành công phải được nhận diện. Tuy nhiên, idempotency không chỉ là biến boolean; restart, transaction đến trễ và state server đều cần xét.

OnTradeTransaction có thể được gọi khi tài khoản nhận transaction, và thứ tự arrival không nhất thiết phản ánh một chuỗi đơn giản như người dùng tưởng. Engine phải xử lý transaction dựa trên dữ liệu/ID, không chỉ dựa vào “event trước chắc xong rồi”. MQL5 Reference — OnTradeTransaction

4. Sai lầm, giới hạn và rủi ro

a. Bốn lỗi cấu trúc phổ biến

  1. Không có state rõ: nhiều biến boolean mâu thuẫn, vừa “busy” vừa “ready”.
  2. Guard cập nhật quá muộn: action đã gửi nhưng last_bar chưa lưu, tick khác vào lại.
  3. Handler quá dài: đọc file/network hoặc vòng lặp nặng trong event chính.
  4. Log không có before/after: chỉ ghi “done”, không biết state chuyển thế nào.

Một lỗi khác là gom mọi thứ vào OnTick: signal, panel, recovery, file I/O và execution. Code vẫn có thể chạy, nhưng khó test từng contract và khó xác định stage gây chậm.

b. Stale state sau restart

Stale state là state cũ không còn khớp thực tế. Terminal restart có thể làm biến memory mất trong khi position/order trên account vẫn tồn tại. Nếu engine mặc định IDLE và tạo action mới mà không reconcile, nguy cơ trùng tăng.

Câu chắc chắn: state memory của chương trình và state account là hai nguồn khác nhau.

Câu có điều kiện: nếu engine có recovery/reconcile đúng contract, nó có thể dựng lại state cần thiết sau restart.

Nếu không chứng minh được recovery, action đúng là SAFE, không phải “thử chạy xem”.

c. Giới hạn của sơ đồ một symbol

OnTick gắn với symbol của chart. EA đa symbol không tự có tick event riêng cho mọi symbol theo cách giản đơn; cần thiết kế nguồn event/data phù hợp. Timer có thể giúp polling, nhưng timer không biến dữ liệu stale thành fresh.

Ngoài ra, queue tuần tự giảm một loại race trong handler nhưng không loại mọi race với trade server, file, external service hoặc nhiều EA cùng account. Guard nội bộ của một instance không tự khóa instance khác.

d. Khi nào phải dừng

Dừng review nếu:

  • không có danh sách state hợp lệ;
  • transition không có trigger;
  • guard không nói rõ cập nhật trước hay sau action;
  • restart không có policy;
  • transaction/request thiếu ID;
  • log không có state trước/sau;
  • một handler chứa việc blocking không giới hạn.

Đây là lỗi quan sát và điều phối, không phải vấn đề “tinh chỉnh tham số”.

5. Checklist và bài tập state trace

a. Checklist đọc engine

  1. Liệt kê event mà engine nhận.
  2. Liệt kê state và ý nghĩa từng state.
  3. Vẽ transition hợp lệ.
  4. Đánh dấu guard chống lặp.
  5. Ghi khi nào state được persist/recover.
  6. Gắn ID cho action/transaction.
  7. Ghi timeout và failure state.
  8. Xác nhận log có event, before, rule, stage, after.

Nếu không điền được mục 2–4, chưa nên nói engine “ổn”.

b. Bài tập 10–15 phút

Dùng giấy hoặc Sheets miễn phí. Không mở terminal, không account và không tiền thật. Vẽ năm ô IDLE, EVALUATING, ACTING, COOLDOWN, SAFE; sau đó điền bảng:

Mẫu đối chiếu đã điền

Event State trước Guard Stage State sau
Tick A IDLE bar mới EVALUATE COOLDOWN
Tick B COOLDOWN cùng bar SKIP COOLDOWN
Timer COOLDOWN hết 60s RESET IDLE
Restart UNKNOWN state thiếu STOP SAFE

Thử thêm một dòng: Transaction R1 | ACTING | action_id khớp | VERIFY | COOLDOWN. Nếu không biết state sau, quay lại contract. Kết quả mong đợi là mọi dòng có before/after và lý do; không cần tạo lệnh.

c. Điểm dừng

Đừng chuyển paper trace thành live khi chưa có test cho duplicate, restart và transaction đến trễ. State machine đẹp trên slide chưa chứng minh code tuân thủ nó.

6. Tổng kết

a. Năm ý chính

  • Engine điều phối event/state/stage; strategy chỉ là một phần.
  • Event queue không phải tài nguyên song song vô hạn.
  • State transition cần trigger và rule rõ.
  • Guard/cooldown giúp ngăn xử lý lặp nhưng cần recovery.
  • Log tốt ghi event, state trước, rule, stage và state sau.

b. Câu hỏi tự kiểm tra

  • Engine khác signal strategy thế nào?
  • Tick B cùng bar 101 nên đi qua guard nào?
  • Vì sao restart có thể tạo stale state?
  • Khi transition không hợp lệ, demo chọn state nào?

c. Gợi ý đáp án

Xem gợi ý câu 1

Engine điều phối thứ tự và state; signal strategy chỉ đề xuất điều kiện hành động. Xem lại mục 1.

Xem gợi ý câu 2

Guard so bar id với last processed bar và trả SKIP_DUPLICATE. Xem lại mục 3.

Xem gợi ý câu 3

State memory có thể mất trong khi state account vẫn còn. Xem lại mục 4.

Xem gợi ý câu 4

Demo chuyển SAFE và log transition sai. Xem lại mục 2 và mục 5.

d. Thuật ngữ cần nhớ

Thuật ngữ Giải thích ngắn
Engine Lớp điều phối event, state và stage.
Event queue Hàng đợi sự kiện của chương trình.
State Trạng thái hiện tại của vòng xử lý.
Transition Chuyển từ state trước sang state sau.
Guard Điều kiện chặn lặp hoặc sai state.
Cooldown State chờ có điều kiện sau xử lý.
Idempotency Request lặp không tạo tác động ngoài ý muốn.
Stale state State cũ không còn khớp thực tế.

e. Nguồn tham khảo

Bài trước: EA là gì? #6. Bài tiếp theo: Các thành phần chính của một EA #8.

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ư, tín hiệu giao dịch hoặc xác nhận engine phù hợp tài khoản thật.