| Snapshot Positions 1-Pass Python | PyNhiQuaiBot Bot Hedging

Được viết bởi thanhdt vào ngày 27/07/2026 lúc 23:10 | 51 lượt xem

Tham chiếu: bot_nhi_quai_v6_pro.py · khóa Python Nâng cao Hedging · PyNhiQuaiBot · KG 01/08/2026


Khi PyNhiQuaiBot chạy grid hedging trên MT5 qua MetaTrader5, mỗi lần gọi mt5.positions_get() là một lần Python quét danh sách vị thế từ terminal. Demo 5–10 lệnh thì không sao; lên 80–150 lệnh, nếu calc_volume(), process_cluster(), draw_dashboard() mỗi hàm tự gọi positions() riêng — bạn đang Multi-Pass ngầm: cùng một tick, cùng một tập lệnh, quét 3–4 lần.

Bài viết thuộc lớp Infrastructure trong lộ trình 4 phần PyNhiQuaiBot (Global State · Grid · Brain · UX). Đây là bài kỹ thuật Python — không phải tín hiệu giao dịch, không cam kết lợi nhuận.

1. PyNhiQuaiBot đọc lệnh như thế nào?

Trong Bot_nhi_quai_v6_pro.py, hàm positions() là cửa vào:

def positions(self, magic: Optional[int] = None) -> List[Any]:
    pos = mt5.positions_get(symbol=self.symbol) or []
    if magic is None:
        return list(pos)
    return [p for p in pos if int(p.magic) == magic]
  • Magic 6111 — cụm Buy · Magic 6112 — cụm Sell (port từ EA MT5 2111/2112).
  • Mọi hàm downstream — calc_volume, ticket_at_step, close_all_magic, draw_dashboard — đều có thể gọi lại positions().

Pain: mỗi lần gọi = một vòng lọc + copy list mới. Grid dày × loop on_tick 4 lần/giây (tick_sleep=0.25) × nhiều hàm = CPU và latency tăng trước khi FSM kịp chặn nhồi lệnh.

2. Multi-Pass — ví dụ thực tế trong code hiện tại

draw_dashboard() đã làm đúng hướng một vòng for gom Buy/Sell float và volume:

for p in self.positions():  # 1 lần positions_get
    pr = float(p.profit + p.swap + p.commission)
    vol = float(p.volume)
    # ... gom theo buy_magic / sell_magic

Nhưng ngay trước đó, on_tick() có thể đã gọi:

self.process_cluster(magic)  # bên trong: positions(magic) nhiều lần
self.tp_logic(magic)         # positions(magic) thêm
self.draw_dashboard()        # positions() lần nữa

Ước lượng: 100 lệnh × 3 hàm × 4 tick/giây ≈ 1.200 lần duyệt phần tử/giây — chưa kể vòng lặp bên trong process_cluster.

Đây là lỗi kiến trúc Infrastructure, không phải “VPS yếu”.

graph LR
    A["on_tick Python"] --> B["process_cluster · positions"]
    A --> C["tp_logic · positions"]
    A --> D["draw_dashboard · positions"]
    B --> E["CPU / latency"]
    C --> E
    D --> E

3. Snapshot 1-Pass — pattern đề xuất cho PyNhiQuaiBot

3.1. Dataclass cache một tick

from dataclasses import dataclass, field
from typing import List, Any

@dataclass
class PositionSnapshot:
    buy_magic: int
    sell_magic: int
    all_positions: List[Any] = field(default_factory=list)
    buy_cluster: List[Any] = field(default_factory=list)
    sell_cluster: List[Any] = field(default_factory=list)

    def refresh(self, symbol: str, buy_magic: int, sell_magic: int) -> None:
        import MetaTrader5 as mt5
        raw = list(mt5.positions_get(symbol=symbol) or [])
        self.all_positions = raw
        self.buy_magic = buy_magic
        self.sell_magic = sell_magic
        self.buy_cluster = [p for p in raw if int(p.magic) == buy_magic]
        self.sell_cluster = [p for p in raw if int(p.magic) == sell_magic]

Gọi refresh() đúng một lần đầu on_tick() — sau đó mọi hàm đọc snapshot.buy_cluster thay vì gọi API lại.

3.2. Sửa on_tick() — thứ tự giữ nguyên, nguồn dữ liệu thống nhất

def on_tick(self) -> None:
    bid, ask, spread = self.rates()
    if bid <= 0 or spread > self.cfg.max_spread:
        return
    self.snapshot.refresh(self.symbol, self.cfg.buy_magic, self.cfg.sell_magic)

    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)
    # ... sell tương tự
    self.draw_dashboard_from_snapshot()
    self.gv.save()

Hai thời điểm bắt buộc refresh (giống MT5 Cache):

  1. Đầu on_tick() — floating đổi theo giá
  2. Ngay sau order_send / close_ticket thành công — inventory đã đổi
graph TD
    A(["Tick mới"]) --> B["snapshot.refresh()"]
    B --> C{Brain · Grid}
    C --> D["tp_logic · process_cluster"]
    D --> E{order_send?}
    E -->|Có| F["refresh lại"]
    E -->|Không| G(["gv.save · sleep"])
    F --> G

3.3. calc_volume đọc snapshot — không gọi API

def calc_volume_from_snapshot(self, cluster: List[Any]) -> tuple[float, float]:
    bv = sv = 0.0
    for p in cluster:
        if p.type == mt5.POSITION_TYPE_BUY:
            bv += p.volume
        else:
            sv += p.volume
    return bv, sv

bias = buy_vol - sell_vol dùng cho MaxAllowedBias (bài deep #04) — cần số liệu nhất quán trong cùng tick, không phải half-old half-new giữa hai lần gọi positions_get.

4. List ticket — đóng basket không quét lại

def tickets_buy(cluster: List[Any]) -> List[int]:
    return [int(p.ticket) for p in cluster if p.type == mt5.POSITION_TYPE_BUY]

def close_all_magic_from_snapshot(self, cluster: List[Any]) -> None:
    for p in list(cluster):
        self.close_ticket(int(p.magic), int(p.ticket))

list(cluster) copy trước khi đóng — tránh sửa collection đang duyệt (tương đương duyệt từ cuối về đầu trong MQL5).

5. Liên hệ 4 phần PyNhiQuaiBot

Phần Module Snapshot giúp gì
Infrastructure positions, GVStore, rates 1 nguồn sự thật / tick
Grid Logic process_cluster, Step Đếm lệnh/step từ comment đã cache
Brain handle_lockdown, FSM Bias/volume không lệch giữa Guard và Grid
UX draw_dashboard Dashboard đọc cùng snapshot — log khớp logic

Đọc thêm: Global State & Pandas · Kiến trúc hai cụm 6111/6112

6. FAQ

Snapshot thay GVStore JSON không?
Không. GVStore lưu P0, Step, FSM qua restart. Snapshot chỉ sống trong một tick.

Pandas có cần không?
Khóa dùng list/dataclass trước; Pandas hữu ích khi dashboard/backtest (bài #09 Dashboard·VPS).

Port từ EA MT5?
Đúng ý tưởng Siêu Cache 1-Pass MQL5 — Python dùng list/dict thay Array. Học MT5 trước giúp đọc bot_nhi_quai_v6_pro.py; khóa PyNhiQuaiBot tập trung Python production.

KG 01/08 còn mấy ngày?
Tính 28/07/2026 — còn 4 ngày · T7+CN 15:00 · đăng ký khóa.

7. Tóm tắt

  • Multi-Pass = nhiều hàm gọi positions_get cùng tick
  • Snapshot 1-Pass = refresh() một lần · Grid/Brain/UX đọc chung
  • Refresh lại sau mỗi lệnh gửi/đóng thành công
  • Nền Infrastructure trước FSM STEP_BUSY và Guard (Buổi 5–7 khóa)

Giao dịch tự động có rủi ro drawdown — bài mang tính giáo dục kỹ thuật.

Liên hệ & đăng ký: PyNhiQuaiBot — Python Nâng cao Hedging · Hotline 0934 145 100 · Zalo 039 791 9841

Khóa PyNhiQuaiBot: https://www.huongnghiepdulieu.com/lap-trinh-python-nang-cao-hedging-tu-dong-hoa/ · Hotline 0934 145 100

Đặng Trí Thanh

Đặng Trí Thanh

Giám đốc Công nghệ · DNT Digital · Giảng viên HNDL
811 Bài viết
15.4k Người theo dõi
120k+ Lượt đọc

Đà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.