Nối TradingView với MT5 để auto trade Forex: hướng dẫn đầy đủ
Forex có một đặc thù: bạn thường phân tích trên TradingView (chỉ báo đẹp, Pine Script linh hoạt, backtest nhanh) nhưng lại giao dịch trên MT5 (nơi broker của bạn cấp tài khoản, spread tốt hơn, hỗ trợ hedging). Hai nền tảng không nói chuyện được với nhau — và đó chính là chỗ cần một cầu nối.
Bài viết này hướng dẫn đầy đủ cách nối chúng bằng Python: thư viện MetaTrader5, khởi tạo và kiểm tra kết nối, tính lot theo % rủi ro với pip value thật, đặt lệnh market kèm SL/TP, xử lý lỗi `type_filling` 10030, phân biệt tài khoản hedging và netting, dùng magic number để quản lý nhiều chiến lược, và cuối cùng là đưa MT5 lên VPS Windows chạy 24/7 mà không bị Windows Update giết giữa đêm.
Đọc trước nếu bạn chưa có phần nhận tín hiệu: Bot Python nhận webhook TradingView.
Trả lời nhanh
Cách chuẩn để nối TradingView với MT5 là: một VPS Windows chạy MT5 và chạy bot Python trên cùng máy. Bot dùng thư viện MetaTrader5 (do MetaQuotes phát hành, chỉ chạy trên Windows) để nói chuyện trực tiếp với terminal MT5 đang đăng nhập sẵn — không cần MQL5, không cần EA.
Ba điều kiện sống còn: (1) MT5 phải đang chạy và đã bật "Allow algorithmic trading", (2) bot phải gửi đúng type_filling mà symbol hỗ trợ (nếu không sẽ nhận lỗi 10030 Invalid filling mode), (3) khoảng cách SL/TP phải lớn hơn trade_stops_level của symbol (nếu không nhận 10016 Invalid stops).
Khác với crypto, Forex có pip value phụ thuộc vào giá và cặp tiền, nên công thức tính lot bắt buộc phải dùng trade_tick_value từ symbol_info() — dùng con số cứng "1 pip = 10 USD" là sai ngay với các cặp cross như GBPJPY.
MT5 có API gì cho Python?
MetaQuotes phát hành một package Python chính thức: MetaTrader5. Đây không phải wrapper quanh file log hay quanh DLL lạ — nó giao tiếp trực tiếp với terminal MT5 qua IPC, và cung cấp gần như mọi thứ bạn cần:
| Nhóm hàm | Dùng để làm gì |
|---|---|
initialize(), login(), shutdown() | Kết nối tới terminal, đăng nhập tài khoản |
terminal_info(), version() | Kiểm tra terminal còn sống, đã bật algo trading chưa |
account_info() | Số dư, equity, margin, chế độ margin (hedging/netting) |
symbol_info(), symbol_info_tick() | Bộ lọc symbol: point, digits, volume_step, trade_stops_level, trade_tick_value; giá bid/ask hiện tại |
symbol_select() | Bật symbol vào Market Watch (bắt buộc trước khi giao dịch) |
order_send() | Gửi lệnh: mở, đóng, sửa SL/TP, lệnh chờ |
positions_get(), orders_get(), history_deals_get() | Truy vấn vị thế, lệnh chờ, lịch sử khớp |
copy_rates_from_pos() | Lấy dữ liệu nến (không cần cho bot webhook, nhưng hữu ích khi đối soát) |
Giới hạn quan trọng nhất: package này chỉ chạy trên Windows. Đây là lý do bot MT5 của bạn buộc phải đặt trên VPS Windows, trong khi bot crypto có thể chạy trên Linux rẻ hơn. Nếu bạn muốn dùng chung một bot cho cả hai, hãy tách endpoint (Linux) và worker MT5 (Windows) như kiến trúc ở bài 3.
Hạ tầng cần chuẩn bị
1. VPS Windows. Cấu hình tối thiểu thực tế: 2 vCPU, 4 GB RAM, SSD 60 GB. MT5 khá nhẹ, nhưng Windows cần chỗ cho updates. Chọn VPS đặt gần server broker nếu bạn chạy chiến lược khung nhỏ.
2. MT5 cài trên VPS và đã đăng nhập tài khoản (demo trước, real sau). Bật sẵn Tools → Options → Expert Advisors → Allow algorithmic trading. Nếu bỏ qua bước này, mọi lệnh của bạn sẽ bị từ chối với lỗi 10027 hoặc 10026.
3. Bot Python trên cùng máy, có thư viện: pip install MetaTrader5 flask requests.
4. Tài khoản broker ở chế độ hedging nếu bạn muốn mở nhiều vị thế trên cùng một cặp. Chế độ này do broker quyết định khi tạo tài khoản, không đổi được sau đó — hãy kiểm tra trước khi thiết kế logic bot.
5. Một symbol đang có trong Market Watch. Nếu symbol không được chọn, order_send trả về lỗi. Luôn gọi symbol_select(symbol, True) một lần khi khởi động.
Một lưu ý về an toàn: đừng bao giờ hardcode mật khẩu MT5 trong code. Nếu MT5 đã đăng nhập sẵn (lưu mật khẩu), bot chỉ cần initialize() là dùng được phiên đăng nhập đó. Chỉ truyền login/password/server khi bạn thật sự cần đăng nhập từ code, và khi đó hãy đọc từ biến môi trường.
Khởi tạo và kiểm tra kết nối
import MetaTrader5 as mt5
def init_mt5(path: str | None = None) -> None:
if not mt5.initialize(path) if path else not mt5.initialize():
raise RuntimeError(f"initialize() failed: {mt5.last_error()}")
ti = mt5.terminal_info()
if ti is None:
raise RuntimeError("Không lấy được terminal_info")
if not ti.trade_allowed:
raise RuntimeError("MT5 đang tắt 'Allow algorithmic trading' — bật lên rồi chạy lại")
ai = mt5.account_info()
log.info("Đã kết nối: account=%s balance=%.2f equity=%.2f margin_mode=%s",
ai.login, ai.balance, ai.equity, ai.margin_mode)
mt5.symbol_select("XAUUSD", True)
info = mt5.symbol_info("XAUUSD")
log.info("point=%s digits=%s volume_min=%s volume_step=%s stops_level=%s tick_value=%s",
info.point, info.digits, info.volume_min, info.volume_step,
info.trade_stops_level, info.trade_tick_value)Đoạn code này là "bài kiểm tra sức khoẻ" mà bạn nên chạy mỗi khi bot khởi động. Nếu initialize() thất bại, nguyên nhân thường là: MT5 chưa chạy, chạy dưới user khác, hoặc Python và MT5 ở hai kiến trúc khác nhau (32-bit vs 64-bit) — hãy cài Python 64-bit và MT5 64-bit cho khớp.
Nếu trade_allowed = False, đừng cố gửi lệnh. Bot nên log rõ và gửi cảnh báo, vì đây là lỗi cấu hình chứ không phải lỗi tạm thời.
Hiểu pip, point và stops level của MT5
Đây là phần gây lỗi nhiều nhất với người mới làm bot MT5, vì MT5 dùng hai đơn vị khác nhau:
- `point`: đơn vị nhỏ nhất của giá. Với EURUSD niêm yết 5 chữ số,
point = 0.00001. - `pip`: đơn vị truyền thống = 10 point với cặp 5 chữ số, = 1 point với cặp 3 chữ số (JPY).
Vậy SL cách 30 pip = 30 × 10 × point = 0.00300 với EURUSD 5 số. Nếu bạn nhầm và dùng 30 × point, SL của bạn cách giá 3 pip thay vì 30 — bot sẽ bị lỗi 10016 Invalid stops hoặc bị đóng lệnh sau vài giây.
`trade_stops_level` là khoảng cách tối thiểu (tính bằng point) giữa giá vào và SL/TP. Nếu broker của bạn yêu cầu 50 point, đặt SL gần hơn sẽ bị từ chối. Công thức an toàn:
def safe_sl_price(side: str, price: float, sl_dist_points: int, info) -> float:
min_dist = max(info.trade_stops_level, 10) * info.point # chừa biên an toàn
dist = max(sl_dist_points * info.point, min_dist)
raw = price - dist if side == "buy" else price + dist
return round(raw, info.digits)Với các cặp có spread giãn (XAUUSD trong phiên Á, GBPNZD, các cặp exotic), hãy cộng thêm spread hiện tại vào khoảng cách SL để tránh bị stop do spread chứ không do giá.
Tính lot theo % rủi ro (đúng cho mọi cặp)
Sai lầm phổ biến nhất: dùng công thức lot cứng cho mọi cặp. Forex có pip value thay đổi theo cặp và theo giá. Cách đúng là dùng `trade_tick_value` — giá trị tiền của một tick trên một lot tiêu chuẩn:
def calc_lot(balance: float, risk_pct: float, sl_points: float, info) -> float:
"""sl_points: khoảng cách SL tính bằng POINT (đã gồm spread nếu muốn)."""
risk_money = balance * risk_pct
ticks = sl_points / (info.trade_tick_size / info.point) # số tick trong khoảng SL
loss_per_lot = ticks * info.trade_tick_value
if loss_per_lot <= 0:
raise ValueError("trade_tick_value không hợp lệ")
raw = risk_money / loss_per_lot
step = info.volume_step
lot = max(info.volume_min, round(raw / step) * step)
return round(lot, 2)Ba chi tiết cần kiểm tra với broker của bạn:
- `trade_tick_value` có thể khác nhau cho lệnh buy và sell trên một số symbol (do quy đổi tiền tệ). Nếu bạn muốn chính xác cao, hãy kiểm tra với
order_calc_profit()trước khi gửi lệnh thật. - `volume_step` thường là 0,01 với tài khoản retail, nhưng có broker dùng 0,1 hoặc 1. Làm tròn sai bước là lỗi
10014 Invalid volume. - Khối lượng tối thiểu có thể lớn hơn mức rủi ro bạn muốn (ví dụ
volume_min = 0.10với tài khoản 200 USD). Khi đó hãy chọn: không vào lệnh, hoặc vào với khối lượng nhỏ nhất và chấp nhận rủi ro cao hơn kế hoạch — đừng để bot tự "làm tròn lên" mà không báo.
Kinh nghiệm chạy thật: hãy log ra ba con số risk_money, loss_per_lot, lot cho mỗi tín hiệu trong tuần đầu. Bạn sẽ nhanh chóng phát hiện nếu có cặp nào tính ra lot lệch bất thường.
Đặt lệnh market kèm SL/TP
def open_trade(symbol: str, side: str, lot: float, sl: float, tp: float,
magic: int = 20261006, comment: str = "tv-webhook") -> dict:
info = mt5.symbol_info(symbol)
tick = mt5.symbol_info_tick(symbol)
request = {
"action": mt5.TRADE_ACTION_DEAL,
"symbol": symbol,
"volume": lot,
"type": mt5.ORDER_TYPE_BUY if side == "buy" else mt5.ORDER_TYPE_SELL,
"price": tick.ask if side == "buy" else tick.bid,
"sl": round(sl, info.digits),
"tp": round(tp, info.digits),
"deviation": 20, # trượt giá tối đa (point)
"magic": magic,
"comment": comment,
"type_time": mt5.ORDER_TIME_GTC,
"type_filling": pick_filling(symbol), # xem mục dưới
}
result = mt5.order_send(request)
if result is None:
raise RuntimeError(f"order_send trả về None: {mt5.last_error()}")
if result.retcode != mt5.TRADE_RETCODE_DONE:
raise RuntimeError(f"Lệnh thất bại retcode={result.retcode} comment={result.comment}")
return result._asdict()Bốn trường quan trọng nhất, và lý do:
- `deviation`: mức trượt giá tối đa bạn chấp nhận, tính bằng point. Với tài khoản ECN và XAUUSD,
20là hợp lý; với chiến lược scalp, hạ xuống 5–10; với tin tức lớn, có thể tăng lên 30–50 nhưng phải chấp nhận rủi ro giá xấu. - `magic`: số nguyên định danh chiến lược/bot. Đây là thứ duy nhất giúp bạn tách vị thế của bot này khỏi bot khác trên cùng tài khoản. Không có magic, bạn sẽ phải "đoán" vị thế nào của mình.
- `comment`: ghi chú ngắn (nên chứa mã tín hiệu, ví dụ
tv-20261006-15m-0007) để đối soát chéo với log của bot. - `type_filling`: chế độ khớp lệnh — chỗ sinh ra lỗi
10030nổi tiếng. Xem mục tiếp theo.
Với lệnh chờ (limit/stop), bạn đổi action thành mt5.TRADE_ACTION_PENDING và type thành ORDER_TYPE_BUY_LIMIT / ORDER_TYPE_SELL_LIMIT (hoặc _STOP). Lưu ý: lệnh chờ cần thêm type_time và có thể cần expiration.
Lỗi 10030: chọn đúng type_filling
10030 (Invalid filling mode) là lỗi khiến rất nhiều bot MT5 "chết" ngay lệnh đầu tiên. Nguyên nhân: mỗi symbol chỉ hỗ trợ một số chế độ khớp lệnh nhất định, và bạn phải hỏi broker qua symbol_info().filling_mode:
| Giá trị bit | Hằng số | Ý nghĩa |
|---|---|---|
| 1 | SYMBOL_FILLING_FOK | Fill or Kill: khớp toàn bộ hoặc huỷ |
| 2 | SYMBOL_FILLING_IOC | Immediate or Cancel: khớp phần nào hay phần đó, phần còn lại huỷ |
def pick_filling(symbol: str):
m = mt5.symbol_info(symbol).filling_mode
if m & 1:
return mt5.ORDER_FILLING_FOK
if m & 2:
return mt5.ORDER_FILLING_IOC
return mt5.ORDER_FILLING_RETURNBa kinh nghiệm thực chiến:
- Đừng hardcode `ORDER_FILLING_FOK` vì hầu hết bot mẫu trên mạng làm vậy. Nhiều broker chỉ cho IOC.
- Một số symbol hỗ trợ cả hai, và broker có thể đổi cấu hình. Vì thế hàm
pick_fillingnên chạy mỗi lần gửi lệnh (hoặc cache theo phiên, không cache vĩnh viễn). - Với lệnh market, chế độ lý tưởng là IOC: khớp ngay phần có thanh khoản, không chờ. FOK có thể làm lệnh bị từ chối khi thanh khoản mỏng (ví dụ đầu phiên Á với GBPNZD).
Nếu bạn vẫn gặp 10030 sau khi đã thử đúng bit mask, hãy kiểm tra: symbol có bị hạn chế giao dịch không (trade_mode), tài khoản có phải read-only không, và MT5 có đang ở chế độ "close only" không.
Sửa SL/TP và đóng vị thế
Khi tín hiệu yêu cầu dời stop lên (trailing) hoặc đóng sớm, bạn dùng hai action khác nhau:
def modify_sl_tp(position, sl: float, tp: float, symbol: str):
req = {"action": mt5.TRADE_ACTION_SLTP, "symbol": symbol,
"position": position.ticket, "sl": sl, "tp": tp, "magic": position.magic}
return mt5.order_send(req)
def close_position(position, symbol: str):
info = mt5.symbol_info(symbol); tick = mt5.symbol_info_tick(symbol)
is_buy = position.type == mt5.POSITION_TYPE_BUY
req = {"action": mt5.TRADE_ACTION_DEAL, "symbol": symbol,
"position": position.ticket, "volume": position.volume,
"type": mt5.ORDER_TYPE_SELL if is_buy else mt5.ORDER_TYPE_BUY,
"price": tick.bid if is_buy else tick.ask,
"deviation": 20, "magic": position.magic,
"comment": "close-by-bot", "type_filling": pick_filling(symbol)}
return mt5.order_send(req)Hai lưu ý:
- Đóng vị thế bằng lệnh ngược chiều kèm `position=ticket` là cách chuẩn và an toàn nhất. Trên tài khoản netting, cần đặc biệt cẩn thận vì mở lệnh ngược chiều có thể chỉ làm giảm khối lượng vị thế hiện có thay vì mở vị thế mới.
- `TRADE_ACTION_SLTP` không kiểm tra `trade_stops_level` giống lúc vào lệnh trên một số broker — nhưng nếu SL quá gần, lệnh sửa vẫn có thể bị từ chối với
10016. Vậy nên hãy dùng chung hàmsafe_sl_pricecho cả hai trường hợp.
Hedging và netting: chọn sai là logic bot sai
MT5 có hai kiểu tài khoản, và bot của bạn phải biết mình đang ở kiểu nào:
| Hedging | Netting | |
|---|---|---|
| Số vị thế trên một cặp | Nhiều vị thế độc lập | Một vị thế gộp |
| Mở lệnh ngược chiều | Tạo vị thế mới (có thể khoá lẫn nhau) | Giảm/đảo vị thế hiện có |
| Phù hợp với bot | Nhiều chiến lược chạy song song | Một chiến lược, quản lý vị thế ròng |
| Kiểm tra bằng code | account_info().margin_mode == mt5.ACCOUNT_MARGIN_MODE_RETAIL_HEDGING | ... == mt5.ACCOUNT_MARGIN_MODE_RETAIL_NETTING |
Nếu bot của bạn giả định có nhiều vị thế nhưng tài khoản là netting, mọi logic "mỗi tín hiệu một vị thế" sẽ sai — tín hiệu thứ hai không mở vị thế mới mà làm thay đổi vị thế cũ. Hãy kiểm tra margin_mode ngay khi khởi động, log ra, và nếu không khớp với thiết kế thì dừng bot thay vì chạy tiếp.
Trên tài khoản netting, hãy viết logic theo hướng "trạng thái mong muốn": tính vị thế mục tiêu (long 0,5 lot / short 0,3 lot / không có vị thế) rồi gửi phần chênh lệch. Cách này miễn nhiễm với câu hỏi "đang có vị thế hay chưa".
Magic number: quản lý nhiều chiến lược trên một tài khoản
Khi bạn chạy 2–3 chiến lược trên cùng một tài khoản, magic number là thứ giữ cho chúng không giẫm lên nhau.
Quy ước đề xuất:
20261001 → chiến lược A (khung 15m)
20261002 → chiến lược B (khung 1H)
20261003 → chiến lược C (bot thủ công có hỗ trợ)Ba quy tắc khi dùng magic:
- Luôn truy vấn vị thế theo magic:
mt5.positions_get(symbol=symbol)rồi lọcp.magic == MAGIC. Đừng bao giờ đóng vị thế không phải của bạn. - Giới hạn vị thế theo magic, không theo tổng số vị thế trên tài khoản. Mỗi chiến lược có trần riêng.
- Ghi magic vào log của mọi lệnh. Ba tháng sau, đây là thứ duy nhất giúp bạn tách hiệu suất của từng chiến lược.
Với bot có trailing stop hoặc quản lý trạng thái, hãy lưu thêm một bảng ánh xạ ticket → strategy trong database, vì không phải lúc nào bạn cũng đọc được magic từ ticket sau khi vị thế đóng (lịch sử deals có thể không giữ comment nguyên vẹn).
Lỗi thường gặp khi giao dịch MT5 bằng Python
| Mã / hiện tượng | Nguyên nhân | Cách xử lý |
|---|---|---|
10030 Invalid filling mode | Gửi chế độ khớp không được symbol hỗ trợ | Dùng pick_filling() theo filling_mode |
10016 Invalid stops | SL/TP quá gần (trade_stops_level) hoặc sai phía | Dùng safe_sl_price(), kiểm tra lại phía SL |
10014 Invalid volume | Lot không đúng volume_step hoặc dưới volume_min | Làm tròn theo step, kiểm tra min |
10019 Not enough money | Ký quỹ không đủ, đòn bẩy thấp | Giảm lot, kiểm tra margin_free trước khi gửi |
10018 Market closed | Ngoài giờ giao dịch của symbol | Chặn gửi lệnh ngoài phiên; log rõ thay vì thử lại |
10027 / 10026 Algo trading disabled | MT5 tắt "Allow algorithmic trading" | Bật lại trong Tools → Options → Expert Advisors |
10004 Requote | Giá thay đổi nhanh, deviation quá nhỏ | Tăng deviation hoặc gửi lại |
10031 No connection | Mất kết nối tới server broker | Kiểm tra terminal_info().connected, thử reconnect |
initialize() trả False | MT5 chưa chạy, khác user, khác kiến trúc bit | Kiểm tra tiến trình, chạy cùng user, cài 64-bit |
| Đặt SL thành công nhưng bị dời | Broker áp trade_freeze_level khi giá gần SL | Đọc trade_freeze_level, tránh sửa SL trong vùng đóng băng |
Bảng này nên được dán ngay trong log của bot: khi gặp retcode lạ, bot ghi cả retcode và phần comment mà MT5 trả về — comment thường nói rõ hơn về lý do.
Đưa MT5 lên VPS chạy 24/7
Phần khó nhất của bot MT5 không phải code, mà là giữ cho MT5 sống. Bốn việc bắt buộc:
1. Tắt sleep và màn hình khoá. Windows Server mặc định có thể sleep. Vào Power Options, đặt Never cho cả sleep và display off. Nếu VPS có console ảo, hãy để phiên đăng nhập luôn mở (MT5 không giao dịch được khi phiên bị "khoá" ở một số cấu hình RDP).
2. Chặn Windows Update restart tự động. Đây là nguyên nhân số một khiến bot "chết lúc 3 giờ sáng". Đặt Active Hours rộng nhất có thể, hoặc dùng Group Policy để chỉ cập nhật khi bạn chủ động.
3. Cho MT5 khởi động cùng Windows. Tạo shortcut tới terminal64.exe (có thể kèm /portable để giữ cấu hình trong thư mục cài) và đặt vào shell:startup. Trong MT5, lưu mật khẩu để tự đăng nhập (Tools → Options → Server: lưu tài khoản) — cẩn thận với yêu cầu bảo mật của bạn khi làm việc này.
4. Watchdog cho cả MT5 và bot. Một script nhỏ chạy mỗi 2 phút, kiểm tra:
def health_check():
if not mt5.initialize():
notify("🚨 MT5 không kết nối được — đang thử khởi động lại")
start_mt5(); return
ti = mt5.terminal_info()
if not ti.connected:
notify("⚠️ MT5 mất kết nối tới broker")
if not ti.trade_allowed:
notify("🚨 Algo trading đang TẮT trong MT5")
ai = mt5.account_info()
if ai.equity < ai.balance * 0.7:
notify(f"🚨 Equity giảm mạnh: {ai.equity:.0f} / {ai.balance:.0f}")Watchdog phải chạy ngoài tiến trình bot (ví dụ Task Scheduler), vì nếu bot chết thì watchdog trong bot cũng chết theo.
Một mẹo vận hành: đặt một lịch khởi động lại MT5 mỗi tuần vào lúc thị trường đóng cửa (cuối tuần). MT5 chạy liên tục hàng tháng có thể bị rò rỉ bộ nhớ hoặc treo kết nối; khởi động lại định kỳ là cách phòng ngừa rẻ nhất.
Đối soát và nhật ký
Với MT5, đối soát có một lợi thế: terminal giữ lịch sử deals rất tốt. Bạn có thể dùng history_deals_get() để tái hiện mọi lệnh trong khoảng thời gian bất kỳ, kèm commission, swap và lợi nhuận.
Ba truy vấn nên có trong bot:
- Vị thế đang mở theo magic — để biết bot đang giữ gì.
- Deals trong 24 giờ qua — để đối chiếu với log của bot.
- Tổng commission + swap trong tuần — chi phí thật của chiến lược. Với các cặp giữ nhiều ngày, swap có thể lớn hơn cả phí commission; nếu bạn không tính nó, bạn không biết lãi thật.
Nhật ký mỗi lệnh nên ghi tối thiểu: trace_id, magic, ticket, symbol, side, lot, price_requested, price_filled, slippage_points, sl, tp, retcode, comment. Với schema này, bạn trả lời được mọi câu hỏi về hiệu suất chiến lược mà không cần mở MT5.
Checklist trước khi chạy tiền thật
- ✅ MT5 đã bật Allow algorithmic trading; bot kiểm tra
trade_allowedkhi khởi động. - ✅
symbol_select()đã gọi cho mọi symbol bot dùng. - ✅ Đã đọc
point,digits,volume_step,volume_min,trade_stops_level,trade_tick_value. - ✅
pick_filling()dùng bit mask củafilling_mode, không hardcode. - ✅ SL/TP luôn qua hàm kiểm tra khoảng cách tối thiểu.
- ✅ Lot tính theo
trade_tick_value, không dùng hằng số. - ✅ Kiểm tra
margin_modeđúng với thiết kế bot (hedging vs netting). - ✅ Mọi lệnh có
magicvàcommentchứatrace_id. - ✅ Có watchdog ngoài tiến trình + cảnh báo Telegram.
- ✅ Chạy demo ít nhất 3 ngày qua cả ba phiên trước khi chuyển tiền thật.
Nếu chỉ làm được ba điều, hãy chọn 3, 4 và 9. Sai bộ lọc hoặc sai filling mode làm bot không vào được lệnh; thiếu watchdog làm bot chết mà bạn không biết.
Chi phí thật khi chạy bot MT5
Forex có ba loại chi phí, và nhiều người chỉ tính một:
1. Spread. Đây là chi phí ẩn lớn nhất với chiến lược khung nhỏ. EURUSD trên tài khoản ECN thường 0,1–0,3 pip; XAUUSD có thể 2–5 pip, giãn rộng gấp 3–5 lần trong phiên Á hoặc khi có tin. Bot vào lệnh bằng market luôn trả spread ở cả hai đầu. Nếu chiến lược của bạn nhắm 10 pip mỗi lệnh, spread 3 pip đã ăn 30% kỳ vọng.
2. Commission. Tài khoản ECN tính hoa hồng theo khối lượng (ví dụ 7 USD/lot khứ hồi). Với bot chạy 200 lệnh/tháng, đây là con số cần đưa vào báo cáo.
3. Swap. Phí giữ vị thế qua đêm, có thể âm (bạn trả) hoặc dương (bạn nhận). Với chiến lược giữ lệnh nhiều ngày, swap có thể vượt cả commission. Hãy kiểm tra swap của cặp bạn giao dịch trước khi thiết kế chiến lược giữ lệnh dài.
Thêm chi phí hạ tầng: VPS Windows thường 10–40 USD/tháng (đắt hơn Linux cùng cấu hình). Cộng lại, một bot MT5 chạy nghiêm túc tốn khoảng 15–50 USD/tháng trước khi tính tới lỗ giao dịch.
Cách kiểm tra nhanh nhất: dùng history_deals_get() cho một tuần chạy thật, cộng commission và swap, chia cho số lệnh. Con số đó chính là "chi phí mỗi lệnh" — và nó phải nhỏ hơn kỳ vọng lợi nhuận trung bình mỗi lệnh của chiến lược.
Khi nào nên viết EA bằng MQL5 thay vì Python?
Cả hai đều hợp lệ; chọn theo bối cảnh:
Dùng Python (thư viện `MetaTrader5`) khi: bạn cần nhận webhook từ TradingView, cần gọi API của nhiều sàn khác nhau trong cùng một hệ thống, cần xử lý dữ liệu phức tạp (pandas, machine learning), hoặc bạn muốn tái dùng code cho crypto và chứng khoán. Đây là lựa chọn cho hầu hết người dùng hôm nay.
Dùng EA MQL5 khi: bot cần chạy ngay trong terminal mà không phụ thuộc tiến trình Python; độ trễ cực thấp; bạn muốn phân phối bot cho người khác cài trên MT5 của họ; hoặc cần backtest trong Strategy Tester với mô hình tick thật.
Một kiến trúc lai rất đáng dùng: Python lo phần nhận webhook, xử lý tín hiệu, học máy; EA MQL5 chỉ làm nhiệm vụ thực thi lệnh lấy tín hiệu từ file được ghi chung (common folder) hoặc từ socket. Cách này tận dụng ưu điểm của cả hai mà tách được rủi ro.
Điều nên tránh: viết mọi thứ trong EA rồi nhúng thêm logic nhận webhook. MQL5 không được thiết kế cho HTTP server, và bạn sẽ mất rất nhiều thời gian cho những việc Python làm trong vài dòng.
Tổng kết
Nối TradingView với MT5 là bài toán cầu nối chứ không phải bài toán chiến lược: một VPS Windows, một MT5 đang chạy, một bot Python dùng thư viện MetaTrader5. Khó nằm ở chi tiết vận hành — pip/point, stops level, filling mode, magic number và việc giữ MT5 sống 24/7.
Năm việc cần làm, theo thứ tự:
- Dựng
init_mt5()có kiểm tratrade_allowedvà log thông số symbol. - Viết
safe_sl_price()vàcalc_lot()dùng dữ liệu từsymbol_info(). - Chọn
type_fillingđộng theofilling_mode. - Quản lý vị thế theo
magic, không theo tổng tài khoản. - Đặt watchdog bên ngoài + khởi động lại định kỳ.
Muốn dựng trọn chuỗi tín hiệu TradingView → bot → MT5 → VPS 24/7 với người hướng dẫn từng buổi? Bootcamp TradingView Webhook Bot gồm 6 buổi online (20:00–22:00 Thứ 2, khai giảng 19/10/2026), học phí 990.000đ, tặng kèm 12 tháng FindMe VPS Guardian để giám sát VPS chạy bot.
Đọc tiếp trong cụm bài:
- TradingView Webhook là gì? Hướng dẫn A–Z
- Bot Python nhận webhook TradingView
- Gửi lệnh từ TradingView lên Binance/Bybit
- Khóa Lập trình MT5 Nâng cao – Hedging & Tự động hóa
Câu hỏi thường gặp
Có cần viết EA bằng MQL5 để nối TradingView với MT5 không?
Không bắt buộc. Thư viện MetaTrader5 cho Python giao tiếp trực tiếp với terminal MT5 nên bạn có thể nhận webhook và gửi lệnh mà không cần viết một dòng MQL5. Viết EA chỉ cần khi bạn muốn bot chạy độc lập ngay trong MT5 (không phụ thuộc tiến trình Python).
Vì sao bot MT5 của tôi bắt buộc phải chạy trên Windows?
Vì thư viện MetaTrader5 do MetaQuotes phát hành chỉ hỗ trợ Windows, và nó giao tiếp với terminal MT5 đang chạy trên cùng máy. Nếu muốn hạ tầng Linux, bạn phải tách phần nhận webhook (Linux) và phần giao dịch MT5 (Windows) thành hai dịch vụ.
Lỗi 10030 Invalid filling mode là gì và sửa thế nào?
Là lỗi khi bạn gửi chế độ khớp lệnh mà symbol không hỗ trợ (FOK, IOC, RETURN). Cách sửa: đọc symbol_info(symbol).filling_mode — đây là bit mask, bit 1 = FOK, bit 2 = IOC — rồi chọn chế độ được hỗ trợ. Đừng hardcode FOK vì nhiều broker chỉ cho IOC.
Đặt SL/TP bị lỗi 10016 Invalid stops?
Nguyên nhân là khoảng cách SL/TP nhỏ hơn trade_stops_level của symbol (tính bằng point), hoặc SL/TP đặt sai phía so với lệnh. Hãy dùng hàm kiểm tra khoảng cách tối thiểu và cộng thêm spread, đồng thời kiểm tra trade_freeze_level khi bạn muốn sửa SL lúc giá đã gần stop.
Tính lot theo % rủi ro thế nào cho đúng với mọi cặp?
Dùng trade_tick_value từ symbol_info(): số tick trong khoảng SL nhân với giá trị mỗi tick cho ra số tiền lỗ trên một lot tiêu chuẩn; lấy số tiền rủi ro chia cho con số đó. Đừng dùng hằng số "1 pip = 10 USD" vì nó chỉ đúng với một vài cặp và một số dư tài khoản cụ thể.
Sự khác nhau giữa tài khoản hedging và netting ảnh hưởng gì đến bot?
Với hedging, mỗi tín hiệu có thể mở một vị thế độc lập trên cùng cặp. Với netting, chỉ có một vị thế gộp cho mỗi cặp nên lệnh ngược chiều sẽ giảm hoặc đảo vị thế hiện có. Hãy kiểm tra account_info().margin_mode khi khởi động và viết logic tương ứng; chạy logic hedging trên tài khoản netting là lỗi nghiêm trọng.
Làm sao để bot không đóng nhầm vị thế vào tay?
Dùng magic number riêng cho từng bot/chiến lược, và luôn lọc vị thế theo magic khi truy vấn hoặc đóng lệnh. Những vị thế có magic khác hoặc magic bằng 0 (vào tay) coi như unmanaged — chỉ ghi log và cảnh báo, không tự ý đóng.
MT5 hay bị mất kết nối về đêm, xử lý thế nào?
Dựng watchdog chạy ngoài tiến trình bot (Task Scheduler) kiểm tra terminal_info().connected và trade_allowed mỗi 1–2 phút; nếu sai thì cảnh báo và khởi động lại MT5. Ngoài ra nên tắt sleep, chặn Windows Update tự restart, và đặt lịch khởi động lại MT5 mỗi tuần lúc thị trường đóng cửa.
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.
