Bài viết gần đây
-
-
Global State Dataclass Python | Schema Vị Thế PyNhiQuaiBot
Tháng 7 28, 2026 -
Học Widget Trước Dart? 5 Câu Self-Check Flutter Buổi 2
Tháng 7 27, 2026 -
Dart Cú Pháp Cơ Bản Flutter Buổi 2 | var final const Null Safety
Tháng 7 27, 2026 -
Bot Python Chậm Vì Multi-Pass positions_get | PyNhiQuaiBot
Tháng 7 27, 2026
| Global State Dataclass Python | Schema Vị Thế PyNhiQuaiBot
Được viết bởi thanhdt vào ngày 28/07/2026 lúc 13:49 | 32 lượt xem
Tham chiếu:
bot_nhi_quai_v6_pro.py· Snapshot 1-pass · KG 01/08/2026
Sau khi đã snapshot positions 1-pass (bài Infrastructure trước), bước tiếp theo trong module ① DATA & STATE trên ảnh kiến trúc PyNhiQuaiBot là biến snapshot thành Global State có schema — không phải dictionary toàn cục cho mọi hàm sửa tùy tiện.
Bài viết dạy cách dùng dataclass trong Python để gom Config, snapshot vị thế, metric cụm 6111/6112 và metadata FSM — nền trước Grid Logic và Brain. Nội dung kỹ thuật Python · không hướng dẫn viết EA MQL5 · không cam kết lợi nhuận.
1. Global State ≠ biến global rải rác
Trong Bot_nhi_quai_v6_pro.py, lớp Config đã là @dataclass — map 1-1 input MQ5 port sang Python:
@dataclass
class Config:
buy_magic: int = 6111
sell_magic: int = 6112
max_allowed_bias: float = 0.3
buy_step: float = 50.0
buy_x: float = 60.0
# ...
Pain phổ biến: dev copy thêm buy_vol = 0, sell_vol = 0, last_bias = 0 rải rác trong class Bot — process_cluster cập nhật một nơi, draw_dashboard đọc nơi khác, reconnect xong số liệu lệch.
Global State đúng: một object (hoặc store có version) mà mọi module đọc snapshot bất biến và chỉ Reconciler được ghi sau khi đối soát MT5.
2. Schema tối thiểu cho bot hedging đa vị thế
| Nhóm | Trường gợi ý | Vai trò |
|---|---|---|
| Identity | symbol, buy_magic, sell_magic |
Tách cụm 6111 / 6112 |
| Volume | buy_vol, sell_vol, bias |
MaxAllowedBias · Guard |
| Positions | buy_cluster, sell_cluster, all_positions |
Grid · Sweep |
| Account | equity, balance, margin_free |
Lockdown · MinEqui2 |
| FSM | step_state, busy_until_ts |
STEP_BUSY 5s |
| Meta | version, as_of_ts |
Phát hiện stale data |
bias = buy_vol - sell_vol phải tính từ cùng snapshot với list lệnh mà process_cluster nhìn thấy — nếu không, Guard pass trong khi Grid đang nhìn half-old data.
3. Dataclass snapshot bất biến (frozen)
from dataclasses import dataclass, field
from typing import Any, List
import time
@dataclass(frozen=True)
class ClusterMetrics:
buy_vol: float
sell_vol: float
buy_float: float
sell_float: float
@property
def bias(self) -> float:
return self.buy_vol - self.sell_vol
@dataclass(frozen=True)
class BotSnapshot:
version: int
as_of_ts: float
symbol: str
buy_magic: int
sell_magic: int
all_positions: tuple # immutable tuple of MT5 position objects
metrics: ClusterMetrics
equity: float
def buy_cluster(self) -> List[Any]:
return [p for p in self.all_positions if int(p.magic) == self.buy_magic]
def sell_cluster(self) -> List[Any]:
return [p for p in self.all_positions if int(p.magic) == self.sell_magic]
frozen=True: strategy/Grid chỉ đọc — không vô tình snapshot.metrics.buy_vol += 0.01 giữa hai hàm.
4. BotState — store có version
@dataclass
class BotStateStore:
_version: int = 0
_current: BotSnapshot | None = None
def publish(self, snap: BotSnapshot) -> None:
self._version += 1
object.__setattr__(snap, "version", self._version) # nếu cần gán post-init
self._current = snap
def get(self) -> BotSnapshot:
if self._current is None:
raise RuntimeError("State chưa publish — gọi refresh trước on_tick")
return self._current
Luồng mỗi tick:
refresh_from_mt5()— một lầnpositions_get+ account_info- Tính
ClusterMetricstừ list đã cache store.publish(BotSnapshot(...))process_cluster/tp_logic/ Guard — chỉstore.get()
graph TD
A(["Tick Python"]) --> B["positions_get 1 lần"]
B --> C["build ClusterMetrics"]
C --> D["store.publish snapshot"]
D --> E["Grid · FSM · Guard đọc get"]
E --> F{order_send?}
F -->|Có| B
F -->|Không| G(["gv.save · sleep"])
5. GVStore JSON — state qua restart
GVStore trong V6 Pro lưu P0, Step, FSM key vào file JSON — bền vững qua restart, khác snapshot sống trong một tick:
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")
Phân tách rõ:
| Layer | Sống bao lâu | Ví dụ |
|---|---|---|
| Snapshot | 1 tick | positions, floating, bias |
| GVStore | Qua restart | P0, Step index, FSM busy |
| Config | Deploy | magic, step, x-level |
Grid không nên ghi P0 vào biến global — dùng gv.set("BUY_P0", price).
6. Tích hợp vào on_tick PyNhiQuaiBot
def refresh_snapshot(self) -> BotSnapshot:
raw = list(mt5.positions_get(symbol=self.symbol) or [])
buy_vol = sell_vol = buy_f = sell_f = 0.0
for p in raw:
pr = float(p.profit + p.swap + p.commission)
vol = float(p.volume)
if int(p.magic) == self.cfg.buy_magic:
buy_vol += vol
buy_f += pr
elif int(p.magic) == self.cfg.sell_magic:
sell_vol += vol
sell_f += pr
acc = mt5.account_info()
equity = float(acc.equity) if acc else 0.0
metrics = ClusterMetrics(buy_vol, sell_vol, buy_f, sell_f)
snap = BotSnapshot(
version=0,
as_of_ts=time.time(),
symbol=self.symbol,
buy_magic=self.cfg.buy_magic,
sell_magic=self.cfg.sell_magic,
all_positions=tuple(raw),
metrics=metrics,
equity=equity,
)
self.state.publish(snap)
return snap
def on_tick(self) -> None:
bid, ask, spread = self.rates()
if bid <= 0 or spread > self.cfg.max_spread:
return
self.refresh_snapshot()
snap = self.state.get()
# process_cluster đọc snap.buy_cluster() — không gọi positions_get lại
7. Pandas — khi nào thêm?
Khóa PyNhiQuaiBot dùng list + dataclass trước Buổi 2–3. Pandas hữu ích khi:
- Dashboard gom history nhiều tick
- Backtest replay snapshot CSV
- Báo cáo exposure theo campaign
Không bắt buộc cho vòng on_tick production — tránh mọi module sửa chung một DataFrame.
Đọc thêm: Global State & Pandas hub · Kiến trúc 6111/6112
8. FAQ
Dataclass thay Pydantic được không?
Được cho bot single-process. Pydantic tốt hơn khi validate JSON API / FastAPI dashboard.
Snapshot frozen có chậm không?
Copy tuple reference — nhẹ hơn gọi positions_get lặp. Refresh sau mỗi lệnh thành công.
Port từ MQ5 GlobalVariable?
Đúng hướng: GVStore Python thay GlobalVariableGet/Set. Logic Grid/Brain vẫn viết Python.
KG 01/08 còn mấy ngày?
Tính 29/07/2026 — còn 3 ngày · T7+CN 15:00.
9. Tóm tắt
- Global State = schema + version, không phải biến rải rác
@dataclass(frozen=True)cho snapshot đọc-only mỗi tick- GVStore JSON cho P0/FSM qua restart · tách khỏi snapshot
- Một
publish()sau refresh — Grid/Brain/Guard dùngget()chung - Nền module ① trước Step/X và FSM STEP_BUSY
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ý: Python Nâng cao Hedging · PyNhiQuaiBot · 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
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Đà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.