| Thuật Toán 3: Tính Toán Độ Lệch Khối Lượng Ròng (Volume Bias) Cho Cụm Vị Thế

Được viết bởi thanhdt vào ngày 01/06/2026 lúc 10:54 | 49 lượt xem

Giới Thiệu: Tại Sao Cần Đo Lệch Khối Lượng?

Trong giao dịch lưới (grid trading) và chiến lược hai chiều, robot không chỉ mở lệnh mua mà còn duy trì đồng thời cả lệnh mua và lệnh bán ở nhiều tầng giá khác nhau. Khi thị trường di chuyển mạnh theo một hướng, tổng khối lượng Buy có thể vượt xa tổng khối lượng Sell — hoặc ngược lại. Sự chênh lệch này gọi là Volume Bias (Độ Lệch Khối Lượng Ròng).

Công thức cơ bản:

ΔV = V_Buy - V_Sell

Khi ΔV > 0: Robot đang nghiêng về Buy — có rủi ro nếu giá tiếp tục giảm.
Khi ΔV < 0: Robot đang nghiêng về Sell — có rủi ro nếu giá tiếp tục tăng.
Khi ΔV ≈ 0: Trạng thái cân bằng — tài khoản được bảo vệ tốt nhất.

Thuật toán Volume Bias là một phần cốt lõi trong hệ thống quản trị rủi ro. Khi equity (vốn thực tế) rơi xuống ngưỡng nguy hiểm InpMinEqui2, thuật toán sẽ tự động tính toán ΔV và mở một lệnh đối ứng với khối lượng bằng |ΔV| để đóng băng tài khoản — tức là vô hiệu hóa mọi biến động P&L cho đến khi trader can thiệp.

Bài viết này sẽ phân tích toàn bộ cơ chế từ lý thuyết đến code MQL5 hoàn chỉnh, bao gồm các trường hợp biên (edge cases) và cách tích hợp với hệ thống Equity Lockdown ở Bài 9 trong series.


Kiến Trúc Tổng Thể: Volume Bias Trong Hệ Thống Lưới


VOLUME BIAS ALGORITHM — LUỒNG XỬ LÝ

OnTick() — Kiểm Tra Equity

Equity <
InpMinEqui2?

NO

Tiếp tục
bình thường

YES

CalculateVolume(magic,
&buy_vol, &sell_vol)

ΔV = buy_vol – sell_vol
delta_vol = |ΔV|

_LOCKED
== 1?

YES

Bỏ qua
(đã khóa)

NO

Mở lệnh đối ứng khối lượng |ΔV| → Set _LOCKED=1

Hình 1: Luồng xử lý thuật toán Volume Bias — từ kiểm tra equity đến mở lệnh đóng băng tài khoản

Như sơ đồ trên minh họa, thuật toán hoạt động theo 4 bước tuần tự:

  1. Giám sát Equity liên tục trong mỗi tick
  2. Tính toán Volume Bias khi equity chạm ngưỡng nguy hiểm
  3. Kiểm tra trạng thái khóa để tránh mở lệnh lặp
  4. Mở lệnh đối ứng với khối lượng chính xác bằng |ΔV|

Hàm CalculateVolume: Trái Tim Của Thuật Toán

Hàm CalculateVolume() là thành phần quan trọng nhất. Nó duyệt qua toàn bộ lệnh đang mở (open positions) và tính tổng khối lượng mua/bán theo magic number.

Tại Sao Lọc Theo Magic Number?

Trong một tài khoản thực tế, trader có thể chạy nhiều robot hoặc đặt lệnh thủ công cùng lúc. Nếu không lọc theo magic, hàm sẽ tính cả khối lượng của các EA khác — gây ra sai lệch nghiêm trọng trong quyết định đóng băng tài khoản.


//+------------------------------------------------------------------+
//| Tính tổng khối lượng Buy và Sell theo magic number               |
//| Trả về true nếu có ít nhất 1 vị thế, false nếu không có gì      |
//+------------------------------------------------------------------+
bool CalculateVolume(long magic_number, double &buy_vol, double &sell_vol)
{
    buy_vol  = 0.0;
    sell_vol = 0.0;

    int total = PositionsTotal();
    if(total == 0) return false;

    bool found = false;

    for(int i = 0; i < total; i++)
    {
        ulong ticket = PositionGetTicket(i);
        if(ticket == 0) continue;

        // Chỉ xử lý các vị thế thuộc EA này
        if(PositionGetInteger(POSITION_MAGIC) != magic_number) continue;

        // Chỉ xử lý symbol hiện tại
        if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;

        double lot = PositionGetDouble(POSITION_VOLUME);
        ENUM_POSITION_TYPE pos_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);

        if(pos_type == POSITION_TYPE_BUY)
        {
            buy_vol  += lot;
            found     = true;
        }
        else if(pos_type == POSITION_TYPE_SELL)
        {
            sell_vol += lot;
            found     = true;
        }
    }

    // Làm tròn để tránh lỗi floating-point (ví dụ: 0.3000000001)
    buy_vol  = NormalizeDouble(buy_vol,  2);
    sell_vol = NormalizeDouble(sell_vol, 2);

    return found;
}

Xử Lý Lỗi Floating-Point

Một vấn đề ẩn thường gặp: khi cộng nhiều giá trị double trong MQL5, kết quả có thể bị lỗi làm tròn nhỏ. Ví dụ, ba lệnh 0.1 lot có thể cho kết quả 0.30000000004 thay vì 0.30. Lệnh NormalizeDouble(value, 2) ở cuối hàm giải quyết vấn đề này bằng cách làm tròn về 2 chữ số thập phân.


Tính Toán Delta Volume: Công Thức Và Ý Nghĩa

Công Thức Đầy Đủ


// Sau khi gọi CalculateVolume()
double delta_vol = buy_vol - sell_vol;    // Có thể âm hoặc dương
double abs_delta = MathAbs(delta_vol);    // Khối lượng đối ứng cần mở

Bảng Diễn Giải Các Trường Hợp

Giá trị ΔV Ý nghĩa Lệnh đối ứng cần mở Kết quả
ΔV = +0.5 Thừa 0.5 lot Buy Bán 0.5 lot Sell Cân bằng ròng = 0
ΔV = -0.3 Thừa 0.3 lot Sell Mua 0.3 lot Buy Cân bằng ròng = 0
ΔV = 0.0 Đã cân bằng Không cần mở lệnh Không làm gì
ΔV rất nhỏ (<0.01) Lỗi làm tròn Bỏ qua Tránh lệnh 0 lot

Hàm OpenHedgeLock: Mở Lệnh Đóng Băng Tài Khoản

Sau khi tính được abs_delta, hàm OpenHedgeLock() sẽ thực hiện việc mở lệnh đối ứng. Đây là thời điểm quan trọng nhất — mọi sai sót ở bước này đều có hậu quả nghiêm trọng.


//+------------------------------------------------------------------+
//| Mở lệnh đối ứng để đóng băng tài khoản                          |
//| Trả về ticket của lệnh mới, hoặc 0 nếu thất bại                 |
//+------------------------------------------------------------------+
ulong OpenHedgeLock(double buy_vol, double sell_vol, long magic_number)
{
    double delta_vol = buy_vol - sell_vol;
    double abs_delta = NormalizeDouble(MathAbs(delta_vol), 2);

    // Edge case 1: Khối lượng quá nhỏ — bỏ qua
    if(abs_delta  max_vol)
    {
        Print("CẢNH BÁO: ΔV=", abs_delta, " vượt giới hạn tối đa ", max_vol,
              ". Giảm xuống mức tối đa.");
        abs_delta = max_vol;
    }

    // Xác định hướng lệnh đối ứng
    ENUM_ORDER_TYPE hedge_type;
    if(delta_vol > 0)
        hedge_type = ORDER_TYPE_SELL;  // Thừa Buy → bán để cân bằng
    else
        hedge_type = ORDER_TYPE_BUY;   // Thừa Sell → mua để cân bằng

    // Lấy giá hiện tại
    double price = (hedge_type == ORDER_TYPE_BUY)
                   ? SymbolInfoDouble(_Symbol, SYMBOL_ASK)
                   : SymbolInfoDouble(_Symbol, SYMBOL_BID);

    // Tạo request
    MqlTradeRequest  request = {};
    MqlTradeResult   result  = {};

    request.action    = TRADE_ACTION_DEAL;
    request.symbol    = _Symbol;
    request.volume    = abs_delta;
    request.type      = hedge_type;
    request.price     = price;
    request.deviation = 20;  // Slippage cho phép: 20 points
    request.magic     = magic_number;
    request.comment   = "HEDGE_LOCK_" + IntegerToString((int)magic_number);

    // Làm tròn giá theo digit của symbol
    request.price = NormalizeDouble(request.price, (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS));

    // Gửi lệnh
    if(!OrderSend(request, result))
    {
        int err = GetLastError();
        Print("HedgeLock FAILED. Error: ", err, " | Retcode: ", result.retcode,
              " | Comment: ", result.comment);
        ResetLastError();
        return 0;
    }

    if(result.retcode != TRADE_RETCODE_DONE)
    {
        Print("HedgeLock retcode không OK: ", result.retcode,
              " | Deal: ", result.deal);
        return 0;
    }

    Print("HedgeLock SUCCESS! Ticket=", result.deal,
          " | Type=", EnumToString(hedge_type),
          " | Volume=", abs_delta,
          " | Price=", result.price);

    return result.deal;
}

Tại Sao Cần Kiểm Tra SYMBOL_VOLUME_MIN?

Mỗi broker có giới hạn khối lượng tối thiểu khác nhau. Một số broker cho phép 0.01 lot, nhưng cũng có broker yêu cầu tối thiểu 0.1 lot. Nếu abs_delta nhỏ hơn giá trị này, lệnh sẽ bị từ chối với lỗi TRADE_RETCODE_INVALID_VOLUME. Kiểm tra trước giúp tránh lỗi không cần thiết.


Hàm CheckVolumeBias: Điều Phối Toàn Bộ Luồng

Hàm CheckVolumeBias() là hàm cấp cao nhất, được gọi trong OnTick(). Nó điều phối toàn bộ logic: kiểm tra điều kiện, tính toán, đánh dấu trạng thái, và gọi hàm mở lệnh.


// Ngưỡng equity nguy hiểm (cấu hình bởi người dùng)
input double InpMinEqui2 = 500.0;  // Ngưỡng equity tối thiểu để trigger Hedge Lock

//+------------------------------------------------------------------+
//| Kiểm tra và thực thi Volume Bias (gọi trong OnTick)              |
//+------------------------------------------------------------------+
void CheckVolumeBias(long magic_number)
{
    // Kiểm tra 1: Đã bị khóa chưa?
    if(GlobalVariableGet("_LOCKED_" + IntegerToString((int)magic_number)) == 1.0)
    {
        // Tài khoản đã bị đóng băng — không làm gì thêm
        return;
    }

    // Kiểm tra 2: Equity còn đủ chưa?
    double current_equity = AccountInfoDouble(ACCOUNT_EQUITY);
    if(current_equity >= InpMinEqui2)
    {
        // Vẫn an toàn — không cần hành động
        return;
    }

    // === EQUITY CHẠM NGƯỠNG NGUY HIỂM ===
    Print("⚠️ VOLUME BIAS TRIGGER! Equity=", current_equity,
          " < Threshold=", InpMinEqui2);

    // Tính toán volume
    double buy_vol, sell_vol;
    bool has_positions = CalculateVolume(magic_number, buy_vol, sell_vol);

    if(!has_positions)
    {
        Print("Không có vị thế nào — không thể hedge.");
        return;
    }

    double delta_vol = buy_vol - sell_vol;
    Print("Volume Bias: Buy=", buy_vol, " | Sell=", sell_vol,
          " | ΔV=", delta_vol);

    // Trường hợp đặc biệt: đã cân bằng tự nhiên
    if(MathAbs(delta_vol)  0)
    {
        // Đặt cờ khóa toàn cục
        GlobalVariableSet("_LOCKED_" + IntegerToString((int)magic_number), 1.0);

        // Lưu thông tin hedge để tham chiếu sau
        GlobalVariableSet("_HEDGE_TICKET_" + IntegerToString((int)magic_number),
                         (double)hedge_ticket);
        GlobalVariableSet("_HEDGE_DELTA_"  + IntegerToString((int)magic_number),
                         delta_vol);

        Print("✅ Hedge Lock thành công! Tài khoản đóng băng.");
        Print("   Hedge Ticket: ", hedge_ticket);
        Print("   Delta Vol: ", delta_vol);
        Print("   Equity tại thời điểm lock: ", current_equity);
    }
    else
    {
        Print("❌ Hedge Lock thất bại! Cần can thiệp thủ công ngay lập tức!");
        // Gửi alert cho trader
        Alert("CRITICAL: Hedge Lock thất bại tại equity ", current_equity,
              "! Kiểm tra ngay!");
        SendNotification("CRITICAL: Hedge Lock thất bại! Equity=" +
                        DoubleToString(current_equity, 2));
    }
}

Xử Lý Edge Cases: Những Tình Huống Nguy Hiểm

Trong thực chiến, có nhiều tình huống bất ngờ mà code cần xử lý đúng cách. Dưới đây là bảng tổng hợp các edge cases quan trọng nhất:

Tình huống Nguyên nhân Cách xử lý Code liên quan
Mở lệnh hedge 2 lần Equity dao động quanh ngưỡng Kiểm tra _LOCKED GlobalVariable trước GlobalVariableGet("_LOCKED_...")
ΔV = 0 (đã cân bằng) Lưới đối xứng hoàn hảo Không mở lệnh, vẫn đặt cờ khóa MathAbs(delta) < 0.01
Volume quá nhỏ ΔV < lot tối thiểu của broker Bỏ qua mở lệnh, vẫn khóa SYMBOL_VOLUME_MIN
Không có vị thế nào Robot chưa mở lệnh bao giờ Return sớm, không làm gì PositionsTotal() == 0
Mạng ngắt khi gửi lệnh Lỗi kết nối server Log lỗi, gửi Alert + Push notification Alert() + SendNotification()
EA restart sau khi đã lock Khởi động lại MetaTrader GlobalVariable được lưu tự động qua restart GV tự persist trên disk

Tích Hợp Với OnTick: Code Hoàn Chỉnh Trong EA

Dưới đây là cách tích hợp thuật toán Volume Bias vào EA thực tế, bao gồm cả phần OnInit() để xử lý trường hợp EA restart:


// === CẤU HÌNH ===
input long   InpMagicNumber = 20240101;  // Magic Number của EA
input double InpMinEqui2    = 500.0;     // Ngưỡng equity trigger Hedge Lock
input bool   InpEnableHedge = true;      // Bật/tắt chức năng Hedge Lock

// === BIẾN TOÀN CỤC ===
string GV_LOCKED; // Key GlobalVariable
string GV_TICKET;
string GV_DELTA;

//+------------------------------------------------------------------+
int OnInit()
{
    // Khởi tạo tên các GlobalVariables
    GV_LOCKED = "_LOCKED_" + IntegerToString((int)InpMagicNumber);
    GV_TICKET = "_HEDGE_TICKET_" + IntegerToString((int)InpMagicNumber);
    GV_DELTA  = "_HEDGE_DELTA_"  + IntegerToString((int)InpMagicNumber);

    // Kiểm tra trạng thái khóa từ lần chạy trước (EA restart)
    if(GlobalVariableCheck(GV_LOCKED) && GlobalVariableGet(GV_LOCKED) == 1.0)
    {
        double saved_delta  = GlobalVariableGet(GV_DELTA);
        double saved_ticket = GlobalVariableGet(GV_TICKET);

        Print("⚠️ EA khởi động lại — tài khoản VẪN ĐANG BỊ ĐÓNG BĂNG!");
        Print("   Hedge Ticket: ", (long)saved_ticket);
        Print("   Delta khi lock: ", saved_delta);
        Print("   Cần can thiệp thủ công để mở khóa!");

        Alert("Tài khoản vẫn đang bị Hedge Lock từ session trước! Ticket=",
              (long)saved_ticket);
    }

    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
void OnTick()
{
    // Chỉ kiểm tra Volume Bias nếu được bật
    if(InpEnableHedge)
    {
        CheckVolumeBias(InpMagicNumber);
    }

    // Nếu đang bị khóa → không chạy logic giao dịch bình thường
    if(GlobalVariableGet(GV_LOCKED) == 1.0)
    {
        Comment("⛔ TÀI KHOẢN ĐANG BỊ HEDGE LOCK — MỌI GIAO DỊCH MỚI ĐÃ BỊ DỪNG");
        return;
    }

    // === LOGIC GIAO DỊCH BÌNH THƯỜNG ===
    // ... (code lưới, gặt X, trailing plowing, v.v.)
}

Giải Phóng Hedge Lock: Quy Trình Mở Khóa

Sau khi equity được bổ sung hoặc trader muốn tiếp tục giao dịch, cần có quy trình mở khóa an toàn. Điều này KHÔNG nên tự động hóa — trader phải xem xét tình hình thị trường trước khi quyết định.


//+------------------------------------------------------------------+
//| Mở khóa Hedge Lock (gọi thủ công bởi trader qua nút trên panel) |
//+------------------------------------------------------------------+
bool ReleasehHedgeLock(long magic_number)
{
    string gv_locked = "_LOCKED_" + IntegerToString((int)magic_number);
    string gv_ticket = "_HEDGE_TICKET_" + IntegerToString((int)magic_number);

    // Kiểm tra xác nhận
    if(!GlobalVariableCheck(gv_locked) || GlobalVariableGet(gv_locked) != 1.0)
    {
        Print("Không tìm thấy Hedge Lock để giải phóng.");
        return false;
    }

    // Lấy ticket của lệnh hedge
    ulong hedge_ticket = (ulong)GlobalVariableGet(gv_ticket);

    if(hedge_ticket > 0)
    {
        // Kiểm tra lệnh hedge vẫn còn tồn tại
        if(PositionSelectByTicket(hedge_ticket))
        {
            double hedge_vol  = PositionGetDouble(POSITION_VOLUME);
            ENUM_POSITION_TYPE hedge_type =
                (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);

            Print("Cảnh báo: Lệnh hedge ticket=", hedge_ticket,
                  " vẫn đang mở với vol=", hedge_vol,
                  " type=", EnumToString(hedge_type));
            Print("Hãy đóng lệnh này thủ công trước khi mở khóa.");
            return false;
        }
    }

    // Xóa các GlobalVariables
    GlobalVariableDel(gv_locked);
    GlobalVariableDel(gv_ticket);
    GlobalVariableDel("_HEDGE_DELTA_" + IntegerToString((int)magic_number));

    Print("✅ Hedge Lock đã được giải phóng. EA tiếp tục giao dịch.");
    return true;
}

Tại Sao Không Tự Động Mở Khóa?

Nhiều trader hỏi: “Tại sao không tự động mở khóa khi equity phục hồi?” Câu trả lời là: equity phục hồi không có nghĩa là rủi ro đã qua. Thị trường có thể đang trong giai đoạn điều chỉnh ngắn hạn trước khi tiếp tục xu hướng nguy hiểm. Chỉ trader mới có thể đánh giá được bối cảnh tổng thể và quyết định khi nào an toàn để tiếp tục.


GlobalVariable: Bộ Nhớ Liên Phiên

Một tính năng quan trọng của GlobalVariables trong MetaTrader 4/5 là chúng được lưu trên disk và tồn tại qua các lần restart của MetaTrader (không phải của VPS/máy tính). Đây là lý do tại sao chúng được chọn để lưu trạng thái khóa:

Phương pháp lưu trạng thái Tồn tại qua EA restart? Tồn tại qua MT restart? Tốc độ đọc/ghi
GlobalVariable ✓ Có ✓ Có (lưu disk) Rất nhanh
Biến static trong EA ✗ Không ✗ Không Cực nhanh
File CSV/TXT ✓ Có ✓ Có Chậm hơn
Comment của lệnh ✓ Có (trên sàn) ✓ Có Phụ thuộc broker

Backtesting Volume Bias: Kiểm Tra Trước Khi Dùng Thực

Trước khi deploy EA với tính năng Hedge Lock lên tài khoản thực, cần kiểm tra kỹ trong Strategy Tester. Tuy nhiên, GlobalVariables trong Strategy Tester hoạt động khác với môi trường thực — chúng không được lưu giữa các lần chạy test.


// Hàm test CalculateVolume trong Strategy Tester
// Chạy trong OnInit() của EA test
void TestCalculateVolume()
{
    // Giả lập: EA có 3 lệnh Buy tổng cộng 0.3 lot
    // và 2 lệnh Sell tổng cộng 0.2 lot
    // ΔV phải là +0.1

    // Trong Strategy Tester, dùng OrderSend để tạo lệnh test trước
    // Sau đó gọi CalculateVolume và kiểm tra kết quả

    double buy_vol, sell_vol;
    CalculateVolume(InpMagicNumber, buy_vol, sell_vol);

    Print("Test CalculateVolume:");
    Print("  Buy Volume: ", buy_vol, " (expected: 0.30)");
    Print("  Sell Volume: ", sell_vol, " (expected: 0.20)");
    Print("  Delta: ", buy_vol - sell_vol, " (expected: 0.10)");

    if(MathAbs((buy_vol - sell_vol) - 0.10) < 0.001)
        Print("✅ Test PASSED");
    else
        Print("❌ Test FAILED");
}

Mối Liên Hệ Với Các Thuật Toán Khác Trong Series

Volume Bias không hoạt động độc lập — nó là một phần của hệ sinh thái thuật toán lớn hơn:

Kết Nối Với Thuật Toán 1 & 2 (Grid Engine)

Grid Engine (Thuật toán 1-2) là nguồn tạo ra các vị thế mua/bán. Khi lưới mở rộng theo một hướng không cân đối, Volume Bias sẽ được kích hoạt. Do đó, cần thiết kế Grid Engine với tham số kiểm soát số tầng tối đa để tránh ΔV quá lớn.

Kết Nối Với Comment String Parser (Thuật Toán 4)

Khi lệnh hedge được mở, nó cũng cần được ghi comment phù hợp (ví dụ: "HEDGE_LOCK") để khi EA restart, Comment Parser (Thuật toán 4) có thể nhận dạng đây là lệnh hedge, không phải lệnh lưới thông thường.

Kết Nối Với Equity Lockdown (Bài 9 — Thuật Toán Nâng Cao)

Volume Bias là phiên bản cơ bản của chiến lược đóng băng tài khoản. Ở Bài 9, Equity Lockdown sẽ mở rộng cơ chế này với nhiều tầng ngưỡng (InpMinEqui1, InpMinEqui2) và logic phức tạp hơn để xử lý nhiều kịch bản khác nhau.


Cạm Bẫy Phổ Biến Khi Triển Khai

Cạm Bẫy 1: Quên Kiểm Tra Symbol

Nếu EA chạy trên EURUSD nhưng tài khoản cũng có lệnh GBPUSD (từ EA khác), hàm CalculateVolume() phải lọc theo _Symbol chứ không chỉ theo magic number. Code trên đã xử lý điều này.

Cạm Bẫy 2: Magic Number Trùng

Nếu hai EA dùng chung magic number trên cùng một tài khoản, CalculateVolume() sẽ tính lẫn lộn khối lượng của cả hai EA. Luôn dùng magic number duy nhất cho mỗi EA và mỗi cặp tiền tệ.

Cạm Bẫy 3: Không Xử Lý Partial Fill

Ở một số broker, lệnh thị trường (TRADE_ACTION_DEAL) có thể bị khớp một phần (partial fill). Code cần kiểm tra result.volume so với request.volume để đảm bảo khớp đủ.


// Kiểm tra partial fill sau OrderSend
if(result.retcode == TRADE_RETCODE_DONE &&
   MathAbs(result.volume - abs_delta) > 0.001)
{
    Print("CẢNH BÁO: Partial fill! Yêu cầu=", abs_delta,
          " Thực tế=", result.volume);
    // Tính toán lại phần còn thiếu và thử mở thêm
}

Tổng Kết Và Lộ Trình Tiếp Theo

Thuật toán Volume Bias là một trong những công cụ quản trị rủi ro mạnh mẽ nhất trong giao dịch lưới hai chiều. Điểm mấu chốt cần nhớ:

  • ΔV = V_Buy – V_Sell: Công thức đơn giản nhưng quyết định vận mệnh tài khoản
  • GlobalVariable: Chìa khóa để duy trì trạng thái qua các lần restart
  • Không tự động mở khóa: Trader phải can thiệp thủ công sau khi đánh giá thị trường
  • Edge cases: Kiểm tra kỹ vol tối thiểu, trùng lệnh, partial fill

Bài 4, chúng ta sẽ khám phá thuật toán tiếp theo trong series: Comment String Parser — cơ chế đọc comment từ các vị thế trên sàn để khôi phục trạng thái tầng lưới sau khi EA bị restart. Đây là thuật toán bổ sung hoàn hảo cho Volume Bias vì nó giải quyết câu hỏi: “Sau khi restart, EA biết mình đang ở tầng nào?”


Bạn Muốn Triển Khai Thuật Toán Này Vào EA Thực Chiến?

Khóa học MQL5 Nâng Cao của chúng tôi bao gồm toàn bộ 9 thuật toán trong series này, kèm source code hoàn chỉnh, video giảng dạy chi tiết, và hỗ trợ trực tiếp từ instructor.

Xem Khóa Học MQL5 Nâng Cao →

Đặng Trí Thanh

Đặng Trí Thanh

Giám đốc Công nghệ · DNT Digital · Giảng viên HNDL
1.322 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.