Gann Forum: Building and Optimizing Indicators Based on Market Geometry

 
I'm trying to create an indicator based on the Gann square of 144 but I'm encountering problems. I ask the community for help to be successful in this project and make the indicator available for free to everyone. ;) 


#property copyright "Copyright 2024"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_chart_window
#property indicator_plots 0

// Incluir arquivos necessários
#include <Object.mqh>
#include <StdLibErr.mqh>
#include <Object.mqh>
#include <ChartObjects\ChartObjectsTxtControls.mqh>
#include <ChartObjects\ChartObjectsShapes.mqh>

// Inputs
input bool ShowTopXAxis = false;           // Mostrar eixo X superior
input bool ShowBottomXAxis = true;         // Mostrar eixo X inferior
input bool ShowLeftYAxis = false;          // Mostrar eixo Y esquerdo
input bool ShowRightYAxis = true;          // Mostrar eixo Y direito
input bool ShowPrices = true;              // Mostrar preços no eixo Y direito
input bool ShowDivisions = true;           // Mostrar divisões verticais
input bool ShowExtraLines = true;          // Mostrar linhas extras
input bool ShowGrid = true;                // Mostrar grade
input bool ShowBackground = true;          // Mostrar fundo

// Cores
input color LabelColor = clrGreen;         // Cor dos números
input color DivisionsColor = clrBlue;      // Cor das linhas verticais
input color GridColor = clrGray;           // Cor da grade

// Constantes
const int SQUARES = 144;
const int MAX_LINES = 500;
const int MAX_LABELS = 500;
const double MIN_PRICE_DIFF = 0.0001;      // Diferença mínima de preço

// Arrays para armazenar objetos gráficos
int gannLines[];
int gannLabels[];
int gannBoxes[];

// Variáveis globais
datetime startTime;
datetime endTime;
double upperPrice;
double lowerPrice;
bool isInitialized = false;
bool isUpdating = false;                   // Flag para evitar atualizações recursivas

//+------------------------------------------------------------------+
//| Função de inicialização do indicador                              |
//+------------------------------------------------------------------+
int OnInit()
{
    // Inicializar arrays
    if(!ArrayResize(gannLines, MAX_LINES) || 
       !ArrayResize(gannLabels, MAX_LABELS) || 
       !ArrayResize(gannBoxes, 9))
    {
        Print("Erro: Falha ao alocar memória para arrays");
        return(INIT_FAILED);
    }
    
    // Limpar objetos existentes
    if(!ObjectsDeleteAll(0, "Gann_"))
    {
        Print("Aviso: Não foi possível limpar todos os objetos existentes");
    }
    
    // Criar o quadrado principal com cantos redimensionáveis
    if(!CreateResizableSquare())
    {
        Print("Erro: Falha ao criar o quadrado de Gann");
        return(INIT_FAILED);
    }
    
    isInitialized = true;
    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Função de desinicialização do indicador                           |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    if(!ObjectsDeleteAll(0, "Gann_"))
    {
        Print("Aviso: Não foi possível limpar todos os objetos durante a desinicialização");
    }
    isInitialized = false;
}

//+------------------------------------------------------------------+
//| Função de iteração do indicador                                   |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
    if(!isInitialized || isUpdating)
        return(rates_total);
        
    return(rates_total);
}

//+------------------------------------------------------------------+
//| Obter preços da semana anterior                                   |
//+------------------------------------------------------------------+
bool GetLastWeekPrices(double &high, double &low, datetime &start, datetime &end)
{
    MqlDateTime currentTime;
    TimeToStruct(TimeCurrent(), currentTime);
    
    // Encontrar o início da semana atual
    currentTime.hour = 0;
    currentTime.min = 0;
    currentTime.sec = 0;
    datetime weekStart = StructToTime(currentTime);
    
    // Encontrar o domingo mais próximo
    while(TimeDayOfWeek(weekStart) != 0) // Domingo
        weekStart -= PeriodSeconds(PERIOD_D1);
        
    // Encontrar o início da semana anterior
    datetime lastWeekStart = weekStart - PeriodSeconds(PERIOD_W1);
    
    // Encontrar o fim da semana anterior
    datetime lastWeekEnd = weekStart - 1;
    
    // Encontrar o índice das barras correspondentes
    int startIndex = iBarShift(_Symbol, _Period, lastWeekStart);
    int endIndex = iBarShift(_Symbol, _Period, lastWeekEnd);
    
    if(startIndex < 0 || endIndex < 0)
        return(false);
        
    // Encontrar máximo e mínimo da semana anterior
    double maxPrice = high[startIndex];
    double minPrice = low[startIndex];
    
    for(int i = startIndex; i <= endIndex; i++)
    {
        if(high[i] > maxPrice) maxPrice = high[i];
        if(low[i] < minPrice) minPrice = low[i];
    }
    
    high = maxPrice;
    low = minPrice;
    start = lastWeekStart;
    end = lastWeekEnd;
    
    return(true);
}

//+------------------------------------------------------------------+
//| Criar quadrado redimensionável                                    |
//+------------------------------------------------------------------+
bool CreateResizableSquare()
{
    // Verificar se já existe
    if(ObjectFind(0, "Gann_MainBox") >= 0)
        return(true);
        
    // Obter preços da semana anterior
    double weekHigh, weekLow;
    datetime weekStart, weekEnd;
    if(!GetLastWeekPrices(weekHigh, weekLow, weekStart, weekEnd))
    {
        Print("Erro: Não foi possível obter os preços da semana anterior");
        return(false);
    }
        
    // Criar o quadrado principal
    if(!ObjectCreate(0, "Gann_MainBox", OBJ_RECTANGLE, 0, 
                weekStart, weekHigh,
                weekEnd, weekLow))
    {
        Print("Erro: Falha ao criar o quadrado principal");
        return(false);
    }
        
    if(!ObjectSetInteger(0, "Gann_MainBox", OBJPROP_COLOR, clrWhite) ||
       !ObjectSetInteger(0, "Gann_MainBox", OBJPROP_STYLE, STYLE_SOLID) ||
       !ObjectSetInteger(0, "Gann_MainBox", OBJPROP_WIDTH, 1) ||
       !ObjectSetInteger(0, "Gann_MainBox", OBJPROP_BACK, true) ||
       !ObjectSetInteger(0, "Gann_MainBox", OBJPROP_SELECTABLE, true) ||
       !ObjectSetInteger(0, "Gann_MainBox", OBJPROP_SELECTED, true))
    {
        Print("Erro: Falha ao configurar propriedades do quadrado principal");
        ObjectsDeleteAll(0, "Gann_");
        return(false);
    }
    
    // Criar cantos redimensionáveis
    if(!CreateCorner("Gann_TopLeft", weekStart, weekHigh) ||
       !CreateCorner("Gann_TopRight", weekEnd, weekHigh) ||
       !CreateCorner("Gann_BottomLeft", weekStart, weekLow) ||
       !CreateCorner("Gann_BottomRight", weekEnd, weekLow))
    {
        Print("Erro: Falha ao criar os cantos redimensionáveis");
        ObjectsDeleteAll(0, "Gann_");
        return(false);
    }
    
    // Atualizar o quadrado de Gann
    UpdateGannSquare();
    return(true);
}

//+------------------------------------------------------------------+
//| Criar canto redimensionável                                       |
//+------------------------------------------------------------------+
bool CreateCorner(string name, datetime time, double price)
{
    if(ObjectFind(0, name) >= 0)
        return(true);
        
    if(!ObjectCreate(0, name, OBJ_ARROW, 0, time, price))
    {
        Print("Erro: Falha ao criar o canto ", name);
        return(false);
    }
        
    if(!ObjectSetInteger(0, name, OBJPROP_ARROWCODE, 159) ||
       !ObjectSetInteger(0, name, OBJPROP_COLOR, clrRed) ||
       !ObjectSetInteger(0, name, OBJPROP_WIDTH, 2) ||
       !ObjectSetInteger(0, name, OBJPROP_SELECTABLE, true) ||
       !ObjectSetInteger(0, name, OBJPROP_SELECTED, true))
    {
        Print("Erro: Falha ao configurar propriedades do canto ", name);
        ObjectDelete(0, name);
        return(false);
    }
    
    return(true);
}

//+------------------------------------------------------------------+
//| Atualizar o quadrado de Gann                                      |
//+------------------------------------------------------------------+
void UpdateGannSquare()
{
    if(isUpdating)
        return;
        
    isUpdating = true;
    
    // Verificar se o quadrado principal existe
    if(ObjectFind(0, "Gann_MainBox") < 0)
    {
        isUpdating = false;
        return;
    }
        
    // Obter coordenadas do quadrado principal
    long time1 = 0, time2 = 0;
    double price1 = 0.0, price2 = 0.0;
    
    if(!ObjectGetInteger(0, "Gann_MainBox", OBJPROP_TIME1, 0, time1) ||
       !ObjectGetInteger(0, "Gann_MainBox", OBJPROP_TIME2, 0, time2) ||
       !ObjectGetDouble(0, "Gann_MainBox", OBJPROP_PRICE1, 0, price1) ||
       !ObjectGetDouble(0, "Gann_MainBox", OBJPROP_PRICE2, 0, price2))
    {
        isUpdating = false;
        return;
    }
    
    startTime = (datetime)time1;
    endTime = (datetime)time2;
    upperPrice = price1;
    lowerPrice = price2;
    
    // Validar tempos e preços
    if(startTime >= endTime || MathAbs(upperPrice - lowerPrice) < MIN_PRICE_DIFF)
    {
        isUpdating = false;
        return;
    }
        
    // Limpar objetos antigos (exceto o quadrado principal e cantos)
    if(!ObjectsDeleteAll(0, "Gann_Division_") ||
       !ObjectsDeleteAll(0, "Gann_Grid_") ||
       !ObjectsDeleteAll(0, "Gann_Label_"))
    {
        Print("Aviso: Não foi possível limpar todos os objetos antigos");
    }
    
    // Criar divisões verticais
    if(ShowDivisions)
    {
        for(int i = 1; i < 3; i++)
        {
            string lineName = "Gann_Division_" + IntegerToString(i);
            double price = lowerPrice + (upperPrice - lowerPrice) * i / 3;
            if(!ObjectCreate(0, lineName, OBJ_TREND, 0,
                        startTime, price,
                        endTime, price))
            {
                Print("Erro: Falha ao criar divisão vertical ", i);
                continue;
            }
            
            if(!ObjectSetInteger(0, lineName, OBJPROP_COLOR, DivisionsColor) ||
               !ObjectSetInteger(0, lineName, OBJPROP_STYLE, STYLE_DASH) ||
               !ObjectSetInteger(0, lineName, OBJPROP_WIDTH, 1))
            {
                Print("Erro: Falha ao configurar propriedades da divisão vertical ", i);
                ObjectDelete(0, lineName);
            }
        }
    }
    
    // Criar grade
    if(ShowGrid)
    {
        long timeDiff = endTime - startTime;
        if(timeDiff > 0)
        {
            for(int i = 0; i <= SQUARES; i += 6)
            {
                string gridName = "Gann_Grid_" + IntegerToString(i);
                datetime gridTime = startTime + (long)(timeDiff * i / SQUARES);
                if(!ObjectCreate(0, gridName, OBJ_TREND, 0,
                            gridTime, upperPrice,
                            gridTime, lowerPrice))
                {
                    Print("Erro: Falha ao criar linha da grade ", i);
                    continue;
                }
                
                if(!ObjectSetInteger(0, gridName, OBJPROP_COLOR, GridColor) ||
                   !ObjectSetInteger(0, gridName, OBJPROP_STYLE, STYLE_DOT) ||
                   !ObjectSetInteger(0, gridName, OBJPROP_WIDTH, 1))
                {
                    Print("Erro: Falha ao configurar propriedades da linha da grade ", i);
                    ObjectDelete(0, gridName);
                }
            }
        }
    }
    
    // Adicionar labels
    if(ShowBottomXAxis)
    {
        long timeDiff = endTime - startTime;
        if(timeDiff > 0)
        {
            for(int i = 0; i <= SQUARES; i += 6)
            {
                string labelName = "Gann_Label_X_" + IntegerToString(i);
                datetime labelTime = startTime + (long)(timeDiff * i / SQUARES);
                if(!ObjectCreate(0, labelName, OBJ_TEXT, 0, labelTime, lowerPrice))
                {
                    Print("Erro: Falha ao criar label X ", i);
                    continue;
                }
                
                if(!ObjectSetString(0, labelName, OBJPROP_TEXT, IntegerToString(i)) ||
                   !ObjectSetInteger(0, labelName, OBJPROP_COLOR, LabelColor))
                {
                    Print("Erro: Falha ao configurar propriedades do label X ", i);
                    ObjectDelete(0, labelName);
                }
            }
        }
    }
    
    if(ShowRightYAxis)
    {
        for(int i = 0; i <= SQUARES; i += 6)
        {
            string labelName = "Gann_Label_Y_" + IntegerToString(i);
            double price = upperPrice - (upperPrice - lowerPrice) * i / SQUARES;
            if(!ObjectCreate(0, labelName, OBJ_TEXT, 0, endTime, price))
            {
                Print("Erro: Falha ao criar label Y ", i);
                continue;
            }
            
            string text = IntegerToString(i);
            if(ShowPrices)
                text += " (" + DoubleToString(price, 2) + ")";
                
            if(!ObjectSetString(0, labelName, OBJPROP_TEXT, text) ||
               !ObjectSetInteger(0, labelName, OBJPROP_COLOR, LabelColor))
            {
                Print("Erro: Falha ao configurar propriedades do label Y ", i);
                ObjectDelete(0, labelName);
            }
        }
    }
    
    isUpdating = false;
}

//+------------------------------------------------------------------+
//| Evento de clique do mouse                                         |
//+------------------------------------------------------------------+
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
{
    if(!isInitialized || isUpdating)
        return;
        
    if(id == CHARTEVENT_OBJECT_DRAG)
    {
        if(StringFind(sparam, "Gann_") == 0)
        {
            if(ObjectFind(0, "Gann_MainBox") < 0)
                return;
                
            datetime newTime = (datetime)ObjectGetInteger(0, sparam, OBJPROP_TIME);
            double newPrice = ObjectGetDouble(0, sparam, OBJPROP_PRICE);
            
            if(newTime == 0 || newPrice == 0)
                return;
                
            if(StringFind(sparam, "TopLeft") > 0)
            {
                if(!ObjectSetInteger(0, "Gann_MainBox", OBJPROP_TIME1, 0, newTime) ||
                   !ObjectSetDouble(0, "Gann_MainBox", OBJPROP_PRICE1, 0, newPrice))
                {
                    Print("Erro: Falha ao atualizar canto superior esquerdo");
                    return;
                }
            }
            else if(StringFind(sparam, "TopRight") > 0)
            {
                if(!ObjectSetInteger(0, "Gann_MainBox", OBJPROP_TIME2, 0, newTime) ||
                   !ObjectSetDouble(0, "Gann_MainBox", OBJPROP_PRICE1, 0, newPrice))
                {
                    Print("Erro: Falha ao atualizar canto superior direito");
                    return;
                }
            }
            else if(StringFind(sparam, "BottomLeft") > 0)
            {
                if(!ObjectSetInteger(0, "Gann_MainBox", OBJPROP_TIME1, 0, newTime) ||
                   !ObjectSetDouble(0, "Gann_MainBox", OBJPROP_PRICE2, 0, newPrice))
                {
                    Print("Erro: Falha ao atualizar canto inferior esquerdo");
                    return;
                }
            }
            else if(StringFind(sparam, "BottomRight") > 0)
            {
                if(!ObjectSetInteger(0, "Gann_MainBox", OBJPROP_TIME2, 0, newTime) ||
                   !ObjectSetDouble(0, "Gann_MainBox", OBJPROP_PRICE2, 0, newPrice))
                {
                    Print("Erro: Falha ao atualizar canto inferior direito");
                    return;
                }
            }
            
            UpdateGannSquare();
        }
    }
} 
Открой новые возможности в MetaTrader 5 с сообществом и сервисами MQL5
Открой новые возможности в MetaTrader 5 с сообществом и сервисами MQL5
  • 2025.05.01
  • www.mql5.com
MQL5: язык торговых стратегий для MetaTrader 5, позволяет писать собственные торговые роботы, технические индикаторы, скрипты и библиотеки функций
 

it looks like you are trying to convert mql4 to mql5. I fixed the code and made it compilable.

#property copyright "Copyright 2024"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_plots 0

// Inputs
input bool ShowTopXAxis = false;           // Show top X axis
input bool ShowBottomXAxis = true;         // Show bottom X axis
input bool ShowLeftYAxis = false;          // Show left Y axis
input bool ShowRightYAxis = true;          // Show right Y axis
input bool ShowPrices = true;              // Show prices on right Y axis
input bool ShowDivisions = true;           // Show vertical divisions
input bool ShowExtraLines = true;          // Show extra lines
input bool ShowGrid = true;                // Show grid
input bool ShowBackground = true;          // Show background

// Colors
input color LabelColor = clrGreen;         // Label color
input color DivisionsColor = clrBlue;      // Division lines color
input color GridColor = clrGray;           // Grid color

// Constants
const int SQUARES = 144;
const int MAX_LINES = 500;
const int MAX_LABELS = 500;
const double MIN_PRICE_DIFF = 0.0001;      // Minimum price difference

// Global variables
datetime startTime;
datetime endTime;
double upperPrice;
double lowerPrice;
bool isInitialized = false;
bool isUpdating = false;                   // Flag to prevent recursive updates

//+------------------------------------------------------------------+
//| Indicator initialization function                                 |
//+------------------------------------------------------------------+
int OnInit()
{
    // Clear existing objects
    ObjectsDeleteAll(0, "Gann_");
    
    // Create the main resizable square
    if(!CreateResizableSquare())
    {
        Print("Error: Failed to create Gann square");
        return(INIT_FAILED);
    }
    
    isInitialized = true;
    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Indicator deinitialization function                               |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    ObjectsDeleteAll(0, "Gann_");
    isInitialized = false;
}

//+------------------------------------------------------------------+
//| Indicator iteration function                                      |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
    if(!isInitialized || isUpdating)
        return(rates_total);
        
    return(rates_total);
}
int TimeDayOfWeek(datetime date)
  {
   MqlDateTime tm;
   TimeToStruct(date,tm);
   return(tm.day_of_week);
  }
//+------------------------------------------------------------------+
//| Get last week's prices                                            |
//+------------------------------------------------------------------+
bool GetLastWeekPrices(double &high, double &low, datetime &start, datetime &end)
{
    MqlDateTime currentTime;
    TimeToStruct(TimeCurrent(), currentTime);
    
    // Find current week's start (Monday)
    currentTime.hour = 0;
    currentTime.min = 0;
    currentTime.sec = 0;
    datetime weekStart = StructToTime(currentTime);
    
    // Find previous Sunday
    while(TimeDayOfWeek(weekStart) != SUNDAY)
        weekStart -= 86400;
        
    // Find previous week's start and end
    datetime lastWeekStart = weekStart - 7*86400;
    datetime lastWeekEnd = weekStart - 1;
    
    // Get the appropriate bars
    int bars = Bars(_Symbol, _Period, lastWeekStart, lastWeekEnd);
    if(bars <= 0)
        return(false);
        
    // Get high and low for the period
    double maxPrice = -1;
    double minPrice = -1;
    
    datetime timeArray[];
    double highArray[], lowArray[];
    
    if(CopyHigh(_Symbol, _Period, lastWeekStart, lastWeekEnd, highArray) <= 0 ||
       CopyLow(_Symbol, _Period, lastWeekStart, lastWeekEnd, lowArray) <= 0)
    {
        return(false);
    }
    
    ArraySetAsSeries(highArray, true);
    ArraySetAsSeries(lowArray, true);
    
    maxPrice = highArray[ArrayMaximum(highArray)];
    minPrice = lowArray[ArrayMinimum(lowArray)];
    
    if(maxPrice <= 0 || minPrice <= 0)
        return(false);
        
    high = maxPrice;
    low = minPrice;
    start = lastWeekStart;
    end = lastWeekEnd;
    
    return(true);
}

//+------------------------------------------------------------------+
//| Create resizable square                                          |
//+------------------------------------------------------------------+
bool CreateResizableSquare()
{
    // Check if already exists
    if(ObjectFind(0, "Gann_MainBox") >= 0)
        return(true);
        
    // Get last week's prices
    double weekHigh, weekLow;
    datetime weekStart, weekEnd;
    if(!GetLastWeekPrices(weekHigh, weekLow, weekStart, weekEnd))
    {
        Print("Error: Could not get last week's prices");
        return(false);
    }
        
    // Create main rectangle
    if(!ObjectCreate(0, "Gann_MainBox", OBJ_RECTANGLE, 0, 
                weekStart, weekHigh,
                weekEnd, weekLow))
    {
        Print("Error: Failed to create main rectangle");
        return(false);
    }
        
    if(!ObjectSetInteger(0, "Gann_MainBox", OBJPROP_COLOR, clrWhite) ||
       !ObjectSetInteger(0, "Gann_MainBox", OBJPROP_STYLE, STYLE_SOLID) ||
       !ObjectSetInteger(0, "Gann_MainBox", OBJPROP_WIDTH, 1) ||
       !ObjectSetInteger(0, "Gann_MainBox", OBJPROP_BACK, true) ||
       !ObjectSetInteger(0, "Gann_MainBox", OBJPROP_SELECTABLE, true) ||
       !ObjectSetInteger(0, "Gann_MainBox", OBJPROP_SELECTED, true))
    {
        Print("Error: Failed to set rectangle properties");
        ObjectsDeleteAll(0, "Gann_");
        return(false);
    }
    
    // Create resizable corners
    if(!CreateCorner("Gann_TopLeft", weekStart, weekHigh) ||
       !CreateCorner("Gann_TopRight", weekEnd, weekHigh) ||
       !CreateCorner("Gann_BottomLeft", weekStart, weekLow) ||
       !CreateCorner("Gann_BottomRight", weekEnd, weekLow))
    {
        Print("Error: Failed to create resizable corners");
        ObjectsDeleteAll(0, "Gann_");
        return(false);
    }
    
    // Update the Gann square
    UpdateGannSquare();
    return(true);
}

//+------------------------------------------------------------------+
//| Create resizable corner                                          |
//+------------------------------------------------------------------+
bool CreateCorner(string name, datetime time, double price)
{
    if(ObjectFind(0, name) >= 0)
        return(true);
        
    if(!ObjectCreate(0, name, OBJ_ARROW, 0, time, price))
    {
        Print("Error: Failed to create corner ", name);
        return(false);
    }
        
    if(!ObjectSetInteger(0, name, OBJPROP_ARROWCODE, 159) ||
       !ObjectSetInteger(0, name, OBJPROP_COLOR, clrRed) ||
       !ObjectSetInteger(0, name, OBJPROP_WIDTH, 2) ||
       !ObjectSetInteger(0, name, OBJPROP_SELECTABLE, true) ||
       !ObjectSetInteger(0, name, OBJPROP_SELECTED, true))
    {
        Print("Error: Failed to set corner properties ", name);
        ObjectDelete(0, name);
        return(false);
    }
    
    return(true);
}

void UpdateGannSquare()
{
    if(isUpdating)
        return;
        
    isUpdating = true;
    
    // Check if main square exists
    if(ObjectFind(0, "Gann_MainBox") < 0)
    {
        isUpdating = false;
        return;
    }
        
    // Get main square coordinates using proper MQL5 methods
    datetime time1 = (datetime)ObjectGetInteger(0, "Gann_MainBox", OBJPROP_TIME, 0);
    datetime time2 = (datetime)ObjectGetInteger(0, "Gann_MainBox", OBJPROP_TIME, 1);
    double price1 = ObjectGetDouble(0, "Gann_MainBox", OBJPROP_PRICE, 0);
    double price2 = ObjectGetDouble(0, "Gann_MainBox", OBJPROP_PRICE, 1);
    
    startTime = time1;
    endTime = time2;
    upperPrice = MathMax(price1, price2);
    lowerPrice = MathMin(price1, price2);
    
    // Validate times and prices
    if(startTime >= endTime || MathAbs(upperPrice - lowerPrice) < MIN_PRICE_DIFF)
    {
        isUpdating = false;
        return;
    }
        
    // Clear old objects (except main square and corners)
    ObjectsDeleteAll(0, "Gann_Division_");
    ObjectsDeleteAll(0, "Gann_Grid_");
    ObjectsDeleteAll(0, "Gann_Label_");
    
    // Create vertical divisions
    if(ShowDivisions)
    {
        for(int i = 1; i < 3; i++)
        {
            string lineName = "Gann_Division_" + IntegerToString(i);
            double price = lowerPrice + (upperPrice - lowerPrice) * i / 3;
            
            if(!ObjectCreate(0, lineName, OBJ_HLINE, 0, 0, price))
            {
                Print("Error: Failed to create division line ", i);
                continue;
            }
            
            if(!ObjectSetInteger(0, lineName, OBJPROP_COLOR, DivisionsColor) ||
               !ObjectSetInteger(0, lineName, OBJPROP_STYLE, STYLE_DASH) ||
               !ObjectSetInteger(0, lineName, OBJPROP_WIDTH, 1) ||
               !ObjectSetInteger(0, lineName, OBJPROP_BACK, true))
            {
                Print("Error: Failed to set division line properties ", i);
                ObjectDelete(0, lineName);
            }
        }
    }
    
    // Create grid
    if(ShowGrid)
    {
        long timeDiff = endTime - startTime;
        if(timeDiff > 0)
        {
            for(int i = 0; i <= SQUARES; i += 6)
            {
                string gridName = "Gann_Grid_" + IntegerToString(i);
                datetime gridTime = (datetime)(startTime + (long)(timeDiff * i / SQUARES));
                
                if(!ObjectCreate(0, gridName, OBJ_VLINE, 0, gridTime, 0))
                {
                    Print("Error: Failed to create grid line ", i);
                    continue;
                }
                
                if(!ObjectSetInteger(0, gridName, OBJPROP_COLOR, GridColor) ||
                   !ObjectSetInteger(0, gridName, OBJPROP_STYLE, STYLE_DOT) ||
                   !ObjectSetInteger(0, gridName, OBJPROP_WIDTH, 1) ||
                   !ObjectSetInteger(0, gridName, OBJPROP_BACK, true))
                {
                    Print("Error: Failed to set grid line properties ", i);
                    ObjectDelete(0, gridName);
                }
            }
        }
    }
    
    // Add labels
    if(ShowBottomXAxis)
    {
        long timeDiff = endTime - startTime;
        if(timeDiff > 0)
        {
            for(int i = 0; i <= SQUARES; i += 6)
            {
                string labelName = "Gann_Label_X_" + IntegerToString(i);
                datetime labelTime = (datetime)(startTime + (long)(timeDiff * i / SQUARES));
                
                if(!ObjectCreate(0, labelName, OBJ_TEXT, 0, labelTime, lowerPrice))
                {
                    Print("Error: Failed to create X label ", i);
                    continue;
                }
                
                if(!ObjectSetString(0, labelName, OBJPROP_TEXT, IntegerToString(i)) ||
                   !ObjectSetInteger(0, labelName, OBJPROP_COLOR, LabelColor) ||
                   !ObjectSetInteger(0, labelName, OBJPROP_ANCHOR, ANCHOR_UPPER))
                {
                    Print("Error: Failed to set X label properties ", i);
                    ObjectDelete(0, labelName);
                }
            }
        }
    }
    
    if(ShowRightYAxis)
    {
        for(int i = 0; i <= SQUARES; i += 6)
        {
            string labelName = "Gann_Label_Y_" + IntegerToString(i);
            double price = upperPrice - (upperPrice - lowerPrice) * i / SQUARES;
            
            if(!ObjectCreate(0, labelName, OBJ_TEXT, 0, endTime, price))
            {
                Print("Error: Failed to create Y label ", i);
                continue;
            }
            
            string text = IntegerToString(i);
            if(ShowPrices)
                text += " (" + DoubleToString(price, _Digits) + ")";
                
            if(!ObjectSetString(0, labelName, OBJPROP_TEXT, text) ||
               !ObjectSetInteger(0, labelName, OBJPROP_COLOR, LabelColor) ||
               !ObjectSetInteger(0, labelName, OBJPROP_ANCHOR, ANCHOR_LEFT))
            {
                Print("Error: Failed to set Y label properties ", i);
                ObjectDelete(0, labelName);
            }
        }
    }
    
    isUpdating = false;
}
//+------------------------------------------------------------------+
//| Chart event handler                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
{
    if(!isInitialized || isUpdating)
        return;
        
    if(id == CHARTEVENT_OBJECT_DRAG)
    {
        if(StringFind(sparam, "Gann_") == 0)
        {
            if(ObjectFind(0, "Gann_MainBox") < 0)
                return;
                
            datetime newTime = (datetime)ObjectGetInteger(0, sparam, OBJPROP_TIME);
            double newPrice = ObjectGetDouble(0, sparam, OBJPROP_PRICE);
            
            if(newTime == 0 || newPrice == 0)
                return;
                
            // Get current rectangle coordinates
            datetime time1 = (datetime)ObjectGetInteger(0, "Gann_MainBox", OBJPROP_TIME, 0);
            datetime time2 = (datetime)ObjectGetInteger(0, "Gann_MainBox", OBJPROP_TIME, 1);
            double price1 = ObjectGetDouble(0, "Gann_MainBox", OBJPROP_PRICE, 0);
            double price2 = ObjectGetDouble(0, "Gann_MainBox", OBJPROP_PRICE, 1);
            
            // Update coordinates based on which corner was dragged
            if(StringFind(sparam, "TopLeft") > 0)
            {
                time1 = newTime;
                price1 = newPrice;
            }
            else if(StringFind(sparam, "TopRight") > 0)
            {
                time2 = newTime;
                price1 = newPrice;
            }
            else if(StringFind(sparam, "BottomLeft") > 0)
            {
                time1 = newTime;
                price2 = newPrice;
            }
            else if(StringFind(sparam, "BottomRight") > 0)
            {
                time2 = newTime;
                price2 = newPrice;
            }
            
            // Update the rectangle coordinates using ObjectMove
            if(!ObjectMove(0, "Gann_MainBox", 0, time1, price1) || 
               !ObjectMove(0, "Gann_MainBox", 1, time2, price2))
            {
                Print("Error updating rectangle coordinates: ", GetLastError());
                return;
            }
            
            // Update the corner position to match exactly
            ObjectMove(0, sparam, 0, newTime, newPrice);
            
            UpdateGannSquare();
        }
    }
}
 
Rajesh Kumar Nait #:

it looks like you are trying to convert mql4 to mql5. I fixed the code and made it compilable.

The current code should draw the angles present in the first image but it is only drawing the box. How can I solve this problem? Thank you very much for your attention. We will be able to overcome this challenge ;)
Files:
gann1.jpg  334 kb
gann2.jpg  239 kb
 
Samuel Cornelio #:
The current code should draw the angles present in the first image but it is only drawing the box. How can I solve this problem? Thank you very much for your attention. We will be able to overcome this challenge ;)
You can look for the code of angles and troubleshoot by printing the error code