Bài viết gần đây
-
Huỳnh Thị Ngọc Loan — Giảng Viên Yoga & Spa | HNDL
Tháng 8 6, 2026
Trang chủ → Bài Viết → Kiến trúc 4 lớp PyNhiQuaiBot — Quant Buổi 1: từ script sang hệ thống quant Python hedging
| Kiến trúc 4 lớp PyNhiQuaiBot — Quant Buổi 1: từ script sang hệ thống quant Python hedging
Được viết bởi Đặng Trí Thanh vào ngày 18/07/2026 lúc 15:04 | 270 lượt xem
> Nguồn: **project PyNhiQuaiBot** (`pynhiquaibot`) · lộ trình 12 buổi PyNhiQuaiBot
---
Hầu hết lập trình viên bắt đầu bot trading bằng một file Python duy nhất: `while True`, đọc giá, nếu điều kiện thì `order_send`, rồi `sleep`. Cách này chạy được trên demo vài phút — nhưng khi reconnect API, khi có hàng chục vị thế Buy/Sell cùng lúc, hoặc khi equity giảm và bot vẫn cố mở lệnh mới, script đơn sẽ sụp đổ vì **không có ranh giới trách nhiệm** giữa dữ liệu, chiến thuật, kiểm soát rủi ro và thực thi.
**Buổi 1 — Kiến trúc & chuẩn hóa bài toán** trong khóa [Lập trình Python nâng cao Hedging tự động hóa](https://www.huongnghiepdulieu.com/lap-trinh-python-nang-cao-hedging-tu-dong-hoa/) (dự án **PyNhiQuaiBot** — *Master Quantitative Trading*) trả lời câu hỏi nền tảng: *một bot hedging production cần được chia thành những lớp nào, và vòng lặp chính đi qua chúng theo thứ tự gì?*
Bài viết bám trực tiếp **project PyNhiQuaiBot** (`pynhiquaibot`) — bản Python port từ Bot Nhị Quái V6 Pro trên MQ5. Đây là tài liệu kỹ thuật và bài lab Buổi 1, **không phải khuyến nghị đầu tư**, không cam kết lợi nhuận. Grid, hedging và giao dịch tự động có thể gây drawdown lớn, margin call, trượt giá, phí và lỗi kết nối. Chỉ thực hành trên demo, đặt giới hạn rủi ro độc lập và tự chịu trách nhiệm triển khai.

## 1. Script một file vs hệ thống quant có trách nhiệm
| Tiêu chí | Script một file | Hệ thống PyNhiQuaiBot |
| :--- | :--- | :--- |
| **Trạng thái** | Biến global rời, mất khi restart | `GVStore` JSON — persist + namespace theo symbol/account/magic |
| **Quyết định mở lệnh** | `if signal: buy()` | Grid Logic (`process_cluster`) tách khỏi Guard (`handle_lockdown`) |
| **Side effect** | Gọi API trực tiếp trong logic | `order_send` — adapter execution, chiến thuật không biết filling mode |
| **Quan sát** | `print(bid)` | `draw_dashboard` — equity, bias, P0, trạng thái Full Hedge |
| **Thất bại** | Crash hoặc nhồi lệnh | Spread guard, lockdown freeze, FSM STEP_BUSY (Buổi 8) |
QuantTrade không bắt đầu bằng "tín hiệu thần kỳ". Nó bắt đầu bằng **cấu trúc có thể kiểm thử**: mỗi lớp trả lời một câu hỏi riêng, và vòng lặp chính gọi chúng theo thứ tự cố định để tránh "sửa API làm hỏng chiến thuật" hoặc "sửa chiến thuật làm bỏ qua guard".
## 2. Bốn phần kiến trúc — bản đồ cả khóa 12 buổi
Ảnh kiến trúc hệ thống: `PyNhiQuaiBot_Kien_Truc_He_Thong.png` (6 module · Core Engine · MT5 API).
Ảnh lộ trình 4 phần: `PyNhiQuaiBot_Lo_Trinh_4_Phan.png` (Infrastructure → Grid Logic → Brain → UX).
| Phần | Buổi học (12 buổi chính) | Module trong project `pynhiquaibot` | Câu hỏi lớp trả lời |
| :--- | :--- | :--- | :--- |
| **1 — Infrastructure** | B1–B4 | `Config`, `GVStore`, `rates`, `order_send`, `positions` | Dữ liệu đúng chưa? API giao tiếp thế nào? State lưu ở đâu? |
| **2 — Grid Logic** | B5–B7 | `process_cluster`, Step/X, Surplus/Hedge, cache | Giá hiện tại = Step mấy? Có được mở lệnh tại Step này không? |
| **3 — Brain** | B8–B10 | `get_fsm`/`set_fsm`, `handle_lockdown`, `check_basket_tp` | Hành động có được phép? Rủi ro vượt ngưỡng chưa? |
| **4 — UX** | B11–B12 | `draw_dashboard`, log, VPS, backtest hook | Người vận hành nhìn thấy gì? Metric quant nào cần đo? |
Buổi 1 không đi sâu Step/X hay FSM — mục tiêu là **đọc được toàn cảnh** trước khi zoom vào từng module ở các buổi sau. Nếu bạn đã đọc [bài tổng quan PyNhiQuaiBot](https://www.huongnghiepdulieu.com/lap-trinh-python-nang-cao-hedging-pynhiquaibot/), bài này là **lab Buổi 1**: cùng chủ đề nhưng gắn trực tiếp vào file code và sơ đồ runtime.
```mermaid
graph TB
subgraph UX["PHẦN 4 — UX"]
DASH[draw_dashboard]
LOG[logging]
end
subgraph BRAIN["PHẦN 3 — Brain"]
LOCK[handle_lockdown]
FSM[get_fsm / set_fsm]
BASKET[check_basket_tp]
end
subgraph GRID["PHẦN 2 — Grid Logic"]
CLUSTER[process_cluster]
TP[tp_logic / check_x_profit]
end
subgraph INFRA["PHẦN 1 — Infrastructure"]
CFG[Config dataclass]
GV[GVStore JSON]
API[rates · order_send · positions]
end
RUN[run → on_tick loop] --> INFRA
INFRA --> BRAIN
BRAIN --> GRID
GRID --> UX
UX --> GV
```
## 3. Khung dự án: Config — map 1-1 với input MQ5
Lớp Infrastructure bắt đầu bằng **cấu hình tách biệt logic**. Trong Python, `@dataclass Config` gom toàn bộ tham số mà trên MQ5 là `input`:
```python
@dataclass
class Config:
bot_name: str = "NHỊ QUÁI V6"
storage_prefix: str = "NHỊ QUÁI V6"
buy_magic: int = 6111
sell_magic: int = 6112
buy_step: float = 50.0
buy_x: float = 60.0
sell_step: float = 100.0
sell_x: float = 120.0
auto_lockdown: bool = True
max_allowed_bias: float = 0.3
tick_sleep: float = 0.25
symbol: str = "BTCUSD"
```
**Deliverable Buổi 1:** liệt kê được mỗi nhóm field thuộc phần kiến trúc nào:
| Nhóm Config | Ví dụ | Thuộc phần |
| :--- | :--- | :--- |
| Identity | `bot_name`, `storage_prefix`, `buy_magic`, `sell_magic` | Infrastructure — namespace |
| Grid | `buy_step`, `buy_x`, `sell_step`, `sell_x`, `buy_lot` | Grid Logic |
| Risk | `auto_lockdown`, `buy_min_equi2`, `max_allowed_bias` | Brain |
| Runtime | `tick_sleep`, `max_spread`, `symbol` | Infrastructure + UX |
Hàm `parse_args()` cho phép override từ CLI (`--symbol BTCUSD`, `--buy-step 50`) mà không sửa class — pattern quant engineer: **config ngoài code**, dễ chạy trên VPS với tham số khác nhau.
## 4. GVStore — Global State thay GlobalVariable MT5
Trên MQ5, EA dùng `GlobalVariableSet/Get`. Port sang Python dùng file JSON:
```python
class GVStore:
def __init__(self, path: Path):
self.path = path
self.data: Dict[str, float] = {}
self._load()
def get(self, name: str, default: float = 0.0) -> float:
return float(self.data.get(name, default))
def set(self, name: str, value: float) -> None:
self.data[name] = float(value)
def save(self) -> None:
self.path.write_text(json.dumps(self.data, ensure_ascii=False, indent=2), encoding="utf-8")
```
Mỗi tick kết thúc bằng `self.gv.save()` — state không chỉ nằm trong RAM. Key được namespace:
```python
def gv_prefix(self, magic: int) -> str:
return f"{self.cfg.storage_prefix}_{self.symbol}_{self._login}_{magic}"
```
Ví dụ key thực tế: `NHỊ QUÁI V6_BTCUSD_12345678_6111_P0`, `..._6111_LastStep`, `..._6111_LOCKED`.
**Vì sao Buổi 1 dạy GVStore trước Grid?** Vì mọi quyết định chiến thuật đều đọc/ghi state (`P0`, `LastStep`, `MinStep`, `MaxStep`, FSM keys). Không có store thống nhất, reconnect sẽ làm bot "quên" P0 và nhồi lệnh sai Step — pain mà [bài Global State](https://www.huongnghiepdulieu.com/global-state-pandas-numpy-bot-hedging-python/) (Buổi 2) sẽ mở rộng thêm schema Pandas.
## 5. Class NhiQuaiV6 — composition thay vì God object một chiều
`NhiQuaiV6` giữ:
- `self.cfg` — cấu hình bất biến trong session
- `self.gv` — store bền vững
- Cache runtime: `buy_cache`, `sell_cache` (Buổi 7 — concurrency)
- Throttle: `last_action_buy`, `last_action_sell` (2 giây giữa hai lần xử lý cụm)
Đây chưa phải OOP "sạch" kiểu microservice — nhưng đã **phân tách method theo trách nhiệm**:
| Method | Trách nhiệm |
| :--- | :--- |
| `rates()` | Đọc Bid/Ask/spread — Infrastructure |
| `order_send()` / `close_ticket()` | Execution adapter MT5 |
| `handle_lockdown()` | Brain — full hedge khi equity thấp |
| `tp_logic()` | Grid — gặt X cục bộ |
| `process_cluster()` | Grid — core rải lệnh theo Step |
| `draw_dashboard()` | UX — quan sát bias, float, P0 |
Nguyên tắc Buổi 1: **chiến thuật không gọi MT5 trực tiếp ngoài `order_send`/`close_ticket`**. Mọi thay đổi filling mode, deviation, comment format chỉ sửa một chỗ.
## 6. Vòng đời: on_init → run → on_tick
### 6.1. Khởi tạo `on_init`
Trước vòng lặp, bot:
1. Kiểm tra `buy_magic != sell_magic` (hai cụm không được trùng)
2. `mt5.symbol_select(symbol)`
3. Lấy `account login` → namespace GVStore
4. Nếu cụm chưa có position → `reset_cluster`
5. Khởi tạo `P0` và `StartTime` cho từng magic nếu chưa có
6. `sync_traversed()` — đồng bộ MinStep/MaxStep từ comment lệnh đang mở
```python
def on_init(self) -> bool:
if self.cfg.buy_magic == self.cfg.sell_magic:
log.error("Buy/Sell magic trùng nhau!")
return False
ai = mt5.account_info()
self._login = int(ai.login) if ai else 0
for magic in (self.cfg.buy_magic, self.cfg.sell_magic):
k = f"{self.gv_prefix(magic)}_P0"
if not self.gv.check(k):
bid, _, _ = self.rates()
self.gv.set(k, bid)
self.sync_traversed()
self.gv.save()
return True
```
**Test Buổi 1 — init:** chạy bot lần đầu trên demo → file `.gv.json` xuất hiện với key `_P0` cho magic 6111 và 6112.
### 6.2. Vòng lặp chính `run`
```python
def run(self) -> None:
if not self.on_init():
return
try:
while True:
self.on_tick()
time.sleep(self.cfg.tick_sleep)
except KeyboardInterrupt:
self.gv.save()
```
`tick_sleep` mặc định 0.25 giây — Python bot polling, không phải hook `OnTick` native như MQ5. Quant engineer cần hiểu: **polling interval ảnh hưởng race window** (Buổi 7) và tải CPU trên VPS (Buổi 12).
### 6.3. Một chu kỳ `on_tick` — flow đầy đủ
Đây là trái tim Buổi 1 — thứ tự gọi **cố định**:
```python
def on_tick(self) -> None:
bid, ask, spread = self.rates()
if bid <= 0 or spread > self.cfg.max_spread:
return
if self.cfg.buy_enable:
self.handle_lockdown(self.cfg.buy_magic)
if not self.is_full_hedge_frozen(self.cfg.buy_magic):
self.tp_logic(self.cfg.buy_magic)
self.process_cluster(self.cfg.buy_magic)
if self.cfg.sell_enable:
self.handle_lockdown(self.cfg.sell_magic)
if not self.is_full_hedge_frozen(self.cfg.sell_magic):
self.tp_logic(self.cfg.sell_magic)
self.process_cluster(self.cfg.sell_magic)
self.draw_dashboard()
self.gv.save()
```
```mermaid
sequenceDiagram
participant Loop as run() while True
participant Tick as on_tick()
participant Rates as rates()
participant Lock as handle_lockdown()
participant TP as tp_logic()
participant Grid as process_cluster()
participant Dash as draw_dashboard()
participant GV as GVStore.save()
Loop->>Tick: mỗi tick_sleep
Tick->>Rates: Bid, Ask, spread
alt spread OK
Tick->>Lock: magic 6111
alt not frozen
Tick->>TP: gặt X cụm BUY
Tick->>Grid: rải lệnh cụm BUY
end
Tick->>Lock: magic 6112
alt not frozen
Tick->>TP: gặt X cụm SELL
Tick->>Grid: rải lệnh cụm SELL
end
Tick->>Dash: in equity, bias, P0
Tick->>GV: persist JSON
else spread quá rộng
Tick-->>Loop: return sớm
end
```
**Thứ tự có ý nghĩa:**
1. **Spread guard trước** — không trade khi thị trường mỏng
2. **Lockdown trước Grid** — equity thấp → hedge ABS, đặt `_LOCKED`, bỏ qua `process_cluster`
3. **tp_logic trước process_cluster** — chốt lệnh đã đủ X trước khi cân nhắc mở mới
4. **Cụm BUY trước SELL** — quy ước code hiện tại (documented, không "đúng/sai" thị trường)
5. **Dashboard + save cuối** — UX và durability
## 7. Execution layer — order_send tách khỏi chiến thuật
```python
def order_send(self, magic: int, side: int, lot: float, comment: str) -> bool:
tick = mt5.symbol_info_tick(self.symbol)
order_type = mt5.ORDER_TYPE_BUY if side == POS_BUY else mt5.ORDER_TYPE_SELL
price = tick.ask if side == POS_BUY else tick.bid
req = {
"action": mt5.TRADE_ACTION_DEAL,
"symbol": self.symbol,
"volume": float(lot),
"type": order_type,
"price": price,
"deviation": int(self.cfg.slippage_allow),
"magic": int(magic),
"comment": comment[:31],
"type_filling": filling,
}
r = mt5.order_send(req)
return r is not None and r.retcode == mt5.TRADE_RETCODE_DONE
```
`process_cluster` chỉ gọi `order_send` — không biết Ask/Bid lấy từ đâu. Buổi 3 sẽ mở rộng thành **adapter đa sàn** (Binance, SSI, DNSE); Buổi 1 chỉ cần nhận ra **interface execution** đã tồn tại.
Comment format: `NHỊ QUÁI V6_B_S12` (cụm BUY, Step 12) — Buổi 4 sẽ học Magic + Comment + lifecycle đầy đủ.
## 8. Hai cụm magic 6111 / 6112 — preview cho Buổi 4
Mỗi `on_tick` xử lý **hai cluster độc lập**:
| Magic | Tên cụm | Step mặc định | X mặc định |
| :--- | :--- | :--- | :--- |
| **6111** | Cụm BUY | 50.0 | 60.0 |
| **6112** | Cụm SELL | 100.0 | 120.0 |
Mỗi cụm có `P0` riêng, basket TP riêng, lockdown riêng. Tên "BUY cluster" **không** có nghĩa chỉ chứa lệnh Buy — cụm vẫn có cả Buy và Sell tại các Step (hedging). Chi tiết: [Kiến trúc hai cụm 6111/6112](https://www.huongnghiepdulieu.com/kien-truc-hai-cum-buy-sell-python-bot/) (Buổi 4).
## 9. Dashboard — UX không phải phần trang trí
```python
def draw_dashboard(self) -> None:
if self.tick_ms() - self.last_draw < 500:
return
lines = [
"=== ROBOT NHI QUAI V6 (Python) ===",
f"EQUITY: {equity:.2f} | FullHed: {hed}",
f"CUM BUY | Float: {b_float:.2f} | P0: {p0_b:.2f}",
f" > Buy: {b_bv:.2f} | Sell: {b_sv:.2f} | BIAS: {b_bv - b_sv:.2f}",
f"BIAS TONG SYMBOL: {tot_b - tot_s:.2f} Lot",
]
log.info("n".join(lines))
```
Quant engineer cần **metric quan sát được** trước khi tin bot chạy 24/7: equity, bias từng cụm, trạng thái Full Hedge. Buổi 11 sẽ nâng lên dashboard Pandas + backtest report (MDD, cost).
## 10. Ba kịch bản kiểm thử Buổi 1
Chạy trên **tài khoản demo**, symbol cố định (vd. `BTCUSD`), log level INFO.
### Kịch bản A — Cold start (happy path)
1. Xóa file `pynhiquaibot.gv.json`
2. Chạy entry point project `pynhiquaibot` (demo: `python main.py --symbol BTCUSD`)
3. **Kỳ vọng:** log `Init OK`, dashboard in equity, file GV có key `_P0` cho 6111 và 6112
4. **Không kỳ vọng:** lợi nhuận — chỉ xác nhận lifecycle
### Kịch bản B — Restart giữa chừng
1. Bot đang chạy, có ít nhất 1 position
2. Ctrl+C → chạy lại cùng symbol/account
3. **Kỳ vọng:** `sync_traversed()` khôi phục MinStep/MaxStep; không reset P0 nếu còn lệnh
4. **Red flag:** P0 = 0 hoặc mở trùng S0
### Kịch bản C — Spread guard
1. Set `max_spread` rất thấp (vd. `0.01`) trong Config test
2. **Kỳ vọng:** `on_tick` return sớm, không gọi `process_cluster`
3. **Ý nghĩa:** Infrastructure layer chặn trade khi điều kiện thị trường xấu
## 11. Checklist deliverable Buổi 1
Sinh viên hoàn thành Buổi 1 khi:
- [ ] Vẽ được sơ đồ 4 phần và chỉ ra method tương ứng trong code
- [ ] Giải thích thứ tự `handle_lockdown` → `tp_logic` → `process_cluster` trong `on_tick`
- [ ] Đọc được file `.gv.json` và giải thích ý nghĩa key `_P0`, `_LastStep`
- [ ] Chạy demo cold start + restart, ghi log quan sát dashboard
- [ ] Phân biệt được Config (input) vs GVStore (state runtime) vs cache RAM (`buy_cache`)
- [ ] Nêu được vì sao bot là hệ thống quant, không phải script signal
## 12. FAQ Buổi 1
**PyNhiQuaiBot khác gì bot BUY/SELL đơn giản?**
Bot quản lý **cụm vị thế** theo Step, có state persist, guard equity và FSM — không chỉ một lệnh một tín hiệu.
**Buổi 1 có cần hiểu hết `process_cluster`?**
Không. Buổi 1 chỉ cần biết đó là Grid Logic, được gọi sau lockdown/TP. Buổi 5–6 sẽ đi sâu Step, Surplus/Hedge.
**GVStore JSON có thay được SQLite?**
Có — Buổi 2 mở rộng schema. JSON đủ cho lab và port từ GlobalVariable MQ5.
**QuantTrade và PyNhiQuaiBot khác nhau thế nào?**
Cùng một khóa: **PyNhiQuaiBot** là tên dự án code thực hành; **QuantTrade** là khung *Master Quantitative Trading* trên kênh phân tích định lượng DNT Quant Trade Solutions.
**Còn bao nhiêu ngày đến khai giảng?**
KG **01/08/2026** — 12 buổi chính + 8 bài tập + 5 phụ đạo. FAQ: [Lộ trình 12 buổi](https://www.huongnghiepdulieu.com/lo-trinh-12-buoi-python-nang-cao-hedging-faq/).
**Có cam kết lợi nhuận không?**
Không. Mọi ví dụ là tài liệu kỹ thuật; rủi ro thị trường vẫn tồn tại dù code đúng.
## 13. Buổi tiếp theo và liên kết nội bộ
| Buổi | Chủ đề | Bài đọc thêm |
| :--- | :--- | :--- |
| **Buổi 2** | Global State, Pandas, schema | [Global State Pandas bot](https://www.huongnghiepdulieu.com/global-state-pandas-numpy-bot-hedging-python/) |
| **Buổi 4** | Magic 6111/6112, Comment, ID | [Kiến trúc hai cụm](https://www.huongnghiepdulieu.com/kien-truc-hai-cum-buy-sell-python-bot/) |
| **Buổi 5** | Step & X-Level | [Toán Step X-Level](https://www.huongnghiepdulieu.com/toan-step-x-level-hedging-python-bot/) |
| **Buổi 8** | FSM STEP_BUSY 5s | [FSM chống nhồi lệnh](https://www.huongnghiepdulieu.com/fsm-step-busy-chong-nhoi-lenh-python/) |
---
**Tóm tắt Buổi 1:** PyNhiQuaiBot không phải một vòng `while` nhồi lệnh — nó là **bốn lớp** (Infrastructure · Grid · Brain · UX) orchestrated bởi `on_tick`, với Config tách input, GVStore persist state, và execution adapter tách khỏi chiến thuật. Master Quantitative Trading bắt đầu từ chỗ đó: đo và kiểm soát rủi ro bằng cấu trúc code, không bằng lời hứa lợi nhuận.
**Khóa học:** [Lập trình Python nâng cao Hedging tự động hóa](https://www.huongnghiepdulieu.com/lap-trinh-python-nang-cao-hedging-tu-dong-hoa/) · PyNhiQuaiBot · QuantTrade · KG 01/08/2026 · Hotline 0934 145 100
Khóa PyNhiQuaiBot · QuantTrade · Master Quantitative Trading: Lập trình Python Nâng cao Hedging & Tự động hóa
Đọc thêm
- Survival Architecture: Kiến trúc sinh tồn – “Vũ khí” giúp Robot MQL5 sống sót trong mọi nghịch cảnh
- Từ ‘Code dạo’ đến ‘Bot công nghiệp’ – Tầm quan trọng của kiến trúc phần mềm trong Trading
- Kiến trúc Bot giao dịch chuyên nghiệp: Nền tảng thành công trong Algo Trading
- Kiến trúc Bot giao dịch chuyên nghiệp: Nền tảng thành công trong Algo Trading
PyBot / PyNhiQuaiBot: PyBot là gì? · Khóa Python Hedging · Landing PyNhiQuaiBot
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.
Đặng Trí Thanh
Giám đốc Công nghệ · DNT Digital · Giảng viên HNDLĐặng Trí Thanh — Founder & CTO · Hướng Nghiệp Dữ Liệu - DNT Digital. Chuyên đào tạo và triển khai thực chiến Python, MT5 và hệ thống bot auto trading / IB cho học viên và doanh nghiệp.