English Русский 中文 Español Deutsch 日本語
Outras classes na biblioteca DoEasy (Parte 67): classe de objeto-gráfico

Outras classes na biblioteca DoEasy (Parte 67): classe de objeto-gráfico

MetaTrader 5Exemplos | 24 maio 2021, 18:21
962 1
Artyom Trishkin
Artyom Trishkin

Sumário


Ideia

Hoje, estamos começando a desenvolver a funcionalidade de biblioteca para trabalhar com gráficos de símbolos. Esta é nossa ferramenta principal e tentaremos torná-la muito conveniente ao longo de alguns artigos. Em primeiro lugar, criaremos um objeto que armazenará todas as propriedades do gráfico, propriedades essas que ao serem alteradas irão permitir gerenciá-lo facilmente. O conjunto de propriedades do objeto-gráfico será um conjunto de parâmetros inteiros, reais e de string para o gráfico. Com um refinamento gradual e sequencial do objeto-gráfico, seu conjunto de parâmetros mudará - alguns parâmetros serão adicionados, alguns serão transferidos para outros objetos, etc. Mas vamos começar devagar.

Além de criar um objeto-gráfico, vamos modificá-lo um pouco hoje a classe de objeto de sinal mql5 e a classe-coleção de sinais MQL5.com. No momento, quando usamos a coleção de sinais, ao criar uma lista completa dos sinais disponíveis, suas propriedades não mudam. Mesmo se tentarmos atualizar a lista-coleção novamente, no máximo, o novo sinal que apareça no banco de dados de sinais MQL5.com será adicionado a ela; e aqueles que já foram adicionados permanecerão sem alterar suas propriedades. Esse não deveria ser o comportamento, uma vez que os sinais mudam suas propriedades como resultado da negociação na conta do provedor de sinais. Por isso, hoje vamos mudar este comportamento - com qualquer atualização da lista-coleção de sinais, novos sinais serão adicionados à lista, e as propriedades dos já presentes serão atualizadas.


Aprimorando as classes da biblioteca

Agora, em nossa biblioteca, na classe-coleção de sinais, isso é feito de modo que todos os valores dos parâmetros do sinal MQL5.com são imediatamente inseridos nas propriedades correspondentes do objeto de sinal mql5 em seu construtor ao criar um novo objeto-sinal. Precisamos adicionar um método no qual todos os valores dos parâmetros do sinal selecionado se ajustem às propriedades do objeto. Assim, poderemos atualizar as propriedades de um objeto-sinal existente, selecionar o sinal desejado e chamar este novo método. Também precisamos de um método que selecione o sinal de que precisamos na banco de dados de sinais MQL5.com com base no identificador de sinal (em MQL5, o sinal é selecionado apenas por seu índice, mas armazenar o índice do sinal nas propriedades do objeto não é uma maneira confiável, já que os índices de sinal no banco de dados podem mudar com certeza).

No arquivo \MQL5\Include\DoEasy\Objects\MQLSignalBase\MQLSignal.mqh inserimos três novos métodos públicos:
método para escrever valores de parâmetros do sinal MQL5.com selecionado nas propriedades correspondentes do objeto-sinal,
método que retorna o índice de sinal no banco de dados de sinais MQL5.com por seu identificador, e
método que seleciona um sinal por identificador no banco de dados de sinais MQL5.com:

//--- Compare CMQLSignal objects by a specified property (to sort the list by an MQL5 signal object)
   virtual int       Compare(const CObject *node,const int mode=0) const;
//--- Compare CMQLSignal objects by all properties (to search for equal MQL5 signal objects)
   bool              IsEqual(CMQLSignal* compared_obj) const;
   
//--- Set signal object properties
   void              SetProperties(void);
//--- Look for a signal with a specified ID in the database, return the signal index
   int               IndexBase(const long signal_id);
//--- Select a signal in the signal database by its ID
   bool              SelectBase(const long signal_id);
   
//--- Constructors
                     CMQLSignal(){;}
                     CMQLSignal(const long signal_id);

A partir do construtor paramétrico da classe, transferimos o registro dos parâmetros do sinal - para as propriedades correspondentes do objeto - para o novo método SetProperties():

//+------------------------------------------------------------------+
//| Set object properties                                            |
//+------------------------------------------------------------------+
void CMQLSignal::SetProperties(void)
  {
   this.m_long_prop[SIGNAL_MQL5_PROP_SUBSCRIPTION_STATUS]            = (::SignalInfoGetInteger(SIGNAL_INFO_ID)==this.ID());
   this.m_long_prop[SIGNAL_MQL5_PROP_TRADE_MODE]                     = ::SignalBaseGetInteger(SIGNAL_BASE_TRADE_MODE);
   this.m_long_prop[SIGNAL_MQL5_PROP_DATE_PUBLISHED]                 = ::SignalBaseGetInteger(SIGNAL_BASE_DATE_PUBLISHED);
   this.m_long_prop[SIGNAL_MQL5_PROP_DATE_STARTED]                   = ::SignalBaseGetInteger(SIGNAL_BASE_DATE_STARTED);
   this.m_long_prop[SIGNAL_MQL5_PROP_DATE_UPDATED]                   = ::SignalBaseGetInteger(SIGNAL_BASE_DATE_UPDATED);
   this.m_long_prop[SIGNAL_MQL5_PROP_LEVERAGE]                       = ::SignalBaseGetInteger(SIGNAL_BASE_LEVERAGE);
   this.m_long_prop[SIGNAL_MQL5_PROP_PIPS]                           = ::SignalBaseGetInteger(SIGNAL_BASE_PIPS);
   this.m_long_prop[SIGNAL_MQL5_PROP_RATING]                         = ::SignalBaseGetInteger(SIGNAL_BASE_RATING);
   this.m_long_prop[SIGNAL_MQL5_PROP_SUBSCRIBERS]                    = ::SignalBaseGetInteger(SIGNAL_BASE_SUBSCRIBERS);
   this.m_long_prop[SIGNAL_MQL5_PROP_TRADES]                         = ::SignalBaseGetInteger(SIGNAL_BASE_TRADES);
   
   this.m_double_prop[this.IndexProp(SIGNAL_MQL5_PROP_BALANCE)]      = ::SignalBaseGetDouble(SIGNAL_BASE_BALANCE);
   this.m_double_prop[this.IndexProp(SIGNAL_MQL5_PROP_EQUITY)]       = ::SignalBaseGetDouble(SIGNAL_BASE_EQUITY);
   this.m_double_prop[this.IndexProp(SIGNAL_MQL5_PROP_GAIN)]         = ::SignalBaseGetDouble(SIGNAL_BASE_GAIN);
   this.m_double_prop[this.IndexProp(SIGNAL_MQL5_PROP_MAX_DRAWDOWN)] = ::SignalBaseGetDouble(SIGNAL_BASE_MAX_DRAWDOWN);
   this.m_double_prop[this.IndexProp(SIGNAL_MQL5_PROP_PRICE)]        = ::SignalBaseGetDouble(SIGNAL_BASE_PRICE);
   this.m_double_prop[this.IndexProp(SIGNAL_MQL5_PROP_ROI)]          = ::SignalBaseGetDouble(SIGNAL_BASE_ROI);
   
   this.m_string_prop[this.IndexProp(SIGNAL_MQL5_PROP_AUTHOR_LOGIN)] = ::SignalBaseGetString(SIGNAL_BASE_AUTHOR_LOGIN);
   this.m_string_prop[this.IndexProp(SIGNAL_MQL5_PROP_BROKER)]       = ::SignalBaseGetString(SIGNAL_BASE_BROKER);
   this.m_string_prop[this.IndexProp(SIGNAL_MQL5_PROP_BROKER_SERVER)]= ::SignalBaseGetString(SIGNAL_BASE_BROKER_SERVER);
   this.m_string_prop[this.IndexProp(SIGNAL_MQL5_PROP_NAME)]         = ::SignalBaseGetString(SIGNAL_BASE_NAME);
   this.m_string_prop[this.IndexProp(SIGNAL_MQL5_PROP_CURRENCY)]     = ::SignalBaseGetString(SIGNAL_BASE_CURRENCY);
  }
//+------------------------------------------------------------------+

Uma vez que o sinal deve ser pré-selecionado no banco de dados de sinais MQL5.com, obter os valores dos parâmetros do sinal e gravá-los nas propriedades do objeto implica que o sinal é selecionado a priori.

No construtor da classe, em vez das linhas transferidas para o novo método escrevemos a chamada deste método:

//+------------------------------------------------------------------+
//| Parametric constructor                                           |
//+------------------------------------------------------------------+
CMQLSignal::CMQLSignal(const long signal_id)
  {
   this.m_long_prop[SIGNAL_MQL5_PROP_ID] = signal_id;
   this.SetProperties();
  }
//+------------------------------------------------------------------+

Método que retorna o índice do sinal especificado por identificador no banco de dados do sinal MQL5.com:

//+------------------------------------------------------------------+
//| Look for a signal with a specified ID in the database,           |
//| return the index of a detected signal                            |
//+------------------------------------------------------------------+
int CMQLSignal::IndexBase(const long signal_id)
  {
   int total=::SignalBaseTotal();
   for(int i=0;i<total;i++)
     {
      if(::SignalBaseSelect(i) && ::SignalBaseGetInteger(SIGNAL_BASE_ID)==signal_id)
         return i;
     }
   return WRONG_VALUE;
  }
//+------------------------------------------------------------------+

Aqui, num loop percorrendo o número total de sinais selecionamos o próximo sinal e comparamos seu identificador com o passado para o método. Se os identificadores corresponderem, retornamos o índice de loop (é o índice do sinal no banco de dados). Se um sinal com tal identificador não for encontrado, retornaremos -1.
Depois de usar este método, desde que o sinal tenha sido encontrado, ele permanecerá selecionado no banco de dados de sinais para trabalhar no futuro com ele.
Assim é construído o método que seleciona o sinal especificado por identificador:

//+------------------------------------------------------------------+
//| Select a signal by its ID in the signal database                 |
//+------------------------------------------------------------------+
bool CMQLSignal::SelectBase(const long signal_id)
  {
   return(this.IndexBase(signal_id)!=WRONG_VALUE);
  }
//+------------------------------------------------------------------+

O método retorna um sinalizador indicando que a busca de sinal pelo identificador especificado não retornou -1. T. se o índice do sinal for encontrado (não é -1), então o sinal também é selecionado e retornará true. Se a pesquisa de sinal retornou -1, então ele retorna false - não há sinal com tal identificador e ele não está selecionado, respectivamente.

No arquivo da classe-coleção de sinais mql5 \MQL5\Include\DoEasy\Collections\MQLSignalsCollection.mqh vamos fazer pequenas melhorias no método de atualização da lista-coleção:

//+------------------------------------------------------------------+
//| Update the collection list of MQL5 signal objects                |
//+------------------------------------------------------------------+
void CMQLSignalsCollection::Refresh(const bool messages=true)
  {
   this.m_signals_base_total=::SignalBaseTotal();
   //--- loop through all signals in the signal database
   for(int i=0;i<this.m_signals_base_total;i++) 
     { 
      //--- Select a signal from the signal database by the loop index
      if(!::SignalBaseSelect(i))
         continue;
      //--- Get the current signal ID and
      //--- create a new MQL5 signal object based on it
      long id=::SignalBaseGetInteger(SIGNAL_BASE_ID);
      CMQLSignal *signal=new CMQLSignal(id);
      if(signal==NULL)
         continue;
      //--- Set the sorting flag for the list by signal ID
      this.m_list.Sort(SORT_BY_SIGNAL_MQL5_ID);
      //--- Get the index of the MQL5 signal object in the list
      int index=this.m_list.Search(signal);
      //--- If such an object exists (the index exceeds -1)
      if(index!=WRONG_VALUE)
        {
         //--- Remove the newly created object,
         delete signal;
         //--- get the pointer to such an object in the list
         signal=this.m_list.At(index);
         //--- if the pointer is received, update all signal properties
         if(signal!=NULL)
            signal.SetProperties();
         //--- move on to the next loop iteration
         continue;
        }
      //--- No such object in the collection list yet
      //--- If failed to add a new signal object to the collection list,
      //--- remove the created object and go to the next loop iteration
      if(!this.m_list.InsertSort(signal))
        {
         delete signal;
         continue;
        }
      //--- If an MQL5 signal object is successfully added to the collection
      //--- and the new object message flag is set in the parameters passed to the method,
      //--- display a message about a newly found signal
      else if(messages)
        {
         ::Print(DFUN,CMessage::Text(MSG_MQLSIG_COLLECTION_TEXT_SIGNALS_NEW),":");
         signal.PrintShort(true);
        }
     } 
  }
//+------------------------------------------------------------------+

Aqui, em um novo bloco de código, toda a lógica é explicada nos comentários. Em suma, agora os objetos existentes na coleção não são pulados, em vez disso, é chamado o novo método SetProperties(), que consideramos acima, que grava em todas as propriedades do objeto os valores dos parâmetros correspondentes do sinal selecionado no banco de dados do sinal.

Assim concluímos o aprimoramento das classes para trabalhar com sinais MQL5.com.

Vamos começar a desenvolver a classe do objeto-gráfico.

O gráfico e o objeto-gráfico têm muitos parâmetros. E, antes de tudo, precisamos criar novas mensagens de texto, relacionadas ao objeto gráfico.

No arquivo \MQL5\Include\DoEasy\Data.mqh inserimos os índices das novas mensagens:

//--- CChartObj
   MSG_CHART_OBJ_ID,                                  // Chart ID
   MSG_CHART_OBJ_SHOW,                                // Draw price chart attributes
   MSG_CHART_OBJ_IS_OBJECT,                           // Chart object
   MSG_CHART_OBJ_BRING_TO_TOP,                        // Chart above all others
   MSG_CHART_OBJ_CONTEXT_MENU,                        // Access the context menu using the right click
   MSG_CHART_OBJ_CROSSHAIR_TOOL,                      // Access the Crosshair tool using the middle click
   MSG_CHART_OBJ_MOUSE_SCROLL,                        // Scroll the chart horizontally using the left mouse button
   MSG_CHART_OBJ_EVENT_MOUSE_WHEEL,                   // Send messages about mouse wheel events to all MQL5 programs on a chart
   MSG_CHART_OBJ_EVENT_MOUSE_MOVE,                    // Send messages about mouse button click and movement events to all MQL5 programs on a chart
   MSG_CHART_OBJ_EVENT_OBJECT_CREATE,                 // Send messages about the graphical object creation event to all MQL5 programs on a chart
   MSG_CHART_OBJ_EVENT_OBJECT_DELETE,                 // Send messages about the graphical object destruction event to all MQL5 programs on a chart
   MSG_CHART_OBJ_MODE,                                // Chart type
   MSG_CHART_OBJ_FOREGROUND,                          // Price chart in the foreground
   MSG_CHART_OBJ_SHIFT,                               // Shift of the price chart from the right border
   MSG_CHART_OBJ_AUTOSCROLL,                          // Auto scroll to the right border of the chart
   MSG_CHART_OBJ_KEYBOARD_CONTROL,                    // Manage the chart using a keyboard
   MSG_CHART_OBJ_QUICK_NAVIGATION,                    // Allow the chart to intercept Space and Enter key strokes to activate the quick navigation bar
   MSG_CHART_OBJ_SCALE,                               // Scale
   MSG_CHART_OBJ_SCALEFIX,                            // Fixed scale
   MSG_CHART_OBJ_SCALEFIX_11,                         // Scale 1:1
   MSG_CHART_OBJ_SCALE_PT_PER_BAR,                    // Scale in points per bar
   MSG_CHART_OBJ_SHOW_TICKER,                         // Display a symbol ticker in the upper left corner
   MSG_CHART_OBJ_SHOW_OHLC,                           // Display OHLC values in the upper left corner
   MSG_CHART_OBJ_SHOW_BID_LINE,                       // Display Bid value as a horizontal line on the chart
   MSG_CHART_OBJ_SHOW_ASK_LINE,                       // Display Ask value as a horizontal line on a chart
   MSG_CHART_OBJ_SHOW_LAST_LINE,                      // Display Last value as a horizontal line on a chart
   MSG_CHART_OBJ_SHOW_PERIOD_SEP,                     // Display vertical separators between adjacent periods
   MSG_CHART_OBJ_SHOW_GRID,                           // Display a grid on the chart
   MSG_CHART_OBJ_SHOW_VOLUMES,                        // Display volumes on a chart
   MSG_CHART_OBJ_SHOW_OBJECT_DESCR,                   // Display text descriptions of objects
   MSG_CHART_OBJ_VISIBLE_BARS,                        // Number of bars on a chart that are available for display
   MSG_CHART_OBJ_WINDOWS_TOTAL,                       // Total number of chart windows including indicator subwindows
   MSG_CHART_OBJ_WINDOW_IS_VISIBLE,                   // Subwindow visibility
   MSG_CHART_OBJ_WINDOW_HANDLE,                       // Chart window handle
   MSG_CHART_OBJ_WINDOW_YDISTANCE,                    // Distance in Y axis pixels between the upper frame of the indicator subwindow and the upper frame of the chart main window   
   MSG_CHART_OBJ_FIRST_VISIBLE_BAR,                   // Number of the first visible bar on the chart
   MSG_CHART_OBJ_WIDTH_IN_BARS,                       // Width of the chart in bars   
   MSG_CHART_OBJ_WIDTH_IN_PIXELS,                     // Width of the chart in pixels   
   MSG_CHART_OBJ_HEIGHT_IN_PIXELS,                    // Height of the chart in pixels   
   MSG_CHART_OBJ_COLOR_BACKGROUND,                    // Color of background of the chart
   MSG_CHART_OBJ_COLOR_FOREGROUND,                    // Color of axes, scale and OHLC line
   MSG_CHART_OBJ_COLOR_GRID,                          // Grid color
   MSG_CHART_OBJ_COLOR_VOLUME,                        // Color of volumes and position opening levels
   MSG_CHART_OBJ_COLOR_CHART_UP,                      // Color for the up bar, shadows and body borders of bull candlesticks
   MSG_CHART_OBJ_COLOR_CHART_DOWN,                    // Color of down bar, its shadow and border of body of the bullish candlestick
   MSG_CHART_OBJ_COLOR_CHART_LINE,                    // Color of the chart line and the Doji candlesticks
   MSG_CHART_OBJ_COLOR_CANDLE_BULL,                   // Color of body of a bullish candlestick
   MSG_CHART_OBJ_COLOR_CANDLE_BEAR,                   // Color of body of a bearish candlestick
   MSG_CHART_OBJ_COLOR_BID,                           // Color of the Bid price line
   MSG_CHART_OBJ_COLOR_ASK,                           // Color of the Ask price line
   MSG_CHART_OBJ_COLOR_LAST,                          // Color of the last performed deal's price line (Last)
   MSG_CHART_OBJ_COLOR_STOP_LEVEL,                    // Color of stop order levels (Stop Loss and Take Profit)
   MSG_CHART_OBJ_SHOW_TRADE_LEVELS,                   // Display trade levels on the chart (levels of open positions, Stop Loss, Take Profit and pending orders)
   MSG_CHART_OBJ_DRAG_TRADE_LEVELS,                   // Drag trading levels on a chart using a mouse
   MSG_CHART_OBJ_SHOW_DATE_SCALE,                     // Display the time scale on a chart
   MSG_CHART_OBJ_SHOW_PRICE_SCALE,                    // Display a price scale on a chart
   MSG_CHART_OBJ_SHOW_ONE_CLICK,                      // Display the quick trading panel on the chart
   MSG_CHART_OBJ_IS_MAXIMIZED,                        // Chart window maximized
   MSG_CHART_OBJ_IS_MINIMIZED,                        // Chart window minimized
   MSG_CHART_OBJ_IS_DOCKED,                           // Chart window docked
   MSG_CHART_OBJ_FLOAT_LEFT,                          // Left coordinate of the undocked chart window relative to the virtual screen
   MSG_CHART_OBJ_FLOAT_TOP,                           // Upper coordinate of the undocked chart window relative to the virtual screen
   MSG_CHART_OBJ_FLOAT_RIGHT,                         // Right coordinate of the undocked chart window relative to the virtual screen
   MSG_CHART_OBJ_FLOAT_BOTTOM,                        // Bottom coordinate of the undocked chart window relative to the virtual screen

   MSG_CHART_OBJ_SHIFT_SIZE,                          // shift size of the zero bar from the right border in %
   MSG_CHART_OBJ_FIXED_POSITION,                      // Chart fixed position from the left border in %   
   MSG_CHART_OBJ_FIXED_MAX,                           // Chart fixed maximum
   MSG_CHART_OBJ_FIXED_MIN,                           // Chart fixed minimum
   MSG_CHART_OBJ_POINTS_PER_BAR,                      // Scale in points per bar
   MSG_CHART_OBJ_PRICE_MIN,                           // Chart minimum
   MSG_CHART_OBJ_PRICE_MAX,                           // Chart maximum

   MSG_CHART_OBJ_COMMENT,                             // Chart comment text
   MSG_CHART_OBJ_EXPERT_NAME,                         // Name of an EA launched on the chart
   MSG_CHART_OBJ_SCRIPT_NAME,                         // Name of a script launched on the chart

   MSG_CHART_OBJ_CHART_BARS,                          // Display as bars
   MSG_CHART_OBJ_CHART_CANDLES,                       // Display as Japaneses candlesticks
   MSG_CHART_OBJ_CHART_LINE,                          // Display as a line drawn at Close prices
   MSG_CHART_OBJ_CHART_VOLUME_HIDE,                   // Volumes not displayed
   MSG_CHART_OBJ_CHART_VOLUME_TICK,                   // Tick volumes
   MSG_CHART_OBJ_CHART_VOLUME_REAL,                   // Trading volumes
   
   MSG_CHART_OBJ_CHART_WINDOW,                        // Chart window
  
  };
//+------------------------------------------------------------------+

e as mensagens de texto correspondentes aos índices adicionados recentemente:

//--- CChartObj
   {"Идентификатор графика","Chart ID"},
   {"Отрисовка атрибутов ценового графика","Drawing attributes of a price chart"},
   {"Объект \"График\"","Object \"Chart\""},
   {"График поверх всех других","Chart on top of other charts"},
   {"Доступ к контекстному меню по нажатию правой клавиши мыши","Accessing the context menu by pressing the right mouse button"},
   {"Доступ к инструменту \"Перекрестие\" по нажатию средней клавиши мыши","Accessing the \"Crosshair tool\" by pressing the middle mouse button"},
   {"Прокрутка графика левой кнопкой мышки по горизонтали","Scrolling the chart horizontally using the left mouse button"},
   {"Отправка всем mql5-программам на графике сообщений о событиях колёсика мыши","Sending messages about mouse wheel events to all mql5 programs on a chart"},
   {"Отправка всем mql5-программам на графике сообщений о событиях перемещения и нажатия кнопок мыши","Send notifications of mouse move and mouse click events to all mql5 programs on a chart"},
   {"Отправка всем mql5-программам на графике сообщений о событии создания графического объекта","Send a notification of an event of new object creation to all mql5-programs on a chart"},
   {"Отправка всем mql5-программам на графике сообщений о событии уничтожения графического объекта","Send a notification of an event of object deletion to all mql5-programs on a chart"},
   {"Тип графика","Chart type"},
   {"Ценовой график на переднем плане","Price chart in the foreground"},
   {"Отступ ценового графика от правого края","Price chart indent from the right border"},
   {"Автоматический переход к правому краю графика","Automatic moving to the right border of the chart"},
   {"Управление графиком с помощью клавиатуры","Managing the chart using a keyboard"},
   {"Перехват графиком нажатий клавиш Space и Enter для активации строки быстрой навигации","Allowed to intercept Space and Enter key presses on the chart to activate the quick navigation bar"},
   {"Масштаб","Scale"},
   {"Фиксированный масштаб","Fixed scale mode"},
   {"Масштаб 1:1","Scale 1:1 mode"},
   {"Масштаб в пунктах на бар","Scale to be specified in points per bar"},
   {"Отображение в левом верхнем углу тикера символа","Display a symbol ticker in the upper left corner"},
   {"Отображение в левом верхнем углу значений OHLC","Display OHLC values in the upper left corner"},
   {"Отображение значения Bid горизонтальной линией на графике","Display Bid values as a horizontal line in a chart"},
   {"Отображение значения Ask горизонтальной линией на графике","Display Ask values as a horizontal line in a chart"},
   {"Отображение значения Last горизонтальной линией на графике","Display Last values as a horizontal line in a chart"},
   {"Отображение вертикальных разделителей между соседними периодами","Display vertical separators between adjacent periods"},
   {"Отображение сетки на графике","Display grid in the chart"},
   {"Отображение объемов на графике","Display volume in the chart"},
   {"Отображение текстовых описаний объектов","Display textual descriptions of objects"},
   {"Количество баров на графике, доступных для отображения","The number of bars on the chart that can be displayed"},
   {"Общее количество окон графика с подокнами индикаторов","The total number of chart windows, including indicator subwindows"},
   {"Видимость подокон","Visibility of subwindows"},
   {"Хэндл окна графика","Chart window handle"},
   {"Дистанция в пикселях по оси Y между верхней рамкой подокна индикатора и верхней рамкой главного окна графика","The distance between the upper frame of the indicator subwindow and the upper frame of the main chart window"},
   {"Номер первого видимого бара на графике","Number of the first visible bar in the chart"},
   {"Ширина графика в барах","Chart width in bars"},
   {"Ширина графика в пикселях","Chart width in pixels"},
   {"Высота графика в пикселях","Chart height in pixels"},
   {"Цвет фона графика","Chart background color"},
   {"Цвет осей, шкалы и строки OHLC","Color of axes, scales and OHLC line"},
   {"Цвет сетки","Grid color"},
   {"Цвет объемов и уровней открытия позиций","Color of volumes and position opening levels"},
   {"Цвет бара вверх, тени и окантовки тела бычьей свечи","Color for the up bar, shadows and body borders of bull candlesticks"},
   {"Цвет бара вниз, тени и окантовки тела медвежьей свечи","Color for the down bar, shadows and body borders of bear candlesticks"},
   {"Цвет линии графика и японских свечей \"Доджи\"","Line chart color and color of \"Doji\" Japanese candlesticks"},
   {"Цвет тела бычьей свечи","Body color of a bull candlestick"},
   {"Цвет тела медвежьей свечи","Body color of a bear candlestick"},
   {"Цвет линии Bid-цены","Bid price level color"},
   {"Цвет линии Ask-цены","Ask price level color"},
   {"Цвет линии цены последней совершенной сделки (Last)","Line color of the last executed deal price (Last)"},
   {"Цвет уровней стоп-ордеров (Stop Loss и Take Profit)","Color of stop order levels (Stop Loss and Take Profit)"},
   {"Отображение на графике торговых уровней (уровни открытых позиций, Stop Loss, Take Profit и отложенных ордеров)","Displaying trade levels in the chart (levels of open positions, Stop Loss, Take Profit and pending orders)"},
   {"Перетаскивание торговых уровней на графике с помощью мышки","Permission to drag trading levels on a chart with a mouse"},
   {"Отображение на графике шкалы времени","Showing the time scale on a chart"},
   {"Отображение на графике ценовой шкалы","Showing the price scale on a chart"},
   {"Отображение на графике панели быстрой торговли","Showing the \"One click trading\" panel on a chart"},
   {"Окно графика развернуто","Chart window is maximized"},
   {"Окно графика свернуто","Chart window is minimized"},
   {"Окно графика закреплено","The chart window is docked"},
   {"Левая координата открепленного графика относительно виртуального экрана","The left coordinate of the undocked chart window relative to the virtual screen"},
   {"Верхняя координата открепленного графика относительно виртуального экрана","The top coordinate of the undocked chart window relative to the virtual screen"},
   {"Правая координата открепленного графика  относительно виртуального экрана","The right coordinate of the undocked chart window relative to the virtual screen"},
   {"Нижняя координата открепленного графика  относительно виртуального экрана","The bottom coordinate of the undocked chart window relative to the virtual screen"},

   {"Размер отступа нулевого бара от правого края в процентах","The size of the zero bar indent from the right border in percents"},
   {"Положение фиксированной позиции графика от левого края в процентах","Chart fixed position from the left border in percent value"},
   {"Фиксированный максимум графика","Fixed  chart maximum"},
   {"Фиксированный минимум графика","Fixed  chart minimum "},
   {"Масштаб в пунктах на бар","Scale in points per bar"},
   {"Минимум графика","Chart minimum"},
   {"Максимум графика","Chart maximum"},

   {"Текст комментария на графике","Text of a comment in a chart"},
   {"Имя эксперта, запущенного на графике","The name of the Expert Advisor running on the chart"},
   {"Имя скрипта, запущенного на графике","The name of the script running on the chart"},

   {"Отображение в виде баров","Display as a sequence of bars"},
   {"Отображение в виде японских свечей","Display as Japanese candlesticks"},
   {"Отображение в виде линии, проведенной по ценам Close","Display as a line drawn by Close prices"},
   {"Объемы не показаны","Volumes are not shown"},
   {"Тиковые объемы","Tick volumes"},
   {"Торговые объемы","Trade volumes"},

   {"Окно графика","Chart window"},
   
  };
//+---------------------------------------------------------------------+

Para entender por que precisamos inserir índices-constantes com nomes para as mensagens, as próprias mensagens e, em geral, para entender como essas listas funcionam, recomendo entrar em ler o artigo 19, que detalha o processo de desenvolvimento da classe de mensagens da biblioteca.

Para exibir uma descrição de algumas das propriedades do objeto gráfico criado, precisamos de duas funções - uma para retornar uma descrição do modo de exibição do gráfico (barras, candles, linha) e outra para retornar uma descrição do modo de exibição dos volumes no gráfico (não mostrado, ticks, reais). Para ter sempre essas funções à mão, iremos adicioná-las ao arquivo de funções de serviço \MQL5\Include\DoEasy\Services\DELib.mqh:

//+------------------------------------------------------------------+
//| Return the description of the method of displaying a price chart |
//+------------------------------------------------------------------+
string ChartModeDescription(ENUM_CHART_MODE mode)
  {
   return
     (
      mode==CHART_BARS     ? CMessage::Text(MSG_CHART_OBJ_CHART_BARS)      :
      mode==CHART_CANDLES  ? CMessage::Text(MSG_CHART_OBJ_CHART_CANDLES)   :
      CMessage::Text(MSG_CHART_OBJ_CHART_LINE)
     );
  }
//+--------------------------------------------------------------------------+
//|Return the description of the mode of displaying volumes on a price chart |
//+--------------------------------------------------------------------------+
string ChartModeVolumeDescription(ENUM_CHART_VOLUME_MODE mode)
  {
   return
     (
      mode==CHART_VOLUME_TICK ? CMessage::Text(MSG_CHART_OBJ_CHART_VOLUME_TICK)  :
      mode==CHART_VOLUME_REAL ? CMessage::Text(MSG_CHART_OBJ_CHART_VOLUME_REAL)  :
      CMessage::Text(MSG_CHART_OBJ_CHART_VOLUME_HIDE)
     );
  }
//+------------------------------------------------------------------+

A propriedade correspondente do gráfico é passada para ambas as funções, a função verifica se corresponde a uma das constantes enumerados e retorna a descrição de string deste modo de gráfico/volume.

Cada um dos objetos da biblioteca possui uma lista de propriedades especificadas no arquivo \MQL5\Include\DoEasy\Defines.mqh. O objeto-gráfico não é exceção. Também escreveremos todas suas propriedades em três enumerações de propriedades inteiras, reais e de string:

//+------------------------------------------------------------------+
//| Data for working with charts 				     |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| List of possible chart events                                    |
//+------------------------------------------------------------------+
#define CHART_EVENTS_NEXT_CODE  (SIGNAL_MQL5_EVENTS_NEXT_CODE+1)   // The code of the next event after the last chart event code
//+------------------------------------------------------------------+
//| Chart integer property                                           |
//+------------------------------------------------------------------+
enum ENUM_CHART_PROP_INTEGER
  {
   CHART_PROP_ID = 0,                                 // Chart ID
   CHART_PROP_TIMEFRAME,                              // Chart timeframe
   CHART_PROP_SHOW,                                   // Price chart drawing
   CHART_PROP_IS_OBJECT,                              // Chart object (OBJ_CHART) identification attribute
   CHART_PROP_BRING_TO_TOP,                           // Show chart above all others
   CHART_PROP_CONTEXT_MENU,                           // Enable/disable access to the context menu using the right click 
   CHART_PROP_CROSSHAIR_TOOL,                         // Enable/disable access to the Crosshair tool using the middle click
   CHART_PROP_MOUSE_SCROLL,                           // Scroll the chart horizontally using the left mouse button
   CHART_PROP_EVENT_MOUSE_WHEEL,                      // Send messages about mouse wheel events (CHARTEVENT_MOUSE_WHEEL) to all MQL5 programs on a chart
   CHART_PROP_EVENT_MOUSE_MOVE,                       // Send messages about mouse button click and movement events (CHARTEVENT_MOUSE_MOVE) to all MQL5 programs on a chart
   CHART_PROP_EVENT_OBJECT_CREATE,                    // Send messages about the graphical object creation event (CHARTEVENT_OBJECT_CREATE) to all MQL5 programs on a chart
   CHART_PROP_EVENT_OBJECT_DELETE,                    // Send messages about the graphical object destruction event (CHARTEVENT_OBJECT_DELETE) to all MQL5 programs on a chart
   CHART_PROP_MODE,                                   // Type of the chart (candlesticks, bars or line (ENUM_CHART_MODE))
   CHART_PROP_FOREGROUND,                             // Price chart in the foreground
   CHART_PROP_SHIFT,                                  // Mode of shift of the price chart from the right border
   CHART_PROP_AUTOSCROLL,                             // The mode of automatic shift to the right border of the chart
   CHART_PROP_KEYBOARD_CONTROL,                       // Allow managing the chart using a keyboard
   CHART_PROP_QUICK_NAVIGATION,                       // Allow the chart to intercept Space and Enter key strokes to activate the quick navigation bar
   CHART_PROP_SCALE,                                  // Scale
   CHART_PROP_SCALEFIX,                               // Fixed scale mode
   CHART_PROP_SCALEFIX_11,                            // 1:1 scale mode
   CHART_PROP_SCALE_PT_PER_BAR,                       // The mode of specifying the scale in points per bar
   CHART_PROP_SHOW_TICKER,                            // Display a symbol ticker in the upper left corner
   CHART_PROP_SHOW_OHLC,                              // Display OHLC values in the upper left corner
   CHART_PROP_SHOW_BID_LINE,                          // Display Bid value as a horizontal line on the chart
   CHART_PROP_SHOW_ASK_LINE,                          // Display Ask value as a horizontal line on a chart
   CHART_PROP_SHOW_LAST_LINE,                         // Display Last value as a horizontal line on a chart
   CHART_PROP_SHOW_PERIOD_SEP,                        // Display vertical separators between adjacent periods
   CHART_PROP_SHOW_GRID,                              // Display a grid on the chart
   CHART_PROP_SHOW_VOLUMES,                           // Display volumes on a chart
   CHART_PROP_SHOW_OBJECT_DESCR,                      // Display text descriptions of objects
   CHART_PROP_VISIBLE_BARS,                           // Number of bars on a chart that are available for display
   CHART_PROP_WINDOWS_TOTAL,                          // The total number of chart windows including indicator subwindows
   //CHART_PROP_WINDOW_IS_VISIBLE,                      // Subwindow visibility
   CHART_PROP_WINDOW_HANDLE,                          // Chart window handle
   //CHART_PROP_WINDOW_YDISTANCE,                       // Distance in Y axis pixels between the upper frame of the indicator subwindow and the upper frame of the chart main window
   CHART_PROP_FIRST_VISIBLE_BAR,                      // Number of the first visible bar on the chart
   CHART_PROP_WIDTH_IN_BARS,                          // Width of the chart in bars
   CHART_PROP_WIDTH_IN_PIXELS,                        // Width of the chart in pixels
   //CHART_PROP_HEIGHT_IN_PIXELS,                       // Height of the chart in pixels
   CHART_PROP_COLOR_BACKGROUND,                       // Color of background of the chart
   CHART_PROP_COLOR_FOREGROUND,                       // Color of axes, scale and OHLC line
   CHART_PROP_COLOR_GRID,                             // Grid color
   CHART_PROP_COLOR_VOLUME,                           // Color of volumes and position opening levels
   CHART_PROP_COLOR_CHART_UP,                         // Color for the up bar, shadows and body borders of bull candlesticks
   CHART_PROP_COLOR_CHART_DOWN,                       // Color of down bar, its shadow and border of body of the bullish candlestick
   CHART_PROP_COLOR_CHART_LINE,                       // Color of the chart line and the Doji candlesticks
   CHART_PROP_COLOR_CANDLE_BULL,                      // Color of body of a bullish candlestick
   CHART_PROP_COLOR_CANDLE_BEAR,                      // Color of body of a bearish candlestick
   CHART_PROP_COLOR_BID,                              // Color of the Bid price line
   CHART_PROP_COLOR_ASK,                              // Color of the Ask price line
   CHART_PROP_COLOR_LAST,                             // Color of the last performed deal's price line (Last)
   CHART_PROP_COLOR_STOP_LEVEL,                       // Color of stop order levels (Stop Loss and Take Profit)
   CHART_PROP_SHOW_TRADE_LEVELS,                      // Display trade levels on the chart (levels of open positions, Stop Loss, Take Profit and pending orders)
   CHART_PROP_DRAG_TRADE_LEVELS,                      // Enable the ability to drag trading levels on a chart using mouse
   CHART_PROP_SHOW_DATE_SCALE,                        // Display the time scale on a chart
   CHART_PROP_SHOW_PRICE_SCALE,                       // Display a price scale on a chart
   CHART_PROP_SHOW_ONE_CLICK,                         // Display the quick trading panel on the chart
   CHART_PROP_IS_MAXIMIZED,                           // Chart window maximized
   CHART_PROP_IS_MINIMIZED,                           // Chart window minimized
   CHART_PROP_IS_DOCKED,                              // Chart window docked
   CHART_PROP_FLOAT_LEFT,                             // Left coordinate of the undocked chart window relative to the virtual screen
   CHART_PROP_FLOAT_TOP,                              // Upper coordinate of the undocked chart window relative to the virtual screen
   CHART_PROP_FLOAT_RIGHT,                            // Right coordinate of the undocked chart window relative to the virtual screen
   CHART_PROP_FLOAT_BOTTOM,                           // Bottom coordinate of the undocked chart window relative to the virtual screen
  };
#define CHART_PROP_INTEGER_TOTAL (62)                 // Total number of integer properties
#define CHART_PROP_INTEGER_SKIP  (0)                  // Number of integer DOM properties not used in sorting
//+------------------------------------------------------------------+
//| Chart real properties                                            |
//+------------------------------------------------------------------+
enum ENUM_CHART_PROP_DOUBLE
  {
   CHART_PROP_SHIFT_SIZE = CHART_PROP_INTEGER_TOTAL,  // Shift size of the zero bar from the right border in %
   CHART_PROP_FIXED_POSITION,                         // Chart fixed position from the left border in %
   CHART_PROP_FIXED_MAX,                              // Chart fixed maximum
   CHART_PROP_FIXED_MIN,                              // Chart fixed minimum
   CHART_PROP_POINTS_PER_BAR,                         // Scale in points per bar
   CHART_PROP_PRICE_MIN,                              // Chart minimum
   CHART_PROP_PRICE_MAX,                              // Chart maximum
  };
#define CHART_PROP_DOUBLE_TOTAL  (7)                  // Total number of real properties
#define CHART_PROP_DOUBLE_SKIP   (0)                  // Number of real properties not used in sorting
//+------------------------------------------------------------------+
//| Chart string properties                                          |
//+------------------------------------------------------------------+
enum ENUM_CHART_PROP_STRING
  {
   CHART_PROP_COMMENT = (CHART_PROP_INTEGER_TOTAL+CHART_PROP_DOUBLE_TOTAL), // Chart comment text
   CHART_PROP_EXPERT_NAME,                            // Name of an EA launched on the chart
   CHART_PROP_SCRIPT_NAME,                            // Name of a script launched on the chart
   CHART_PROP_SYMBOL,                                 // Chart symbol
  };
#define CHART_PROP_STRING_TOTAL  (4)                  // Total number of string properties
//+------------------------------------------------------------------+

Ainda não precisamos das três propriedades comentadas na enumeração de propriedades inteiras do objeto - elas estão inseridas porque essas propriedades estão presentes no gráfico, mas se referem não apenas ao objeto gráfico (a janela principal do gráfico), mas também ás subjanelas e não podem ser propriedades exclusivas de apenas um objeto-gráfico. Apresentaremos seu uso um pouco mais tarde.

E, como de costume, após adicionar novas enumerações de propriedades de objeto, precisamos adicionar uma enumeração de possíveis critérios de classificação para esses objetos:

//+------------------------------------------------------------------+
//| Possible chart sorting criteria                                  |
//+------------------------------------------------------------------+
#define FIRST_CHART_DBL_PROP  (CHART_PROP_INTEGER_TOTAL-CHART_PROP_INTEGER_SKIP)
#define FIRST_CHART_STR_PROP  (CHART_PROP_INTEGER_TOTAL-CHART_PROP_INTEGER_SKIP+CHART_PROP_DOUBLE_TOTAL-CHART_PROP_DOUBLE_SKIP)
enum ENUM_SORT_CHART_MODE
  {
//--- Sort by integer properties
   SORT_BY_CHART_SHOW = 0,                            // Sort by the price chart drawing attribute
   SORT_BY_CHART_IS_OBJECT,                           // Sort by chart object (OBJ_CHART) identification attribute
   SORT_BY_CHART_BRING_TO_TOP,                        // Sort by the flag of displaying a chart above all others
   SORT_BY_CHART_CONTEXT_MENU,                        // Sort by the flag of enabling/disabling access to the context menu using the right click
   SORT_BY_CHART_CROSSHAIR_TOO,                       // Sort by the flag of enabling/disabling access to the Crosshair tool using the middle click
   SORT_BY_CHART_MOUSE_SCROLL,                        // Sort by the flag of scrolling the chart horizontally using the left mouse button
   SORT_BY_CHART_EVENT_MOUSE_WHEEL,                   // Sort by the flag of sending messages about mouse wheel events to all MQL5 programs on a chart
   SORT_BY_CHART_EVENT_MOUSE_MOVE,                    // Sort by the flag of sending messages about mouse button click and movement events to all MQL5 programs on a chart
   SORT_BY_CHART_EVENT_OBJECT_CREATE,                 // Sort by the flag of sending messages about the graphical object creation event to all MQL5 programs on a chart
   SORT_BY_CHART_EVENT_OBJECT_DELETE,                 // Sort by the flag of sending messages about the graphical object destruction event to all MQL5 programs on a chart
   SORT_BY_CHART_MODE,                                // Sort by chart type
   SORT_BY_CHART_FOREGROUND,                          // Sort by the "Price chart in the foreground" flag
   SORT_BY_CHART_SHIFT,                               // Sort by the "Mode of shift of the price chart from the right border" flag
   SORT_BY_CHART_AUTOSCROLL,                          // Sort by the "The mode of automatic shift to the right border of the chart" flag
   SORT_BY_CHART_KEYBOARD_CONTROL,                    // Sort by the flag allowing the chart management using a keyboard
   SORT_BY_CHART_QUICK_NAVIGATION,                    // Sort by the flag allowing the chart to intercept Space and Enter key strokes to activate the quick navigation bar
   SORT_BY_CHART_SCALE,                               // Sort by scale
   SORT_BY_CHART_SCALEFIX,                            // Sort by the fixed scale flag
   SORT_BY_CHART_SCALEFIX_11,                         // Sort by the 1:1 scale flag
   SORT_BY_CHART_SCALE_PT_PER_BAR,                    // Sort by the flag of specifying the scale in points per bar
   SORT_BY_CHART_SHOW_TICKER,                         // Sort by the flag displaying a symbol ticker in the upper left corner
   SORT_BY_CHART_SHOW_OHLC,                           // Sort by the flag displaying OHLC values in the upper left corner
   SORT_BY_CHART_SHOW_BID_LINE,                       // Sort by the flag displaying Bid value as a horizontal line on the chart
   SORT_BY_CHART_SHOW_ASK_LINE,                       // Sort by the flag displaying Ask value as a horizontal line on the chart
   SORT_BY_CHART_SHOW_LAST_LINE,                      // Sort by the flag displaying Last value as a horizontal line on the chart
   SORT_BY_CHART_SHOW_PERIOD_SEP,                     // Sort by the flag displaying vertical separators between adjacent periods
   SORT_BY_CHART_SHOW_GRID,                           // Sort by the flag of displaying a grid on the chart
   SORT_BY_CHART_SHOW_VOLUMES,                        // Sort by the mode of displaying volumes on a chart
   SORT_BY_CHART_SHOW_OBJECT_DESCR,                   // Sort by the flag of displaying object text descriptions
   SORT_BY_CHART_VISIBLE_BARS,                        // Sort by the number of bars on a chart that are available for display
   SORT_BY_CHART_WINDOWS_TOTAL,                       // Sort by the total number of chart windows including indicator subwindows
   SORT_BY_CHART_WINDOW_IS_VISIBLE,                   // Sort by the subwindow visibility flag
   SORT_BY_CHART_WINDOW_HANDLE,                       // Sort by the chart handle
   SORT_BY_CHART_WINDOW_YDISTANCE,                    // Sort by the distance in Y axis pixels between the upper frame of the indicator subwindow and the upper frame of the chart main window
   SORT_BY_CHART_FIRST_VISIBLE_BAR,                   // Sort by the number of the first visible bar on the chart
   SORT_BY_CHART_WIDTH_IN_BARS,                       // Sort by the width of the chart in bars
   SORT_BY_CHART_WIDTH_IN_PIXELS,                     // Sort by the width of the chart in pixels
   SORT_BY_CHART_HEIGHT_IN_PIXELS,                    // Sort by the height of the chart in pixels
   SORT_BY_CHART_COLOR_BACKGROUND,                    // Sort by the color of the chart background
   SORT_BY_CHART_COLOR_FOREGROUND,                    // Sort by color of axes, scale and OHLC line
   SORT_BY_CHART_COLOR_GRID,                          // Sort by grid color
   SORT_BY_CHART_COLOR_VOLUME,                        // Sort by the color of volumes and position opening levels
   SORT_BY_CHART_COLOR_CHART_UP,                      // Sort by the color for the up bar, shadows and body borders of bull candlesticks
   SORT_BY_CHART_COLOR_CHART_DOWN,                    // Sort by the color of down bar, its shadow and border of body of the bullish candlestick
   SORT_BY_CHART_COLOR_CHART_LINE,                    // Sort by the color of the chart line and the Doji candlesticks
   SORT_BY_CHART_COLOR_CANDLE_BULL,                   // Sort by the color of a bullish candlestick body
   SORT_BY_CHART_COLOR_CANDLE_BEAR,                   // Sort by the color of a bearish candlestick body
   SORT_BY_CHART_COLOR_BID,                           // Sort by the color of the Bid price line
   SORT_BY_CHART_COLOR_ASK,                           // Sort by the color of the Ask price line
   SORT_BY_CHART_COLOR_LAST,                          // Sort by the color of the last performed deal's price line (Last)
   SORT_BY_CHART_COLOR_STOP_LEVEL,                    // Sort by the color of stop order levels (Stop Loss and Take Profit)
   SORT_BY_CHART_SHOW_TRADE_LEVELS,                   // Sort by the flag of displaying trading levels on the chart
   SORT_BY_CHART_DRAG_TRADE_LEVELS,                   // Sort by the flag enabling the ability to drag trading levels on a chart using mouse
   SORT_BY_CHART_SHOW_DATE_SCALE,                     // Sort by the flag of displaying the time scale on the chart
   SORT_BY_CHART_SHOW_PRICE_SCALE,                    // Sort by the flag of displaying the price scale on the chart
   SORT_BY_CHART_SHOW_ONE_CLICK,                      // Sort by the flag of displaying the quick trading panel on the chart
   SORT_BY_CHART_IS_MAXIMIZED,                        // Sort by the "Chart window maximized" flag
   SORT_BY_CHART_IS_MINIMIZED,                        // Sort by the "Chart window minimized" flag
   SORT_BY_CHART_IS_DOCKED,                           // Sort by the "Chart window docked" flag
   SORT_BY_CHART_FLOAT_LEFT,                          // Sort by the left coordinate of the undocked chart window relative to the virtual screen
   SORT_BY_CHART_FLOAT_TOP,                           // Sort by the upper coordinate of the undocked chart window relative to the virtual screen
   SORT_BY_CHART_FLOAT_RIGHT,                         // Sort by the right coordinate of the undocked chart window relative to the virtual screen
   SORT_BY_CHART_FLOAT_BOTTOM,                        // Sort by the bottom coordinate of the undocked chart window relative to the virtual screen
//--- Sort by real properties
   SORT_BY_CHART_SHIFT_SIZE = FIRST_CHART_DBL_PROP,   // Sort by the shift size of the zero bar from the right border in %
   SORT_BY_CHART_FIXED_POSITION,                      // Sort by the chart fixed position from the left border in %
   SORT_BY_CHART_FIXED_MAX,                           // Sort by the fixed chart maximum
   SORT_BY_CHART_FIXED_MIN,                           // Sort by the fixed chart minimum
   SORT_BY_CHART_POINTS_PER_BAR,                      // Sort by the scale value in points per bar
   SORT_BY_CHART_PRICE_MIN,                           // Sort by the chart minimum
   SORT_BY_CHART_PRICE_MAX,                           // Sort by the chart maximum
//--- Sort by string properties
   SORT_BY_CHART_COMMENT = FIRST_CHART_STR_PROP,      // Sort by a comment text on the chart
   SORT_BY_CHART_EXPERT_NAME,                         // Sort by a name of an EA launched on the chart
   SORT_BY_CHART_SCRIPT_NAME,                         // Sort by a name of a script launched on the chart
  };
//+------------------------------------------------------------------+

Você pode aprender mais sobre a estrutura dos objetos da biblioteca no primeiro artigo e nos seguintes.

Agora estamos prontos para criar a classe do objeto-gráfico diretamente.

Classe de objeto-gráfico

No diretório da biblioteca na nova pasta \MQL5\Include\DoEasy\Objects\Chart\ criamos o novo arquivo ChartObj.mqh da classe CChartObj.

O objeto base deve ser o objeto base de todos os objetos da biblioteca, e seu arquivo deve estar vinculado ao arquivo da classe:

//+------------------------------------------------------------------+
//|                                                     ChartObj.mqh |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
#property strict    // Necessary for mql4
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "..\..\Objects\BaseObj.mqh"
//+------------------------------------------------------------------+
//| Chart object class                                               |
//+------------------------------------------------------------------+
class CChartObj : public CBaseObj
  {
  }

Na seção privada da classe, iremos escrever as matrizes para armazenar propriedades, os métodos que retornam o índice real da propriedade e a variável-membro para armazenar o valor Digits() do símbolo.

//+------------------------------------------------------------------+
//| Chart object class                                               |
//+------------------------------------------------------------------+
class CChartObj : public CBaseObj
  {
private:
   long              m_long_prop[CHART_PROP_INTEGER_TOTAL];       // Integer properties
   double            m_double_prop[CHART_PROP_DOUBLE_TOTAL];      // Real properties
   string            m_string_prop[CHART_PROP_STRING_TOTAL];      // String properties
   int               m_digits;                                    // Symbol's Digits()
   
//--- Return the index of the array the (1) double and (2) string properties are actually located at
   int               IndexProp(ENUM_CHART_PROP_DOUBLE property)   const { return(int)property-CHART_PROP_INTEGER_TOTAL;                         }
   int               IndexProp(ENUM_CHART_PROP_STRING property)   const { return(int)property-CHART_PROP_INTEGER_TOTAL-CHART_PROP_DOUBLE_TOTAL; }

Na seção pública da classe, também escreveremos todos os métodos padrão para objetos de biblioteca: métodos de instalação e retorno de propriedades do objeto, métodos virtuais que retornam sinalizadores indicando que o objeto mantém esta ou aquela propriedade (embora não façamos objetos herdados, mas os métodos devem ser virtuais para que possam ser alterados nas classes herdadas se forem necessários), métodos que retornam descrições de propriedades, métodos de registro e descrições de propriedades e nomes de objeto, métodos de comparação e construtores.

public:
//--- Set object's (1) integer, (2) real and (3) string properties
   void              SetProperty(ENUM_CHART_PROP_INTEGER property,long value)    { this.m_long_prop[property]=value;                      }
   void              SetProperty(ENUM_CHART_PROP_DOUBLE property,double value)   { this.m_double_prop[this.IndexProp(property)]=value;    }
   void              SetProperty(ENUM_CHART_PROP_STRING property,string value)   { this.m_string_prop[this.IndexProp(property)]=value;    }
//--- Return object’s (1) integer, (2) real and (3) string property from the properties array
   long              GetProperty(ENUM_CHART_PROP_INTEGER property)         const { return this.m_long_prop[property];                     }
   double            GetProperty(ENUM_CHART_PROP_DOUBLE property)          const { return this.m_double_prop[this.IndexProp(property)];   }
   string            GetProperty(ENUM_CHART_PROP_STRING property)          const { return this.m_string_prop[this.IndexProp(property)];   }
//--- Return itself
   CChartObj        *GetObject(void)                                             { return &this;}

//--- Return the flag of the object supporting this property
   virtual bool      SupportProperty(ENUM_CHART_PROP_INTEGER property)           { return true; }
   virtual bool      SupportProperty(ENUM_CHART_PROP_DOUBLE property)            { return true; }
   virtual bool      SupportProperty(ENUM_CHART_PROP_STRING property)            { return true; }

//--- Get description of (1) integer, (2) real and (3) string properties
   string            GetPropertyDescription(ENUM_CHART_PROP_INTEGER property);
   string            GetPropertyDescription(ENUM_CHART_PROP_DOUBLE property);
   string            GetPropertyDescription(ENUM_CHART_PROP_STRING property);

//--- Display the description of object properties in the journal (full_prop=true - all properties, false - supported ones only)
   void              Print(const bool full_prop=false);
//--- Display a short description of the object in the journal
   virtual void      PrintShort(const bool dash=false);
//--- Return the object short name
   virtual string    Header(void);
   
//--- Compare CChartObj objects by a specified property (to sort the list by a specified chart object property)
   virtual int       Compare(const CObject *node,const int mode=0) const;
//--- Compare CChartObj objects by all properties (to search for equal chart objects)
   bool              IsEqual(CChartObj* compared_obj) const;
   
//--- Constructors
                     CChartObj(){;}
                     CChartObj(const long chart_id);

Este é um conjunto padrão de métodos para objetos de biblioteca, cujo propósito foi discutido e descrito muitas vezes. Não vamos nos deter neles.

Uma vez que ao criar um objeto gráfico, é assumido que o gráfico apropriado está selecionado, e você pode obter suas propriedades usando as funções ChartGetInteger(), ChartGetDouble() e ChartGetString(), então no construtor da classe são preenchidas todas as propriedades do objeto-gráfico com valores retornados pelas funções correspondentes às propriedades e finalmente o valor de Digits() do símbolo é inserido na variável destinada a armazená-lo:

//+------------------------------------------------------------------+
//| Parametric constructor                                           |
//+------------------------------------------------------------------+
CChartObj::CChartObj(const long chart_id)
  {
//--- Set integer properties
   this.SetProperty(CHART_PROP_ID,chart_id);                                                             // Chart ID
   this.SetProperty(CHART_PROP_TIMEFRAME,::ChartPeriod(this.ID()));                                      // Chart timeframe
   this.SetProperty(CHART_PROP_SHOW,::ChartGetInteger(this.ID(),CHART_SHOW));                            // Price chart drawing attribute
   this.SetProperty(CHART_PROP_IS_OBJECT,::ChartGetInteger(this.ID(),CHART_IS_OBJECT));                  // Chart object identification attribute
   this.SetProperty(CHART_PROP_BRING_TO_TOP,false);                                                      // Show chart above all others
   this.SetProperty(CHART_PROP_CONTEXT_MENU,::ChartGetInteger(this.ID(),CHART_CONTEXT_MENU));            // Access to the context menu using the right click
   this.SetProperty(CHART_PROP_CROSSHAIR_TOOL,::ChartGetInteger(this.ID(),CHART_CROSSHAIR_TOOL));        // Access the Crosshair tool by pressing the middle mouse button
   this.SetProperty(CHART_PROP_MOUSE_SCROLL,::ChartGetInteger(this.ID(),CHART_MOUSE_SCROLL));            // Scroll the chart horizontally using the left mouse button
   this.SetProperty(CHART_PROP_EVENT_MOUSE_WHEEL,::ChartGetInteger(this.ID(),CHART_EVENT_MOUSE_WHEEL));  // Send messages about mouse wheel events to all MQL5 programs on a chart
   this.SetProperty(CHART_PROP_EVENT_MOUSE_MOVE,::ChartGetInteger(this.ID(),CHART_EVENT_MOUSE_MOVE));    // Send messages about mouse button click and movement events to all MQL5 programs on a chart
   this.SetProperty(CHART_PROP_EVENT_OBJECT_CREATE,::ChartGetInteger(this.ID(),CHART_EVENT_OBJECT_CREATE)); // Send messages about the graphical object creation event to all MQL5 programs on a chart
   this.SetProperty(CHART_PROP_EVENT_OBJECT_DELETE,::ChartGetInteger(this.ID(),CHART_EVENT_OBJECT_DELETE)); // Send messages about the graphical object destruction event to all MQL5 programs on a chart
   this.SetProperty(CHART_PROP_MODE,::ChartGetInteger(this.ID(),CHART_MODE));                            // Type of the chart (candlesticks, bars or line)
   this.SetProperty(CHART_PROP_FOREGROUND,::ChartGetInteger(this.ID(),CHART_FOREGROUND));                // Price chart in the foreground
   this.SetProperty(CHART_PROP_SHIFT,::ChartGetInteger(this.ID(),CHART_SHIFT));                          // Mode of shift of the price chart from the right border
   this.SetProperty(CHART_PROP_AUTOSCROLL,::ChartGetInteger(this.ID(),CHART_AUTOSCROLL));                // The mode of automatic shift to the right border of the chart
   this.SetProperty(CHART_PROP_KEYBOARD_CONTROL,::ChartGetInteger(this.ID(),CHART_KEYBOARD_CONTROL));    // Allow managing the chart using a keyboard
   this.SetProperty(CHART_PROP_QUICK_NAVIGATION,::ChartGetInteger(this.ID(),CHART_QUICK_NAVIGATION));    // Allow the chart to intercept Space and Enter key strokes to activate the quick navigation bar
   this.SetProperty(CHART_PROP_SCALE,::ChartGetInteger(this.ID(),CHART_SCALE));                          // Scale
   this.SetProperty(CHART_PROP_SCALEFIX,::ChartGetInteger(this.ID(),CHART_SCALEFIX));                    // Fixed scale mode
   this.SetProperty(CHART_PROP_SCALEFIX_11,::ChartGetInteger(this.ID(),CHART_SCALEFIX_11));              // 1:1 scale mode
   this.SetProperty(CHART_PROP_SCALE_PT_PER_BAR,::ChartGetInteger(this.ID(),CHART_SCALE_PT_PER_BAR));    // Mode for specifying the scale in points per bar
   this.SetProperty(CHART_PROP_SHOW_TICKER,::ChartGetInteger(this.ID(),CHART_SHOW_TICKER));              // Display a symbol ticker in the upper left corner
   this.SetProperty(CHART_PROP_SHOW_OHLC,::ChartGetInteger(this.ID(),CHART_SHOW_OHLC));                  // Display OHLC values in the upper left corner
   this.SetProperty(CHART_PROP_SHOW_BID_LINE,::ChartGetInteger(this.ID(),CHART_SHOW_BID_LINE));          // Display Bid value as a horizontal line on the chart
   this.SetProperty(CHART_PROP_SHOW_ASK_LINE,::ChartGetInteger(this.ID(),CHART_SHOW_ASK_LINE));          // Display Ask value as a horizontal line on the chart
   this.SetProperty(CHART_PROP_SHOW_LAST_LINE,::ChartGetInteger(this.ID(),CHART_SHOW_LAST_LINE));        // Display Last value as a horizontal line on the chart
   this.SetProperty(CHART_PROP_SHOW_PERIOD_SEP,::ChartGetInteger(this.ID(),CHART_SHOW_PERIOD_SEP));      // Display vertical separators between adjacent periods
   this.SetProperty(CHART_PROP_SHOW_GRID,::ChartGetInteger(this.ID(),CHART_SHOW_GRID));                  // Display the chart grid
   this.SetProperty(CHART_PROP_SHOW_VOLUMES,::ChartGetInteger(this.ID(),CHART_SHOW_VOLUMES));            // Display volumes on the chart
   this.SetProperty(CHART_PROP_SHOW_OBJECT_DESCR,::ChartGetInteger(this.ID(),CHART_SHOW_OBJECT_DESCR));  // Display text descriptions of the objects
   this.SetProperty(CHART_PROP_VISIBLE_BARS,::ChartGetInteger(this.ID(),CHART_VISIBLE_BARS));            // Number of bars on a chart that are available for display
   this.SetProperty(CHART_PROP_WINDOWS_TOTAL,::ChartGetInteger(this.ID(),CHART_WINDOWS_TOTAL));          // The total number of chart windows including indicator subwindows
   this.SetProperty(CHART_PROP_WINDOW_HANDLE,::ChartGetInteger(this.ID(),CHART_WINDOW_HANDLE));          // Chart window handle
   this.SetProperty(CHART_PROP_FIRST_VISIBLE_BAR,::ChartGetInteger(this.ID(),CHART_FIRST_VISIBLE_BAR));  // Number of the first visible bar on the chart
   this.SetProperty(CHART_PROP_WIDTH_IN_BARS,::ChartGetInteger(this.ID(),CHART_WIDTH_IN_BARS));          // Chart width in bars
   this.SetProperty(CHART_PROP_WIDTH_IN_PIXELS,::ChartGetInteger(this.ID(),CHART_WIDTH_IN_PIXELS));      // Chart width in pixels
   this.SetProperty(CHART_PROP_COLOR_BACKGROUND,::ChartGetInteger(this.ID(),CHART_COLOR_BACKGROUND));    // Chart background color
   this.SetProperty(CHART_PROP_COLOR_FOREGROUND,::ChartGetInteger(this.ID(),CHART_COLOR_FOREGROUND));    // Color of axes, scale and OHLC line
   this.SetProperty(CHART_PROP_COLOR_GRID,::ChartGetInteger(this.ID(),CHART_COLOR_GRID));                // Grid color
   this.SetProperty(CHART_PROP_COLOR_VOLUME,::ChartGetInteger(this.ID(),CHART_COLOR_VOLUME));            // Color of volumes and position opening levels
   this.SetProperty(CHART_PROP_COLOR_CHART_UP,::ChartGetInteger(this.ID(),CHART_COLOR_CHART_UP));        // Color for the up bar, shadows and body borders of bullish candlesticks
   this.SetProperty(CHART_PROP_COLOR_CHART_DOWN,::ChartGetInteger(this.ID(),CHART_COLOR_CHART_DOWN));    // Color for the down bar, shadows and body borders of bearish candlesticks
   this.SetProperty(CHART_PROP_COLOR_CHART_LINE,::ChartGetInteger(this.ID(),CHART_COLOR_CHART_LINE));    // Color of the chart line and the Doji candlesticks
   this.SetProperty(CHART_PROP_COLOR_CANDLE_BULL,::ChartGetInteger(this.ID(),CHART_COLOR_CANDLE_BULL));  // Color of the bullish candle body
   this.SetProperty(CHART_PROP_COLOR_CANDLE_BEAR,::ChartGetInteger(this.ID(),CHART_COLOR_CANDLE_BEAR));  // Color of the bearish candle body
   this.SetProperty(CHART_PROP_COLOR_BID,::ChartGetInteger(this.ID(),CHART_COLOR_BID));                  // Bid price line color
   this.SetProperty(CHART_PROP_COLOR_ASK,::ChartGetInteger(this.ID(),CHART_COLOR_ASK));                  // Ask price line color
   this.SetProperty(CHART_PROP_COLOR_LAST,::ChartGetInteger(this.ID(),CHART_COLOR_LAST));                // Color of the last performed deal's price line (Last)
   this.SetProperty(CHART_PROP_COLOR_STOP_LEVEL,::ChartGetInteger(this.ID(),CHART_COLOR_STOP_LEVEL));    // Color of stop order levels (Stop Loss and Take Profit)
   this.SetProperty(CHART_PROP_SHOW_TRADE_LEVELS,::ChartGetInteger(this.ID(),CHART_SHOW_TRADE_LEVELS));  // Display trade levels on the chart (levels of open positions, Stop Loss, Take Profit and pending orders)
   this.SetProperty(CHART_PROP_DRAG_TRADE_LEVELS,::ChartGetInteger(this.ID(),CHART_DRAG_TRADE_LEVELS));  // Enable the ability to drag trading levels on a chart using mouse
   this.SetProperty(CHART_PROP_SHOW_DATE_SCALE,::ChartGetInteger(this.ID(),CHART_SHOW_DATE_SCALE));      // Display the time scale on the chart
   this.SetProperty(CHART_PROP_SHOW_PRICE_SCALE,::ChartGetInteger(this.ID(),CHART_SHOW_PRICE_SCALE));    // Display the price scale on the chart
   this.SetProperty(CHART_PROP_SHOW_ONE_CLICK,::ChartGetInteger(this.ID(),CHART_SHOW_ONE_CLICK));        // Display the quick trading panel on the chart
   this.SetProperty(CHART_PROP_IS_MAXIMIZED,::ChartGetInteger(this.ID(),CHART_IS_MAXIMIZED));            // Chart window maximized
   this.SetProperty(CHART_PROP_IS_MINIMIZED,::ChartGetInteger(this.ID(),CHART_IS_MINIMIZED));            // Chart window minimized
   this.SetProperty(CHART_PROP_IS_DOCKED,::ChartGetInteger(this.ID(),CHART_IS_DOCKED));                  // Chart window docked
   this.SetProperty(CHART_PROP_FLOAT_LEFT,::ChartGetInteger(this.ID(),CHART_FLOAT_LEFT));                // Left coordinate of the undocked chart window relative to the virtual screen
   this.SetProperty(CHART_PROP_FLOAT_TOP,::ChartGetInteger(this.ID(),CHART_FLOAT_TOP));                  // Upper coordinate of the undocked chart window relative to the virtual screen
   this.SetProperty(CHART_PROP_FLOAT_RIGHT,::ChartGetInteger(this.ID(),CHART_FLOAT_RIGHT));              // Right coordinate of the undocked chart window relative to the virtual screen
   this.SetProperty(CHART_PROP_FLOAT_BOTTOM,::ChartGetInteger(this.ID(),CHART_FLOAT_BOTTOM));            // Bottom coordinate of the undocked chart window relative to the virtual screen
//--- Set real properties
   this.SetProperty(CHART_PROP_SHIFT_SIZE,::ChartGetDouble(this.ID(),CHART_SHIFT_SIZE));                 // Shift size of the zero bar from the right border in %
   this.SetProperty(CHART_PROP_FIXED_POSITION,::ChartGetDouble(this.ID(),CHART_FIXED_POSITION));         // Chart fixed position from the left border in %
   this.SetProperty(CHART_PROP_FIXED_MAX,::ChartGetDouble(this.ID(),CHART_FIXED_MAX));                   // Fixed chart maximum
   this.SetProperty(CHART_PROP_FIXED_MIN,::ChartGetDouble(this.ID(),CHART_FIXED_MIN));                   // Fixed chart minimum
   this.SetProperty(CHART_PROP_POINTS_PER_BAR,::ChartGetDouble(this.ID(),CHART_POINTS_PER_BAR));         // Scale in points per bar
   this.SetProperty(CHART_PROP_PRICE_MIN,::ChartGetDouble(this.ID(),CHART_PRICE_MIN));                   // Chart minimum
   this.SetProperty(CHART_PROP_PRICE_MAX,::ChartGetDouble(this.ID(),CHART_PRICE_MAX));                   // Chart maximum
//--- Set string properties
   this.SetProperty(CHART_PROP_COMMENT,::ChartGetString(this.ID(),CHART_COMMENT));                       // Comment text on the chart
   this.SetProperty(CHART_PROP_EXPERT_NAME,::ChartGetString(this.ID(),CHART_EXPERT_NAME));               // name of an EA launched on the chart
   this.SetProperty(CHART_PROP_SCRIPT_NAME,::ChartGetString(this.ID(),CHART_SCRIPT_NAME));               // name of a script launched on the chart
   this.SetProperty(CHART_PROP_SYMBOL,::ChartSymbol(this.ID()));                                         // Chart symbol
   
   this.m_digits=(int)::SymbolInfoInteger(this.Symbol(),SYMBOL_DIGITS);
  }
//+------------------------------------------------------------------+

Digits() do símbolo é necessário para a exibição correta de alguns valores das propriedades do gráfico.

Método que compara a propriedade de objetos CChartObj:

//+------------------------------------------------------------------+
//| Compare the CChartObj objects by a specified property            |
//+------------------------------------------------------------------+
int CChartObj::Compare(const CObject *node,const int mode=0) const
  {
   const CChartObj *obj_compared=node;
//--- compare integer properties of two objects
   if(mode<CHART_PROP_INTEGER_TOTAL)
     {
      long value_compared=obj_compared.GetProperty((ENUM_CHART_PROP_INTEGER)mode);
      long value_current=this.GetProperty((ENUM_CHART_PROP_INTEGER)mode);
      return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0);
     }
//--- compare real properties of two objects
   else if(mode<CHART_PROP_DOUBLE_TOTAL+CHART_PROP_INTEGER_TOTAL)
     {
      double value_compared=obj_compared.GetProperty((ENUM_CHART_PROP_DOUBLE)mode);
      double value_current=this.GetProperty((ENUM_CHART_PROP_DOUBLE)mode);
      return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0);
     }
//--- compare string properties of two objects
   else if(mode<CHART_PROP_DOUBLE_TOTAL+CHART_PROP_INTEGER_TOTAL+CHART_PROP_STRING_TOTAL)
     {
      string value_compared=obj_compared.GetProperty((ENUM_CHART_PROP_STRING)mode);
      string value_current=this.GetProperty((ENUM_CHART_PROP_STRING)mode);
      return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0);
     }
   return 0;
  }
//+------------------------------------------------------------------+

Verifica-se que as propriedades inteiras, reais ou string da propriedade passada, e no bloco de código correspondente, a propriedade do objeto atual é comparada com a propriedade passada ao método. Retorna o resultado de uma comparação maior que (1), menor que (-1) ou igual a (0).

Método que compara todas as propriedades de objetos CChartObj:

//+------------------------------------------------------------------+
//| Compare the CChartObj objects by all properties                  |
//+------------------------------------------------------------------+
bool CChartObj::IsEqual(CChartObj *compared_obj) const
  {
   int beg=0, end=CHART_PROP_INTEGER_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_CHART_PROP_INTEGER prop=(ENUM_CHART_PROP_INTEGER)i;
      if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) return false; 
     }
   beg=end; end+=CHART_PROP_DOUBLE_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_CHART_PROP_DOUBLE prop=(ENUM_CHART_PROP_DOUBLE)i;
      if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) return false; 
     }
   beg=end; end+=CHART_PROP_STRING_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_CHART_PROP_STRING prop=(ENUM_CHART_PROP_STRING)i;
      if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) return false; 
     }
   return true;
  }
//+------------------------------------------------------------------+

Em três loops para todas as propriedades do objeto, todas as propriedades de dois objetos são comparadas - a atual e a passada para o método. Se pelo menos uma das propriedades de dois objetos comparados não forem iguais, ele retorna imediatamente false - os objetos não são idênticos. Após a conclusão de todos os loops em todas as propriedades, ele retorna true, o que indica que não existem propriedades diferentes - os objetos são idênticos.

Métodos que retornam a descrição de propriedades inteiras, reais e de string do objeto:

//+------------------------------------------------------------------+
//| Return description of object's integer property                  |
//+------------------------------------------------------------------+
string CChartObj::GetPropertyDescription(ENUM_CHART_PROP_INTEGER property)
  {
   return
     (
      property==CHART_PROP_ID     ?  CMessage::Text(MSG_CHART_OBJ_ID)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==CHART_PROP_TIMEFRAME      ?  CMessage::Text(MSG_LIB_TEXT_BAR_PERIOD)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+TimeframeDescription((ENUM_TIMEFRAMES)this.GetProperty(property))
         )  :
      property==CHART_PROP_SHOW   ?  CMessage::Text(MSG_CHART_OBJ_SHOW)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_IS_OBJECT      ?  CMessage::Text(MSG_CHART_OBJ_IS_OBJECT)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_BRING_TO_TOP   ?  CMessage::Text(MSG_CHART_OBJ_BRING_TO_TOP)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_CONTEXT_MENU   ?  CMessage::Text(MSG_CHART_OBJ_CONTEXT_MENU)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_CROSSHAIR_TOOL ?  CMessage::Text(MSG_CHART_OBJ_CROSSHAIR_TOOL)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_MOUSE_SCROLL   ?  CMessage::Text(MSG_CHART_OBJ_MOUSE_SCROLL)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_EVENT_MOUSE_WHEEL ?  CMessage::Text(MSG_CHART_OBJ_EVENT_MOUSE_WHEEL)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_EVENT_MOUSE_MOVE  ?  CMessage::Text(MSG_CHART_OBJ_EVENT_MOUSE_MOVE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_EVENT_OBJECT_CREATE  ?  CMessage::Text(MSG_CHART_OBJ_EVENT_OBJECT_CREATE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_EVENT_OBJECT_DELETE  ?  CMessage::Text(MSG_CHART_OBJ_EVENT_OBJECT_DELETE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_MODE           ?  CMessage::Text(MSG_CHART_OBJ_MODE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+ChartModeDescription((ENUM_CHART_MODE)this.GetProperty(property))
         )  :
      property==CHART_PROP_FOREGROUND     ?  CMessage::Text(MSG_CHART_OBJ_FOREGROUND)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_SHIFT        ?  CMessage::Text(MSG_CHART_OBJ_SHIFT)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_AUTOSCROLL        ?  CMessage::Text(MSG_CHART_OBJ_AUTOSCROLL)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_KEYBOARD_CONTROL        ?  CMessage::Text(MSG_CHART_OBJ_KEYBOARD_CONTROL)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_QUICK_NAVIGATION        ?  CMessage::Text(MSG_CHART_OBJ_QUICK_NAVIGATION)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_SCALE        ?  CMessage::Text(MSG_CHART_OBJ_SCALE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==CHART_PROP_SCALEFIX        ?  CMessage::Text(MSG_CHART_OBJ_SCALEFIX)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_SCALEFIX_11        ?  CMessage::Text(MSG_CHART_OBJ_SCALEFIX_11)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_SCALE_PT_PER_BAR  ?  CMessage::Text(MSG_CHART_OBJ_SCALE_PT_PER_BAR)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_SHOW_TICKER        ?  CMessage::Text(MSG_CHART_OBJ_SHOW_TICKER)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_SHOW_OHLC        ?  CMessage::Text(MSG_CHART_OBJ_SHOW_OHLC)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_SHOW_BID_LINE  ?  CMessage::Text(MSG_CHART_OBJ_SHOW_BID_LINE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_SHOW_ASK_LINE  ?  CMessage::Text(MSG_CHART_OBJ_SHOW_ASK_LINE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_SHOW_LAST_LINE ?  CMessage::Text(MSG_CHART_OBJ_SHOW_LAST_LINE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_SHOW_PERIOD_SEP   ?  CMessage::Text(MSG_CHART_OBJ_SHOW_PERIOD_SEP)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_SHOW_GRID        ?  CMessage::Text(MSG_CHART_OBJ_SHOW_GRID)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_SHOW_VOLUMES   ?  CMessage::Text(MSG_CHART_OBJ_SHOW_VOLUMES)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+ChartModeVolumeDescription((ENUM_CHART_VOLUME_MODE)this.GetProperty(property))
         )  :
      property==CHART_PROP_SHOW_OBJECT_DESCR ?  CMessage::Text(MSG_CHART_OBJ_SHOW_OBJECT_DESCR)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_VISIBLE_BARS   ?  CMessage::Text(MSG_CHART_OBJ_VISIBLE_BARS)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==CHART_PROP_WINDOWS_TOTAL  ?  CMessage::Text(MSG_CHART_OBJ_WINDOWS_TOTAL)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==CHART_PROP_WINDOW_HANDLE  ?  CMessage::Text(MSG_CHART_OBJ_WINDOW_HANDLE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==CHART_PROP_FIRST_VISIBLE_BAR ?  CMessage::Text(MSG_CHART_OBJ_FIRST_VISIBLE_BAR)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==CHART_PROP_WIDTH_IN_BARS  ?  CMessage::Text(MSG_CHART_OBJ_WIDTH_IN_BARS)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==CHART_PROP_WIDTH_IN_PIXELS   ?  CMessage::Text(MSG_CHART_OBJ_WIDTH_IN_PIXELS)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==CHART_PROP_COLOR_BACKGROUND        ?  CMessage::Text(MSG_CHART_OBJ_COLOR_BACKGROUND)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::ColorToString((color)this.GetProperty(property),true)
         )  :
      property==CHART_PROP_COLOR_FOREGROUND  ?  CMessage::Text(MSG_CHART_OBJ_COLOR_FOREGROUND)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::ColorToString((color)this.GetProperty(property),true)
         )  :
      property==CHART_PROP_COLOR_GRID     ?  CMessage::Text(MSG_CHART_OBJ_COLOR_GRID)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::ColorToString((color)this.GetProperty(property),true)
         )  :
      property==CHART_PROP_COLOR_VOLUME   ?  CMessage::Text(MSG_CHART_OBJ_COLOR_VOLUME)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::ColorToString((color)this.GetProperty(property),true)
         )  :
      property==CHART_PROP_COLOR_CHART_UP ?  CMessage::Text(MSG_CHART_OBJ_COLOR_CHART_UP)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::ColorToString((color)this.GetProperty(property),true)
         )  :
      property==CHART_PROP_COLOR_CHART_DOWN  ?  CMessage::Text(MSG_CHART_OBJ_COLOR_CHART_DOWN)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::ColorToString((color)this.GetProperty(property),true)
         )  :
      property==CHART_PROP_COLOR_CHART_LINE  ?  CMessage::Text(MSG_CHART_OBJ_COLOR_CHART_LINE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::ColorToString((color)this.GetProperty(property),true)
         )  :
      property==CHART_PROP_COLOR_CANDLE_BULL ?  CMessage::Text(MSG_CHART_OBJ_COLOR_CANDLE_BULL)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::ColorToString((color)this.GetProperty(property),true)
         )  :
      property==CHART_PROP_COLOR_CANDLE_BEAR ?  CMessage::Text(MSG_CHART_OBJ_COLOR_CANDLE_BEAR)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::ColorToString((color)this.GetProperty(property),true)
         )  :
      property==CHART_PROP_COLOR_BID        ?  CMessage::Text(MSG_CHART_OBJ_COLOR_BID)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::ColorToString((color)this.GetProperty(property),true)
         )  :
      property==CHART_PROP_COLOR_ASK        ?  CMessage::Text(MSG_CHART_OBJ_COLOR_ASK)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::ColorToString((color)this.GetProperty(property),true)
         )  :
      property==CHART_PROP_COLOR_LAST        ?  CMessage::Text(MSG_CHART_OBJ_COLOR_LAST)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::ColorToString((color)this.GetProperty(property),true)
         )  :
      property==CHART_PROP_COLOR_STOP_LEVEL  ?  CMessage::Text(MSG_CHART_OBJ_COLOR_STOP_LEVEL)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::ColorToString((color)this.GetProperty(property),true)
         )  :
      property==CHART_PROP_SHOW_TRADE_LEVELS ?  CMessage::Text(MSG_CHART_OBJ_SHOW_TRADE_LEVELS)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_DRAG_TRADE_LEVELS ?  CMessage::Text(MSG_CHART_OBJ_DRAG_TRADE_LEVELS)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_SHOW_DATE_SCALE   ?  CMessage::Text(MSG_CHART_OBJ_SHOW_DATE_SCALE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_SHOW_PRICE_SCALE  ?  CMessage::Text(MSG_CHART_OBJ_SHOW_PRICE_SCALE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_SHOW_ONE_CLICK ?  CMessage::Text(MSG_CHART_OBJ_SHOW_ONE_CLICK)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_IS_MAXIMIZED   ?  CMessage::Text(MSG_CHART_OBJ_IS_MAXIMIZED)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_IS_MINIMIZED   ?  CMessage::Text(MSG_CHART_OBJ_IS_MINIMIZED)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_IS_DOCKED      ?  CMessage::Text(MSG_CHART_OBJ_IS_DOCKED)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==CHART_PROP_FLOAT_LEFT     ?  CMessage::Text(MSG_CHART_OBJ_FLOAT_LEFT)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==CHART_PROP_FLOAT_TOP      ?  CMessage::Text(MSG_CHART_OBJ_FLOAT_TOP)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==CHART_PROP_FLOAT_RIGHT    ?  CMessage::Text(MSG_CHART_OBJ_FLOAT_RIGHT)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==CHART_PROP_FLOAT_BOTTOM   ?  CMessage::Text(MSG_CHART_OBJ_FLOAT_BOTTOM)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      ""
     );
  }
//+------------------------------------------------------------------+
//| Return description of object's real property                     |
//+------------------------------------------------------------------+
string CChartObj::GetPropertyDescription(ENUM_CHART_PROP_DOUBLE property)
  {
   return
     (
      property==CHART_PROP_SHIFT_SIZE        ?  CMessage::Text(MSG_CHART_OBJ_SHIFT_SIZE)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::DoubleToString(this.GetProperty(property),2)
         )  :
      property==CHART_PROP_FIXED_POSITION    ?  CMessage::Text(MSG_CHART_OBJ_FIXED_POSITION)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::DoubleToString(this.GetProperty(property),2)
         )  :
      property==CHART_PROP_FIXED_MAX         ?  CMessage::Text(MSG_CHART_OBJ_FIXED_MAX)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::DoubleToString(this.GetProperty(property),this.m_digits)
         )  :
      property==CHART_PROP_FIXED_MIN         ?  CMessage::Text(MSG_CHART_OBJ_FIXED_MIN)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::DoubleToString(this.GetProperty(property),this.m_digits)
         )  :
      property==CHART_PROP_POINTS_PER_BAR    ?  CMessage::Text(MSG_CHART_OBJ_POINTS_PER_BAR)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::DoubleToString(this.GetProperty(property),2)
         )  :
      property==CHART_PROP_PRICE_MIN         ?  CMessage::Text(MSG_CHART_OBJ_PRICE_MIN)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::DoubleToString(this.GetProperty(property),this.m_digits)
         )  :
      property==CHART_PROP_PRICE_MAX         ?  CMessage::Text(MSG_CHART_OBJ_PRICE_MAX)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::DoubleToString(this.GetProperty(property),this.m_digits)
         )  :
      ""
     );
  }
//+------------------------------------------------------------------+
//| Return description of object's string property                   |
//+------------------------------------------------------------------+
string CChartObj::GetPropertyDescription(ENUM_CHART_PROP_STRING property)
  {
   return
     (
      property==CHART_PROP_COMMENT     ?  CMessage::Text(MSG_CHART_OBJ_COMMENT)+": \""+this.GetProperty(property)+"\""     :
      property==CHART_PROP_EXPERT_NAME ?  CMessage::Text(MSG_CHART_OBJ_EXPERT_NAME)+": \""+this.GetProperty(property)+"\"" :
      property==CHART_PROP_SCRIPT_NAME ?  CMessage::Text(MSG_CHART_OBJ_SCRIPT_NAME)+": \""+this.GetProperty(property)+"\"" :
      property==CHART_PROP_SYMBOL      ?  CMessage::Text(MSG_LIB_PROP_SYMBOL)+": \""+this.GetProperty(property)+"\""       :
      ""
     );
  }
//+------------------------------------------------------------------+

Nos métodos, é verificada a propriedade passada, e de acordo com o valor, uma string com uma descrição é criada e retornada.

Um método que imprime a descrição completa das propriedades do objeto no log:

//+------------------------------------------------------------------+
//| Display object properties in the journal                         |
//+------------------------------------------------------------------+
void CChartObj::Print(const bool full_prop=false)
  {
   ::Print("============= ",CMessage::Text(MSG_LIB_PARAMS_LIST_BEG)," (",this.Header(),") =============");
   int beg=0, end=CHART_PROP_INTEGER_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_CHART_PROP_INTEGER prop=(ENUM_CHART_PROP_INTEGER)i;
      if(!full_prop && !this.SupportProperty(prop)) continue;
      ::Print(this.GetPropertyDescription(prop));
     }
   ::Print("------");
   beg=end; end+=CHART_PROP_DOUBLE_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_CHART_PROP_DOUBLE prop=(ENUM_CHART_PROP_DOUBLE)i;
      if(!full_prop && !this.SupportProperty(prop)) continue;
      ::Print(this.GetPropertyDescription(prop));
     }
   ::Print("------");
   beg=end; end+=CHART_PROP_STRING_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_CHART_PROP_STRING prop=(ENUM_CHART_PROP_STRING)i;
      if(!full_prop && !this.SupportProperty(prop)) continue;
      ::Print(this.GetPropertyDescription(prop));
     }
   ::Print("============= ",CMessage::Text(MSG_LIB_PARAMS_LIST_END)," (",this.Header(),") =============\n");
  }
//+------------------------------------------------------------------+

Em três loops para todas as propriedades do objeto, obtemos uma descrição de cada propriedade e a imprimimos no log.

Método que imprime uma breve descrição do objeto no log:

//+------------------------------------------------------------------+
//| Display a short description of the object in the journal         |
//+------------------------------------------------------------------+
void CChartObj::PrintShort(const bool dash=false)
  {
   ::Print((dash ? "- " : ""),this.Header()," ID: ",(string)this.ID(),", HWND: ",(string)this.Handle());
  }
//+------------------------------------------------------------------+

Ao método é passado o sinalizador de que é necessário imprimir um hífen antes da descrição do objeto. O hífen será necessário na classe-coleção de objetos-gráficos para exibir uma breve descrição de toda a coleção. Por padrão, não há hífen. O método cria uma string com uma descrição do objeto e algumas de suas propriedades adicionais - identificadores de gráfico e identificador de janela.

Método que retorna o nome abreviado do objeto:

//+------------------------------------------------------------------+
//| Return the object short name                                     |
//+------------------------------------------------------------------+
string CChartObj::Header(void)
  {
   return(CMessage::Text(MSG_CHART_OBJ_CHART_WINDOW)+" "+this.Symbol()+" "+TimeframeDescription(this.Timeframe()));
  }
//+------------------------------------------------------------------+

O método cria e retorna uma string que consiste no título e nomes do símbolo e período do gráfico.

Todos esses métodos são padrão para objetos de biblioteca e formam a base de cada um deles. Mas, para o uso conveniente desses métodos, geralmente adicionamos métodos para acessar rapidamente as propriedades do objeto. E teremos muitos métodos assim, uma vez que existem muitas e diferentes propriedades do objeto-gráfico.
Basicamente, todas as suas propriedades são sinalizadores que indicam o estado de um ou outro parâmetro do gráfico. Eles podem ser ligados e desligados - tem apenas dois estados. Portanto, precisamos de métodos para definir sinalizadores de tais propriedades de objeto. E esses serão métodos privados. Faremos com que os métodos para habilitar e desabilitar a propriedade sejam públicos. Isso será mais fácil de usar.

Na seção privada da classe iremos declarar métodos para definir sinalizadores de algumas propriedades de objeto, e no mesmo lugar declaramos métodos para definir propriedades que têm um número limite de valores (3 e 6), assim como métodos para definir apenas propriedades do objeto-gráfico - para os parâmetros do gráfico somente leitura - para inserir o valor do parâmetro do gráfico correspondente na propriedade do objeto-gráfico:

//+------------------------------------------------------------------+
//|                                                     ChartObj.mqh |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
#property strict    // Necessary for mql4
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "..\..\Objects\BaseObj.mqh"
//+------------------------------------------------------------------+
//| Chart object class                                               |
//+------------------------------------------------------------------+
class CChartObj : public CBaseObj
  {
private:
   long              m_long_prop[CHART_PROP_INTEGER_TOTAL];       // Integer properties
   double            m_double_prop[CHART_PROP_DOUBLE_TOTAL];      // Real properties
   string            m_string_prop[CHART_PROP_STRING_TOTAL];      // String properties
   int               m_digits;                                    // Symbol's Digits()
   
//--- Return the index of the array the (1) double and (2) string properties are actually located at
   int               IndexProp(ENUM_CHART_PROP_DOUBLE property)   const { return(int)property-CHART_PROP_INTEGER_TOTAL;                         }
   int               IndexProp(ENUM_CHART_PROP_STRING property)   const { return(int)property-CHART_PROP_INTEGER_TOTAL-CHART_PROP_DOUBLE_TOTAL; }

//--- The methods of setting parameter flags 
   bool              SetShowFlag(const string source,const bool flag,const bool redraw=false);
   bool              SetBringToTopFlag(const string source,const bool flag,const bool redraw=false);
   bool              SetContextMenuFlag(const string source,const bool flag,const bool redraw=false);
   bool              SetCrosshairToolFlag(const string source,const bool flag,const bool redraw=false);
   bool              SetMouseScrollFlag(const string source,const bool flag,const bool redraw=false);
   bool              SetEventMouseWhellFlag(const string source,const bool flag,const bool redraw=false);
   bool              SetEventMouseMoveFlag(const string source,const bool flag,const bool redraw=false);
   bool              SetEventObjectCreateFlag(const string source,const bool flag,const bool redraw=false);
   bool              SetEventObjectDeleteFlag(const string source,const bool flag,const bool redraw=false);
   bool              SetForegroundFlag(const string source,const bool flag,const bool redraw=false);
   bool              SetShiftFlag(const string source,const bool flag,const bool redraw=false);
   bool              SetAutoscrollFlag(const string source,const bool flag,const bool redraw=false);
   bool              SetKeyboardControlFlag(const string source,const bool flag,const bool redraw=false);
   bool              SetQuickNavigationFlag(const string source,const bool flag,const bool redraw=false);
   bool              SetScaleFixFlag(const string source,const bool flag,const bool redraw=false);
   bool              SetScaleFix11Flag(const string source,const bool flag,const bool redraw=false);
   bool              SetScalePTPerBarFlag(const string source,const bool flag,const bool redraw=false);
   bool              SetShowTickerFlag(const string source,const bool flag,const bool redraw=false);
   bool              SetShowOHLCFlag(const string source,const bool flag,const bool redraw=false);
   bool              SetShowBidLineFlag(const string source,const bool flag,const bool redraw=false);
   bool              SetShowAskLineFlag(const string source,const bool flag,const bool redraw=false);
   bool              SetShowLastLineFlag(const string source,const bool flag,const bool redraw=false);
   bool              SetShowPeriodSeparatorsFlag(const string source,const bool flag,const bool redraw=false);
   bool              SetShowGridFlag(const string source,const bool flag,const bool redraw=false);
   bool              SetShowObjectDescriptionsFlag(const string source,const bool flag,const bool redraw=false);
   bool              SetShowTradeLevelsFlag(const string source,const bool flag,const bool redraw=false);
   bool              SetDragTradeLevelsFlag(const string source,const bool flag,const bool redraw=false);
   bool              SetShowDateScaleFlag(const string source,const bool flag,const bool redraw=false);
   bool              SetShowPriceScaleFlag(const string source,const bool flag,const bool redraw=false);
   bool              SetShowOneClickPanelFlag(const string source,const bool flag,const bool redraw=false);
   bool              SetDockedFlag(const string source,const bool flag,const bool redraw=false);

//--- The methods of setting property values
   bool              SetMode(const string source,const ENUM_CHART_MODE mode,const bool redraw=false);
   bool              SetScale(const string source,const int scale,const bool redraw=false);
   bool              SetModeVolume(const string source,const ENUM_CHART_VOLUME_MODE mode,const bool redraw=false);
   void              SetVisibleBars(void);
   void              SetWindowsTotal(void);
   void              SetFirstVisibleBars(void);
   void              SetWidthInBars(void);
   void              SetWidthInPixels(void);
   void              SetMaximizedFlag(void);
   void              SetMinimizedFlag(void);
   void              SetExpertName(void);
   void              SetScriptName(void);

public:

Fora do corpo da classe, escreveremos a implementação dos métodos privados declarados.
Os métodos para definir sinalizadores são idênticos.
Portanto, veremos a lógica usando o exemplo do método que define o sinalizador para desenhar o gráfico de preços:

//+------------------------------------------------------------------+
//| Set the flag of drawing the price chart                          |
//+------------------------------------------------------------------+
bool CChartObj::SetShowFlag(const string source,const bool flag,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_SHOW,flag))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_SHOW,flag);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+

Ao método é passada a fonte (source) - o nome do método a partir do qual este método privado é chamado, o valor do sinalizador (flag), que deve ser definido nos parâmetros do gráfico e na propriedade do objeto gráfico, e o sinalizador que indica a necessidade de redesenhar o gráfico (redraw)

As funções para trabalhar com gráficos ChartSet * são assíncronas, ou seja, retornam apenas o resultado de colocar o comando na fila de eventos do gráfico, mas não o resultado da alteração do próprio parâmetro Normalmente, o resultado da função aparece após um determinado evento no gráfico - alteração de seu tamanho, a chegada de um novo tick, atualização do gráfico, etc. Para exibir imediatamente a mudança no parâmetro, precisamos forçar a atualização do gráfico, que é o que a função ChartRedraw() faz.

Existe um "MAS" aqui - normalmente vários valores dos parâmetros do gráfico mudam. Neste caso, deve-se primeiro enviar todos os eventos de alteração de todos os parâmetros do gráfico necessários, e só então chamar o redesenho forçado do gráfico para que após cada comando de alteração dos parâmetros, o gráfico não seja redesenhado. É para isso que serve o sinalizador redraw definido por padrão como false.

Aqui, primeiro, enviamos um comando para alterar o parâmetro do gráfico e, se o evento não foi enfileirado, reportamos um erro e retornamos false.
Se o evento foi colocado na fila com sucesso, mudamos a propriedade do objeto-gráfico e, se o sinalizador de redesenho estiver definido, redesenhamos o gráfico à força. Retornamos true, o que significa que o método funcionou corretamente.

Implementação dos métodos privados restantes para definir sinalizadores idêntico ao considerado; nós daremos sua lista completa:

//+------------------------------------------------------------------+
//| Set the chart flag above all others                              |
//+------------------------------------------------------------------+
bool CChartObj::SetBringToTopFlag(const string source,const bool flag,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_BRING_TO_TOP,flag))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_BRING_TO_TOP,flag);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the flag of accessing the context menu                       |
//| upon pressing the right mouse button                             |
//+------------------------------------------------------------------+
bool CChartObj::SetContextMenuFlag(const string source,const bool flag,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_CONTEXT_MENU,flag))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_CONTEXT_MENU,flag);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the flag of accessing the Crosshair                          |
//| upon pressing the middle mouse button                            |
//+------------------------------------------------------------------+
bool CChartObj::SetCrosshairToolFlag(const string source,const bool flag,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_CROSSHAIR_TOOL,flag))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_CROSSHAIR_TOOL,flag);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the chart scroll flag                                        |
//| horizontally using the left mouse button                         |
//+------------------------------------------------------------------+
bool CChartObj::SetMouseScrollFlag(const string source,const bool flag,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_MOUSE_SCROLL,flag))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_MOUSE_SCROLL,flag);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the flag of sending mouse wheel event messages               |
//| to all MQL5 programs on the chart                                |
//+------------------------------------------------------------------+
bool CChartObj::SetEventMouseWhellFlag(const string source,const bool flag,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_EVENT_MOUSE_WHEEL,flag))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_EVENT_MOUSE_WHEEL,flag);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the flag of sending mouse wheel event messages               |
//| to all MQL5 programs on the chart                                |
//+------------------------------------------------------------------+
bool CChartObj::SetEventMouseMoveFlag(const string source,const bool flag,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_EVENT_MOUSE_MOVE,flag))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_EVENT_MOUSE_MOVE,flag);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the flag of sending mouse wheel event messages               |
//| to all MQL5 programs on the chart                                |
//+------------------------------------------------------------------+
bool CChartObj::SetEventObjectCreateFlag(const string source,const bool flag,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_EVENT_OBJECT_CREATE,flag))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_EVENT_OBJECT_CREATE,flag);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the flag of sending mouse wheel event messages               |
//| to all MQL5 programs on the chart                                |
//+------------------------------------------------------------------+
bool CChartObj::SetEventObjectDeleteFlag(const string source,const bool flag,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_EVENT_OBJECT_DELETE,flag))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_EVENT_OBJECT_DELETE,flag);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the price chart flag in the foreground                       |
//+------------------------------------------------------------------+
bool CChartObj::SetForegroundFlag(const string source,const bool flag,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_FOREGROUND,flag))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_FOREGROUND,flag);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the flag of the price chart shift from the right border      |
//+------------------------------------------------------------------+
bool CChartObj::SetShiftFlag(const string source,const bool flag,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_SHIFT,flag))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_SHIFT,flag);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//|Set the flag for automatically moving to the right chart border   |
//+------------------------------------------------------------------+
bool CChartObj::SetAutoscrollFlag(const string source,const bool flag,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_AUTOSCROLL,flag))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_AUTOSCROLL,flag);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the flag of managing the chart using a keyboard              |
//+------------------------------------------------------------------+
bool CChartObj::SetKeyboardControlFlag(const string source,const bool flag,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_KEYBOARD_CONTROL,flag))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_KEYBOARD_CONTROL,flag);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+---------------------------------------------------------------------+
//| Set the flag of intercepting Space and Enter keystrokes by the chart|
//| to activate the fast navigation bar                                 |
//+---------------------------------------------------------------------+
bool CChartObj::SetQuickNavigationFlag(const string source,const bool flag,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_QUICK_NAVIGATION,flag))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_QUICK_NAVIGATION,flag);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the fixed scale flag                                         |
//+------------------------------------------------------------------+
bool CChartObj::SetScaleFixFlag(const string source,const bool flag,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_SCALEFIX,flag))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_SCALEFIX,flag);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the 1:1 scale flag                                           |
//+------------------------------------------------------------------+
bool CChartObj::SetScaleFix11Flag(const string source,const bool flag,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_SCALEFIX_11,flag))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_SCALEFIX_11,flag);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the flag of specifying a scale in points per bar             |
//+------------------------------------------------------------------+
bool CChartObj::SetScalePTPerBarFlag(const string source,const bool flag,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_SCALE_PT_PER_BAR,flag))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_SCALE_PT_PER_BAR,flag);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//|Set the flag displaying a symbol ticker in the upper left corner  |
//+------------------------------------------------------------------+
bool CChartObj::SetShowTickerFlag(const string source,const bool flag,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_SHOW_TICKER,flag))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_SHOW_TICKER,flag);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//|Set the flag displaying OHLC values in the upper left corner      |
//+------------------------------------------------------------------+
bool CChartObj::SetShowOHLCFlag(const string source,const bool flag,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_SHOW_OHLC,flag))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_SHOW_OHLC,flag);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the flag of displaying the Bid value                         |
//| using a horizontal line on the chart                             |
//+------------------------------------------------------------------+
bool CChartObj::SetShowBidLineFlag(const string source,const bool flag,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_SHOW_BID_LINE,flag))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_SHOW_BID_LINE,flag);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the flag of displaying the Ask value                         |
//| using a horizontal line on the chart                             |
//+------------------------------------------------------------------+
bool CChartObj::SetShowAskLineFlag(const string source,const bool flag,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_SHOW_ASK_LINE,flag))
     {
      CMessage::ToLog(source,::GetLastError(),flag);
      return false;
     }
   this.SetProperty(CHART_PROP_SHOW_ASK_LINE,flag);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the flag of displaying the Last value                        |
//| using a horizontal line on the chart                             |
//+------------------------------------------------------------------+
bool CChartObj::SetShowLastLineFlag(const string source,const bool flag,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_SHOW_LAST_LINE,flag))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_SHOW_LAST_LINE,flag);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the flag of displaying vertical separators                   |
//| between adjacent periods                                         |
//+------------------------------------------------------------------+
bool CChartObj::SetShowPeriodSeparatorsFlag(const string source,const bool flag,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_SHOW_PERIOD_SEP,flag))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_SHOW_PERIOD_SEP,flag);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the flag of displaying a grid on the chart                   |
//+------------------------------------------------------------------+
bool CChartObj::SetShowGridFlag(const string source,const bool flag,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_SHOW_GRID,flag))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_SHOW_GRID,flag);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the flag of displaying object text descriptions              |
//+------------------------------------------------------------------+
bool CChartObj::SetShowObjectDescriptionsFlag(const string source,const bool flag,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_SHOW_OBJECT_DESCR,flag))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_SHOW_OBJECT_DESCR,flag);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the flag of displaying trading levels on the chart           |
//+------------------------------------------------------------------+
bool CChartObj::SetShowTradeLevelsFlag(const string source,const bool flag,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_SHOW_TRADE_LEVELS,flag))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_SHOW_TRADE_LEVELS,flag);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the flag enabling dragging                                   |
//| trading levels on a chart using a mouse                          |
//+------------------------------------------------------------------+
bool CChartObj::SetDragTradeLevelsFlag(const string source,const bool flag,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_DRAG_TRADE_LEVELS,flag))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_DRAG_TRADE_LEVELS,flag);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the flag of displaying the time scale on the chart           |
//+------------------------------------------------------------------+
bool CChartObj::SetShowDateScaleFlag(const string source,const bool flag,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_SHOW_DATE_SCALE,flag))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_SHOW_DATE_SCALE,flag);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the flag of displaying the price scale on the chart          |
//+------------------------------------------------------------------+
bool CChartObj::SetShowPriceScaleFlag(const string source,const bool flag,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_SHOW_PRICE_SCALE,flag))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_SHOW_PRICE_SCALE,flag);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//|Set the flag of displaying the quick trading panel on the chart   |
//+------------------------------------------------------------------+
bool CChartObj::SetShowOneClickPanelFlag(const string source,const bool flag,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_SHOW_ONE_CLICK,flag))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_SHOW_ONE_CLICK,flag);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the flag of docking a chart window                           |
//+------------------------------------------------------------------+
bool CChartObj::SetDockedFlag(const string source,const bool flag,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_IS_DOCKED,flag))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_IS_DOCKED,flag);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+

Como podemos ver, todos esses métodos são idênticos aos anteriores, com exceção da propriedade mutável (marcada com cor no último método)

Três métodos privados para definir os modos de exibição do gráfico, escala e volumes no gráfico:

//+------------------------------------------------------------------+
//| Set the chart type                                               |
//+------------------------------------------------------------------+
bool CChartObj::SetMode(const string source,const ENUM_CHART_MODE mode,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_MODE,mode))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_MODE,mode);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the chart scale                                              |
//+------------------------------------------------------------------+
bool CChartObj::SetScale(const string source,const int scale,const bool redraw=false)
  {
   int value=(scale<0 ? 0 : scale>5 ? 5 : scale);
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_SCALE,value))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_SCALE,value);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the mode of displaying the volumes on a chart                |
//+------------------------------------------------------------------+
bool CChartObj::SetModeVolume(const string source,ENUM_CHART_VOLUME_MODE mode,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_SHOW_VOLUMES,mode))
     {
      CMessage::ToLog(source,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_SHOW_VOLUMES,mode);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+

Os métodos também são idênticos aos considerados acima, exceto para os parâmetros de entrada, para os que os modos necessários são passados em vez de sinalizadores, e no método para definir a escala do gráfico, adicionalmente são verificados os limites do valor de escala transmitido - de 0 a 5.

Os gráficos têm propriedades que não podem ser definidas - podem apenas ser obtidas. Mas para que o objeto do gráfico tenha os mesmos valores do gráfico, precisamos de métodos que nos permitam inserir os valores dos parâmetros do gráfico nas propriedades do objeto correspondente. Eles são definidos no momento da criação do objeto de gráfico, mas se forem alterados pelo terminal, precisaremos reagir a essa mudança e fazer as edições apropriadas nas propriedades do objeto-gráfico.
Para isso, são usados os seguintes métodos privados:

//+------------------------------------------------------------------+
//|  Set the property                                                |
//| "Number of bars on a chart that are available for display"       |
//+------------------------------------------------------------------+
void CChartObj::SetVisibleBars(void)
  {
   this.SetProperty(CHART_PROP_VISIBLE_BARS,::ChartGetInteger(this.ID(),CHART_VISIBLE_BARS));
  }
//+--------------------------------------------------------------------+
//|  Set the property                                                  |
//| "The total number of chart windows including indicator subwindows" |
//+--------------------------------------------------------------------+
void CChartObj::SetWindowsTotal(void)
  {
   this.SetProperty(CHART_PROP_WINDOWS_TOTAL,::ChartGetInteger(this.ID(),CHART_WINDOWS_TOTAL));
  }
//+---------------------------------------------------------------------+
//| Set the property "The number of the first visible bar on the chart" |
//+---------------------------------------------------------------------+
void CChartObj::SetFirstVisibleBars(void)
  {
   this.SetProperty(CHART_PROP_FIRST_VISIBLE_BAR,::ChartGetInteger(this.ID(),CHART_FIRST_VISIBLE_BAR));
  }
//+------------------------------------------------------------------+
//| Set the property "Width of the chart in bars"                    |
//+------------------------------------------------------------------+
void CChartObj::SetWidthInBars(void)
  {
   this.SetProperty(CHART_PROP_WIDTH_IN_BARS,::ChartGetInteger(this.ID(),CHART_WIDTH_IN_BARS));
  }
//+------------------------------------------------------------------+
//| Set the property "Width of the chart in pixels"                  |
//+------------------------------------------------------------------+
void CChartObj::SetWidthInPixels(void)
  {
   this.SetProperty(CHART_PROP_WIDTH_IN_PIXELS,::ChartGetInteger(this.ID(),CHART_WIDTH_IN_PIXELS));
  }
//+------------------------------------------------------------------+
//| Set the property "Chart window maximized"                        |
//+------------------------------------------------------------------+
void CChartObj::SetMaximizedFlag(void)
  {
   this.SetProperty(CHART_PROP_IS_MAXIMIZED,::ChartGetInteger(this.ID(),CHART_IS_MAXIMIZED));
  }
//+------------------------------------------------------------------+
//| Set the property "Chart window minimized"                        |
//+------------------------------------------------------------------+
void CChartObj::SetMinimizedFlag(void)
  {
   this.SetProperty(CHART_PROP_IS_MINIMIZED,::ChartGetInteger(this.ID(),CHART_IS_MINIMIZED));
  }
//+------------------------------------------------------------------+
//| Set the property "Name of an EA launched on the chart"           |
//+------------------------------------------------------------------+
void CChartObj::SetExpertName(void)
  {
   this.SetProperty(CHART_PROP_EXPERT_NAME,::ChartGetString(this.ID(),CHART_EXPERT_NAME));
  }
//+------------------------------------------------------------------+
//| Set the property "Name of a script launched on the chart"        |
//+------------------------------------------------------------------+
void CChartObj::SetScriptName(void)
  {
   this.SetProperty(CHART_PROP_SCRIPT_NAME,::ChartGetString(this.ID(),CHART_SCRIPT_NAME));
  }
//+------------------------------------------------------------------+

Somente aqui é registrado o parâmetro do gráfico na sua propriedade de objeto correspondente. A implementação do trabalho com esses métodos será feita em artigos futuros.

Agora precisamos adicionar métodos à seção pública da classe para acesso simplificado às propriedades do objeto-gráfico. Estes serão métodos para definir os parâmetros do gráfico no estado On/Off, a cor, o tamanho e outras funcionalidades necessárias para trabalhar com o gráfico.

Existem muitos métodos, vamos considerá-los em grupos.

Métodos para retornar/definir propriedades de valor On/Off:

//--- Constructors
                     CChartObj(){;}
                     CChartObj(const long chart_id);
//+------------------------------------------------------------------+ 
//| Methods of simplified access to chart object properties          |
//+------------------------------------------------------------------+
//--- (1) Return, (2) enable, (3) disable drawing a price chart 
   bool              IsShow(void)                                    const { return (bool)this.GetProperty(CHART_PROP_SHOW);              }
   bool              SetShowON(const bool redraw=false)                    { return this.SetShowFlag(DFUN,true,redraw);                   }
   bool              SetShowOFF(const bool redraw=false)                   { return this.SetShowFlag(DFUN,true,redraw);                   }
   
//--- (1) Return, (2) enable, (3) disable access to the context menu using the right click
   bool              IsAllowedContextMenu(void)                      const { return (bool)this.GetProperty(CHART_PROP_CONTEXT_MENU);      }
   bool              SetContextMenuON(const bool redraw=false)             { return this.SetContextMenuFlag(DFUN,true,redraw);            }
   bool              SetContextMenuOFF(const bool redraw=false)            { return this.SetContextMenuFlag(DFUN,false,redraw);           }
   
//--- (1) Return, (2) enable, (3) disable access to the Crosshair using the middle click
   bool              IsCrosshairTool(void)                           const { return (bool)this.GetProperty(CHART_PROP_CROSSHAIR_TOOL);    }
   bool              SetCrosshairToolON(const bool redraw=false);
   bool              SetCrosshairToolOFF(const bool redraw=false);
   
//--- (1) Return, (2) enable, (3) disable scrolling the chart horizontally using the left click
   bool              IsMouseScroll(void)                             const { return (bool)this.GetProperty(CHART_PROP_MOUSE_SCROLL);      }
   bool              SetMouseScrollON(const bool redraw=false)             { return this.SetMouseScrollFlag(DFUN,true,redraw);            }
   bool              SetMouseScrollOFF(const bool redraw=false)            { return this.SetMouseScrollFlag(DFUN,false,redraw);           }
   
//--- (1) Return, (2) enable, (3) disable sending messages about mouse wheel events to all MQL5 programs on a chart
   bool              IsEventMouseWhell(void)                         const { return (bool)this.GetProperty(CHART_PROP_EVENT_MOUSE_WHEEL); }
   bool              SetEventMouseWhellON(const bool redraw=false)         { return this.SetEventMouseWhellFlag(DFUN,true,redraw);        }
   bool              SetEventMouseWhellOFF(const bool redraw=false)        { return this.SetEventMouseWhellFlag(DFUN,false,redraw);       }
   
//--- (1) Return, (2) enable, (3) disable sending messages about mouse button movement and click events to all MQL5 programs on a chart
   bool              IsEventMouseMove(void)                          const { return (bool)this.GetProperty(CHART_PROP_EVENT_MOUSE_MOVE);  }
   bool              SetEventMouseMoveON(const bool redraw=false)          { return this.SetEventMouseMoveFlag(DFUN,true,redraw);         }
   bool              SetEventMouseMoveOFF(const bool redraw=false)         { return this.SetEventMouseMoveFlag(DFUN,false,redraw);        }
   
//--- (1) Return, (2) enable, (3) disable sending messages about the graphical object creation event to all MQL5 programs on a chart
   bool              IsEventObjectCreate(void)                       const { return (bool)this.GetProperty(CHART_PROP_EVENT_OBJECT_CREATE);}
   bool              SetEventObjectCreateON(const bool redraw=false)       { return this.SetEventObjectCreateFlag(DFUN,true,redraw);      }
   bool              SetEventObjectCreateOFF(const bool redraw=false)      { return this.SetEventObjectCreateFlag(DFUN,false,redraw);     }
   
//--- (1) Return, (2) enable, (3) disable sending messages about the graphical object destruction event to all MQL5 programs on a chart
   bool              IsEventObjectDelete(void)                       const { return (bool)this.GetProperty(CHART_PROP_EVENT_OBJECT_DELETE);}
   bool              SetEventObjectDeleteON(const bool redraw=false)       { return this.SetEventObjectDeleteFlag(DFUN,true,redraw);      }
   bool              SetEventObjectDeleteOFF(const bool redraw=false)      { return this.SetEventObjectDeleteFlag(DFUN,false,redraw);     }
   
//--- (1) Return, (2) enable, (3) disable price chart in the foreground
   bool              IsForeground(void)                              const { return (bool)this.GetProperty(CHART_PROP_FOREGROUND);        }
   bool              SetForegroundON(const bool redraw=false)              { return this.SetForegroundFlag(DFUN,true,redraw);             }
   bool              SetForegroundOFF(const bool redraw=false)             { return this.SetForegroundFlag(DFUN,false,redraw);            }
   
//--- (1) Return, (2) enable, (3) disable shift of the price chart from the right border
   bool              IsShift(void)                                   const { return (bool)this.GetProperty(CHART_PROP_SHIFT);             }
   bool              SetShiftON(const bool redraw=false)                   { return this.SetShiftFlag(DFUN,true,redraw);                  }
   bool              SetShiftOFF(const bool redraw=false)                  { return this.SetShiftFlag(DFUN,false,redraw);                 }
   
//--- (1) Return, (2) enable, (3) disable auto scroll to the right border of the chart
   bool              IsAutoscroll(void)                              const { return (bool)this.GetProperty(CHART_PROP_AUTOSCROLL);        }
   bool              SetAutoscrollON(const bool redraw=false)              { return this.SetAutoscrollFlag(DFUN,true,redraw);             }
   bool              SetAutoscrollOFF(const bool redraw=false)             { return this.SetAutoscrollFlag(DFUN,false,redraw);            }
   
//--- (1) Return, (2) enable, (3) disable the permission to manage the chart using a keyboard
   bool              IsKeyboardControl(void)                         const { return (bool)this.GetProperty(CHART_PROP_KEYBOARD_CONTROL);  }
   bool              SetKeyboardControlON(const bool redraw=false)         { return this.SetKeyboardControlFlag(DFUN,true,redraw);        }
   bool              SetKeyboardControlOFF(const bool redraw=false)        { return this.SetKeyboardControlFlag(DFUN,false,redraw);       }
   
//--- (1) Return, (2) enable, (3) disable the permission for the chart to intercept Space and Enter key strokes to activate the quick navigation bar
   bool              IsQuickNavigation(void)                         const { return (bool)this.GetProperty(CHART_PROP_QUICK_NAVIGATION);  }
   bool              SetQuickNavigationON(const bool redraw=false)         { return this.SetQuickNavigationFlag(DFUN,true,redraw);        }
   bool              SetQuickNavigationOFF(const bool redraw=false)        { return this.SetQuickNavigationFlag(DFUN,false,redraw);       }
   
//--- (1) Return, (2) enable, (3) disable a fixed scale
   bool              IsScaleFix(void)                                const { return (bool)this.GetProperty(CHART_PROP_SCALEFIX);          }
   bool              SetScaleFixON(const bool redraw=false)                { return this.SetScaleFixFlag(DFUN,true,redraw);               }
   bool              SetScaleFixOFF(const bool redraw=false)               { return this.SetScaleFixFlag(DFUN,false,redraw);              }
   
//--- (1) Return, (2) enable, (3) disable the 1:1 scale
   bool              IsScaleFix11(void)                              const { return (bool)this.GetProperty(CHART_PROP_SCALEFIX_11);       }
   bool              SetScaleFix11ON(const bool redraw=false)              { return this.SetScaleFix11Flag(DFUN,true,redraw);             }
   bool              SetScaleFix11OFF(const bool redraw=false)             { return this.SetScaleFix11Flag(DFUN,false,redraw);            }
   
//--- (1) Return, (2) enable, (3) disable the mode of specifying the chart scale in points per bar
   bool              IsScalePTPerBar(void)                           const { return (bool)this.GetProperty(CHART_PROP_SCALE_PT_PER_BAR);  }
   bool              SetScalePTPerBarON(const bool redraw=false)           { return this.SetScalePTPerBarFlag(DFUN,true,redraw);          }
   bool              SetScalePTPerBarOFF(const bool redraw=false)          { return this.SetScalePTPerBarFlag(DFUN,false,redraw);         }
   
//--- (1) Return, (2) enable, (3) disable a display of a symbol ticker in the upper left corner
   bool              IsShowTicker(void)                              const { return (bool)this.GetProperty(CHART_PROP_SHOW_TICKER);       }
   bool              SetShowTickerON(const bool redraw=false)              { return this.SetShowTickerFlag(DFUN,true,redraw);             }
   bool              SetShowTickerOFF(const bool redraw=false)             { return this.SetShowTickerFlag(DFUN,false,redraw);            }
   
//--- (1) Return, (2) enable, (3) disable a display of OHLC values in the upper left corner
   bool              IsShowOHLC(void)                                const { return (bool)this.GetProperty(CHART_PROP_SHOW_OHLC);         }
   bool              SetShowOHLCON(const bool redraw=false)                { return this.SetShowOHLCFlag(DFUN,true,redraw);               }
   bool              SetShowOHLCOFF(const bool redraw=false)               { return this.SetShowOHLCFlag(DFUN,false,redraw);              }
   
//--- (1) Return, (2) enable, (3) disable the display of a Bid value as a horizontal line on the chart
   bool              IsShowBidLine(void)                             const { return (bool)this.GetProperty(CHART_PROP_SHOW_BID_LINE);     }
   bool              SetShowBidLineON(const bool redraw=false)             { return this.SetShowBidLineFlag(DFUN,true,redraw);            }
   bool              SetShowBidLineOFF(const bool redraw=false)            { return this.SetShowBidLineFlag(DFUN,false,redraw);           }
   
//--- (1) Return, (2) enable, (3) disable the display of a Ask value as a horizontal line on the chart
   bool              IsShowAskLine(void)                             const { return (bool)this.GetProperty(CHART_PROP_SHOW_ASK_LINE);     }
   bool              SetShowAskLineON(const bool redraw=false)             { return this.SetShowAskLineFlag(DFUN,true,redraw);            }
   bool              SetShowAskLineOFF(const bool redraw=false)            { return this.SetShowAskLineFlag(DFUN,false,redraw);           }
   
//--- (1) Return, (2) enable, (3) disable the display of a Last value as a horizontal line on the chart
   bool              IsShowLastLine(void)                            const { return (bool)this.GetProperty(CHART_PROP_SHOW_LAST_LINE);    }
   bool              SetShowLastLineON(const bool redraw=false)            { return this.SetShowLastLineFlag(DFUN,true,redraw);           }
   bool              SetShowLastLineOFF(const bool redraw=false)           { return this.SetShowLastLineFlag(DFUN,false,redraw);          }
   
//--- (1) Return, (2) enable, (3) disable the display of vertical separators between adjacent periods
   bool              IsShowPeriodSeparators(void)                    const { return (bool)this.GetProperty(CHART_PROP_SHOW_PERIOD_SEP);   }
   bool              SetShowPeriodSeparatorsON(const bool redraw=false)    { return this.SetShowPeriodSeparatorsFlag(DFUN,true,redraw);   }
   bool              SetShowPeriodSeparatorsOFF(const bool redraw=false)   { return this.SetShowPeriodSeparatorsFlag(DFUN,false,redraw);  }
   
//--- (1) Return, (2) enable, (3) disable the display of the chart grid
   bool              IsShowGrid(void)                                const { return (bool)this.GetProperty(CHART_PROP_SHOW_GRID);         }
   bool              SetShowGridON(const bool redraw=false)                { return this.SetShowGridFlag(DFUN,true,redraw);               }
   bool              SetShowGridOFF(const bool redraw=false)               { return this.SetShowGridFlag(DFUN,false,redraw);              }
   
//--- (1) Return, (2) enable, (3) disable the display of text descriptions of objects
   bool              IsShowObjectDescriptions(void)   const { return (bool)this.GetProperty(CHART_PROP_SHOW_OBJECT_DESCR);                }
   bool              SetShowObjectDescriptionsON(const bool redraw=false);
   bool              SetShowObjectDescriptionsOFF(const bool redraw=false);
 
//--- (1) Return, (2) enable, (3) disable the display of trade levels on the chart (levels of open positions, Stop Loss, Take Profit and pending orders)
   bool              IsShowTradeLevels(void)                         const { return (bool)this.GetProperty(CHART_PROP_SHOW_TRADE_LEVELS); }
   bool              SetShowTradeLevelsON(const bool redraw=false)         { return this.SetShowTradeLevelsFlag(DFUN,true,redraw);        }
   bool              SetShowTradeLevelsOFF(const bool redraw=false)        { return this.SetShowTradeLevelsFlag(DFUN,false,redraw);       }
   
//--- (1) Return, (2) enable, (3) disable the ability to drag trading levels on a chart using mouse
   bool              IsDragTradeLevels(void)                         const { return (bool)this.GetProperty(CHART_PROP_DRAG_TRADE_LEVELS); }
   bool              SetDragTradeLevelsON(const bool redraw=false)         { return this.SetDragTradeLevelsFlag(DFUN,true,redraw);        }
   bool              SetDragTradeLevelsOFF(const bool redraw=false)        { return this.SetDragTradeLevelsFlag(DFUN,false,redraw);       }
   
//--- (1) Return, (2) enable, (3) disable the display of the time scale on the chart
   bool              IsShowDateScale(void)                           const { return (bool)this.GetProperty(CHART_PROP_SHOW_DATE_SCALE);   }
   bool              SetShowDateScaleON(const bool redraw=false)           { return this.SetShowDateScaleFlag(DFUN,true,redraw);          }
   bool              SetShowDateScaleOFF(const bool redraw=false)          { return this.SetShowDateScaleFlag(DFUN,false,redraw);         }
   
//--- (1) Return, (2) enable, (3) disable the display of the price scale on the chart
   bool              IsShowPriceScale(void)                          const { return (bool)this.GetProperty(CHART_PROP_SHOW_PRICE_SCALE);  }
   bool              SetShowPriceScaleON(const bool redraw=false)          { return this.SetShowPriceScaleFlag(DFUN,true,redraw);         }
   bool              SetShowPriceScaleOFF(const bool redraw=false)         { return this.SetShowPriceScaleFlag(DFUN,false,redraw);        }
   
//--- (1) Return, (2) enable, (3) disable the display of the quick trading panel on the chart
   bool              IsShowOneClickPanel(void)                       const { return (bool)this.GetProperty(CHART_PROP_SHOW_ONE_CLICK);    }
   bool              SetShowOneClickPanelON(const bool redraw=false)       { return this.SetShowOneClickPanelFlag(DFUN,true,redraw);      }
   bool              SetShowOneClickPanelOFF(const bool redraw=false)      { return this.SetShowOneClickPanelFlag(DFUN,false,redraw);     }
   
//--- (1) Return, (2) enable, (3) disable docking the chart window
   bool              IsDocked(void)                                  const { return (bool)this.GetProperty(CHART_PROP_IS_DOCKED);         }
   bool              SetDockedON(const bool redraw=false)                  { return this.SetDockedFlag(DFUN,true,redraw); }
   bool              SetDockedOFF(const bool redraw=false)                 { return this.SetDockedFlag(DFUN,false,redraw); }
   
//--- (1) Enable and (2) disable the display of the chart above all others
   bool              SetBringToTopON(const bool redraw=false)              { return this.SetBringToTopFlag(DFUN,true,redraw);             }
   bool              SetBringToTopOFF(const bool redraw=false)             { return this.SetBringToTopFlag(DFUN,false,redraw);            }
   

Todos os métodos de sinalização são idênticos e retornam a saída dos métodos de sinalização privados correspondentes discutidos acima. Os métodos de retorno de propriedade retornam o valor escrito na propriedade correspondente do objeto. Os dois últimos métodos apenas definem sinalizadores, já que não há como retornar a propriedade do gráfico "Acima de todos os outros" usando a função ChartGetInteger() com o identificador CHART_BRING_TO_TOP - esta é uma propriedade do gráfico apenas para escrever valores.

Métodos de configuração/retorno de modos de exibição de gráfico, escala do gráfico e volumes no gráfico:

//--- (1) Return, set the chart type (2) bars, (3) candles, (4) line 
   ENUM_CHART_MODE   Mode(void)                                      const { return (ENUM_CHART_MODE)this.GetProperty(CHART_PROP_MODE);   }
   bool              SetModeBars(const bool redraw=false)                  { return this.SetMode(DFUN,CHART_BARS,redraw);                 }
   bool              SetModeCandles(const bool redraw=false)               { return this.SetMode(DFUN,CHART_CANDLES,redraw);              }
   bool              SetModeLine(const bool redraw=false)                  { return this.SetMode(DFUN,CHART_LINE,redraw);                 }

//--- (1) Return, (2 - 7) set the chart scale
   int               Scale(void)                                     const { return (int)this.GetProperty(CHART_PROP_SCALE);              }
   bool              SetScale0(const bool redraw=false)                    { return this.SetScale(DFUN,0,redraw);                         }
   bool              SetScale1(const bool redraw=false)                    { return this.SetScale(DFUN,1,redraw);                         }
   bool              SetScale2(const bool redraw=false)                    { return this.SetScale(DFUN,2,redraw);                         }
   bool              SetScale3(const bool redraw=false)                    { return this.SetScale(DFUN,3,redraw);                         }
   bool              SetScale4(const bool redraw=false)                    { return this.SetScale(DFUN,4,redraw);                         }
   bool              SetScale5(const bool redraw=false)                    { return this.SetScale(DFUN,5,redraw);                         }
   
//--- (1) Return, set the volume display modes (2) disabled, (3) tick volumes, (4) real volumes 
   ENUM_CHART_VOLUME_MODE  ModeVolume(void)                          const { return (ENUM_CHART_VOLUME_MODE)this.GetProperty(CHART_PROP_SHOW_VOLUMES);}
   bool              SetModeVolumeHide(const bool redraw=false)            { return this.SetModeVolume(DFUN,CHART_VOLUME_HIDE,redraw);    }
   bool              SetModeVolumeTick(const bool redraw=false)            { return this.SetModeVolume(DFUN,CHART_VOLUME_TICK,redraw);    }
   bool              SetModeVolumeReal(const bool redraw=false)            { return this.SetModeVolume(DFUN,CHART_VOLUME_REAL,redraw);    }

Aqui, os métodos de retorno para valores de propriedade são idênticos aos métodos de retorno para sinalizadores - é retornado valor definido na propriedade correspondente do objeto. Os métodos de definição de valores retornam o resultado do funcionamento dos métodos privados com o valor especificado que deve ser definido para a propriedade do objeto e do gráfico.

Métodos para retornar e definir cores de exibição de vários elementos do gráfico e outros parâmetros do gráfico alteráveis:

//--- Return, (2) set the chart background color
   color             ColorBackground(void)                           const { return (color)this.GetProperty(CHART_PROP_COLOR_BACKGROUND); }
   bool              SetColorBackground(const color colour,const bool redraw=false);
   
//--- (1) Return, (2) set the color of axes, scale and OHLC line
   color             ColorForeground(void)                           const { return (color)this.GetProperty(CHART_PROP_COLOR_FOREGROUND); }
   bool              SetColorForeground(const color colour,const bool redraw=false);
   
//--- (1) Return and (2) set the grid color
   color             ColorGrid(void)                                 const { return (color)this.GetProperty(CHART_PROP_COLOR_GRID);       }
   bool              SetColorGrid(const color colour,const bool redraw=false);
   
//--- (1) Return and (2) set the volume color and position opening levels
   color             ColorVolume(void)                               const { return (color)this.GetProperty(CHART_PROP_COLOR_VOLUME);     }
   bool              SetColorVolume(const color colour,const bool redraw=false);
   
//--- (1) Return and (2) set the color of up bar, its shadow and border of bullish candle body
   color             ColorUp(void)                                   const { return (color)this.GetProperty(CHART_PROP_COLOR_CHART_UP);   }
   bool              SetColorUp(const color colour,const bool redraw=false);
   
//--- (1) Return and (2) set the color of down bar, its shadow and border of bearish candle body
   color             ColorDown(void)                                 const { return (color)this.GetProperty(CHART_PROP_COLOR_CHART_DOWN); }
   bool              SetColorDown(const color colour,const bool redraw=false);
   
//--- (1) Return and (2) set the color of the chart line and Doji candles
   color             ColorLine(void)                                 const { return (color)this.GetProperty(CHART_PROP_COLOR_CHART_LINE); }
   bool              SetColorLine(const color colour,const bool redraw=false);
   
//--- (1) Return and (2) set the color of the bullish candle body
   color             ColorCandleBull(void)                           const { return (color)this.GetProperty(CHART_PROP_COLOR_CANDLE_BULL);}
   bool              SetColorCandleBull(const color colour,const bool redraw=false);
   
//--- (1) Return and (2) set the color of the bearish candle body
   color             ColorCandleBear(void)                           const { return (color)this.GetProperty(CHART_PROP_COLOR_CANDLE_BEAR);}
   bool              SetColorCandleBear(const color colour,const bool redraw=false);
   
//--- (1) Return and (2) set the Bid price line color
   color             ColorBid(void)                                  const { return (color)this.GetProperty(CHART_PROP_COLOR_BID);        }
   bool              SetColorBid(const color colour,const bool redraw=false);
   
//--- (1) Return and (2) set the Ask price line color
   color             ColorAsk(void)                                  const { return (color)this.GetProperty(CHART_PROP_COLOR_ASK);        }
   bool              SetColorAsk(const color colour,const bool redraw=false);
   
//--- (1) Return and (2) set the color of the price line of the last performed deal (Last)
   color             ColorLast(void)                                 const { return (color)this.GetProperty(CHART_PROP_COLOR_LAST);       }
   bool              SetColorLast(const color colour,const bool redraw=false);
   
//--- (1) Return and (2) set the color of stop order levels (Stop Loss and Take Profit)
   color             ColorStops(void)                                const { return (color)this.GetProperty(CHART_PROP_COLOR_STOP_LEVEL); }
   bool              SetColorStops(const color colour,const bool redraw=false);
   
//--- (1) Return and (2) set the left coordinate of the undocked chart window relative to the virtual screen
   int               FloatLeft(void)                                 const { return (int)this.GetProperty(CHART_PROP_FLOAT_LEFT);         }
   bool              SetFloatLeft(const int value,const bool redraw=false);
   
//--- (1) Return and (2) set the top coordinate of the undocked chart window relative to the virtual screen
   int               FloatTop(void)                                  const { return (int)this.GetProperty(CHART_PROP_FLOAT_TOP);          }
   bool              SetFloatTop(const int value,const bool redraw=false);
   
//--- (1) Return and (2) set the right coordinate of the undocked chart window relative to the virtual screen
   int               FloatRight(void)                                const { return (int)this.GetProperty(CHART_PROP_FLOAT_RIGHT);        }
   bool              SetFloatRight(const int value,const bool redraw=false);
   
//--- (1) Return and (2) set the bottom coordinate of the undocked chart window relative to the virtual screen
   int               FloatBottom(void)                               const { return (int)this.GetProperty(CHART_PROP_FLOAT_BOTTOM);       }
   bool              SetFloatBottom(const int value,const bool redraw=false);
   
//--- (1) Return and (2) set the shift size of the zero bar from the right border in %
   double            ShiftSize(void)                                 const { return this.GetProperty(CHART_PROP_SHIFT_SIZE);              }
   bool              SetShiftSize(const double value,const bool redraw=false);
   
//--- (1) Return and (2) set the chart fixed position from the left border in %
   double            FixedPosition(void)                             const { return this.GetProperty(CHART_PROP_FIXED_POSITION);          }
   bool              SetFixedPosition(const double value,const bool redraw=false);
   
//--- (1) Return and (2) set the fixed chart maximum
   double            FixedMaximum(void)                              const { return this.GetProperty(CHART_PROP_FIXED_MAX);               }
   bool              SetFixedMaximum(const double value,const bool redraw=false);
   
//--- (1) Return and (2) set the fixed chart minimum
   double            FixedMinimum(void)                              const { return this.GetProperty(CHART_PROP_FIXED_MIN);               }
   bool              SetFixedMinimum(const double value,const bool redraw=false);
   
//--- (1) Return and (2) set the value of the scale in points per bar
   double            PointsPerBar(void)                              const { return this.GetProperty(CHART_PROP_POINTS_PER_BAR);          }
   bool              SetPointsPerBar(const double value,const bool redraw=false);
  
//--- (1) Return and (2) set the comment on the chart
   string            Comment(void)                                   const { return this.GetProperty(CHART_PROP_COMMENT);                 }
   bool              SetComment(const string comment,const bool redraw=false);
   
//--- (1) Return and (2) set the chart symbol
   string            Symbol(void)                                    const { return this.GetProperty(CHART_PROP_SYMBOL);                  }
   bool              SetSymbol(const string symbol);
   
//--- (1) Return and (2) set the chart period
   ENUM_TIMEFRAMES   Timeframe(void)                                 const { return (ENUM_TIMEFRAMES)this.GetProperty(CHART_PROP_TIMEFRAME); }
   bool              SetTimeframe(const ENUM_TIMEFRAMES timeframe);

Os métodos de retorno de valores de propriedade retornam os valores escritos na propriedade correspondente do objeto, e os métodos de definição são declarados apenas aqui, e veremos sua implementação mais tarde.

Métodos que retornam as propriedades do objeto-gráfico correspondente aos parâmetros de gráfico somente para leitura:

//--- (1) Return the Chart object identification attribute
   bool              IsObject(void)                                  const { return (bool)this.GetProperty(CHART_PROP_IS_OBJECT);         }

//--- Return the chart ID
   long              ID(void)                                        const { return this.GetProperty(CHART_PROP_ID);                      }

//--- Return the number of bars on a chart that are available for display
   int               VisibleBars(void)                               const { return (int)this.GetProperty(CHART_PROP_VISIBLE_BARS);       }

//--- Return the total number of chart windows including indicator subwindows
   int               WindowsTotal(void)                              const { return (int)this.GetProperty(CHART_PROP_WINDOWS_TOTAL);      }

//--- Return the chart window handle
   int               Handle(void)                                    const { return (int)this.GetProperty(CHART_PROP_WINDOW_HANDLE);      } 

//--- Return the number of the first visible bar on the chart
   int               FirstVisibleBars(void)                          const { return (int)this.GetProperty(CHART_PROP_FIRST_VISIBLE_BAR);  }

//--- Return the chart width in bars
   int               WidthInBars(void)                               const { return (int)this.GetProperty(CHART_PROP_WIDTH_IN_BARS);      }

//--- Return the chart width in pixels
   int               WidthInPixels(void)                             const { return (int)this.GetProperty(CHART_PROP_WIDTH_IN_PIXELS);    }

//--- Return the "Chart window maximized" property
   bool              IsMaximized(void)                               const { return (bool)this.GetProperty(CHART_PROP_IS_MAXIMIZED);      }

//--- Return the "Chart window minimized" property
   bool              IsMinimized(void)                               const { return (bool)this.GetProperty(CHART_PROP_IS_MINIMIZED);      }

//--- Return the name of an EA launched on the chart
   string            ExpertName(void)                                const { return this.GetProperty(CHART_PROP_EXPERT_NAME);             }

//--- Return the name of a script launched on the chart
   string            ScriptName(void)                                const { return this.GetProperty(CHART_PROP_SCRIPT_NAME);             }

Os métodos retornam o valor escrito na propriedade correspondente do objeto-gráfico.

Métodos que retornam/definem os valores dos parâmetros do gráfico, para os quais o número da subjanela deve ser especificado:

//--- (1) Return and (2) set the height of the specified chart in pixels
   int               WindowHeightInPixels(const int sub_window)      const { return (int)::ChartGetInteger(this.ID(),CHART_HEIGHT_IN_PIXELS,sub_window);       }
   bool              SetWindowHeightInPixels(const int height,const int sub_window,const bool redraw=false);
   
//--- Return the distance in Y axis pixels between the upper frame of the indicator subwindow and the upper frame of the chart main window
   int               WindowYDistance(const int sub_window)           const { return (int)::ChartGetInteger(this.ID(),CHART_WINDOW_YDISTANCE,sub_window);       }
   
//--- Return the specified subwindow visibility
   bool              IsVisibleWindow(const int sub_window)           const { return (bool)::ChartGetInteger(this.Handle(),CHART_WINDOW_IS_VISIBLE,sub_window); }
   
//--- Return the minimum of the specified chart
   double            PriceMinimum(const int sub_window)              const { return ::ChartGetDouble(this.ID(),CHART_PRICE_MIN,sub_window);  }

//--- Return the maximum of the specified chart
   double            PriceMaximum(const int sub_window)              const { return ::ChartGetDouble(this.ID(),CHART_PRICE_MAX,sub_window);  }

Esses métodos ainda estão aqui temporariamente, pois mais tarde no objeto de gráfico haverá uma lista de subjanelas de indicadores pertencentes ao gráfico, cujos números devem ser especificados nas funções de configuração/retorno de valores, e esses métodos serão retrabalhados. Portanto, os valores são retornados não das propriedades do objeto, mas diretamente do gráfico, que é descrito por este objeto-gráfico.

Método para emular um tick:

//--- Emulate a tick (chart updates - similar to the terminal Refresh command)
   void              EmulateTick(void)                                     { ::ChartSetSymbolPeriod(this.ID(),this.Symbol(),this.Timeframe());}

  };
//+------------------------------------------------------------------+
//| Parametric constructor                                           |
//+------------------------------------------------------------------+

Chamada de função ChartSetSymbolPeriod() indicando o mesmo símbolo e período do gráfico atual pode ser usada para atualizar o gráfico (semelhante ao comando Refresh no terminal). A atualização do gráfico, por sua vez, inicia o recálculo dos indicadores a ele anexados. Assim, é possível calcular o indicador no gráfico mesmo na ausência de ticks (por exemplo, nos finais de semana).

Fora do corpo da classe, escreveremos a implementação dos métodos declarados no bloco de métodos para acesso simplificado às propriedades do objeto.

Métodos para definir a cor dos elementos do gráfico e outros parâmetros personalizados:

//+------------------------------------------------------------------+
//| Set the chart background color                                   |
//+------------------------------------------------------------------+
bool CChartObj::SetColorBackground(const color colour,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_COLOR_BACKGROUND,colour))
     {
      CMessage::ToLog(DFUN,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_COLOR_BACKGROUND,colour);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the color of axes, scale and OHLC line                       |
//+------------------------------------------------------------------+
bool CChartObj::SetColorForeground(const color colour,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_COLOR_FOREGROUND,colour))
     {
      CMessage::ToLog(DFUN,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_COLOR_FOREGROUND,colour);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the grid color                                               |
//+------------------------------------------------------------------+
bool CChartObj::SetColorGrid(const color colour,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_COLOR_GRID,colour))
     {
      CMessage::ToLog(DFUN,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_COLOR_GRID,colour);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the volume color and position opening levels                 |
//+------------------------------------------------------------------+
bool CChartObj::SetColorVolume(const color colour,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_COLOR_VOLUME,colour))
     {
      CMessage::ToLog(DFUN,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_COLOR_VOLUME,colour);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+----------------------------------------------------------------------+
//|Set the color of up bar, its shadow and border of bullish candle body |
//+----------------------------------------------------------------------+
bool CChartObj::SetColorUp(const color colour,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_COLOR_CHART_UP,colour))
     {
      CMessage::ToLog(DFUN,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_COLOR_CHART_UP,colour);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+-----------------------------------------------------------------------+
//|Set the color of down bar, its shadow and border of bearish candle body|
//+-----------------------------------------------------------------------+
bool CChartObj::SetColorDown(const color colour,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_COLOR_CHART_DOWN,colour))
     {
      CMessage::ToLog(DFUN,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_COLOR_CHART_DOWN,colour);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the color of the chart line and Doji candles                 |
//+------------------------------------------------------------------+
bool CChartObj::SetColorLine(const color colour,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_COLOR_CHART_LINE,colour))
     {
      CMessage::ToLog(DFUN,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_COLOR_CHART_LINE,colour);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the color of bullish candle body                             |
//+------------------------------------------------------------------+
bool CChartObj::SetColorCandleBull(const color colour,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_COLOR_CANDLE_BULL,colour))
     {
      CMessage::ToLog(DFUN,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_COLOR_CANDLE_BULL,colour);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the color of bearish candle body                             |
//+------------------------------------------------------------------+
bool CChartObj::SetColorCandleBear(const color colour,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_COLOR_CANDLE_BEAR,colour))
     {
      CMessage::ToLog(DFUN,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_COLOR_CANDLE_BEAR,colour);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the Bid price line color                                     |
//+------------------------------------------------------------------+
bool CChartObj::SetColorBid(const color colour,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_COLOR_BID,colour))
     {
      CMessage::ToLog(DFUN,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_COLOR_BID,colour);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the Ask price line color                                     |
//+------------------------------------------------------------------+
bool CChartObj::SetColorAsk(const color colour,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_COLOR_ASK,colour))
     {
      CMessage::ToLog(DFUN,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_COLOR_ASK,colour);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//|Set the color of the price line of the last performed deal (Last) |
//+------------------------------------------------------------------+
bool CChartObj::SetColorLast(const color colour,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_COLOR_LAST,colour))
     {
      CMessage::ToLog(DFUN,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_COLOR_LAST,colour);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//|Set the color of stop order levels (Stop Loss and Take Profit)    |
//+------------------------------------------------------------------+
bool CChartObj::SetColorStops(const color colour,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_COLOR_STOP_LEVEL,colour))
     {
      CMessage::ToLog(DFUN,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_COLOR_STOP_LEVEL,colour);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the left coordinate of the undocked chart                    |
//| relative to the virtual screen                                   |
//+------------------------------------------------------------------+
bool CChartObj::SetFloatLeft(const int value,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_FLOAT_LEFT,value))
     {
      CMessage::ToLog(DFUN,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_FLOAT_LEFT,value);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the top coordinate of the undocked chart                     |
//| relative to the virtual screen                                   |
//+------------------------------------------------------------------+
bool CChartObj::SetFloatTop(const int value,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_FLOAT_TOP,value))
     {
      CMessage::ToLog(DFUN,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_FLOAT_TOP,value);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the right coordinate of the undocked chart                   |
//| relative to the virtual screen                                   |
//+------------------------------------------------------------------+
bool CChartObj::SetFloatRight(const int value,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_FLOAT_RIGHT,value))
     {
      CMessage::ToLog(DFUN,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_FLOAT_RIGHT,value);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the bottom coordinate of the undocked chart                  |
//| relative to the virtual screen                                   |
//+------------------------------------------------------------------+
bool CChartObj::SetFloatBottom(const int value,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_FLOAT_BOTTOM,value))
     {
      CMessage::ToLog(DFUN,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_FLOAT_BOTTOM,value);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Sets the value of zeroth bar shift                               |
//| from the right edge in %                                         |
//+------------------------------------------------------------------+
bool CChartObj::SetShiftSize(const double value,const bool redraw=false)
  {
   double size=(value<10.0 ? 10.0 : value>50.0 ? 50.0 : value);
   ::ResetLastError();
   if(!::ChartSetDouble(this.ID(),CHART_SHIFT_SIZE,size))
     {
      CMessage::ToLog(DFUN,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_SHIFT_SIZE,size);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the location of the chart fixed position                     |
//| from the left edge in %                                          |
//+------------------------------------------------------------------+
bool CChartObj::SetFixedPosition(const double value,const bool redraw=false)
  {
   double pos=(value<0 ? 0 : value>100.0 ? 100.0 : value);
   ::ResetLastError();
   if(!::ChartSetDouble(this.ID(),CHART_FIXED_POSITION,pos))
     {
      CMessage::ToLog(DFUN,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_FIXED_POSITION,pos);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the fixed chart maximum                                      |
//+------------------------------------------------------------------+
bool CChartObj::SetFixedMaximum(const double value,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetDouble(this.ID(),CHART_FIXED_MAX,value))
     {
      CMessage::ToLog(DFUN,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_FIXED_MAX,value);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the fixed chart minimum                                      |
//+------------------------------------------------------------------+
bool CChartObj::SetFixedMinimum(const double value,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetDouble(this.ID(),CHART_FIXED_MIN,value))
     {
      CMessage::ToLog(DFUN,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_FIXED_MIN,value);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the value of the scale in points per bar                     |
//+------------------------------------------------------------------+
bool CChartObj::SetPointsPerBar(const double value,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetDouble(this.ID(),CHART_POINTS_PER_BAR,value))
     {
      CMessage::ToLog(DFUN,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_POINTS_PER_BAR,value);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the comment on the chart                                     |
//+------------------------------------------------------------------+
bool CChartObj::SetComment(const string comment,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetString(this.ID(),CHART_COMMENT,comment))
     {
      CMessage::ToLog(DFUN,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_COMMENT,comment);
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the height of the specified chart in pixels                  |
//+------------------------------------------------------------------+
bool CChartObj::SetWindowHeightInPixels(const int height,const int sub_window,const bool redraw=false)
  {
   ::ResetLastError();
   if(!::ChartSetInteger(this.ID(),CHART_HEIGHT_IN_PIXELS,sub_window,height))
     {
      CMessage::ToLog(DFUN,::GetLastError(),true);
      return false;
     }
   if(redraw)
      ::ChartRedraw(this.ID());
   return true;
  }
//+------------------------------------------------------------------+
//| Set the chart symbol                                             |
//+------------------------------------------------------------------+
bool CChartObj::SetSymbol(const string symbol)
  {
   ::ResetLastError();
   if(!::ChartSetSymbolPeriod(this.ID(),symbol,this.Timeframe()))
     {
      CMessage::ToLog(DFUN,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_SYMBOL,symbol);
   this.m_digits=(int)::SymbolInfoInteger(this.Symbol(),SYMBOL_DIGITS);
   return true;
  }
//+------------------------------------------------------------------+
//| Set the chart period                                             |
//+------------------------------------------------------------------+
bool CChartObj::SetTimeframe(const ENUM_TIMEFRAMES timeframe)
  {
   ::ResetLastError();
   if(!::ChartSetSymbolPeriod(this.ID(),this.Symbol(),timeframe))
     {
      CMessage::ToLog(DFUN,::GetLastError(),true);
      return false;
     }
   this.SetProperty(CHART_PROP_TIMEFRAME,timeframe);
   return true;
  }
//+------------------------------------------------------------------+

Os métodos são idênticos aos métodos privados acima e têm a mesma lógica, portanto, vamos deixá-los para um estudo independente. De qualquer forma, na discussão do artigo podem ser feitas todas as perguntas.

Assim concluímos a criação do objeto-gráfico. Sua lista completa pode ser encontrada nos arquivos da biblioteca anexados ao artigo.


Teste

Para testar, vamos pegar o Expert Advisor do artigo anterior
e o salvamos na nova pasta \MQL5\Experts\TestDoEasy\Part67\ com o novo nome TestDoEasyPart67.mq5.

Faremos isso... Vamos abrir três gráficos de instrumentos diferentes, ou seja, no primeiro será executado o Expert Advisor, e os outros dois serão simplesmente abertos. Ao iniciar pela primeira vez, o EA irá ler todos os gráficos, criar objetos gráficos correspondentes, adicioná-los à lista criada temporariamente para teste e, em seguida, ler a lista criada e exibir breves descrições dos objetos-gráficos localizados nela. Para o primeiro gráfico - no qual o Expert Advisor opera - exibiremos uma descrição completa do objeto-gráfico.

Visto que as classes de sinais agora estão conectadas através do objeto principal da biblioteca CEngine, então

em vez da string de conexão da classe do objeto-sinal-mql5

//|                                             TestDoEasyPart66.mq5 |
//|                        Copyright 2021, MetaQuotes Software Corp. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Software Corp."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
//--- includes
#include <DoEasy\Engine.mqh>
#include <DoEasy\Objects\MQLSignalBase\MQLSignal.mqh>
//--- enums

anexamos o arquivo de classe do objeto-gráfico:

//|                                             TestDoEasyPart67.mq5 |
//|                        Copyright 2021, MetaQuotes Software Corp. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Software Corp."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
//--- includes
#include <DoEasy\Engine.mqh>
#include <DoEasy\Objects\Chart\ChartObj.mqh>
//--- enums

No manipulador OnTick()em vez de um bloco de código para trabalhar com sinais

//--- Search for available signals in the database and check the ability to subscribe to a signal by its name
   static bool done=false;
   //--- If the first launch and working with signals is enabled in EA custom settings
   if(InpUseMqlSignals && !done)
     {
      //--- Display the list of all free signals in the journal
      Print("");
      engine.GetSignalsMQL5Collection().PrintShort(true,false,true);
      //--- Get the list of free signals
      CArrayObj *list=engine.GetListSignalsMQL5Free();
      //--- If the list is obtained
      if(list!=NULL)
        {
         //--- Find a signal with the maximum growth in % in the list
         int index_max_gain=CSelect::FindMQLSignalMax(list,SIGNAL_MQL5_PROP_GAIN);
         CMQLSignal *signal_max_gain=list.At(index_max_gain);
         //--- If the signal is found
         if(signal_max_gain!=NULL)
           {
            //--- Display the full signal description in the journal
            signal_max_gain.Print();
            //--- If managed to subscribe to a signal
            if(engine.SignalsMQL5Subscribe(signal_max_gain.ID()))
              {
               //--- Set subscription parameters
               //--- Enable copying deals by subscription
               engine.SignalsMQL5CurrentSetSubscriptionEnableON();
               //--- Set synchronization without the confirmation dialog
               engine.SignalsMQL5CurrentSetConfirmationsDisableOFF();
               //--- Set copying Stop Loss and Take Profit
               engine.SignalsMQL5CurrentSetSLTPCopyON();
               //--- Set the market order slippage used when synchronizing positions and copying deals
               engine.SignalsMQL5CurrentSetSlippage(2);
               //--- Set the percentage for converting deal volume
               engine.SignalsMQL5CurrentSetEquityLimit(50);
               //--- Set deposit limitations (in %)
               engine.SignalsMQL5CurrentSetDepositPercent(70);
               //--- Display subscription parameters in the journal
               engine.SignalsMQL5CurrentSubscriptionParameters();
              }
           }
        }
      done=true;
      return;
     }
   //--- If a signal subscription is active,  unsubscribe
   if(engine.SignalsMQL5CurrentID()>0)
     {
      engine.SignalsMQL5Unsubscribe();
     }
//---

escrevemos um bloco de código para trabalhar com objetos-gráficos:

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- Handle the NewTick event in the library
   engine.OnTick(rates_data);

//--- If working in the tester
   if(MQLInfoInteger(MQL_TESTER))
     {
      engine.OnTimer(rates_data);   // Working in the timer
      PressButtonsControl();        // Button pressing control
      engine.EventsHandling();      // Working with events
     }

//--- If the trailing flag is set
   if(trailing_on)
     {
      TrailingPositions();          // Trailing positions
      TrailingOrders();             // Trailing pending orders
     }
   
//--- If it is the first launch
   static bool done=false;
   if(!done)
     {
      //--- Create the list object for storing chart objects
      CArrayObj *list=new CArrayObj();
      if(list==NULL)
         return;
      //--- Declare the variables and get the first chart ID
      long currChart,prevChart=ChartFirst(); 
      int i=0; 
      //--- Create the chart object and add it to the list
      CChartObj *chart_first=new CChartObj(prevChart);
      list.Add(chart_first);
      //--- In the loop by the total number of terminal charts (not more than 100)
      while(i<CHARTS_MAX)
        { 
         //--- based on the previous one, get the new chart
         currChart=ChartNext(prevChart);
         //--- When reaching the end of the chart list, complete the loop
         if(currChart<0) break;
         //--- Create the chart object based on the current chart ID in the loop and add it to the list
         CChartObj *chart=new CChartObj(currChart);
         list.Add(chart);
         //--- remember the current chart ID for ChartNext() and increase the loop counter
         prevChart=currChart;
         i++;
        }
      Print("");
      //--- From the filled list in the loop, receive the next chart object and display its short description
      int total=list.Total();
      for(int j=0;j<total;j++)
        {
         CChartObj *chart_obj=list.At(j);
         chart_obj.PrintShort();
        }
      Print("");
      //--- Display the full description of the very first chart
      chart_first=list.At(0);
      chart_first.Print();
      //--- Destroy the list of chart objects
      delete list;
      done=true;
     }
//---
  }
//+------------------------------------------------------------------+

Toda a lógica é detalhada no código e não precisa de explicações adicionais. Em qualquer caso, todas as perguntas podem ser feitas na discussão do artigo.

Isso é tudo que queríamos fazer hoje.

Vamos compilar o Expert Advisor, abrir três gráficos no terminal e iniciar o Expert Advisor no primeiro deles, tendo especificado anteriormente nos parâmetros "trabalhar apenas com o símbolo atual e período gráfico":


Quando aparece o primeiro tick, o EA irá criar três objetos-gráficos e exibir no log, além de mensagens sobre a inicialização de várias classes da biblioteca, bem como breves descrições dos três objetos-gráficos criados:

Chart window EURUSD H4 ID: 131733844391938630, HWND: 918600
Chart window AUDUSD H1 ID: 131733844391938632, HWND: 1182638
Chart window GBPUSD H4 ID: 131733844391938633, HWND: 1705036

Em seguida, ele exibirá uma descrição completa de todas as propriedades do objeto-gráfico, descrevendo o primeiro gráfico do terminal:

============= The beginning of the parameter list (Chart window EURUSD H4) =============
Chart ID: 131733844391938630
Timeframe: H4
Drawing attributes of a price chart: Yes
Object "Chart": No
Chart on top of other charts: No
Accessing the context menu by pressing the right mouse button: Yes
Accessing the "Crosshair tool" by pressing the middle mouse button: Yes
Scrolling the chart horizontally using the left mouse button: Yes
Sending messages about mouse wheel events to all mql5 programs on a chart: No
Send notifications of mouse move and mouse click events to all mql5 programs on a chart: No
Send a notification of an event of new object creation to all mql5-programs on a chart: No
Send a notification of an event of object deletion to all mql5-programs on a chart: No
Chart type: Display as Japanese candlesticks
Price chart in the foreground: No
Price chart indent from the right border: Yes
Automatic moving to the right border of the chart: Yes
Managing the chart using a keyboard: Yes
Allowed to intercept Space and Enter key presses on the chart to activate the quick navigation bar: Yes
Scale: 2
Fixed scale mode: No
Scale 1:1 mode: No
Scale to be specified in points per bar: No
Display a symbol ticker in the upper left corner: Yes
Display OHLC values in the upper left corner: Yes
Display Bid values as a horizontal line in a chart: Yes
Display Ask values as a horizontal line in a chart: Yes
Display Last values as a horizontal line in a chart: No
Display vertical separators between adjacent periods: No
Display grid in the chart: No
Display volume in the chart: Tick volumes
Display textual descriptions of objects: Yes
The number of bars on the chart that can be displayed: 96
The total number of chart windows, including indicator subwindows: 1
Chart window handle: 918600
Number of the first visible bar in the chart: 95
Chart width in bars: 117
Chart width in pixels: 466
Chart background color: clrWhite
Color of axes, scales and OHLC line: clrBlack
Grid color: clrSilver
Color of volumes and position opening levels: clrGreen
Color for the up bar, shadows and body borders of bull candlesticks: clrBlack
Color for the down bar, shadows and body borders of bear candlesticks: clrBlack
Line chart color and color of "Doji" Japanese candlesticks: clrBlack
Body color of a bull candlestick: clrWhite
Body color of a bear candlestick: clrBlack
Bid price level color: clrLightSkyBlue
Ask price level color: clrCoral
Line color of the last executed deal price (Last): clrSilver
Color of stop order levels (Stop Loss and Take Profit): clrOrangeRed
Displaying trade levels in the chart (levels of open positions, Stop Loss, Take Profit and pending orders): Yes
Permission to drag trading levels on a chart with a mouse: Yes
Showing the time scale on a chart: Yes
Showing the price scale on a chart: Yes
Showing the "One click trading" panel on a chart: No
Chart window is maximized: No
Chart window is minimized: No
The chart window is docked: Yes
The left coordinate of the undocked chart window relative to the virtual screen: 0
The top coordinate of the undocked chart window relative to the virtual screen: 0
The right coordinate of the undocked chart window relative to the virtual screen: 0
The bottom coordinate of the undocked chart window relative to the virtual screen: 0
------
The size of the zero bar indent from the right border in percents: 18.63
Chart fixed position from the left border in percent value: 0.00
Fixed  chart maximum: 1.22650
Fixed  chart minimum : 1.17770
Scale in points per bar: 1.00
Chart minimum: 1.17770
Chart maximum: 1.22650
------
Text of a comment in a chart: ""
The name of the Expert Advisor running on the chart: "TestDoEasyPart67"
The name of the script running on the chart: ""
Symbol: "EURUSD"
============= End of the parameter list (Chart window EURUSD H4) =============


O que vem agora?

No próximo artigo, expandiremos os recursos do objeto-gráfico criando objetos de subjanela e uma coleção de objetos-gráficos

Todos os arquivos da versão atual da biblioteca e o arquivo do EA de teste para MQL5 estão anexados abaixo. Você pode baixá-los e testar tudo sozinho.
Gostaria de ressaltar que não é recomendado usar os objetos-gráficos como estão agora atual devido a que posteriormente serão alterados.
Se você tiver perguntas, comentários e sugestões, poderá expressá-los nos comentários do artigo.

Complementos

*Artigos desta série:

Trabalhando com preços na biblioteca DoEasy (Parte 62): atualização em tempo real da série de ticks, preparação para trabalhar com o livro de ofertas Trabalhando preços na biblioteca DoEasy (Parte 63): livro de ofertas, classe de ordem abstrata do livro de ofertas
Trabalhando com preços na biblioteca DoEasy (Parte 64): livro de ofertas, classes do objeto-instantâneo e objeto-série de instantâneos do livro de ofertas
Trabalhando com preços e sinais na biblioteca DoEasy (Parte 65): coleção de livros de ofertas e classe para trabalhar com sinais MQL5.com
Outras classes na biblioteca DoEasy (Parte 66): classe-coleção de sinais MQL5.com

Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/9213

Arquivos anexados |
MQL5.zip (3940.41 KB)
Últimos Comentários | Ir para discussão (1)
Jessie Gold Trader
Jessie Gold Trader | 5 jun 2021 em 16:22
informacao muito importante!
Padrão de design MVC e a possibilidade de usá-lo Padrão de design MVC e a possibilidade de usá-lo
Este artigo falará sobre um padrão MVC comum, bem como sobre os prós e os contras de seu uso em programas MQL. Seu propósito é o de "dividir" o código existente em três componentes separados: Modelo (Model), Visualização (View) e Controlador (Controller).
Força bruta para encontrar padrões (Parte IV): funcionalidade mínima Força bruta para encontrar padrões (Parte IV): funcionalidade mínima
Neste artigo, mostrarei uma versão aprimorada da abordagem de força bruta, com base nos objetivos definidos no artigo anterior, e tentarei cobrir este tópico da forma mais ampla possível usando os EAs e as configurações obtidas por meio desse método. Também deixarei que a comunidade experimente a nova versão do programa.
Outras classes na biblioteca DoEasy (Parte 68): classe de objeto-gráfico e classes de objetos-indicadores na janela do gráfico Outras classes na biblioteca DoEasy (Parte 68): classe de objeto-gráfico e classes de objetos-indicadores na janela do gráfico
Neste artigo, continuaremos a desenvolver a classe do objeto-gráfico. Vamos adicionar uma lista de objetos-janelas, onde, por sua vez, estarão disponíveis as listas de indicadores colocados nestas.
Aprendizado de máquina em sistemas de negociação baseados em grade e martingale. Deveríamos apostar nele? Aprendizado de máquina em sistemas de negociação baseados em grade e martingale. Deveríamos apostar nele?
Este artigo apresentará ao leitor a técnica de aprendizado de máquina para negociação baseada em grade e martingale. Para minha surpresa, essa abordagem, por algum motivo, não é afetada de forma alguma na rede global. Após ler o artigo, podemos criar nossos próprios bots.