Erros, bugs, perguntas - página 2452

 
A100:

A que copia as matrizes não é pelas regras a = b, mas pelas regras doArrayCopy( a, b )

Foi você que o inventou ou está escrito algures?
Deixem-me lembrar-vos que se trata de um operador implícito para estruturas com matrizes dinâmicas.

 
Sergey Dzyublik:

Foram eles próprios que o inventaram ou está escrito algures?
Deixem-me lembrar-vos, é o trabalho de operador de atribuição implícita para estruturas com matrizes dinâmicas.

A ideia não foi minha, foi dos Desenvolvedores.

        uchar a[], b[]; a = b; //Error: invalid array access
Porque é que existe um erro? Envolveu-o numa estrutura e o erro desapareceu? E porquê? O que mudou fundamentalmente? As minhas respostas acima
 
Alexey Viktorov:

É apenas uma questão de organizar a sequência de acções e eventos.

Você mesmo citou do manual, que diz que a consistência não é garantida. É por isso que é arriscado.

Já comecei a reescrever o código de acordo com o conselho de Vladimir, mas tropecei num caso quando o fecho é mais longo do que um tick - contagem dupla novamente (o nó de filtro na contagem é muito pesado). Até agora não encontrei nada melhor do que parar antes de fechar completamente por uma questão de compromisso com a velocidade de optimização.

É sexta-feira :) Talvez depois de algum descanso eu pense em algo.

Em qualquer caso, obrigado pelas ideias - elas não se perderão!

 
A100:

A ideia não foi minha, foi dos Desenvolvedores.

Nunca compreendi onde foi escrito, mas não importa...
Obrigado pelo colívar.

Apoiou-a com uma muleta e continuou a correr:

struct MyArray{
   uchar data[];
   
   void operator=(MyArray &bytes){
      ArrayCopy(this.data, bytes.data);
      ArrayResize(this.data, ArraySize(bytes.data));
   }
};


MyArray GetArray(int i){
   MyArray arr;
   
   if (i%2 == 0){
      ArrayResize(arr.data, 8);
      ArrayInitialize(arr.data, 0x8);
   }else{
      ArrayResize(arr.data, 4);
      ArrayInitialize(arr.data, 0x4);
   }
   return arr;
}


void OnStart(){
   MyArray arr_1 = GetArray(1);
   ArrayPrint(arr_1.data);        // 4 4 4 4
   
   MyArray arr_2 = GetArray(2);
   ArrayPrint(arr_2.data);        // 8 8 8 8 8 8 8 8
   
   arr_2 = arr_1;
   ArrayPrint(arr_2.data);        // 4 4 4 4            
}
 
Igor Zakharov:

Você mesmo citou do manual, que diz que a consistência não é garantida. É por isso que é arriscado.

Já comecei a reescrever o código de acordo com o conselho de Vladimir, mas tropecei num caso quando o fecho é mais longo do que um tick - contagem dupla novamente (o nó de filtro na contagem é muito pesado). Até agora não encontrei nada melhor do que parar antes de fechar completamente por uma questão de compromisso com a velocidade de optimização.

É sexta-feira :) Talvez depois de algum descanso eu pense em algo.

De qualquer forma, obrigado pelas ideias - não vão para o lixo!

Eu estava a falar da minha própria consistência.

De acordo com as minhas observações, acontece que após a OnTick, quando a transacção ocorre, a execução do código é passada para a função OnTradeTransaction sem esperar pelo próximo tick. Por conseguinte, não há diferença no processamento do fecho pelas suas próprias funções ou pela OnTradeTransaction. Mas eu prefiro trabalhar com aOnTradeTransaction. O principal é organizar correctamente a sequência de operações sem depender da sequência de transacções provenientes do servidor. E é importante compreender correctamente esta sequência. Mais uma vez, de acordo com as minhas próprias observações, a sequência pode ser quebrada no tipo de transacção. Isto é, TRADE_TRANSACTION_DEAL_ADD pode ser executado primeiro , e depois TRADE_TRANSACTION_HISTORY_ADD, enquanto que logicamente uma ordem deve ser adicionada primeiro à história e depois uma transacção.

ps; depois, como eu disse, ao rastrear a transacção TRADE_TRANSACTION_DEAL_ADD pode rastrear por abertura de posição e por fecho de posição. Afinal, estamos a falar de um Expert Advisor para o mercado cambial e de uma conta, certo? Portanto, não há necessidade de recalcular todas as posições a cada espirro. Basta adicionar um se foi aberto, ou eliminar um dos contados se foi fechado.
 
Alexey Viktorov:

do mercado forex e da conta, certo?

Grelha :) Sim.

A lógica actual é a seguinte: existe uma estrutura que armazena toda a informação sobre cada grelha: símbolo-número de posições-lucro e algumas outras coisas sem importância... O lucro é recalculado por temporizador, se houver encomendas (robô multisímbolos). Mas lotes e quantidades foram recalculados na OnTradeTransaction (no caso de o utilizador "ajudar").

Queria verificar um caso quando uma grelha, por exemplo, está em lucro por 100$, e a outra está em prejuízo por 50$ - para fechar ambas com um lucro de 50$ para evitar que crescesse.

De momento, já o fiz:

void  OnTradeTransaction(
   const MqlTradeTransaction&    trans,     // trade transaction structure 
   const MqlTradeRequest&        reqst,     // request structure 
   const MqlTradeResult&         reslt      // response structure 
    )
{
 int index=-1;
 for(index=0;index<symbols_total;index++)
  if(ARRAY[index].symbol==trans.symbol) break; //нашли индекс символа по которому прошла трансакция в массиве структур
 
 if(index>=0) CountOrders(index); //пересчитали элемент
}

Até agora adicioneiCountOrders()depois de fechar um par de grelhas. Para um Testador de Estratégia, funciona. Para uma conta real vou utilizar o esquema de Vladimir (com uma série de bilhetes fechados).

A propósito, o encerramento de pares não se justificou - o saque não diminui consideravelmente, enquanto que o lucro diminui decentemente.

 
Vladimir Karputov:

Eu desistiria de TODOS enquanto, Sleep e OnTimer para a tarefa de fechar posições. Eu faria o seguinte: disparar ordens para fechar - sair do OnTick, na próxima verificação do tick: se as posições com bilhetes necessários ainda estiverem vivas - disparar ordens para fechar novamente e assim por diante num círculo através da entrada/saída para o OnTick.

A lógica é a seguinte: o fecho de uma posição é a primeira prioridade, pelo que o ciclo de fecho está no início do OnTick. E a formação de uma série de bilhetes de encerramento pode ser em qualquer lugar do OnTick - mesmo no final.

Mais cedo ou mais tarde, acabará com o seguinte: precisa de fechar uma posição, é enviada uma ordem para fechar (MQL5), ou seja, é enviada uma ordem do tipo oposto, uma vez que não está a seguir as acções de negociação no manipulador apropriado (ou não está a guardar o estado da posição na sua EA) e no tick seguinte uma ordem para fechar pode estar em processo de ser enviada e enviará outra ordem. O resultado é uma posição na direcção oposta.

 
Alexey Kozitsyn:

Mais cedo ou mais tarde, acabará com o seguinte: precisa de fechar uma posição, envia uma ordem de fecho (MQL5), ou seja, envia uma ordem do tipo oposto, uma vez que não acompanha as acções comerciais no manipulador correspondente (ou não guarda o estado da posição na sua EA) e no tick seguinte uma ordem de fecho pode estar em processo de ser enviada, mas envia outra ordem. O resultado é uma posição na direcção oposta.

Para um caso destes, temos:

10036

TRADE_RETCODE_POSITION_CLOSED

Aposição com o POSITION_IDENTIFIERespecificado já foi encerrada

A posição de encerramento é enviada com o bilhete da posição a ser fechada, por isso é improvável que a posição descrita venha a acontecer.

 
Sergey Dzyublik:

Nunca compreendi onde está escrito, mas não importa...
Obrigado pelo colívar.

Apoiou-a com uma muleta e continuou a correr:

Bem, é estranho como as matrizes são copiadas, mas algumas pessoas até gostam...

Fiz um embrulho mais ou menos adequado sobre uma matriz e não tenho problemas.

https://www.mql5.com/ru/forum/221917/page26#comment_11233214

 
A100:

A ideia não foi minha, foi dos Desenvolvedores.

Não me lembro de alguma vez o terem dito.

O operador de atribuição destina-se a criar uma cópia idêntica de um objecto. É esse o seu objectivo. Quando se equipara algo a algo, deve obviamente obter uma cópia completa do lado esquerdo, e não outra coisa qualquer. Por isso, há obviamente um bug aqui.