Trang chủ Kiến thức Biến và Hằng Số trong MQL5: Khai Báo và Phạm Vi
Knowledge

Biến và Hằng Số trong MQL5: Khai Báo và Phạm Vi

14 tháng 11, 2025

Học cách khai báo biến local, global, static và constants trong MQL5 với scope và lifetime management.

Biến (Variables) và Hằng Số (Constants)

Trong MQL5, biến là vùng nhớ lưu trữ giá trị có thể thay đổi trong quá trình chạy chương trình, trong khi hằng số là giá trị không thể thay đổi sau khi khởi tạo.

Khai Báo Biến Local (Cục Bộ)

void OnTick() {
    // Biến local - chỉ tồn tại trong hàm OnTick()
    int counter = 0;
    double price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
    string message = "Hello";
    
    counter++;  // Biến này sẽ reset về 0 mỗi lần OnTick() được gọi
    Print("Counter: ", counter);  // Luôn in ra 1
}

// ❌ Lỗi: Không thể truy cập biến local từ hàm khác
void AnotherFunction() {
    Print(counter);  // ERROR: 'counter' - undeclared identifier
}

Biến Static: Giữ Giá Trị Giữa Các Lần Gọi

void OnTick() {
    // Biến static - giữ giá trị giữa các lần gọi hàm
    static int counter = 0;
    static double lastPrice = 0;
    
    counter++;  // Tăng dần: 1, 2, 3, 4, ...
    Print("Counter: ", counter);
    
    double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
    if(lastPrice > 0) {
        double change = currentPrice - lastPrice;
        Print("Price changed by: ", change);
    }
    lastPrice = currentPrice;
}

// Ứng dụng: Detect new bar
void CheckNewBar() {
    static datetime lastBarTime = 0;
    datetime currentBarTime = iTime(_Symbol, PERIOD_CURRENT, 0);
    
    if(currentBarTime != lastBarTime) {
        Print("New bar detected!");
        lastBarTime = currentBarTime;
        // Execute logic only on new bar
    }
}

Biến Global: Phạm Vi Toàn File

// Khai báo ở đầu file, bên ngoài mọi hàm
int g_magicNumber = 12345;
double g_lotSize = 0.1;
string g_symbol = "EURUSD";
bool g_isTrading = false;

// Có thể truy cập từ mọi hàm trong file
void OnInit() {
    Print("Magic Number: ", g_magicNumber);
    g_isTrading = true;
}

void OnTick() {
    if(!g_isTrading) return;
    
    double ask = SymbolInfoDouble(g_symbol, SYMBOL_ASK);
    // Use g_lotSize for trading...
}

void OnDeinit(const int reason) {
    g_isTrading = false;
    Print("EA stopped");
}

Input Variables: Tham Số Cấu Hình

// Input variables - có thể thay đổi từ EA properties
input int InpMagicNumber = 12345;          // Magic number
input double InpLotSize = 0.1;             // Lot size
input int InpStopLoss = 50;                // Stop loss (pips)
input int InpTakeProfit = 100;             // Take profit (pips)
input bool InpUseTrailingStop = true;      // Use trailing stop
input string InpComment = "My EA";         // Order comment

// Enum input
enum ENUM_TRADE_MODE {
    TRADE_MANUAL,      // Manual trading
    TRADE_AUTO,        // Automatic trading
    TRADE_SEMI_AUTO    // Semi-automatic
};
input ENUM_TRADE_MODE InpTradeMode = TRADE_AUTO;

// Sinput: Simple input (hiển thị đơn giản hơn)
sinput string s1 = "=== Risk Management ===";
input double InpRiskPercent = 2.0;
input int InpMaxOrders = 5;

void OnInit() {
    // Sử dụng input variables
    Print("Lot Size: ", InpLotSize);
    Print("Stop Loss: ", InpStopLoss, " pips");
}

Constants: Hằng Số

// Hằng số - không thể thay đổi
const int MAGIC_NUMBER = 20250114;
const double MAX_LOT = 100.0;
const string EA_NAME = "My Expert Advisor";
const int MAX_SLIPPAGE = 3;

// ❌ Lỗi: Không thể thay đổi giá trị const
void OnTick() {
    MAGIC_NUMBER = 99999;  // ERROR: Cannot modify const variable
}

// ✅ Sử dụng đúng
void OpenOrder() {
    MqlTradeRequest request = {};
    request.magic = MAGIC_NUMBER;
    request.volume = 0.1;
    request.deviation = MAX_SLIPPAGE;
    request.comment = EA_NAME;
    // ...
}

// Enum constants
enum ENUM_SIGNAL_TYPE {
    SIGNAL_NONE = 0,
    SIGNAL_BUY = 1,
    SIGNAL_SELL = -1
};

ENUM_SIGNAL_TYPE CheckSignal() {
    // Logic to determine signal
    return SIGNAL_BUY;
}

Naming Conventions (Best Practices)

// Global variables: prefix g_
int g_totalOrders = 0;
double g_accountBalance = 0;

// Input variables: prefix Inp
input int InpPeriod = 14;
input double InpRisk = 2.0;

// Constants: UPPERCASE
const int MAX_RETRY = 3;
const double EPSILON = 0.000001;

// Local variables: camelCase hoặc snake_case
int orderCount = 0;
double stop_loss = 0;

// Static variables: prefix s_
static int s_barCounter = 0;

// Private member variables (in class): prefix m_
class CMyClass {
private:
    int m_value;
    double m_price;
};

Variable Scope Examples

// Global scope
int g_globalVar = 100;

void Function1() {
    // Local scope
    int localVar = 10;
    
    Print("Global: ", g_globalVar);    // ✅ OK
    Print("Local: ", localVar);         // ✅ OK
    
    {
        // Block scope
        int blockVar = 5;
        Print("Block: ", blockVar);     // ✅ OK
        Print("Local: ", localVar);     // ✅ OK
    }
    
    // Print("Block: ", blockVar);      // ❌ ERROR: out of scope
}

void Function2() {
    Print("Global: ", g_globalVar);    // ✅ OK
    // Print("Local: ", localVar);      // ❌ ERROR: undefined
}

Initialization: Khởi Tạo Giá Trị

// ✅ Khởi tạo ngay khi khai báo
int counter = 0;
double price = 1.12345;
string symbol = "EURUSD";

// ⚠️ Không khởi tạo: Giá trị mặc định
int uninitializedInt;        // = 0
double uninitializedDouble;  // = 0.0
string uninitializedString;  // = ""
bool uninitializedBool;      // = false

// Khởi tạo từ expression
int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
datetime now = TimeCurrent();

// Multiple declaration and initialization
int a = 10, b = 20, c = 30;
double x = 1.1, y = 2.2, z = 3.3;

Ứng Dụng Thực Tế: Trading Variables

// === Input Parameters ===
input int InpMagicNumber = 12345;
input double InpLotSize = 0.1;
input int InpStopLoss = 50;
input int InpTakeProfit = 100;

// === Global Variables ===
int g_totalBuyOrders = 0;
int g_totalSellOrders = 0;
double g_totalProfit = 0;
datetime g_lastTradeTime = 0;

// === Constants ===
const int MAX_ORDERS = 10;
const int MIN_DISTANCE = 20;  // pips

// === OnInit: Initialize ===
int OnInit() {
    // Reset global variables
    g_totalBuyOrders = 0;
    g_totalSellOrders = 0;
    g_totalProfit = 0;
    g_lastTradeTime = 0;
    
    Print("EA Initialized - Magic: ", InpMagicNumber);
    return INIT_SUCCEEDED;
}

// === OnTick: Main Logic ===
void OnTick() {
    // Static variable: track last bar
    static datetime s_lastBarTime = 0;
    datetime currentBarTime = iTime(_Symbol, PERIOD_CURRENT, 0);
    
    if(currentBarTime == s_lastBarTime) return;
    s_lastBarTime = currentBarTime;
    
    // Local variables
    int signal = CheckSignal();
    double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
    double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
    
    // Update global counters
    g_totalBuyOrders = CountOrders(ORDER_TYPE_BUY);
    g_totalSellOrders = CountOrders(ORDER_TYPE_SELL);
    
    // Check max orders limit
    if(g_totalBuyOrders + g_totalSellOrders >= MAX_ORDERS) {
        return;
    }
    
    // Trading logic...
}

Memory Management Tips

  • ✅ Biến local: Tự động free khi hàm kết thúc
  • ✅ Biến static: Tồn tại suốt thời gian chạy EA
  • ✅ Biến global: Tồn tại suốt thời gian chạy EA
  • ⚠️ Arrays và objects cần free memory thủ công nếu cấp phát động

Best Practices

  • ✅ Sử dụng const cho giá trị không đổi
  • ✅ Prefix g_ cho global, Inp cho input
  • ✅ Khởi tạo biến ngay khi khai báo
  • ✅ Sử dụng static cho biến cần giữ giá trị
  • ✅ Giới hạn phạm vi biến càng nhỏ càng tốt
  • ⛔ Tránh quá nhiều biến global (khó debug)
  • ⛔ Không đặt tên biến trùng với keywords

Bài Tập Thực Hành

  1. Viết EA với 5 input parameters: Magic, Lot, SL, TP, TrailingStop
  2. Tạo global counter đếm tổng số trades đã thực hiện (buy + sell)
  3. Sử dụng static variable để detect new bar và print "New Bar!" chỉ 1 lần

Tài Liệu Tham Khảo