| Magic Number & Comment MT5 chuyên sâu — Buổi 3: định danh lệnh bot, tránh đóng nhầm basket

Được viết bởi thanhdt vào ngày 14/07/2026 lúc 17:17 | 31 lượt xem


Một EA chạy đơn lẻ trên một Symbol, chỉ mở vài lệnh, hầu như không cần quan tâm “lệnh này là của ai”. Nhưng ngay khi robot bước sang giai đoạn thực chiến — chạy song song Grid Buy/Sell, quản lý nhiều cụm lệnh (basket) độc lập, hoặc dùng chung tài khoản với người mở lệnh tay — bài toán định danh lệnh trở thành xương sống của hệ thống. Thiếu nó, EA dễ “bắn nhầm quân mình”: chốt lời nhầm cả basket đang gồng lỗ, hoặc tệ hơn, đóng luôn lệnh tay của người dùng.

Bài viết trình bày lại nội dung Buổi 3 — Quản trị Magic & Comment chuyên sâu trong khóa Lập trình MT5 Nâng cao Hedging & Tự động hóa tại Hướng Nghiệp Dữ Liệu, dựa trên cấu trúc thực chiến của Bot Nhị Quái V9.2.1 Pro. Đây là bài kỹ thuật — trình bày cách một EA tổ chức dữ liệu để tự nhận diện lệnh của chính nó, không phải tín hiệu giao dịch hay lời hứa lợi nhuận.

1. Tại sao một EA phải “định danh” được lệnh của chính nó?

Khi robot chỉ có một lưới lệnh, mọi thứ đơn giản: PositionsTotal() trả về bao nhiêu lệnh, EA coi tất cả là của mình. Nhưng thực tế vận hành phức tạp hơn nhiều: nhiều chiến thuật chạy song song trên cùng tài khoản (Grid Buy, Grid Sell, Hedging, Trend Following); nhiều cụm lệnh (Cluster/Basket) riêng biệt trên cùng Symbol, mỗi cụm có mục tiêu chốt lời (TP) và điểm neo giá (P0) khác nhau; lệnh giao dịch tay của chính người dùng; và EA khác cùng chạy trên Terminal hoặc cùng Symbol.

Nếu không phân biệt rạch ròi bốn nhóm lệnh trên, một hàm quét sàn viết cẩu thả có thể vô tình gộp cả lệnh tay vào phép tính lợi nhuận của basket, dẫn đến chốt lời hoặc nhồi lệnh sai. Nghiêm trọng hơn, một hàm “đóng hết lệnh” viết sai điều kiện lọc có thể đóng luôn vị thế người dùng đang tự quản lý bằng tay — lỗi không thể chấp nhận trong hệ thống tự động hóa chuyên nghiệp.

Giải pháp của MQL5 nằm ở hai trường dữ liệu luôn đi kèm mọi lệnh: Magic NumberOrder Comment. Kết hợp đúng cách, hai trường này biến mỗi lệnh thành một “chứng minh nhân dân” không thể giả mạo, giúp EA tự tin quét sàn, phân loại và xử lý đúng nhóm lệnh của chính nó.

2. Magic Number: tách biệt lưới Buy và Sell bằng cặp số 2111/2112

2.1. Vì sao không dùng chung một Magic cho cả tài khoản?

Trong nhiều EA đời đầu, người viết thường gán một số Magic duy nhất cho toàn bộ robot — ổn nếu EA chỉ chạy một hướng giao dịch. Nhưng với kiến trúc hedging hai lưới độc lập, nơi Grid Buy và Grid Sell vận hành như hai “cơ thể” riêng và có thể một bên đang lãi, một bên đang lỗ tại cùng thời điểm, dùng chung Magic sẽ khiến hàm tính lợi nhuận cộng gộp cả hai lưới vào một con số duy nhất.

Hệ quả: khi lưới Sell đã đạt mục tiêu chốt lời (Basket TP) trong lúc lưới Buy đang gồng lỗ chờ hồi giá, phép tính tổng “lãi trừ lỗ” có thể vẫn dương và khiến EA chốt nhầm toàn bộ — kể cả các lệnh Buy chưa đến lúc thoát. Basket Buy đang chờ hồi giá bị cắt đứt oan uổng, phá vỡ kế hoạch quản trị vốn ban đầu.

2.2. Giải pháp thực chiến: cặp Magic 2111 / 2112

Bot Nhị Quái V9 giải quyết vấn đề bằng cách tách hẳn hai lưới thành hai “công dân” độc lập, mỗi công dân có một số Magic riêng:

graph TD
    A[Tài Khoản Giao Dịch] --> B[Lưới Buy - Magic 2111]
    A --> C[Lưới Sell - Magic 2112]
    A --> D[Lệnh Giao Dịch Tay - Magic 0]
  • InpBuyMagic = 2111; — quản lý riêng cụm lưới Buy (Buy Grid Basket).
  • InpSellMagic = 2112; — quản lý riêng cụm lưới Sell (Sell Grid Basket).

Việc tách biệt này giúp EA tính lợi nhuận và điều kiện chốt lời của Basket Sell hoàn toàn tách rời với Basket Buy. Khi Basket Sell đạt target, EA chỉ đóng đúng các lệnh mang Magic 2112, để nguyên vẹn dải lệnh Buy đang chờ hồi giá.

2.3. Triển khai MQL5: mỗi lưới một CTrade riêng

// Cấu hình Input của Robot
input int InpBuyMagic  = 2111; // Magic Number cho cụm Buy
input int InpSellMagic = 2112; // Magic Number cho cụm Sell

// Đối tượng CTrade riêng biệt cho từng lưới
CTrade m_trade_buy, m_trade_sell;

void OnInitMagic()
{
   // Gán Magic Number vào từng đối tượng giao dịch
   m_trade_buy.SetExpertMagicNumber(InpBuyMagic);
   m_trade_sell.SetExpertMagicNumber(InpSellMagic);
}

Điểm hay của kỹ thuật này nằm ở việc tách theo đối tượng CTrade thay vì gọi lại SetExpertMagicNumber() mỗi lần đặt lệnh. Khi robot gọi m_trade_buy.Buy(...), lệnh sinh ra tự động mang Magic 2111 — không có khả năng lập trình viên quên đổi Magic giữa hai lượt gọi liên tiếp, lỗi khá phổ biến khi dùng chung một object CTrade cho cả hai hướng. Khi quét sàn phân loại, EA chỉ cần so sánh trực tiếp Magic với InpBuyMagic/InpSellMagic — phép so sánh số nguyên nhanh, không cần parse chuỗi.

3. Order Comment — “DNA” bất tử của lệnh giao dịch

3.1. Vì sao Comment quan trọng hơn nhiều người nghĩ

Magic Number chỉ trả lời câu hỏi “lệnh này thuộc cụm nào”. Bên trong một cụm, EA còn cần biết thêm: lệnh này ở Step (tầng) thứ mấy, mở vì lý do gì, thuộc hướng Buy hay Sell. Đây là lúc Order Comment phát huy vai trò.

Điểm đặc biệt của Comment nằm ở nơi nó được lưu trữ: Comment đi liền với lệnh và được đồng bộ trực tiếp lên server của Broker — không phải RAM của Terminal, không phải tệp tin trên ổ cứng VPS. Nghĩa là dù bạn tắt máy đột ngột, cài lại Windows, hay chuyển EA sang VPS khác, Comment của mọi lệnh đang mở không bao giờ bị mất — vì nó không hề tồn tại ở phía máy khách.

Tuy vậy, Comment có hai giới hạn quan trọng: độ dài tối đa 31 ký tự (vượt quá, MQL5 sẽ cắt bớt hoặc từ chối, tùy phiên bản/broker), và không thể sửa sau khi lệnh đã mở thành công — Comment “đóng băng” ngay tại thời điểm gửi lệnh, nếu thiết kế sai cấu trúc thì không có cách vá lại cho các lệnh đang chạy. Hai giới hạn này buộc người thiết kế EA phải nghĩ đến một cấu trúc comment tối giản nhưng đủ thông tin, thay vì nhồi nhét dữ liệu tùy ý.

3.2. Giao thức đóng gói Comment của Nhị Quái V9

Khi đặt lệnh nhồi (DCA), Bot Nhị Quái V9 đóng gói comment theo cấu trúc cố định:

[BotName]_[Direction]_S[Step]

Ví dụ: NHI QUAI V9_B_S3 nghĩa là lệnh thuộc lưới Buy (B), đang ở Step 3. Ba thành phần — tên bot, hướng, số Step — đủ để EA tái tạo trạng thái một lệnh chỉ bằng cách đọc chuỗi comment, không cần tra cứu nguồn dữ liệu nào khác.

3.3. Lỗi kinh điển khi parse comment: StringFind đơn giản

Một lỗi rất phổ biến khi lập trình viên mới viết hàm giải mã Step từ comment là dùng thẳng StringFind(comment, "_S") để tìm vị trí đầu tiên của cụm _S, rồi cắt chuỗi lấy phần số phía sau. Cách này hoạt động tốt với ví dụ đơn giản, nhưng sẽ âm thầm sai ngay khi tên bot (InpBotName) chứa chữ cái S hoặc một cụm gạch dưới trùng lặp.

Ví dụ: nếu InpBotName"NHI_QUAI_SUPER", chuỗi comment đầy đủ sẽ là "NHI_QUAI_SUPER_B_S3". Cụm _S xuất hiện hai lần: một lần ở đầu chữ SUPER, một lần ở đuôi _S3. Nếu hàm chỉ lấy vị trí xuất hiện đầu tiên, nó sẽ cắt nhầm tại chữ SUPER và trả về Step sai — lỗi rất khó phát hiện vì code vẫn chạy, chỉ trả kết quả sai lệch trong âm thầm.

3.4. Giải pháp: vòng lặp while lấy vị trí xuất hiện cuối cùng

Để giải quyết triệt để, Bot Nhị Quái V9.2.1 Pro dùng một vòng lặp while quét toàn bộ chuỗi từ trái sang phải, liên tục ghi đè vị trí tìm được, chỉ dừng khi không còn cụm _S nào phía sau. Biến last luôn giữ vị trí xuất hiện cuối cùng — chính xác nơi đặt số Step, bất kể tên bot chứa bao nhiêu chữ S hay gạch dưới phía trước.

int GetStepFromComment(string c)
{
   int cur = 0, last = -1;

   // Vòng lặp tìm kiếm liên tục từ trái qua phải
   while((cur = StringFind(c, "_S", cur)) != -1)
   {
      last = cur; // Cập nhật vị trí xuất hiện mới nhất
      cur += 1;   // Tiến lên 1 ký tự để quét tiếp
   }

   // Nếu tìm thấy ký tự _S cuối cùng, cắt chuỗi lấy giá trị số phía sau
   if(last != -1)
   {
      return (int)StringToInteger(StringSubstr(c, last + 2));
   }

   return 0; // Mặc định trả về Step 0 nếu không tìm thấy
}

Bạn có thể tự kiểm chứng bằng cách chạy hàm trên bốn chuỗi “gài mìn”: "NHI_QUAI_SUPER_B_S3", "TY_HUU_ULTRA_S_S7", "NQ_SIMPLE_GRID_S0""ORDER_TEST_WITHOUT_STEP". Kết quả đúng phải là 3, 7, 00. Nguyên lý này không chỉ áp dụng cho comment MT5: bất kỳ lúc nào bạn cần parse một chuỗi định danh có ký tự phân tách trùng với nội dung phía trước, kỹ thuật “quét lấy vị trí cuối cùng” luôn an toàn hơn “lấy vị trí đầu tiên”.

4. Siêu Cache 1-Pass: quét sàn một lần, phân loại toàn bộ lệnh

4.1. Vấn đề hiệu năng khi quét sàn nhiều lần

Một cách viết EA thiếu tối ưu là mỗi khi cần thông tin (tổng lệnh Buy, tổng lệnh Sell, Step cao nhất…), lập trình viên lại viết một vòng lặp riêng chạy qua PositionsTotal(). Nếu EA cần 5 loại thông tin trong một tick, đó là 5 lần quét toàn bộ danh sách lệnh — lãng phí CPU khi tài khoản có hàng trăm lệnh mở đồng thời.

4.2. Giải pháp: một hàm quét, nạp toàn bộ vào RAM

Bot Nhị Quái V9.2.1 Pro giải quyết bằng nguyên tắc “1-Pass”: chỉ dùng duy nhất một hàm quét sàn ở đầu OnTick(), gom toàn bộ lệnh liên quan của EA vào các mảng lưu trong RAM (EA Cache). Mọi logic tính toán phía sau — tổng lợi nhuận, Step cao nhất, số lệnh đang mở — đều đọc từ Cache, không quét lại sàn trong cùng một tick.

// Khai báo các mảng Cache toàn cục
ulong m_pos_buy_tickets[],  m_pos_sell_tickets[];
int   m_pos_buy_steps[],    m_pos_sell_steps[];
ENUM_POSITION_TYPE m_pos_buy_types[], m_pos_sell_types[];

void CacheAllPositions()
{
   // Giải phóng bộ nhớ mảng cũ
   ArrayResize(m_pos_buy_tickets, 0);
   ArrayResize(m_pos_sell_tickets, 0);

   int total = PositionsTotal();
   for(int i = 0; i < total; i++)
   {
      // Chọn lệnh và lọc theo Symbol
      if(m_position.SelectByIndex(i) && m_position.Symbol() == _Symbol)
      {
         int magic = (int)m_position.Magic();

         // Phân nhóm lọc lệnh trực tiếp theo Magic Buy/Sell
         if(magic == InpBuyMagic)
         {
            int n = ArraySize(m_pos_buy_tickets);
            ArrayResize(m_pos_buy_tickets, n + 1);
            ArrayResize(m_pos_buy_steps, n + 1);
            ArrayResize(m_pos_buy_types, n + 1);

            m_pos_buy_tickets[n] = m_position.Ticket();
            m_pos_buy_steps[n]   = GetStepFromComment(m_position.Comment()); // Giải mã Comment
            m_pos_buy_types[n]   = m_position.PositionType();
         }
         else if(magic == InpSellMagic)
         {
            int n = ArraySize(m_pos_sell_tickets);
            ArrayResize(m_pos_sell_tickets, n + 1);
            ArrayResize(m_pos_sell_steps, n + 1);
            ArrayResize(m_pos_sell_types, n + 1);

            m_pos_sell_tickets[n] = m_position.Ticket();
            m_pos_sell_steps[n]   = GetStepFromComment(m_position.Comment()); // Giải mã Comment
            m_pos_sell_types[n]   = m_position.PositionType();
         }
      }
   }
}

Ba điểm đáng chú ý: (1) lọc theo Symbol trước — tránh nạp nhầm lệnh của Symbol khác; (2) Magic quyết định nhóm, Comment cung cấp chi tiếtmagic tách lệnh vào đúng mảng Buy/Sell, GetStepFromComment() được gọi ngay để giải mã Step trong cùng lượt quét; (3) ArrayResize tăng dần — đơn giản, phù hợp quy mô lệnh hedging thông thường; số lệnh cực lớn có thể resize theo lô, nhưng nguyên tắc “quét một lần, dùng nhiều lần” vẫn giữ nguyên giá trị.

4.3. Phân loại lệnh: EA của ta — lệnh tay — EA khác

Từ nền tảng Magic + Comment, EA có thể phân loại rõ ràng mọi lệnh đang mở trên tài khoản vào ba nhóm:

Nhóm Điều kiện nhận diện EA nên xử lý thế nào
1. EA của ta Magic bằng InpBuyMagic/InpSellMagic Comment bắt đầu bằng tiền tố định danh (ví dụ "NHI QUAI") Nạp vào Cache, tính lợi nhuận, quyết định nhồi lệnh/chốt lời
2. Giao dịch tay Magic bằng 0 Bỏ qua hoàn toàn — tuyệt đối không đóng, không sửa SL/TP
3. EA khác / ngoài dải Magic khác 0 và khác InpBuyMagic/InpSellMagic Bỏ qua, không can thiệp

Kiểm tra kép Magic Comment là một lớp bảo vệ bổ sung: nếu một EA khác vô tình trùng số Magic (đặc biệt các số nhỏ như 1, 100), tiền tố Comment ("NHI QUAI") đóng vai trò xác thực thứ hai, giảm rủi ro nhận nhầm lệnh của người khác.

4.4. Basket TP isolation: chốt một cụm không đụng cụm khác

Kết quả trực tiếp của việc phân loại Magic + Cache 1-Pass là khả năng cô lập điều kiện chốt lời theo từng basket. EA chỉ cộng các phần tử trong m_pos_buy_tickets[] khi kiểm tra Basket Buy, và chỉ cộng m_pos_sell_tickets[] khi kiểm tra Basket Sell — hai phép tính độc lập tuyệt đối, không có tình huống lợi nhuận Sell “kéo theo” lệnh Buy vào cùng một quyết định đóng lệnh. Đây chính là lời giải cho vấn đề đặt ra ở Mục 2: với Magic riêng biệt cho từng lưới, EA chốt lời Basket Sell độc lập trong khi Basket Buy vẫn gồng chờ hồi giá theo đúng kế hoạch.

5. Cơ chế phục hồi Dual-Layer: Global Variables + Comment

5.1. Vì sao cần “bất tử” sau khi VPS restart?

Một EA hedging vận hành 24/7 chắc chắn sẽ đối mặt với sự cố: mất điện, VPS restart định kỳ, Terminal crash, hoặc broker bảo trì server. Câu hỏi quan trọng không phải “làm sao tránh sự cố” mà là “làm sao EA tự khôi phục đúng trạng thái chỉ trong vài giây, không cần con người can thiệp tay”. Bot Nhị Quái V9 giải quyết bằng cơ chế Dual-Layer Persistence — kết hợp hai tầng lưu trữ độc lập, mỗi tầng chịu trách nhiệm một loại dữ liệu khác nhau:

Tầng lưu trữ Vị trí lưu Dữ liệu phù hợp Đặc điểm
Global Variables (GV) File gvariables.dat trên ổ cứng Terminal P0 (giá neo), StartTime, trạng thái Locked/Hedged Chỉ lưu double, tồn tại cả khi gỡ EA khỏi chart, mất nếu đổi VPS mà không copy file
Order Comment Server của Broker Step của từng lệnh, Cluster ID, lý do vào lệnh Bất tử ngay cả khi đổi máy/đổi VPS, giới hạn 31 ký tự, không sửa được sau khi mở lệnh

5.2. Global Variables: “bộ nhớ môi trường” của EA

Global Variables lưu các thông số mang tính trạng thái hệ thống — giá trị EA cần nhớ nhưng không gắn với một lệnh cụ thể, ví dụ P0 (giá neo, xác định lưới Grid bắt đầu từ đâu) và StartTime (thời điểm bắt đầu tính Basket Profit). Để tránh ghi đè chéo biến GV giữa các tài khoản hoặc các Magic lưới khác nhau chạy trên cùng Terminal, Nhị Quái V9 dùng một cấu trúc khóa (key) độc bản:

[StoragePrefix]_[AccountNumber]_[Magic]_[VarName]
string GetGVPrefix(int magic)
{
   return InpStoragePrefix + "_" + IntegerToString((int)AccountInfoInteger(ACCOUNT_LOGIN)) + "_" + IntegerToString(magic);
}

// Ví dụ khi đọc giá trị P0 của lưới Buy (InpBuyMagic = 2111)
string gv_buy_p0 = GetGVPrefix(InpBuyMagic) + "_P0";
if(GlobalVariableCheck(gv_buy_p0))
{
   m_buy_p0 = GlobalVariableGet(gv_buy_p0);
}

Một khóa GV thực tế có dạng NHI QUAI V9_12345678_2111_P0 — gồm cả số tài khoản và Magic ngay trong tên biến, nên dù chạy nhiều tài khoản/nhiều lưới trên cùng Terminal, các biến GV không bao giờ “va” vào nhau. Ngược lại, Comment lưu thông tin gắn liền với từng lệnh cụ thể — Step, giúp EA biết lệnh này thuộc tầng giá nào. Vì sống trên server sàn, Comment không phụ thuộc việc EA có đang chạy hay VPS có còn tồn tại.

5.3. Sơ đồ luồng phục hồi (Recovery Flow) khi EA khởi động lại

graph TD
    A([Khởi chạy EA - OnInit]) --> B[1. Tái tạo Khóa GV độc bản bằng GetGVPrefix]
    B --> C[2. Đọc Global Variables để lấy lại P0 & StartTime]
    C --> D[3. Gọi CacheAllPositions để quét toàn bộ sàn]
    D --> E[Giải mã Comment lấy Step của từng lệnh nạp vào RAM]
    E --> F[4. Đồng bộ trạng thái: Xác định chính xác bước đi tiếp theo]
    F --> G([Bot Nhị Quái sẵn sàng giao dịch an toàn])

Bốn bước trên diễn ra chỉ trong một phần nhỏ của giây, ngay tại OnInit(): (1) tái tạo khóa GV bằng GetGVPrefix(magic); (2) đọc GV để lấy lại P0 và StartTime; (3) gọi CacheAllPositions() quét toàn bộ lệnh đang mở, lọc theo Symbol và Magic; (4) giải mã Comment từng lệnh bằng GetStepFromComment() để xác định Step cao nhất đang mở — câu trả lời cho “bước tiếp theo là Step nào”. Toàn bộ quá trình không cần database hay CSV — chỉ GV, Comment và một hàm quét sàn duy nhất.

5.4. Vì sao không dùng file CSV/Binary để lưu trạng thái?

Nhiều học viên hỏi: tại sao không ghi mọi thứ vào một file JSON/CSV trên VPS? Ba lý do: tốc độ (GV và Comment truy xuất trực tiếp qua API, không cần mở/đóng file hay parse cú pháp), độ tin cậy (file ổ cứng có thể hỏng nếu VPS mất điện đúng lúc ghi, còn Comment do sàn quản lý, gắn liền với lệnh đã khớp vĩnh viễn) và tính di động (chuyển VPS mới, EA chỉ cần tự tính lại P0, còn Comment luôn có sẵn trên sàn).

6. Checklist tự kiểm tra EA của bạn đã định danh lệnh đúng chưa

Trước khi đưa một EA hedging lên tài khoản live, hãy tự trả lời từng dòng checklist bằng code thật, không phải bằng cảm giác “chắc là ổn”:

Magic Number

  • [ ] Mỗi hướng/lưới độc lập (Buy, Sell, hoặc từng chiến thuật) có một số Magic riêng, không dùng chung.
  • [ ] Mỗi lưới dùng một đối tượng CTrade riêng, đã gọi SetExpertMagicNumber() ngay trong OnInit.
  • [ ] Hàm tính lợi nhuận/điều kiện chốt lời của một basket chỉ đọc lệnh có đúng Magic của basket đó.
  • [ ] Đã kiểm tra: nếu chạy 2 tài khoản hoặc 2 Symbol cùng lúc, Magic không bị đụng nhau.

Order Comment & phân loại

  • [ ] Cấu trúc comment cố định trước khi chạy live, tổng độ dài không vượt 31 ký tự kể cả khi Step lên tới 2-3 chữ số.
  • [ ] Hàm giải mã comment lấy vị trí xuất hiện cuối cùng, đã test với chuỗi “gài mìn” và trường hợp không tìm thấy Step.
  • [ ] Có một hàm quét sàn duy nhất chạy ở đầu mỗi tick, lọc theo Symbol trước.
  • [ ] Phân loại rõ ba nhóm — EA của ta, lệnh tay (Magic 0), EA khác — code không bao giờ đóng/sửa nhóm 2, nhóm 3.
  • [ ] Basket TP của từng lưới tính độc lập, đã test kịch bản một lưới lãi/một lưới lỗ cùng lúc.

Persistence (Global Variables + Comment)

  • [ ] Khóa GV có cấu trúc độc bản gồm tên bot, số tài khoản, Magic — không hard-code tên cố định.
  • [ ] Đã test khởi động lại và xác nhận EA đọc đúng P0, đúng Step lớn nhất, không nhồi lệnh trùng.
  • [ ] Có kế hoạch cho trường hợp GV bị mất (đổi VPS không copy file).
  • [ ] Không đổi tên bot/tiền tố Comment giữa đường mà quên cập nhật hàm lọc.

Nếu bất kỳ dòng nào trong checklist trên chưa được kiểm chứng bằng test thực tế, hãy dừng lại và viết test trước khi cân nhắc chạy tài khoản live.

7. Ai nên học sâu về Magic Number & Comment?

Nội dung Buổi 3 phù hợp với người đã viết được EA cơ bản (biết OnTick, OnInit, dùng CTrade để đặt lệnh) nhưng chưa từng quản lý nhiều cụm lệnh song song trên cùng tài khoản — kiến thức bắt buộc với bất kỳ ai muốn xây EA hedging hai chiều, grid đa cụm, hoặc để EA chạy cùng lúc với giao dịch tay mà không lo xung đột. Nếu bạn chỉ chạy một EA đơn giản trên một Symbol và chưa có kế hoạch mở rộng, phần này có thể chưa cần ngay, nhưng nắm được tư duy Magic + Comment vẫn giúp code sẵn sàng mở rộng mà không phải viết lại từ đầu.

8. Vị trí Buổi 3 trong lộ trình khóa MT5 Hedging

Buổi 3 nằm trong Phần 1 — Công nghệ lõi (Infrastructure) của khóa, ngay sau Buổi 1 (Cấu trúc dữ liệu & Global Variables) và Buổi 2 (Kỹ thuật Cache & Array) — nền tảng bắt buộc trước khi sang Phần 2 (Grid Logic, Surplus/Hedge, Multi-Cluster). Magic Number và Comment không phải “mẹo nhỏ” tùy chọn: chúng là hạ tầng mà toàn bộ logic Grid, Hedge, FSM và Guard ở các phần sau dựa vào để phân biệt đúng lệnh thuộc basket nào. Bỏ qua hoặc làm sơ sài phần này, các buổi học sau về Sweep hay Guard sẽ rất khó triển khai chính xác.

Khóa học hiện giảng dạy theo lịch Thứ 3 và Thứ 5, 20:00–22:00 (lớp đang học đến Buổi 3/25), cùng một lớp khai giảng mới theo lịch Thứ 7 và Chủ nhật cho học viên muốn bắt đầu từ đầu. Cấu trúc tổng thể gồm 5 phần: Phụ đạo nền tảng, Công nghệ lõi, Chiến thuật rải quân, Bộ não điều khiển (FSM/Sweep/Guard) và Giao diện & triển khai VPS — kèm coaching 1-1 trong vòng 1 năm sau khi hoàn thành khóa.

9. Câu hỏi thường gặp (FAQ)

1. Magic Number có bắt buộc phải là số cụ thể như 2111/2112 không?

Không. Điều quan trọng là mỗi lưới/chiến thuật độc lập phải có một Magic riêng, không trùng nhau và không trùng EA khác trên cùng Terminal. Cặp 2111/2112 chỉ là ví dụ thực chiến dễ nhớ, dễ phân biệt khi xem log.

2. Nếu Comment vượt quá 31 ký tự thì điều gì xảy ra?

Tùy phiên bản MetaTrader và broker, chuỗi có thể bị cắt bớt tự động, hoặc lệnh vẫn gửi nhưng comment không đầy đủ. Cách an toàn nhất là tự tính độ dài chuỗi trước khi gửi lệnh và thiết kế cấu trúc đủ ngắn cho cả trường hợp Step lên đến 2-3 chữ số.

3. Có thể sửa lại Comment của một lệnh đang mở không?

Không. Comment gắn cố định tại thời điểm lệnh mở thành công, không thể chỉnh sửa sau đó bằng hàm chuẩn của MQL5 — phải thiết kế đúng cấu trúc trước khi chạy live.

4. Kiểm tra Magic thôi có đủ không, sao phải kiểm tra cả tiền tố Comment?

Vẫn hoạt động trong đa số trường hợp, nhưng kiểm tra kép là lớp bảo vệ bổ sung cho trường hợp hiếm gặp một EA khác vô tình dùng cùng số Magic, đặc biệt với các Magic nhỏ dễ đụng số.

5. Hàm GetStepFromComment áp dụng cho cấu trúc comment khác được không?

Được, với nguyên lý “quét lấy vị trí xuất hiện cuối cùng”. Nếu cấu trúc của bạn đặt Step ở vị trí khác, cần điều chỉnh logic cắt chuỗi tương ứng, nhưng nguyên tắc test với dữ liệu “gài mìn” luôn cần thiết.

6. Global Variables có bị mất khi đổi VPS không?

Có, nếu không copy file gvariables.dat sang máy mới, GV sẽ mất và EA đọc như lần đầu chạy. EA nên có cơ chế fallback — ví dụ tự tính lại P0 từ giá hiện tại hoặc dữ liệu lệnh đang mở — thay vì crash khi GV không tồn tại.

7. Có cần dùng database thay cho GV + Comment không?

Với quy mô một vài lưới/basket, GV + Comment đủ nhanh, đủ tin cậy, không cần thêm hạ tầng phức tạp. Database chỉ cần thiết khi hệ thống mở rộng sang mức lưu lịch sử phân tích lớn hoặc chạy nhiều instance cần đồng bộ qua mạng.

8. Học phần này có giúp tránh lỗi “đóng nhầm lệnh tay” không?

Có, nếu bạn triển khai đúng bước phân loại ở Mục 4.3 — luôn kiểm tra Magic bằng 0 và loại hoàn toàn nhóm này khỏi mọi vòng lặp đóng/sửa lệnh của EA.

Kết luận

Magic Number và Order Comment không phải hai trường dữ liệu “tiện thì dùng” trong MQL5 — chúng là công cụ định danh lệnh nền tảng, quyết định một EA hedging đa cụm có vận hành an toàn hay không. Cặp Magic 2111/2112 tách biệt hai lưới Buy/Sell để chốt lời độc lập; giao thức comment [BotName]_[Direction]_S[Step] cùng thuật toán quét lấy vị trí cuối cùng giúp EA giải mã đúng Step dù tên bot phức tạp đến đâu; Cache 1-Pass giữ hiệu năng ổn định; và Global Variables + Comment kết hợp tạo khả năng phục hồi trạng thái gần như tức thì sau bất kỳ sự cố VPS.

Đây là bài viết giáo dục kỹ thuật lập trình MQL5, không phải khuyến nghị giao dịch, không bán tín hiệu và không cam kết lợi nhuận. Áp dụng bất kỳ đoạn code nào vào tài khoản thật là quyết định và trách nhiệm của người vận hành; hãy luôn kiểm thử kỹ trên demo trước khi đưa EA lên tài khoản live.

Nếu bạn muốn đi tiếp từ nền tảng định danh lệnh này sang toàn bộ kiến trúc Grid, Surplus/Hedge, FSM, Sweep và Guard của một EA hedging thực chiến kiểu Nhị Quái V9, Mời các bạn xem khóa và đăng ký ở đây.


Bài viết thuộc chuỗi nội dung kỹ thuật đi kèm khóa Lập trình MT5 Nâng cao Hedging & Tự động hóa — Hướng Nghiệp Dữ Liệu. Nội dung tập trung vào kỹ thuật định danh và vận hành EA, không khuyến nghị đầu tư, không bán tín hiệu giao dịch.

Mời các bạn xem khóa và đăng ký ở đây:

admin

admin

Biên tập viên, Hướng Nghiệp Dữ Liệu
767 Bài viết
15.4k Người theo dõi
120k+ Lượt đọc

Biên tập viên nội dung tại Hướng Nghiệp Dữ Liệu, phụ trách tổng hợp và biên soạn các bài viết về lập trình Python, dữ liệu và công nghệ.