Trang chủ Kiến thức OnDeinit() trong MQL5: Dọn Dẹp Khi EA Dừng
Knowledge

OnDeinit() trong MQL5: Dọn Dẹp Khi EA Dừng

14 tháng 11, 2025

Hướng dẫn OnDeinit() event handler - cleanup resources, save state, handle different deinit reasons.

OnDeinit(): Cleanup Event Handler

OnDeinit() được gọi khi EA bị remove khỏi chart hoặc terminal đóng. Đây là nơi dọn dẹp resources, save state, và close connections.

Cú Pháp và Deinit Reasons

void OnDeinit(const int reason) {
    // reason parameter indicates WHY EA is stopping
    
    string deInitReason = "";
    switch(reason) {
        case REASON_PROGRAM:
            deInitReason = "EA được remove thủ công";
            break;
        case REASON_REMOVE:
            deInitReason = "EA bị xóa khỏi chart";
            break;
        case REASON_RECOMPILE:
            deInitReason = "EA được recompile";
            break;
        case REASON_CHARTCHANGE:
            deInitReason = "Symbol hoặc timeframe thay đổi";
            break;
        case REASON_CHARTCLOSE:
            deInitReason = "Chart đóng";
            break;
        case REASON_PARAMETERS:
            deInitReason = "Input parameters thay đổi";
            break;
        case REASON_ACCOUNT:
            deInitReason = "Account thay đổi";
            break;
        case REASON_TEMPLATE:
            deInitReason = "Template mới apply";
            break;
        case REASON_INITFAILED:
            deInitReason = "OnInit() trả về INIT_FAILED";
            break;
        case REASON_CLOSE:
            deInitReason = "Terminal đóng";
            break;
    }
    
    Print("EA stopping. Reason: ", deInitReason);
}

Release Indicator Handles

// Global indicator handles
int g_maHandle = INVALID_HANDLE;
int g_rsiHandle = INVALID_HANDLE;
int g_macdHandle = INVALID_HANDLE;

void OnDeinit(const int reason) {
    // Release all indicator handles
    if(g_maHandle != INVALID_HANDLE) {
        IndicatorRelease(g_maHandle);
        Print("MA indicator released");
    }
    
    if(g_rsiHandle != INVALID_HANDLE) {
        IndicatorRelease(g_rsiHandle);
        Print("RSI indicator released");
    }
    
    if(g_macdHandle != INVALID_HANDLE) {
        IndicatorRelease(g_macdHandle);
        Print("MACD indicator released");
    }
}

Delete Chart Objects

void OnDeinit(const int reason) {
    // Delete all objects created by EA
    string prefix = "EA_";
    
    int total = ObjectsTotal(0);
    for(int i = total - 1; i >= 0; i--) {
        string objName = ObjectName(0, i);
        if(StringFind(objName, prefix) == 0) {
            ObjectDelete(0, objName);
            Print("Deleted object: ", objName);
        }
    }
    
    // Or delete all objects at once
    ObjectsDeleteAll(0, prefix);
    
    ChartRedraw();
}

Save EA State to File

void OnDeinit(const int reason) {
    // Save current state to file
    string filename = "EA_State_" + _Symbol + ".txt";
    int handle = FileOpen(filename, FILE_WRITE|FILE_TXT);
    
    if(handle != INVALID_HANDLE) {
        // Save statistics
        FileWriteString(handle, "Last Run: " + TimeToString(TimeCurrent()) + "\n");
        FileWriteString(handle, "Total Positions: " + IntegerToString(PositionsTotal()) + "\n");
        FileWriteString(handle, "Balance: " + DoubleToString(AccountInfoDouble(ACCOUNT_BALANCE), 2) + "\n");
        FileWriteString(handle, "Reason: " + IntegerToString(reason) + "\n");
        
        FileClose(handle);
        Print("State saved to ", filename);
    }
}

Best Practices

  • ✅ Luôn release indicator handles
  • ✅ Delete chart objects tạo bởi EA
  • ✅ Kill timers nếu có: EventKillTimer()
  • ✅ Save important state to file
  • ✅ Log deinit reason để debug