Calculadora de sinais

Vladimir Karputov | 27 junho, 2016

Tabela de conteúdos


Introdução

A questão que os assinantes tendem a perguntar mais freqüentemente é: "Será que eu posso assinar um sinal NNN, e que volume da posição será copiado para a minha conta de negociação?". Este artigo irá ajudar a criar uma calculadora de sinais, um assistente para aqueles que desejam assinar sinais. Aqui também encontrará um breve guia para utilizar a calculadora de sinais.

A calculadora em si é um painel com base na classe CDialog. Neste painel são usados os seguintes elementos:

A calculadora de sinais funciona com os sinais disponíveis no terminal. Essa abordagem garante a máxima compatibilidade entre os sinais e a sua conta de negociação, pois no terminal realiza-se a filtragem adicional de sinais de acordo com certas caraterísticas. A tarefa principal dessa filtragem é remover do campo de visão do usuário quer os sinais com um notável pobre desempenho de cópia, quer os sinais que não podem ser copiados.

A calculadora apresentada neste artigo pode ser baixada gratuitamente a partir do Mercado tanto para MetaTrader 5, como MetaTrader 4:


1. Restrição de uso

Deve ser claramente entendido que no terminal na guia "Sinais" são exibidos apenas os sinais que sejam altamente compatíveis com a conta de negociação do assinante. Em outras palavras, no terminal, você não irá ver todos os sinais que estão disponíveis no mostruário de sinais no site. Além disso, no terminal, ao alternar de um servidor de negociação (conta de negociação) para outro, você vai ver que a lista de sinais no terminal muda.


2. Guia para trabalhar com a calculadora de sinais

2.1. Introdução

Para ser operacional, a calculadora de sinais precisa de uma base atualizada de sinais de negociação no terminal. Por tanto, é necessário ativar a guia "Sinais" na janela "Caixa de ferramentas" (clicar na guia "Sinais"):


Fig. 1. Ativação da guia "Sinais" 

Se na base de sinais houver alterações, elas serão atualizadas dentro de três a cinco segundos.

A guia "Sinais" deve ser ativada depois de se conectar a uma conta de negociação, assim como no caso de se conectar a outra conta de negociação.


2.2. Interface do usuário

A interface da calculadora de sinais inclui os seguintes elementos:


Fig. 2. Interface da calculadora sinais 

  • Saldo da conta de negociação — saldo da conta de negociação atualmente conectada — campo editável. Depois de anexar a calculadora de sinais ao gráfico ou depois de alterar o período do gráfico, no campo editável "Saldo da conta de negociação" aparece o saldo da conta de negociação atualmente conectada. Neste campo é permitido digitar apenas dígitos de 0 a 9.
  • Moeda da conta de negociação — moeda da conta de negociação atualmente conectada; uma lista drop-down das moedas mais comuns. Depois de anexar a calculadora de sinais ao gráfico ou depois de alterar o período do gráfico, a calculadora de sinais tenta encontrar na lista o nome da moeda da conta de negociação conectada nesse momento. Se não houver nenhuma correspondência, então "USD" será selecionado como moeda padrão.
  • Alavancagem da conta de negociação — alavancagem de negociação da conta de negociação conectada nesse momento — uma lista drop-down das alavancagens de negociação mais comuns. Depois de anexar a calculadora de sinais ao gráfico ou depois de alterar o período do gráfico, a calculadora de sinais tenta encontrar na lista a alavancagem de negociação da conta de negociação conectada nesse momento. Se não houver nenhuma correspondência, então "1:100" será selecionado como alavancagem de negociação padrão.
  • Carga de depósito ao copiar o sinal — uma lista drop-down a partir do menu do terminal "Ferramentas" - "Opções" - "Sinais". Depois de anexar a calculadora de sinais ao gráfico ou depois de alterar o período do gráfico, a calculadora de sinais tenta encontrar na lista a carga de depósito da conta de negociação conectada nesse momento. Se não houver nenhuma correspondência, então 95% será selecionado como carga padrão.
  • Tabela de sinais disponíveis no terminal — tabela com sinais a partir da guia do terminal "Sinais". A tabela é automaticamente classificada em ordem decrescente pela coluna "Coeficiente de cópia". Colunas da tabela:
    • Coluna "Crescimento, %" — porcentagem do aumento de fundos na conta devido a operações de negociação.
    • Coluna "Sinal" — nome do sinal de negociação.
    • Coluna "Fundos" — quantidade de fundos próprios na conta do provedor do sinal tendo em conta todas as obrigações.
    • Coluna "Moeda" — moeda da conta de negociação do provedor do sinal.
    • Coluna "Alavancagem" — alavancagem da conta de negociação do provedor do sinal.
    • Coluna "Preço, $" — preço do sinal de negociação, em $.
    • Coluna "Coeficiente de cópia" — coeficiente de cópia calculado para cada sinal com as configurações selecionadas: "Saldo da conta de negociação", "Moeda da conta de negociação", "Alavancagem da conta de negociação" e "Carga de depósito ao copiar o sinal".
    • Coluna "Depósito min. *" — depósito necessário para cópia 1:1 ao usar um depósito para 95%. Ou seja, com esse depósito, as negociações do provedor de sinais serão copiadas para a sua conta de negociação na proporção de 1:1, desde que a carga de depósito selecionada seja "95%".
  • Cálculos detalhados do coeficiente de cópia — cálculo detalhado passo a passo do coeficiente de cópia do sinal selecionado.
    • К1 — coeficiente da correlação das moedas da sua conta de negociação e da conta de negociação do provedor do sinal.
    • К2 — coeficiente de correlação dos saldos da sua conta de negociação e a conta de negociação do provedor do sinal.
    • К3 — coeficiente de uso do depósito. Conversão das porcentagens para o coeficiente.
    • К4 — coeficiente de correção para a diferencia de alavancagens de negociação.
    • К — coeficiente final. Calcula-se como o produto dos coeficientes К1*К2*К3*К4.
    • Coeficiente de cópia final - coeficiente K, arredondado usando um algoritmo de várias etapas.

2.3. Obtendo o coeficiente de cópia

Na tabela de sinais para cada sinal, na coluna "Coeficiente de cópia", é possível ver o coeficiente de cópia calculado para cada sinal com as configurações selecionadas: "Saldo da conta de negociação", "Moeda da conta de negociação", "Alavancagem da conta de negociação" e "Carga de depósito ao copiar o sinal". 

Se você quiser, pode alterar as configurações: "Saldo da conta de negociação", "Moeda da conta de negociação", "Alavancagem da conta de negociação" ou "Carga de depósito ao copiar o sinal". A alteração de quaisquer uma dessas configurações conduz ao recalculo do coeficiente de cópia e à atualização da tabela, e não há nenhuma garantia de que os sinais de negociação permaneçam nos seus lugares na tabela após a classificação decrescente pela coluna "Depósito min.*". Assim, é possível, em tempo real, ver como é alterado o coeficiente de cópia do sinal de negociação da conta de negociação ao ter diferentes configurações.

2.4. Cálculo detalhado do coeficiente de cópia

Para obter um cálculo detalhado do coeficiente de cópia para um sinal específico, você precisa clicar na tabela de sinais na linha do sinal do seu interesse (ação 1). Isso fará com que um cálculo detalhado do coeficiente de cópia para o sinal selecionado apareça embaixo da tabela do sinal (ação 2):

 

Fig. 3. Cálculo detalhado do coeficiente de cópia  

2.5. Impossibilidade de mapeamento

Após a seleção de outra moeda na lista drop-down "Moeda da conta de negociação", para calcular o coeficiente de cópia, a calculadora de sinais vai tentar encontra na janela "Observação do mercado" o símbolo que contém no seu nome a moeda da sua conta de negociação (ou a moeda selecionada na lista drop-down "Moeda da conta de negociação"). Por exemplo, a moeda da sua conta de negociação é "USD", enquanto a a moeda da conta de negociação do provedor do sinal é "EUR". Nesse caso, a calculadora tentará encontrar na janela "Observação do mercado" o símbolo "USDEUR" e "EURUSD". Se o símbolo não for encontrado, uma mensagem de erro será exibida na guia "Experts" do terminal.

Exemplo de uma mensagem de erro depois de selecionar a moeda "SGD" na lista drop-down "Moeda da conta de negociação":

Сalculator for signals (EURUSD,M5)      Error find symbols: (Account currency SGD, Signal currency RUB)
Сalculator for signals (EURUSD,M5)      Error find symbols: (Account currency SGD, Signal currency EUR)
Сalculator for signals (EURUSD,M5)      Error find symbols: (Account currency SGD, Signal currency EUR)

Esta mensagem significa que na janela "Observação do mercado" não existem os símbolos "SGDRUB", "SGDEUR", "RUBSGD", "EURSGD". Verificamos se este for o caso: na janela "Observação do mercado" tentamos encontrar qualquer um símbolo cujo nome tenha "SGD". Para fazer isso, na janela "Observação do mercado" é necessário clicar no botão "+ adicionar":


Fig. 4. Comando "adicionar" na janela "Observação do mercado"   

e inserir "SGD" no campo que se abriu:


Fig. 5. Lista de símbolos disponíveis na janela "Observação do mercado", cujo nome tenha "SGD"   

Como você pode ver a janela "Observação do mercado" já têm um símbolo "USDSGD" e é possível adicionar mais um, o "SGDJPY", no entanto estão ausentes outros símbolos como "SGDRUB", "SGDEUR", "RUBSGD", "EURSGD". 

Se o mapeamento não for possível, na tabela de sinais na coluna "Coeficiente de cópia" será exibido "n/d", indicando "não há dados".

Pequeno vídeo sobre a calculadora de sinais:



3. Desenvolvendo a calculadora de sinais

3.1. Projetamos a interface

Os elementos de controle na calculadora de sinais estão localizados da seguinte forma:

Localização dos elementos de controle  

Fig. 6. Localização dos elementos de controle 

O arquivo anexado "Сalculator for signals Dialog.mqh" é responsável pelo visual, o tamanho e a criação dos elementos de controle. As dimensões principais dos elementos de controle e as margens são definidas usando o bloco substituição de macro:

//+------------------------------------------------------------------+
//| defines                                                          |
//+------------------------------------------------------------------+
//--- indents and gaps
#define INDENT_LEFT                         (11)      // indent from left (with allowance for border width)
#define INDENT_TOP                          (11)      // indent from top (with allowance for border width)
#define CONTROLS_GAP_Y                      (5)       // gap by Y coordinate
//--- for combo boxes
#define COMBOBOX_WIDTH                      (60)      // size by X coordinate
#define COMBOBOX_HEIGHT                     (20)      // size by Y coordinate
//--- for list view
#define LIST_HEIGHT                         (102)     // size by Y coordinate
//--- for buttons
#define BUTTON_WIDTH                        (72)      // size by X coordinate
#define BUTTON_HEIGHT                       (20)      // size by Y coordinate
//--- for the indication area
#define EDIT_WIDTH                          (60)      // size by X coordinate
#define EDIT_HEIGHT                         (20)      // size by Y coordinate

Os elementos de controle estão localizados em um painel constituído por 5 linhas:

  1. primeira linha — Label1, Edit1, ComboBox1, Label2, ComboBox2, Label3, ComboBox2
  2. segunda linha — Label 4
  3. terceira linha — botões de Button1 a Button8 inclusive
  4. quarta linha — novo elemento de controle, tabela TableListView1
  5. quinta linha — objeto BmpButton1, ele possui um recurso gráfico baseado em CCanvas nomeado como um arquivo bmp para exibir o elemento no estado ON.
O principal é manter em mente que todos os elementos de controle estão localizados no painel de diálogo (o painel principal criado aqui):
//+------------------------------------------------------------------+
//| Create                                                           |
//+------------------------------------------------------------------+
bool CoSDialog::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
  {
//---
   m_error=true;
   if(!CAppDialog::Create(chart,name,subwin,x1,y1,x2,y2))
      return(false);
//---

Isso significa que, na seqüência da criação, cada objeto de controle deve ser adicionado à área de cliente usando o método Add da classe CDialog. Abaixo há um exemplo claro de como se cria o objeto Label4:

//+------------------------------------------------------------------+
//| Create the "Signals" Label                                       |
//+------------------------------------------------------------------+
bool CoSDialog::CreateLabel4(void)
  {
//--- coordinates
   int x1=INDENT_LEFT;
   int y1=INDENT_TOP+COMBOBOX_HEIGHT+CONTROLS_GAP_Y;
   int x2=x1+100;
   int y2=y1+COMBOBOX_HEIGHT;
//--- create
   if(!m_label4.Create(m_chart_id,m_name+"Label4",m_subwin,x1,y1,x2,y2))
      return(false);
   if(!m_label4.Text(m_languages.GetText(3)))
      return(false);
   if(!Add(m_label4))
      return(false);
//--- succeed
   return(true);
  }

Primeiro, criamos o objeto Label4:

   if(!m_label4.Create(m_chart_id,m_name+"Label4",m_subwin,x1,y1,x2,y2))
      return(false);

e antes de sair da função, não se esqueça de adicionar o objeto recém-criado Label4 à área de cliente usando o método Add:

   if(!Add(m_label4))
      return(false);

Em geral, o processo de criação do painel e elementos de controle neste painel pode ser representado com uma amostra da criação de um painel de calculadora de sinais sob a forma de um esquema:

Esquema de criação de objetos do painel

Fig. 7. Esquema de criação de objetos do painel 

Para resumir. Em geral, o painel é criado de acordo com o plano seguinte:

  • criação do painel em si (CAppDialog::Create)
  • criação alternada de elementos de controle, cada um dos quais é criado na seguinte seqüência:
    • criação do elemento (element_N.Create)
    • alteração das propriedades do elemento
    • adição obrigatória do elemento ao painel (Add (elenemt_N))

3.2. Criamos a tela no painel

A tela é criada no CoSDialog::CreateBmpButton1.

Primeiro brevemente em várias etapas:

Passo 1: criamos um recurso gráfico, sem ancoragem no objeto gráfico (usamos o método Create da classe CCanvas)

Passo 2: criamos o elemento de controle m_bmp_button1 da classe CBmpButton (classe de um elemento de controle simples na base do objeto 'Marca gráfica' (Bitmap label))

Passo 3: montamos a nossa tela para o elemento de controle m_bmp_button1, como arquivo bmp no estado ON (método BmpOnName), .

Passo 4: adicionamos o elemento de controle m_bmp_button1 ao painel (método Add da classe CDialog)

Agora mais sobre cada passo.

Passo 1

//--- create canvas
   if(!m_canvas1.Create("Canvas1",x2,y2,COLOR_FORMAT_XRGB_NOALPHA))
     {
      Print("Error creating canvas: ",GetLastError());
      return(false);
     }
   m_canvas1.FontSet("Trebuchet MS",-100,FW_THIN);
   m_canvas1.Erase(ColorToARGB(C'0xF7,0xF7,0xF7',255));
   m_canvas1.Update(true);

Por favor, note que ao criar a tela (m_canvas1.Create) é indicada a largura x2 e altura y2, pois são as dimensões da imagem que não mudarão:

Dimensões da tela  

Fig. 8. Dimensões da tela 

A seguir, é especificado a fonte para a tela (m_canvas1.FontSet), a tela é preenchida com a cor da área interior do painel (m_canvas1.Erase) e, NECESSARIAMENTE, as alterações devem ser exibidas (m_canvas1.Update).

Passo 2.

//--- create
   if(!m_bmp_button1.Create(m_chart_id,m_name+"BmpButton1",m_subwin,x1,y1,x1+10,y1+10))
      return(false);

Criação do elemento de controle m_bmp_button1 de 10*10 pixels. Não importa que o tamanho do elemento de controle seja pequeno. Aqui o mais importante são as coordenadas x1 e y1. Estes são os pontos de ancoragem. Isto é, quando o tamanho do elemento de controle se ajuste ao tamanho da imagem, o ângulo com as coordenadas (x1; y1) permanecerá no seu lugar.

Passo 3.

//--- sets the name of bmp files of the control CBmpButton
   if(!m_bmp_button1.BmpOnName(m_canvas1.ResourceName()))
      return(false);

Obtemos o nome do recurso (m_canvas1.ResourceName()) e atribuímos como arquivo bmp no estado ON (m_bmp_button1.BmpOnName). É nesta fase que o controle m_bmp_button1 estende-se ao tamanho da tela.

Passo 4.

Após a criação do elemento de controle, não nos esqueçamos de adicionar este elemento de controle ao painel: 

   if(!Add(m_bmp_button1))
      return(false);

3.3. Matriz bidimensional. Classificação

A classificação realiza-se no arquivo "Сalculator for signals Dialog.mqh" no método CoSDialog::InitStructurs. 

Na calculadora de sinais, os dados na tabela são classificados segundo o índice calculado, isto é, o coeficiente de cópia. Mas, no processo de obtenção do coeficiente de cópia, a lista, contendo o nome do sinal e do coeficiente de cópia, não está classificada e tem aproximadamente esta aparência:

Name Copy ratio
TestUSD 15.0
TradeLargeVolumes 120.0
Zeus PRO 15.0
CS Trading Co Beta Free Provider 1510.0
Mint blueberry ice cream 8.0
MT5Hedging 7.0
Forex Leos Trading 160.0
Hedge 1.0
Siksikawa 8770.0
Week H4 15.0
WGT Live Signal 45.0
Atrader 30.0
Trajecta Advisor FX491 30.0
MOsg style 6.0 

Para classificar, temos aplicado a solução sugerida pelo usuário Vasiliy Sokolov: cada linha deve ser apresentada como um objeto CObject, enquanto toda a tabela, como um objeto CArrayObj. Essa tabela foi chamada de linear, a classe da tabela linear virtual (virtual, porque não tem uma interface visual) foi colocada no arquivo "LineTable.mqh".

O resultado da classificação na tabela linear é apresentado abaixo (o exemplo é para as algumas das primeiras inserções de linhas na tabela). Primeiro, são exibidos os parâmetros que são inseridos na tabela linear (Insert : ), abaixo, a iteração sobre todos os elementos da tabela linear (row #):

name rate  min_deposit
 Insert : MyCorrelation EURUSD XAUUSD  7  133134.7143
 row #0: MyCorrelation EURUSD XAUUSD  7  133134.7143
 Insert : EA microPatience AvzPrecio v6 HG 10  7  133134.7143
 row #0: MyCorrelation EURUSD XAUUSD  7  133134.7143
 row #1: EA microPatience AvzPrecio v6 HG 10  7  133134.7143
 Insert : EURUSD Daytrade  170  5482.017647
 row #0: EURUSD Daytrade  170  5482.017647
 row #1: MyCorrelation EURUSD XAUUSD  7   133134.7143
 row #2: EA microPatience AvzPrecio v6 HG 10  7  133134.7143
 Insert : Exp TickSniper PRO FULL MT5  50  18638.86
 row #0: EURUSD Daytrade  170  5482.017647
 row #1: Exp TickSniper PRO FULL MT5  50  18638.86
 row #2: MyCorrelation EURUSD XAUUSD  7  133134.7143
 row #3: EA microPatience AvzPrecio v6 HG 10  7  133134.7143
 Insert : Example1  3  310647.6667
 row #0: EURUSD Daytrade  170  5482.017647
 row #1: Exp TickSniper PRO FULL MT5  50  18638.86
 row #2: MyCorrelation EURUSD XAUUSD  7  133134.7143
 row #3: EA microPatience AvzPrecio v6 HG 10  7  133134.7143
 row #4: Example1  3  310647.6667
 Insert : Big sale  80  11649.2875
 row #0: EURUSD Daytrade  170  5482.017647
 row #1: Big sale  80  11649.2875
 row #2: Exp TickSniper PRO FULL MT5  50  18638.86
 row #3: MyCorrelation EURUSD XAUUSD  7  133134.7143
 row #4: EA microPatience AvzPrecio v6 HG 10  7  133134.7143
 row #5: Example1  3  310647.6667

A imagem mostra claramente que, após a adição à tabela linear, é feita a classificação pelo campo "rate", e isto é exatamente o que precisamos. No futuro, sabendo que todos os elementos de controle na tabela linear estão classificados, podemos copiar os seus valores para o novo elemento de controle, para a tabela CTableListView, e ficar confiantes de que os dados serão apresentados numa lista classificada.

Se você deseja imprimir a classificação passo a passo e obter a mesma tabela, simplesmente descomente as linhas no arquivo "Сalculator for signals Dialog.mqh" no método CoSDialog::InitStructurs: 

         else
           {
            min_deposit=AccInfo.balance/rate*100.0;
           }
         //Print("Insert : ",name,"; ",rate,"; ",min_deposit); 
         m_table.InsertSort(new CLineTable(name,rate,min_deposit));
         //for(int m=0;m<m_table.Total();m++)
         //  {
         //   CLineTable *line=m_table.At(m);
         //   Print("row #",m,": ",line.Text(),"; ",line.Number(),"; ",line.Number1());
         //  }
        }
      else PrintFormat("Error in call of SignalBaseSelect. Error code=%d",GetLastError());
     }
//---
   return(true);
  }

3.4. Novo elemento de controle, tabela CTableListView

A fim de exibir sinais, as suas características e dados calculados, vamos criar um elemento de controle visual, isto é, uma tabela que pode exibir algumas linhas e colunas. Além disso, se o número de linhas exceder a altura da tabela, em seguida, aparecerá uma barra de rolagem vertical. Depois de pesquisar, decidimos tomas o elemento de controle da classe CListView e modernizá-lo significativamente.

O elemento de controle da tabla CTableListView tem duas partes, uma visível com a qual o usuário tem contato visual e físico, e invisível, na qual são armazenados os dados das células da tabela.

A parte visível da tabela é estipulada pelo tamanho do mesmo elemento de controle. Ele está restringido pelo retângulo com coordenadas (x1; y1) e (x2; y2) e pela quantidade de botões columns, que são estabelecidos ao criar o elemento no método Create:

   virtual bool      Create(const long chart,const string name,const int subwin,const int x1,
                            const int y1,const int x2,const int y2,const uchar columns,const ushort &columns_size[]);

A parte visível está formada pelos elementos de controle CEdit

Construção da parte visível da tabela CTableListView

Fig. 9. Construção da parte visível da tabela CTableListView

Os elementos de controle CEdit da parte visível são criados e gerenciados usando a matriz dinâmica de ponteiros m_arr_rows, objetos da classe CArrayObj:

   CArrayObj         m_arr_rows;             // array of pointer to objects-rows (CEdit) 

(artigo sobre uso de ponteiros Quando é necessário usar ponteiros na MQL5)

A matriz de ponteiros m_arr_rows é uma matreoshka de dois níveis. No primeiro nível, são armazenados os ponteiros para os objetos-linhasrow, pela sua vez, os objetos-linhas row armazenas os ponteiros para objetos-células (elementos CEdit) da tabela:

Ponteiros para objetos visíveis

Fig. 10. Ponteiros para objetos visíveis 

A parte invisível é também realizada com a ajuda da classe CArrayObj. Pela a parte invisível respondem duas matrizes dinâmicas de ponteiros m_arr_rows_str e m_arr_rows_val,

   CArrayObj         m_arr_rows_str;         // array of pointer to objects-rows (CArrayString) 
   CArrayObj         m_arr_rows_val;         // array of pointer to objects-rows (CArrayLong) 

que armazenam o texto das células e valores, respectivamente.

Estrutura da matriz do ponteiro m_arr_rows_str и m_arr_rows_val semelhante à estrutura da matriz de ponteiros m_arr_rows, só as matrizes de classes CArrayStringCArrayLong são usadas como linhas.

3.4.1. Matriz dinâmica de ponteiros, exemplo de operação

Vamos analisar a operação com uma matriz dinâmica de ponteiros baseada no exemplo da criação de um objeto (tabela):

//+------------------------------------------------------------------+
//| Create a control                                                 |
//+------------------------------------------------------------------+
bool CTableListView::Create(const long chart,const string name,const int subwin,const int x1,
                            const int y1,const int x2,const int y2,const uchar columns,const ushort &columns_size[])
  {
   m_columns=columns;
   ArrayResize(m_columns_size,m_columns);
   if(ArraySize(columns_size)!=m_columns)
      return(false);
   ArrayCopy(m_columns_size,columns_size,0,0,WHOLE_ARRAY);
   m_columns_size[0]-=1;
   m_columns_size[m_columns-1]-=1;
   int y=y2;
//--- if the number of visible rows is previously determined, adjust the vertical size
   if(!TotalView((y2-y1)/m_item_height))
      y=m_item_height+y1+2*CONTROLS_BORDER_WIDTH;
//--- check the number of visible rows
   if(m_total_view<1)
      return(false);
//--- call method of the parent class
   if(!CWndClient::Create(chart,name,subwin,x1,y1,x2,y))
      return(false);
//--- set up
   if(!m_background.ColorBackground(CONTROLS_LIST_COLOR_BG))
      return(false);
   if(!m_background.ColorBorder(CONTROLS_LIST_COLOR_BORDER))
      return(false);
//--- create dependent controls
   CArrayObj *m_arr_cells;
   for(int i=0;i<m_total_view;i++)
     {
      m_arr_cells=new CArrayObj;
      if(CheckPointer(m_arr_cells)==POINTER_INVALID)
         return(false);
      for(int j=0;j<m_columns;j++)
        {
         CEdit *m_cell;
         m_cell=new CEdit;
         if(CheckPointer(m_cell)==POINTER_INVALID)
            return(false);
         m_arr_cells.Add(m_cell);
        }
      m_arr_rows.Add(m_arr_cells);
     }
//---
   for(int i=0;i<m_total_view;i++)
     {
      if(!CreateRow(i))
         return(false);
      if(m_height_variable && i>0)
        {
         // m_rows[i].Hide(); ///
         CArrayObj *m_arr_cells_i=m_arr_rows.At(i);
         if(CheckPointer(m_arr_cells_i)==POINTER_INVALID)
            return(false);
         for(int j=0;j<m_arr_cells_i.Total();j++)
           {
            CEdit *m_cell=m_arr_cells_i.At(j);
            if(CheckPointer(m_cell)==POINTER_INVALID)
               return(false);
            if(!m_cell.Hide())
               return(false);
           }
        }
     }
//--- succeed
   return(true);
  }

O bloco do código a seguir

//--- if the number of visible rows is previously determined, adjust the vertical size
   if(!TotalView((y2-y1)/m_item_height))
      y=m_item_height+y1+2*CONTROLS_BORDER_WIDTH;

é usado para chamar TotalView, onde se calcula a quantidade de linhas visíveis. Esta quantidade é armazenada na variável m_total_view.

Em seguida, no ciclo for(int i=0;i<m_total_view;i++) são criadas as linhas m_arr_cells, e no ciclo for(int j=0;j<m_columns;j++) as linhas são preenchidas com células m_cell:

//--- create dependent controls
   CArrayObj *m_arr_cells;
   for(int i=0;i<m_total_view;i++)
     {
      m_arr_cells=new CArrayObj;
      if(CheckPointer(m_arr_cells)==POINTER_INVALID)
         return(false);
      for(int j=0;j<m_columns;j++)
        {
         CEdit *m_cell;
         m_cell=new CEdit;
         if(CheckPointer(m_cell)==POINTER_INVALID)
            return(false);
         m_arr_cells.Add(m_cell);
        }
      m_arr_rows.Add(m_arr_cells);
     }
//---

Após o bypass completo do ciclo for(int j=0;j<m_columns;j++) cada linha concluída é adicionada para a matriz principal m_arr_rows:

      m_arr_rows.Add(m_arr_cells);

Assim, depois de um bypass completo do ciclo for(int i=0;i<m_total_view;i++) temos a matriz de ponteiros preenchida m_arr_rows que na sua estrutura corresponde à parte visível da tabela (veja a fig. 9).

Depois de preencher a matriz de ponteiros no segundo ciclo for(int i=0;i<m_total_view;i++) ocorre a visualização da tabela (criação da parte visível da tabela), chamando CreateRow:

//---
   for(int i=0;i<m_total_view;i++)
     {
      if(!CreateRow(i))
         return(false);
      .
      .
      .
     }
//--- succeed
   return(true);

Método CreateRow:

//+------------------------------------------------------------------+
//| Create "row"                                                     |
//+------------------------------------------------------------------+
bool CTableListView::CreateRow(const int index)
  {
   .
   .
   .
//--- create
   CArrayObj *m_arr_cells=m_arr_rows.At(index);
   if(CheckPointer(m_arr_cells)==POINTER_INVALID)
      return(false);
   for(int i=0;i<m_arr_cells.Total();i++)
     {
      CEdit *m_cell=m_arr_cells.At(i);
      if(CheckPointer(m_cell)==POINTER_INVALID)
         return(false);
      x1+=x2;
      x2=m_columns_size[i];
      if(!m_cell.Create(m_chart_id,m_name+"_"+IntegerToString(index)+"_"+IntegerToString(i),
         m_subwin,x1,y1,x1+x2,y2))
         return(false);
      if(!m_cell.Text(""))
         return(false);
      if(!m_cell.ReadOnly(true))
         return(false);
      if(!Add(m_cell))
         return(false);
     }
   .
   .
   .
   return(true);
  }

No bloco do código obtemos a partir da matriz de ponteiros m_arr_rows o ponteiro para o elemento m_arr_cells (o elemento m_arr_cells tem o tipo CArrayObj) localizado na posição index. O elemento m_arr_cells  é a linha da tabela row (veja a fig. 10). Usamos o método At da classe CArrayObj:

   .
//--- create
   CArrayObj *m_arr_cells=m_arr_rows.At(index);
   if(CheckPointer(m_arr_cells)==POINTER_INVALID)
      return(false);
   for(int i=0;i<m_arr_cells.Total();i++)

Em seguida, no ciclo for(int i=0;i<m_arr_cells.Total();i++) trabalhamos com o elemento m_arr_cells (com a matriz de ponteiros): obtemos a partir da matriz de ponteiros m_arr_cells o ponteiro para o elemento m_cell (o elemento m_cell tem o tipo CEdit) localizado na posição i:

      CEdit *m_cell=m_arr_cells.At(i);
      if(CheckPointer(m_cell)==POINTER_INVALID)
         return(false);

Depois, criamos as células (elementod de controle da classe CEdit) com um nome único:

      if(!m_cell.Create(m_chart_id,m_name+"_"+IntegerToString(index)+"_"+IntegerToString(i),
         m_subwin,x1,y1,x1+x2,y2))
         return(false);

alteramos algumas das propriedades dos elementos de controle criados(apagamos todo o texto do elemento de controle e tornamos o elemento de controle não-editável):

      if(!m_cell.Text(""))
         return(false);
      if(!m_cell.ReadOnly(true))
         return(false);

E a última etapa, mas não menos importante consiste em adicionar o elemento de controle recém-criado para o nosso painel:

      if(!Add(m_cell))
         return(false);
     }

 

Conclusão

Espero que a calculadora de sinais seja útil ao selecionar o sinal, o mais importante é que a calculadora ajudará a ver como se altera o coeficiente de cópia, ao alterar (na calculadora) o tamanho do depósito e/ou a alavancagem da sua conta de negociação.