Perguntas de Iniciantes MQL4 MT4 MetaTrader 4 - página 137

 
Игорь Васильев:

Estranho porque o compilador não informa quando vê comandos comerciais no código indicador.

Agora teremos que puxar a parte comercial do indicador para a EA, ligando-a a ela via ICustom().

Parece "a cauda na cabeça e o arco na lateral".

O compilador verifica apenas a sintaxe. Sua tarefa não é determinar como o programa resultante irá funcionar (ou não funcionar). A inoperabilidade dos comandos comerciais só pode ser constatada na etapa de execução do programa. Ou seja, um erro de tempo de execução será recebido.

 

Olá a todos, vocês poderiam me dizer se é possível fazer o seguinte?

Existe uma estrutura, por exemplo:
// uma estrutura de alguns eventos.
estrutura MyStruct
{
int Número;
data/hora DTm;
valor duplo;
Tipo de corda;
}

Declaro um conjunto dinâmico de estruturas do tipo MyStruct:
MyStruct DataEvents[];

Eu formulo e preencho uma matriz em alguma função, por exemplo
void GetDataEventsTest(MyStruct& DataEvents[], int countEvent=5)
{
MathSrand(GetTickCount());
ArrayResize(DataEvents, countEvent);
int i = 0;
while( i<countEvent )
{
DataEvents.Number = i;
DataEvents.DTm = TimeCurrent();
DataEvents.Value = (double)MathRand();
if( MathMod(i, 2)>0 ) DataEvents.Type = "Up"; else DataEvents.Type = "Dn";
i = i + 1;
}
}

Em algum lugar nós preenchemos a matriz chamando GetDataEventsTest():
GetDataEventsTest(DataEvents);

Precisamos, por exemplo, inserir um novo elemento do tipo MyStruct no meio do intervalo dos elementos da matriz, em algum lugar no índice 2.
A lógica sugere os seguintes passos:
ArrayResize(DataEvents, ArraySize(DataEvents)+1));
e algo parecido com isto:
int iNew = 2;
int i = ArraySize(DataEvents) - 2;
while( i>=iNovo )
{
// DataEvents[i+1] = DataEvents[i]; // não funciona, é claro, porque temos que trabalhar com os endereços referenciados pelo elemento array, portanto
// escrever DataEvents[i+1] para um elemento de matriz que aponta para o elemento DataEvents[i] array;
i = i - 1;
}
... Então eu preencho o elemento DataEvents[iNew] array com dados.


Pergunta, é possível fazer isso com estruturas mql4?

 
GitSM:

É possível fazer isso com estruturas em mql4?

Sim, isso é possível. Se a estrutura estivesse sem um tipo de dados complexo (aqui inclui um fio), tudo funcionaria de uma só vez. E quando a estrutura contém tipos de dados, cujo tamanho pode mudar com o tempo, você precisa sobrecarregar o operador de atribuição:

struct MyStruct
{
    int Number;
    datetime DTm;
    double Value;
    string Type;

    void operator = (const MyStruct &stMyStruct)
    {
      Number = stMystruct.Number;
      DTm = stMyStruct.DTm;
      Value = stMyStruct.Value;
      Type = stMyStruct.Type;
    }
}
 
Ihor Herasko:

Sim, isso é possível. Se a estrutura estivesse sem um tipo de dados complexo (aqui inclui uma string), ela funcionaria imediatamente. E quando a estrutura contém tipos de dados cujo tamanho pode mudar com o tempo, você precisa sobrecarregar o operador de atribuição:

Obrigado pela dica!
 

Mais uma vez, uma questão surgiu na mesma direção do último exemplo.
Se a estrutura for complexa e puder conter matrizes com outras estruturas. Por exemplo, eu faço declarações como esta:

// elemento com propriedades
Estrutura ItemPropriedade
{
duplo Baixo;
duplo Alto;
duplo Meio;
faixa dupla;
Área dupla;
Tipo de corda;

operador vazio = (const ItemProperty &SourceItemProperty)
{
Low = SourceItemProperty.Low;
Alto = SourceItemProperty.High;
Middle = SourceItemProperty.Middle;
Gama = SourceItemProperty.Range;
Área = SourceItemProperty.Area;
Tipo = SourceItemProperty.Type;
}
}

// itens com propriedades estatísticas
itens estruturantesPropriedade;
{
duplo MinLow;
duplo MaxHigh;
dupla AvgRange;
dupla AvgArea;
Fase de corda;

Item Itens[];

operador vazio = (const ItemProperty &SourceItemsProperty)
{
MinLow = SourceItemsProperty.MinLow;
MaxHigh = SourceItemsProperty.MaxHigh;
AvgRange = SourceItemsProperty.AvgRange;
AvgArea = SourceItemsProperty.AvgArea;
Fase = SourceItemsProperty.Phase;

// Itens = SourceItemProperty.Items; // Como posso fazer múltiplas variáveis de array apontar para o mesmo array físico na memória?
}
}

// estrutura de alguns eventos com base na análise dos itens
Evento EstruturaPropriedade
{
int Número;
data/hora DTm;
valor duplo;
Tipo de corda;

níveis duplos[];
int Weigths[];

ItensPropriedade ItensProp[];

operador vazio = (const ItemProperty &SourceEventProperty)
{
Número = SourceEventProperty.Number;
DTm = SourceEventProperty.DTm;
Valor = SourceEventProperty.Value;
Tipo = SourceEventProperty.Type;

// Níveis = SourceEventProperty.Levels; // há um engate
// Weigths = SourceEventProperty.Weigths; // ehhhh.

// ItemsProp = SourceEventProperty.ItemsProp; // aqui também é um problema

}
}

Declarando um conjunto dinâmico de eventos:
EventoPropriedade MyEvents[];

Preencho os dados da matriz de eventos em alguma função.
void GetEventsProperty(EventoPropriedade& MyEvents)
{
// código de preenchimento
}

e em algum lugar há a necessidade de manipular os elementos da matriz MyEvents adicionando-os ou removendo-os.

int iNew = 2;
int i = ArraySize(MyEvents) - 2;
while( i>=iNovo )
{
// MyEvents[i+1] = MyEvents[i]; // aqui temos um engate
i = i - 1;
}

É possível fazer isso com um conjunto de estruturas em mt4? Acontece que precisamos ser capazes de nos referir a um e o mesmo elemento de uma série de estruturas em memória a partir de diferentes variáveis de referência de variáveis, criando e apagando-as.
É possível trabalhar com uma série de referências a estruturas?

 
GitSM:

É possível fazer isso com um conjunto de estruturas em mt4? Acontece que você precisa ser capaz de referenciar um e o mesmo elemento do conjunto de estruturas em memória a partir de diferentes referências variáveis, criando e apagando-as.

É possível trabalhar com uma série de referências a estruturas?

Em teoria, deveria ser assim:

struct ItemsProperty;
{
    double MinLow;
    double MaxHigh;
    double AvgRange;
    double AvgArea;
    string Phase;
    
    Item Items[];
    
    void operator = (const ItemProperty &SourceItemsProperty)
    {
        MinLow = SourceItemsProperty.MinLow;
        MaxHigh = SourceItemsProperty.MaxHigh;
        AvgRange = SourceItemsProperty.AvgRange;
        AvgArea = SourceItemsProperty.AvgArea;
        Phase = SourceItemsProperty.Phase;
 
        int nTotal = ArraySize(SourceItemProperty.Items);
        ArrayResize(Items, nTotal);
        for (int i = 0; i < nTotal; ++i)
           Items[i] = SourceItemProperty.Items[i];
    }
}

E com todas as outras matrizes exatamente o mesmo. Pergunta:

Como posso fazer com que várias variáveis de array apontem para o mesmo array físico na memória?

Eu não entendo.

P. S. Para inserir código, use o ícone "</>" ou Alt+S.

 

Как сделать так чтобы на один и тот же физический массив в памяти могло указывать несколько переменных массива?

Eu não entendo.

Desculpe, não formulei a pergunta de forma muito correta. Se entendi corretamente, um conjunto de estruturas é essencialmente referências-endereços por índices de matriz, cada um dos quais aponta para algum endereço físico na memória, distribuído de certa forma de acordo com a estrutura de dados. Por "Como fazer várias variáveis de array apontar para o mesmo array físico na memória?" eu quis dizer a possibilidade de fazer MyEvents[2] e MyEvents[5] apontarem para a mesma estrutura na memória, ou seja, MyEvents[2] e MyEvents[5] não devem apontar para duas estruturas idênticas, elas devem apontar para a mesma estrutura.

A sobrecarga do operador criará uma cópia da estrutura. As estruturas de dados podem ser muito pesadas ou pode haver muitas delas e não há necessidade de copiá-las, basta um array para saltar de um índice para outro para endereçar a estrutura de dados. Algo assim *MeusEventos[2] = *MeusEventos[1]. Talvez eu tenha usado as indicações incorretamente aqui, por isso vou explicar desta forma. Você precisa pegar o endereço da MyEvents[2] e mudá-lo para o endereço da MyEvents[1].

E então, por mais complexas e pesadas que sejam as estruturas de dados, você poderia "embaralhá-las" na matriz em qualquer ordem que você precise, quase sem desperdício de recursos computacionais. Afinal, copiar um endereço de memória de um lugar para outro é muito mais fácil, ordens de magnitude mais rápidas e não requerem memória adicional, do que copiar estruturas cuja complexidade pode variar muito para alterar o índice referenciado a esta estrutura em uma matriz.

Распределенные вычисления в сети MQL5 Cloud Network
Распределенные вычисления в сети MQL5 Cloud Network
  • cloud.mql5.com
Большую часть времени современные компьютеры простаивают и не используют всех возможностей процессора. Мы предлагаем задействовать их с пользой. Вы можете сдавать мощности вашего компьютера другим участникам нашей сети для выполнения разнообразных...
 
Pelo que entendi, para implementar tal mecanismo de "embaralhar" referências a estruturas em uma matriz, essas estruturas terão que ser implementadas através de classes.
Tentei tal exemplo, e parece funcionar. Entendo que também precisarei monitorar a remoção de objetos de classe criados através de novos.
Descrevi uma classe de teste e um conjunto dinâmico de indicadores (como eu entendo, são essencialmente os mesmos links) para as classes na declaração da variável:
class MyClassTest
{
        public:
        int a;
        double b;
        string c;
};

MyClassTest* arrayRefsMyClassTest[];
Eu também fiz estes controles:
Print("Тест операций над массивом ссылок на классы: начало");

// создаём объекты классов и сохраняем ссылки на них в массиве ссылок.
i = 0;
while( i<5 )
{
        ArrayResize(arrayRefsMyClassTest, i+1);
        arrayRefsMyClassTest[i] = new MyClassTest();
        arrayRefsMyClassTest[i].a = i;
        arrayRefsMyClassTest[i].b = 3.14+i;
        arrayRefsMyClassTest[i].c = "testclass" + i;
        i = i + 1;
}

i = 0;
while( i<ArraySize(arrayRefsMyClassTest) ) { if( CheckPointer(arrayRefsMyClassTest[i])!=POINTER_INVALID ) Print("arrayRefsMyClassTest[" + i + "]: a = " + arrayRefsMyClassTest[i].a, ", b = " + arrayRefsMyClassTest[i].b + ", c = " + arrayRefsMyClassTest[i].c); i = i + 1; }

Print("Изменяем размер массива ссылок на классы");
ArrayResize(arrayRefsMyClassTest, ArraySize(arrayRefsMyClassTest)+2);

i = 0;
while( i<ArraySize(arrayRefsMyClassTest) ) { if( CheckPointer(arrayRefsMyClassTest[i])!=POINTER_INVALID ) Print("arrayRefsMyClassTest[" + i + "]: a = " + arrayRefsMyClassTest[i].a, ", b = " + arrayRefsMyClassTest[i].b + ", c = " + arrayRefsMyClassTest[i].c); i = i + 1; }

Print("Присваиваю последнему элементу ссылку во втором элементе");
i =  ArraySize(arrayRefsMyClassTest) - 1;
arrayRefsMyClassTest[i] = arrayRefsMyClassTest[2];

i = 0;
while( i<ArraySize(arrayRefsMyClassTest) ) { if( CheckPointer(arrayRefsMyClassTest[i])!=POINTER_INVALID ) Print("arrayRefsMyClassTest[" + i + "]: a = " + arrayRefsMyClassTest[i].a, ", b = " + arrayRefsMyClassTest[i].b + ", c = " + arrayRefsMyClassTest[i].c); i = i + 1; }

Print("Присваиваю 2 элементу ссылку в 5 элементе");
arrayRefsMyClassTest[1] = arrayRefsMyClassTest[5];

i = 0;
while( i<ArraySize(arrayRefsMyClassTest) ) { if( CheckPointer(arrayRefsMyClassTest[i])!=POINTER_INVALID ) Print("arrayRefsMyClassTest[" + i + "]: a = " + arrayRefsMyClassTest[i].a, ", b = " + arrayRefsMyClassTest[i].b + ", c = " + arrayRefsMyClassTest[i].c); i = i + 1; }

Print("\nТест операций над массивом ссылок на классы: конец");
Obtive estes resultados no diário de bordo:
Тест операций над массивом ссылок на классы: начало
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[0]: a = 0, b = 3.14, c = testclass0
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[1]: a = 1, b = 4.14, c = testclass1
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[2]: a = 2, b = 5.14, c = testclass2
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[3]: a = 3, b = 6.14, c = testclass3
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[4]: a = 4, b = 7.14, c = testclass4
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: Изменяем размер массива ссылок на классы
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[0]: a = 0, b = 3.14, c = testclass0
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[1]: a = 1, b = 4.14, c = testclass1
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[2]: a = 2, b = 5.14, c = testclass2
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[3]: a = 3, b = 6.14, c = testclass3
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[4]: a = 4, b = 7.14, c = testclass4
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: Присваиваю последнему элементу ссылку во втором элементе
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[0]: a = 0, b = 3.14, c = testclass0
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[1]: a = 1, b = 4.14, c = testclass1
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[2]: a = 2, b = 5.14, c = testclass2
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[3]: a = 3, b = 6.14, c = testclass3
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[4]: a = 4, b = 7.14, c = testclass4
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[6]: a = 2, b = 5.14, c = testclass2
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: Присваиваю 2 элементу ссылку в 5 элементе
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[0]: a = 0, b = 3.14, c = testclass0
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[1]: a = 4, b = 7.14, c = testclass4
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[2]: a = 2, b = 5.14, c = testclass2
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[3]: a = 3, b = 6.14, c = testclass3
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[4]: a = 4, b = 7.14, c = testclass4
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[6]: a = 2, b = 5.14, c = testclass2
Тест операций над массивом ссылок на классы: конец
Parece funcionar como pretendido. Cópias supérfluas de dados neste caso, como eu entendo, não são criadas. Se eu estiver errado, por favor, me corrija. Talvez haja algum comentário ou esclarecimento?
 
Como a MQL5 (ou WinAPI) pode expandir o gráfico para tela cheia???
 
GitSM:
Até onde entendi, para implementar tal mecanismo de "embaralhar" referências a estruturas em uma matriz, essas estruturas devem ser implementadas através de classes.

Sim, infelizmente, você não pode fazer indicações de estruturas em MQL. Não está claro porque tal limitação é feita, se você pode fazer isso com aulas. Afinal de contas, as estruturas não diferem muito das classes.