Bài viết gần đây
-
-
Buổi 21 IB Bot — Autorebates & minh bạch backcom OPC
Tháng 7 17, 2026 -
Buổi 13 IB Bot — Telegram API, báo cáo PnL và phễu Investor Pass
Tháng 7 15, 2026
Trang chủ → Bài Viết → FSM + Global Variables cho Bot IB MT5 — Buổi 3: không mất trạng thái khi VPS restart
| FSM + Global Variables cho Bot IB MT5 — Buổi 3: không mất trạng thái khi VPS restart
Được viết bởi thanhdt vào ngày 14/07/2026 lúc 17:17 | 51 lượt xem
Ghép FSM + Global Variables cho Bot IB MT5: bot không mất trạng thái khi VPS restart
Một buổi sáng, VPS chạy MT5 tự khởi động lại vì cập nhật Windows. Terminal mở lên, EA gắn lại vào chart, biểu tượng vẫn cười ở góc trên phải. Nhìn thoáng qua, mọi thứ bình thường. Nhưng bot cày commission cho tài khoản IB của bạn đã quên hoàn toàn nó đang ở “bước” nào trong cụm lệnh, đang gánh bao nhiêu bias Buy/Sell, đã từng khóa lockdown hay chưa. Nó bắt đầu lại từ đầu, như thể tài khoản vừa mở tối qua.
Đây không phải kịch bản hiếm. VPS Windows dùng cho MT5 restart vì nhiều lý do: patch Tuesday, mất điện, MT5 tự đóng khi hết bộ nhớ, hoặc chính bạn chủ động restart để dọn RAM. Với tài khoản demo chỉ để test, mất trạng thái gây khó chịu. Nhưng với hệ thống đang cày volume thật để nhận backcom IB, mất trạng thái đồng nghĩa mất kiểm soát rủi ro đúng lúc cần nhất — ngay sau một biến động giá mạnh, khi tài khoản có thể đang gồng một cụm lệnh âm mà bot “mới sinh ra” không hề biết.
Hai buổi trước trong lộ trình Xây Dựng IB Bằng Bot Auto Trading, chúng ta học riêng lẻ hai công cụ: FSM (máy trạng thái hữu hạn) để phân loại rõ tài khoản đang ở bước nào, và Global Variables của Terminal MT5 để ghi nhớ dữ liệu sống ngoài phạm vi một lần chạy EA. Buổi 3 ghép hai công cụ đó lại thành một khối thống nhất, chạy trên tài khoản demo, với một tiêu chí duy nhất để coi là đạt: bot phục hồi đúng trạng thái sau khi Terminal hoặc VPS restart, không tự “reset về 0” và không nhồi lệnh sai vì tưởng mình đang ở trạng thái ban đầu.
Bài viết này nhắc lại nhanh nền tảng Buổi 1 và Buổi 2, rồi đi sâu vào phần ghép nối của Buổi 3: luồng phục hồi trong OnInit, cách đặt tên Global Variables để không đụng nhau giữa nhiều EA, cảnh báo Telegram khi mất kết nối, và checklist trước khi lớp chuyển sang Phần 2 — thuật toán O(N) và cache.
Vì sao “mất trạng thái” là rủi ro vận hành, không phải lỗi vặt
Bot IB commission farming cố ý duy trì nhiều lệnh cùng lúc theo một cấu trúc rải quân có kiểm soát, và cấu trúc đó chỉ an toàn nếu bot biết chính xác mình đang ở đâu trong cấu trúc — ngay cả sau khi vừa khởi động lại. Một số câu hỏi bot cần trả lời đúng ở mọi thời điểm: tài khoản đang rải đến step thứ mấy theo mỗi hướng; cụm hiện tại đã chạm ngưỡng chốt lời X-tier nào chưa; bias Buy/Sell đang lệch bao nhiêu; bot đã từng kích hoạt lockdown chưa; lần thu hoạch cụm gần nhất diễn ra khi nào để tránh mở lại quá sớm.
Nếu câu trả lời sau khi restart là “không biết, coi như chưa có gì cả”, hệ quả thường không phải bot dừng lại an toàn — mà là bot mở lại logic ban đầu trên một tài khoản đã có vị thế đang mở: mở thêm lệnh cùng hướng với cụm đã lệch bias nặng, hoặc tính lại mốc giá tham chiếu (P0) từ giá hiện tại thay vì giá mở cụm ban đầu, làm sai toàn bộ phép tính step tiếp theo.
Với một trader tự chạy bot cho mình, đây đã là vấn đề nghiêm trọng. Với vai trò IB — có thể đang chạy bot mẫu để khách quan sát, hoặc cày commission trên nhiều tài khoản theo mô hình OPC (One Person Company) — một lỗi mất trạng thái lặp lại ở quy mô nhiều tài khoản sẽ nhân rủi ro lên tương ứng. Đây là lý do Phần 1 của khóa dành nguyên ba buổi cho vấn đề tưởng “kỹ thuật vặt” này.
Nhắc lại FSM — Buổi 1: máy trạng thái cho bot IB
FSM (Finite State Machine) mô hình hóa bot dưới dạng tập hợp trạng thái hữu hạn, cùng quy tắc chuyển trạng thái rõ ràng giữa chúng. Thay vì viết một mớ biến bool rời rạc như is_locked, is_hedging, just_reset và để bot tự suy luận tổ hợp cờ đó nghĩa là gì, FSM buộc bạn khai báo trước: bot chỉ ở một trạng thái tại một thời điểm, mỗi trạng thái chỉ cho phép một số hành động nhất định.
Buổi 1 đề xuất một tập trạng thái tối giản đủ dùng cho bản demo:
| Trạng thái | Ý nghĩa | Hành động được phép |
|---|---|---|
IDLE |
Chưa có lệnh, chờ điều kiện mở cụm đầu tiên | Mở lệnh mở đầu theo tín hiệu |
BUILDING |
Đang rải quân theo step, cụm chưa chốt | Mở thêm theo step, theo dõi bias |
HARVESTING |
Cụm đã chạm ngưỡng, đang thu hoạch theo tầng | Đóng theo X-tier, không mở mới cùng hướng |
LOCKED |
Bias hoặc drawdown vượt ngưỡng an toàn | Chỉ giảm rủi ro, cấm mở lệnh mới |
RECOVERING |
Vừa khởi động lại, đang xác nhận trạng thái thật | Không giao dịch, chỉ đọc và đối chiếu |
Điểm quan trọng nhất không phải danh sách trạng thái — mỗi bot có thể đặt tên khác nhau — mà là nguyên tắc: OnTick không được tự do làm bất cứ điều gì; nó phải hỏi FSM “hành động này có hợp lệ ở trạng thái hiện tại không” trước khi gửi lệnh. Đây là lớp phòng thủ đầu tiên chống nhồi lệnh: tín hiệu giá đến giữa lúc bot đang HARVESTING sẽ bị chặn mở thêm, dù giá có “đẹp” đến đâu.
OnTick chỉ xử lý sự kiện giá và gọi hàm chuyển trạng thái tương ứng; OnInit chịu trách nhiệm xác định bot nên bắt đầu ở trạng thái nào khi EA vừa được nạp — đây là cầu nối sang vấn đề của Buổi 2: OnInit lấy dữ liệu đó từ đâu, nếu không phải từ bộ nhớ tạm đã biến mất cùng lần chạy trước?
Nhắc lại Global Variables — Buổi 2: bộ nhớ ngoài file của Terminal MT5
Biến thông thường trong MQL5 chỉ sống trong phạm vi một lần EA được nạp vào chart. Khi Terminal đóng vì VPS restart, toàn bộ giá trị biến biến mất; lần chạy tiếp theo, OnInit khởi động với giá trị mặc định — không phải giá trị bot đã tích lũy trước đó.
Global Variables là cơ chế riêng của Terminal MT5, nằm ở cấp Terminal (không phải cấp EA hay chart) và vẫn còn đó sau khi Terminal đóng mở lại, miễn thư mục dữ liệu Terminal không bị xóa và biến chưa bị dọn tự động do quá lâu không được truy cập (mỗi lần đọc/ghi làm mới “đồng hồ sống” của biến).
Bốn hàm cốt lõi Buổi 2 thực hành:
| Hàm | Vai trò |
|---|---|
GlobalVariableSet(name, value) |
Ghi/cập nhật giá trị double cho một Global Variable |
GlobalVariableGet(name) |
Đọc giá trị hiện tại; trả 0 nếu biến chưa tồn tại |
GlobalVariableCheck(name) |
Kiểm tra biến đã tồn tại chưa, tránh nhầm “chưa từng ghi” với “giá trị thật là 0” |
GlobalVariableDel(name) |
Xóa biến khi trạng thái đó không còn ý nghĩa |
Lỗi phổ biến khi mới học là quên gọi GlobalVariableCheck trước GlobalVariableGet. Vì GlobalVariableGet trả 0.0 cho cả hai trường hợp “chưa từng tạo” và “tồn tại với giá trị đúng là 0”, nếu không kiểm tra tồn tại trước, bot dễ hiểu sai “P0 = 0” là “chưa có mốc giá tham chiếu” trong khi biến chỉ đơn giản chưa từng được ghi.
Buổi 2 thực hành trực tiếp: chạy EA trên demo, ghi vài giá trị, chủ động đóng Terminal, mở lại, rồi kiểm tra tab Global Variables trong MT5 xem giá trị còn nguyên hay không. Bài tập này giúp học viên nhận ra: Global Variables ở cấp Terminal, nên nếu chạy nhiều EA hoặc nhiều tài khoản trên cùng Terminal, tên biến trùng nhau sẽ ghi đè lẫn nhau — vấn đề Buổi 3 phải giải quyết bằng quy ước đặt tên.
Buổi 3 — ghép FSM + Global Variables trên demo
Ghép hai công cụ nghe đơn giản trên lý thuyết: mỗi khi FSM chuyển trạng thái, ghi trạng thái mới vào Global Variables; mỗi khi OnInit chạy, đọc lại để dựng trạng thái. Nhưng thực hành trên demo lộ ra nhiều chi tiết mà slide không thấy.
Trạng thái không chỉ là một con số. Để phục hồi đúng, bot cần thêm dữ liệu phụ đi kèm trạng thái: giá tham chiếu mở cụm (P0), step hiện tại theo từng hướng, tầng X-tier đã chạm, thời điểm chuyển trạng thái gần nhất (tính cooldown), bias tích lũy. Một trạng thái FSM logic tương ứng với một nhóm Global Variables, không phải một biến đơn lẻ.
Đặt tên để không đụng nhau. Nếu chạy cùng EA trên hai symbol hoặc hai magic khác nhau trên cùng Terminal (phổ biến khi test song song nhiều tham số), Global Variables phải có prefix riêng cho từng cấu hình. Quy ước thống nhất trong lớp:
IB_<Symbol>_<Magic>_<TenBien>
Ví dụ: IB_XAUUSD_10021_State, IB_XAUUSD_10021_P0, IB_XAUUSD_10021_LastStepBuy. Prefix IB_ đánh dấu biến thuộc hệ thống của khóa; Symbol và Magic đảm bảo hai cấu hình không ghi đè nhau. Thiếu quy ước này là nguyên nhân phổ biến nhất khiến học viên báo “bot phục hồi sai” — hóa ra hai EA test song song đang đọc/ghi cùng một biến.
Khi nào nên xóa, khi nào nên giữ. Khi một cụm lệnh đã đóng hoàn toàn (tổng vị thế theo magic về 0), các biến mô tả cụm đó — P0, step, tầng X-tier — nên bị xóa bằng GlobalVariableDel, để lần rải quân tiếp theo bắt đầu từ dữ liệu sạch, không kế thừa nhầm mốc giá của cụm cũ. Ngược lại, biến đếm tích lũy như tổng số lần reset, tổng số lần lockdown, nên được giữ lại và cộng dồn, vì phục vụ mục đích giám sát dài hạn.
Buổi 3 thực hành theo bốn bước trên demo: (1) gắn EA đã ghép FSM + Global Variables, để chạy tự nhiên và rải một cụm nhỏ; (2) ghi lại “ảnh chụp” trạng thái hiện tại — state, P0, step, bias, in qua Comment() hoặc log ra file; (3) chủ động mô phỏng sự cố — đóng Terminal hoàn toàn hoặc restart VPS thật rồi mở lại; (4) so sánh ảnh chụp sau khi mở lại với trước đó — nếu khớp, OnInit phục hồi đúng; nếu lệch, cả lớp cùng debug xem thiếu biến nào.
Bước 4 là bước học được nhiều nhất, vì rất nhiều lỗi phục hồi không nằm ở logic Global Variables mà ở thứ tự đọc trong OnInit — ví dụ đọc P0 trước khi đọc State, dẫn đến một đoạn code trung gian dùng P0 mặc định 0 trước khi State thật được xác lập.
Recovery flow: OnInit đọc lại trạng thái thế nào
Một hàm OnInit phục hồi tốt cần trình tự cố định:
- Xác nhận kết nối và đồng bộ dữ liệu — kiểm tra symbol đã chọn đúng trước khi đọc Global Variables. Đọc trạng thái trên dữ liệu chưa đồng bộ dễ dẫn đến quyết định sai.
- Đọc trạng thái FSM thô từ Global Variables bằng
GlobalVariableCheck+GlobalVariableGet, không suy đoán. Nếu biến chưa tồn tại, đây là lần chạy đầu tiên — gánIDLE. - Đối chiếu với vị thế thật trên tài khoản — dùng
PositionsTotal()lọc theo magic để đếm số lệnh đang mở. Nếu Global Variables nói “đangBUILDING” nhưng thực tế không còn vị thế, dữ liệu đã lệch thực tế (lệnh bị đóng thủ công hoặc Stop Out) — bot phải ưu tiên thực tế trên sàn, tự sửa trạng thái vềIDLEkèm xóa biến phụ liên quan. - Chỉ sau khi đối chiếu xong mới đặt lại trạng thái chính thức và cho phép
OnTickhoạt động. Trong lúc đối chiếu, FSM nên tạm ởRECOVERING— không giao dịch. - Ghi log rõ ràng quá trình phục hồi — in ra Experts tab trạng thái đọc được, số vị thế thực tế, trạng thái cuối cùng được chọn. Log này là thứ đầu tiên bạn cần khi VPS restart giữa đêm và cần biết bot đã tự xử lý đúng hay chưa.
Nguyên tắc bao trùm: dữ liệu trên sàn (vị thế thật) luôn có quyền phủ quyết dữ liệu trong Global Variables. Global Variables là bộ nhớ hỗ trợ, không phải nguồn sự thật duy nhất. Nếu hai nguồn lệch nhau, bot phải nghiêng về phía an toàn hơn — thường là giả định ít thông tin nhất và không mở lệnh mới cho đến khi trạng thái được xác nhận lại từ dữ liệu thật.
Telegram cảnh báo khi mất kết nối
Phục hồi trạng thái giải quyết vế “bot tự lo cho nó”, nhưng người vận hành vẫn cần biết có sự cố đã xảy ra, đặc biệt nếu VPS restart nhiều lần liên tiếp. Buổi 3 thêm cảnh báo Telegram tối giản cho hai tình huống:
- EA vừa khởi động lại — gửi tin nhắn ngắn gồm thời điểm, symbol, magic, trạng thái vừa phục hồi. Đây là bản ghi vận hành giúp bạn biết chính xác VPS đã restart lúc nào mà không cần đăng nhập kiểm tra.
- Mất kết nối tới sàn kéo dài quá một ngưỡng — kiểm tra định kỳ trong
OnTimerbằngTerminalInfoInteger(TERMINAL_CONNECTED); nếu mất kết nối liên tục vượt ngưỡng (ví dụ 60 giây), gửi cảnh báo. Không cảnh báo ngay ở giây đầu tiên, vì rớt mạng vài giây rồi tự nối lại là bình thường — cảnh báo quá nhạy làm bạn bỏ qua tin nhắn thật quan trọng lẫn giữa hàng loạt tin nhắn nhiễu.
Gửi tin nhắn Telegram từ MQL5 dùng WebRequest() gọi tới Telegram Bot API. Ba điều dễ quên khi mới làm lần đầu: domain https://api.telegram.org phải được thêm vào danh sách URL cho phép ở Tools → Options → Expert Advisors, nếu không WebRequest báo lỗi ngay từ dòng gọi đầu; không gọi WebRequest liên tục trong OnTick vì tốn thời gian chờ mạng, nên tách qua OnTimer; token bot và Chat ID không nên hardcode trong file .mq5 nếu có ý định chia sẻ hoặc bán bot.
Trong phạm vi Buổi 3, mục tiêu chỉ là bản tối giản chạy được trên demo: bot restart → gửi được tin nhắn xác nhận trạng thái phục hồi. Các phiên bản nâng cao — báo cáo PnL định kỳ, cảnh báo drawdown, kênh riêng cho từng khách Investor Pass — thuộc Phần 5 của lộ trình, khi hệ thống đã sẵn sàng phục vụ nhiều tài khoản khách.
Checklist OPC trước khi qua Phần 2
Phần 1 (ba buổi FSM + Global Variables) là nền tảng cho toàn bộ 21 buổi còn lại — từ tối ưu thuật toán, kiến trúc sinh tồn, Basket TP, đến Copy Trading và Auto Marketing OPC. Trước khi chuyển sang Phần 2 (thuật toán O(N) & Cache), Buổi 3 chốt bằng checklist tự đánh giá:
| # | Mục kiểm tra |
|---|---|
| 1 | Bot có 4–5 trạng thái FSM rõ ràng, mỗi trạng thái quy định hành động được/không được phép |
| 2 | Global Variables đặt tên theo prefix IB_<Symbol>_<Magic>_..., không trùng giữa các cấu hình chạy song song |
| 3 | OnInit đọc lại trạng thái từ Global Variables trước khi cho phép OnTick giao dịch |
| 4 | OnInit đối chiếu trạng thái đọc được với vị thế thật (PositionsTotal theo magic), ưu tiên dữ liệu sàn khi lệch |
| 5 | Đã thử thực tế: đóng Terminal, mở lại, kiểm tra trạng thái phục hồi đúng như trước khi đóng |
| 6 | Global Variables gắn với một cụm cụ thể được xóa (GlobalVariableDel) sau khi cụm đó đóng hoàn toàn |
| 7 | Có cảnh báo Telegram tối thiểu khi EA khởi động lại |
| 8 | Không có đoạn code nào trong OnTick tự mở lệnh mà không qua kiểm tra trạng thái FSM hiện tại |
| 9 | Đã chạy thử liên tục tối thiểu 24 giờ trên demo mà không cần can thiệp tay để “sửa” trạng thái sai |
| 10 | Hiểu rõ khác biệt giữa Global Variables cấp Terminal và biến cục bộ cấp EA khi debug |
Nếu một mục “Chưa đạt”, đừng vội chuyển sang Buổi 4. Một bot tối ưu tốc độ nhưng vẫn mất trạng thái khi restart chỉ đang tối ưu nhầm chỗ. Mục số 4 (đối chiếu vị thế thật) thường bị bỏ qua nhất, vì nó không tạo hiệu ứng gì nhìn thấy trong điều kiện chạy bình thường — chỉ lộ ra khi có sự cố thật.
Code MQL5 minh họa
Các đoạn code dưới đây mang tính minh họa cho nguyên lý, không phải bản đầy đủ của một bot commercial. Mục tiêu là giúp bạn hình dung cách enum FSM, quy ước Global Variables, và hàm OnInit phục hồi khớp với nhau.
A. Enum trạng thái FSM
enum ENUM_IB_STATE
{
IB_STATE_IDLE = 0, // chưa có cụm nào đang mở
IB_STATE_BUILDING = 1, // đang rải quân theo step
IB_STATE_HARVESTING = 2, // đang thu hoạch theo tầng X-tier
IB_STATE_LOCKED = 3, // bias/drawdown vượt ngưỡng an toàn
IB_STATE_RECOVERING = 4 // vừa khởi động lại, chưa xác nhận xong
};
bool CanOpenNewOrder(ENUM_IB_STATE state)
{
return (state == IB_STATE_IDLE || state == IB_STATE_BUILDING);
}
// Chuyển trạng thái có kiểm soát — không gán tự do ở bất kỳ đâu trong code
void TransitionState(ENUM_IB_STATE ¤t, ENUM_IB_STATE next, string reason)
{
if(current == next) return;
PrintFormat("[FSM] %s -> %s | Ly do: %s", EnumToString(current), EnumToString(next), reason);
current = next;
}
Nguyên tắc bắt buộc: không có dòng code nào trong OnTick được gán trực tiếp state = IB_STATE_BUILDING. Mọi thay đổi phải qua TransitionState, để mọi lần chuyển trạng thái đều được log — cách duy nhất để debug khi có sự cố lúc bạn không trực tiếp quan sát màn hình.
B. Quy ước đặt tên Global Variables
string GVName(string suffix)
{
return StringFormat("IB_%s_%d_%s", _Symbol, InpMagic, suffix);
}
void SaveState(ENUM_IB_STATE state)
{
GlobalVariableSet(GVName("State"), (double)state);
GlobalVariableSet(GVName("LastChangeTime"), (double)TimeCurrent());
}
ENUM_IB_STATE LoadState()
{
string gv = GVName("State");
if(!GlobalVariableCheck(gv)) return IB_STATE_IDLE;
return (ENUM_IB_STATE)(int)GlobalVariableGet(gv);
}
// Xóa toàn bộ dữ liệu gắn với một cụm đã đóng hoàn toàn
void ClearClusterData()
{
GlobalVariableDel(GVName("P0"));
GlobalVariableDel(GVName("LastStepBuy"));
GlobalVariableDel(GVName("LastStepSell"));
GlobalVariableDel(GVName("XTierHit"));
// State và LastChangeTime giữ lại — không thuộc riêng cụm
}
Dùng InpMagic (input do người vận hành khai báo) trong GVName bảo đảm hai instance của cùng EA — ví dụ chạy song song trên XAUUSD với hai magic khác nhau để test hai bộ tham số — không đọc/ghi chồng lên nhau, dù chạy trên cùng một Terminal.
C. OnInit — luồng phục hồi đầy đủ
ENUM_IB_STATE g_state = IB_STATE_IDLE;
int OnInit()
{
g_state = IB_STATE_RECOVERING;
if(!SymbolSelect(_Symbol, true))
{
PrintFormat("[RECOVERY] Khong chon duoc symbol %s -> dung khoi dong", _Symbol);
return INIT_FAILED;
}
ENUM_IB_STATE savedState = LoadState();
PrintFormat("[RECOVERY] Trang thai doc tu Global Variables: %s", EnumToString(savedState));
int realPositionCount = 0;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(PositionSelectByTicket(ticket) && PositionGetInteger(POSITION_MAGIC) == InpMagic)
realPositionCount++;
}
// Dữ liệu sàn có quyền phủ quyết Global Variables
if(realPositionCount == 0 && savedState != IB_STATE_IDLE)
{
PrintFormat("[RECOVERY] GV noi '%s' nhung khong con vi the -> reset IDLE", EnumToString(savedState));
ClearClusterData();
savedState = IB_STATE_IDLE;
SaveState(savedState);
}
else if(realPositionCount > 0 && savedState == IB_STATE_IDLE)
{
// Có vị thế thật nhưng GV nói IDLE — dữ liệu mất đồng bộ
// -> vào LOCKED tạm thời để kiểm tra tay, an toàn hơn đoán bừa
PrintFormat("[RECOVERY] Phat hien %d vi the thuc nhung State=IDLE -> chuyen LOCKED", realPositionCount);
savedState = IB_STATE_LOCKED;
SaveState(savedState);
}
TransitionState(g_state, savedState, "Hoan tat phuc hoi sau khoi dong");
SendTelegramAlert(StringFormat("Bot %s (magic %d) da khoi dong lai. Trang thai: %s | Vi the thuc: %d",
_Symbol, InpMagic, EnumToString(g_state), realPositionCount));
return INIT_SUCCEEDED;
}
Ba nhánh xử lý ở giữa hàm là phần dễ bị bỏ sót nhất: đa số chỉ nghĩ đến trường hợp “đọc được trạng thái thì dùng luôn”, quên trường hợp hai nguồn dữ liệu lệch nhau theo cả hai chiều. Xử lý đúng cả hai chiều lệch là phần cốt lõi khiến bot an toàn khi restart, không chỉ “chạy được khi restart”.
Câu hỏi thường gặp
1. Global Variables có mất khi cài lại MT5 hoặc đổi VPS không?
Có, vì chúng lưu trong thư mục dữ liệu của Terminal cụ thể đó. Đây là lý do bot không nên coi Global Variables là nguồn dữ liệu duy nhất — luôn cần đối chiếu với vị thế thật.
2. Global Variables có tự bị xóa sau một thời gian không?
MT5 dọn Global Variable không được truy cập trong thời gian dài. Với bot chạy liên tục và đọc/ghi thường xuyên, “đồng hồ sống” được làm mới liên tục nên hầu như không gặp vấn đề này.
3. Có cần dùng file thay Global Variables không?
Với một EA đơn giản trên một Terminal, Global Variables đủ dùng. Hệ thống nhiều Terminal cần dashboard tổng hợp riêng, nhưng đó thuộc các phần sau của lộ trình.
4. FSM có làm bot chạy chậm hơn không?
Không đáng kể — kiểm tra một biến enum và vài hàm điều kiện tốn ít hơn nhiều so với phép tính giá hay vòng lặp quét vị thế.
5. Có thể chỉ lưu trạng thái vào comment lệnh, bỏ Global Variables không?
Không. Comment lệnh gắn với từng lệnh cụ thể, không thay được dữ liệu cấp cụm hoặc cấp tài khoản — ví dụ trạng thái FSM khi không còn vị thế nào để gắn comment.
6. Buổi 3 có bắt buộc VPS thật để thực hành không?
Không. Đóng và mở lại Terminal trên máy đang dùng đã đủ mô phỏng việc EA bị nạp lại từ đầu — đúng bài toán mà OnInit phục hồi cần giải quyết.
7. Bot chạy nhiều tài khoản theo mô hình OPC thì Global Variables có đủ dùng không?
Ở vài tài khoản trên các Terminal riêng biệt thì đủ. Khi scale lên hàng chục khách (Phần 6), cần thêm lớp giám sát tập trung, nhưng FSM + Global Variables ở từng Terminal vẫn là lớp phục hồi cấp thấp nhất.
8. Học xong Buổi 3 thì sang buổi nào?
Buổi 4 mở đầu Phần 2 — thuật toán 1-Pass O(N) tránh vòng lặp lồng làm nặng VPS. Nền tảng trạng thái vừa xây tiếp tục được dùng lại xuyên suốt các phần sau.
Không cam kết lợi nhuận — cam kết kỹ năng vận hành
Toàn bộ nội dung Buổi 3, và cả Phần 1 của khóa, tập trung vào một mục tiêu: giúp người vận hành kiểm soát được trạng thái hệ thống của mình, không phải hứa hẹn một chiến lược sinh lời cố định. FSM và Global Variables không dự đoán được giá sẽ đi đâu, không đảm bảo cụm lệnh nào cũng chốt lời, và không thay thế việc bạn hiểu rõ rủi ro của cấu hình mình đang chạy.
Buổi học này chỉ đảm bảo: nếu bot từng chạy đúng logic trước khi VPS restart, nó sẽ tiếp tục chạy đúng logic đó sau khi restart, thay vì âm thầm chuyển sang hành vi khác mà bạn không hề biết cho đến khi kiểm tra tài khoản và thấy kết quả bất thường. Đây là điều kiện cần để vận hành bất kỳ chiến lược nào có trách nhiệm, không phải điều kiện đủ để chiến lược đó sinh lời. Kết quả giao dịch thực tế phụ thuộc tham số, điều kiện thị trường, kỷ luật vận hành và khả năng chịu rủi ro của từng người — không nằm trong phạm vi cam kết của khóa học.
Với vai trò IB, minh bạch nguyên tắc này với khách hàng cũng quan trọng không kém việc code đúng: một hệ thống phục hồi trạng thái tốt giúp bạn báo cáo chính xác những gì đã xảy ra trên tài khoản, thay vì phải giải thích một khoảng “mất kết nối, không rõ chuyện gì đã diễn ra”.
Nếu bạn muốn tiếp tục xây phần còn lại của hệ thống — từ tối ưu thuật toán, kiến trúc sinh tồn, Basket TP, Copy Trading, đến mô hình scale IB theo OPC — Mời các bạn xem khóa và đăng ký ở đây.
Mời các bạn xem khóa và đăng ký ở đây:
Weekly Digest — Nhận Bản Tin Hàng Tuần
Nhận các bài viết phân tích kỹ thuật chuyên sâu, thuật toán giao dịch tự động (Trading Bot) và các giải pháp công nghệ mới nhất từ Hướng Nghiệp Dữ Liệu.
admin
Biên tập viên, Hướng Nghiệp Dữ LiệuBiê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ệ.