Qualquer pergunta de novato, de modo a não desorganizar o fórum. Profissionais, não passem por aqui. Em nenhum lugar sem você - 6. - página 641

 
simpleton:

Por que emular um erro?

Erro - é para sinalizar que, por alguma razão relacionada às limitações/falhas do sistema, o algoritmo não pôde ser executado e o resultado obtido com algumas (limitadas, é claro, mas - ) garantias. A função FillAndPrint() mostra de forma eloqüente o que significa uma situação de erro e o que não significa. Quando ocorre um erro, ele não tenta sequer imprimir o resultado. Se não houver erro, o resultado pode ser confiável. É assim que a lógica erro/não erro deve ser construída.

Você precisa modificar o algoritmo aqui: você precisa aplicar um filtro adicional.

É assim que deve ser feito:

Primeiro, "filtramos" por tipos de objetos e parâmetros, selecionando apenas os objetos que precisamos de todos os disponíveis, e depois aplicamos um filtro adicional. É mais ou menos como uma pessoa o faria. Isso é o que uma pessoa faria, certo?

Para cada sub-tarefa tão pequena, uma função separada é desejável.

Não deve haver números nas expressões, exceto em casos muito especiais, por exemplo, se você precisar dobrar e está na natureza do algoritmo para fazer isso. Então o número 2 pode ser usado diretamente em expressões. E em outros casos muito raros como este.

Em outros casos, a mnemônica deve ser utilizada. Em primeiro lugar, elas melhoram muito a compreensão do que está acontecendo em um determinado lugar e, portanto, ajudam a reduzir a probabilidade de se cometer um erro. Em segundo lugar, o próprio valor é definido em um só lugar e é fácil mudá-lo se necessário, e será impossível cometer um erro em relação ao caso em que o número é usado no algoritmo mais de uma vez, e sem usar a mnemônica você tem que corrigir os números em vários lugares do algoritmo.

Resultado da corrida:

Não é encontrado um único objeto. Aumentar os valores de ambos os mnemônicos 10 vezes para 36000 (10 horas), e executar novamente:

Uma tendência já "passou" a filtragem. Agora vamos restaurar o valor da primeira mnemônica para 3600 e correr:

Pode-se ver que ambas as tendências agora "passaram" pela filtragem. A propósito, recomendo depurar todos os ramos (partes) do programa de tal forma, ao invés de qualquer ramo.

Para ajudar a formalizar de alguma forma, vou tentar explicar desta forma. O programa é aparentemente como um plano.

Cada item do plano principal pode ser decomposto em itens menores do subplano. Os mais pequenos em ainda menores. Os itens dos menores sub-planos são executados diretamente.

Cada plano, sub-plano e até mesmo os menores sub-planos correspondem às funções do programa. Os itens nos menores sub-planos correspondem a funções "finais" que chamam apenas funções do sistema ou até mesmo não as chamam, por exemplo, AddValue() ou DiffInSecs() são exemplos daqueles discutidos acima. Os itens do subplano acima correspondem às funções que chamam as funções que implementam os itens do subplano abaixo. Nos discutidos acima, estes são MassTrendNumber(), AddValueIfFound(), AddValueIfFiltered(). Funções de "baixo nível" não devem chamar funções de "alto nível", e funções de "alto nível" basicamente não devem saltar vários níveis abaixo, ou seja, só devem chamar funções basicamente no nível abaixo. Esta regra é muito mais estrita para "baixo nível" do que para "alto nível".

Tente construir seus programas, organizando as ações neles como (curtas) funções ligadas por este tipo de estrutura em árvore, no sentido de quem chama quem.

Este programa tem uma árvore degenerada: um ramo que "ramifica" várias vezes. E "ramos" não em dois pequenos ramos, mas em um só. Mas o ponto que as funções de "alto nível" chamam consistentemente de "baixo nível" pode ser visto. Nesta modificação, eu inseri mais um nível nesta estrutura, mais um "ramo não ramificado" - AddValueIfFiltered().

Estou colando o código pronto.

A tarefa: procurar linhas de tendência(OBJ_TREND) e registrar valores de preços relativos à barra atual em uma matriz. Filtrado contra a existência de parâmetros de tempo de objeto (OBJ_TREND).

#property strict

/******************************************************************************/
bool AddValue(double &array[], const double value) {
  const int size = ArraySize(array);

  if (ArrayResize(array, size + 1) != size + 1) {
    return false; // Ошибка, значение не может быть добавлено к массиву
  }

  array[size] = value; //записываем
  return true; // Нет ошибки, значение добавлено к массиву
}

/******************************************************************************/
bool AddValueIfFound(double &array[], const string name) {
  const int type = ObjectType(name);

  if (type == OBJ_TREND) {
    switch ((color)ObjectGet(name, OBJPROP_COLOR)) { // Тип color допустимо использовать в switch
    case Goldenrod:
    case Gainsboro:
    case White:
      if (!AddValueIfFiltered(array, name)) { // Пропускаем через фильтр
        return false;
      }
    }
  }

  return true; // Нет ошибки, значение, если найдено, добавлено к массиву
}
/******************************************************************************/
bool MassTrendNumber(double &array[], const bool buy) { // Поиск значения цены трендовой линии, текущего бара, запись в массив. Два массива: masS и masB
  const string subname = (buy ? "uptrendline" : "downtrendline"); // существует два названия трендовых линий, первое и второе

  if (ArrayResize(array, 0) != 0) {
    return false; // Ошибка, массив не может быть заполнен достоверно
  }

  for (int i = 0, limit = ObjectsTotal(OBJ_TREND); i < limit+2; i++) {
    if (!AddValueIfFound(array, subname + IntegerToString(i))) {
      return false; // Ошибка, массив, если и заполнен, то недостоверно
    }
  }
 
  return true; // Нет ошибки, массив заполнен достоверно
}
/******************************************************************************/
long DiffInSecs(const datetime dt1, const datetime dt2) {
  return dt1 - dt2;
}
/******************************************************************************/
bool AddValueIfFiltered(double &array[], const string name) {
#define MIN_SECS_BETWEEN_PRICE1_AND_PRICE2 3600
#define MAX_SECS_AFTER_PRICE2              3600

  const datetime dt1 = (datetime)ObjectGet(name, OBJPROP_TIME1);
  const datetime dt2 = (datetime)ObjectGet(name, OBJPROP_TIME2);
  const datetime dt = TimeCurrent();
  
  Print("name = ", name,// ", dt = ", dt, ", dt1 = ", dt1,"\n", 
  " DiffInSecs = ", DiffInSecs(dt,dt2)," DiffInSecs = ", DiffInSecs(dt2,dt1));

   if( DiffInSecs(dt,dt2)>MAX_SECS_AFTER_PRICE2 && DiffInSecs(dt2,dt1)> MIN_SECS_BETWEEN_PRICE1_AND_PRICE2){
    if (!AddValue(array, ObjectGetValueByShift(name, 1))) { // Пытаемся добавить
      return false; // Ошибка, значение не добавлено
    }
  }

  return true; // Нет ошибки, значение, если удовлетворило условию фильтра, добавлено к массиву
}

/******************************************************************************/
void FillAndPrint(double &array[], const bool buy) {
  if (MassTrendNumber(array, buy)) {
    const int limit = ArraySize(array);

    Print("Найдено объектов: ", limit);

    for (int i = 0; i < limit; i++) {
      Print("Price[", i, "] = ", DoubleToStr(array[i], Digits));
    }
  } else {
    Print("Чёрт!");
  }
}

/******************************************************************************/
void OnTick()

//=============================================================================================
//====================================== Линии тренда =========================================
//=============================================================================================
 double masS[]; double masB[];

  Print("Sell:");
  FillAndPrint(masS, false);

  Print("Buy:");
  FillAndPrint(masB, true);
 simpletonСпасибо вам большое, вы за пестовали меня на ощущения правильного кода!) (Правда я немногое понял))))
 
evillive:

Tenho agora 4 dígitos, no ewardollar a 1 ponto do lote 1 custa $10 e sempre foi assim. Para os cruzamentos o custo será de 8 a 16, a fórmula é um pouco mais complicada lá.

Por exemplo, para o mercado da libra esterlina, a taxa de câmbio libra-dólar = 1,6984, ou seja, 1 pip da libra esterlina vale 1 libra, multiplicado pelo valor em pontos da libra esterlina, que é sempre 10,0 (100000 * 0,0001 = 10,0 ou 100000 * 0,00010 = 10,0 - o que quer que se goste).


Todos estes cálculos estão corretos somente se sua conta estiver em dólares:

Neste caso, para xUSD (EURUSD, GBPUSD etc.) tickvalue = lote*ponto = 100000*0,0001 = 10,0

para USDh (USDCHF, USDJPY etc.) tickvalue = lote*ponto/Bid = 100000*0.01/101.93=9.8107

para xUSD/yUSD (EURGBP) tickvalue = Bid(yUSD)*lot*point = 1,6980*100000*0,0001 = 16,98

para xUSD/USDy (EURJPY) tickvalue = lote*ponto/Bid(USDy) = 100000*0.01/101.91 = 9.8126


Algo que você estragou! Levou tempo para examinar o código, expressões selecionadas e olhar:

  double TV = MarketInfo(Symbol(),MODE_TICKVALUE); 
  string sTV = DoubleToStr(TV,4); 
  Comment("TV ",sTV); //sTV = 1.0/Bid

Não poderia ser mais simples! No 10, 16, etc.

 
evillive:

Tenho agora 4 dígitos, no ewardollar a 1 ponto do lote 1 custa $10 e sempre foi assim. Para os cruzamentos o custo será de 8 a 16, a fórmula é um pouco mais complicada lá.

Por exemplo, para o mercado da libra esterlina, a taxa de câmbio libra-dólar = 1,6984, ou seja, 1 ponto da libra esterlina vale 1 libra, multiplicado pelo valor do ponto libra-dólar, que é sempre 10,0 (100000 * 0,0001 = 10,0 ou 100000 * 0,00010 = 10,0 - o que quiserem).


Todos estes cálculos estão corretos somente se sua conta estiver em dólares:

Neste caso, para xUSD (EURUSD, GBPUSD etc.) tickvalue = lote*ponto = 100000*0,0001 = 10,0

para USDx (USDCHF, USDJPY etc.) tickvalue = lote*ponto/Bid = 100000*0.01/101.93 = 9.8107

para xUSD/yUSD (EURGBP) tickvalue = Bid(yUSD)*lot*point = 1,6980*100000*0,0001 = 16,98

para xUSD/USDy (EURJPY) crosses tickvalue = lote*ponto/Bid(USDy) = 100000*0.01/101.91=9.8126




Isto está errado! O valor de uma cotação não importa!E o valor de um tick min. deve ser calculado a partir do preço atual! O que é igual a TICK_VALUE! Acima está um exemplo do meu código.
 
borilunad:

borilunad:

Isto está errado! O valor de uma cotação é irrelevante! E o valor de um min.tick deve ser calculado a partir do preço atual! O que é igual a TICK_VALUE! Acima está um exemplo do meu código.

Como isso está errado? Marketinfo retorna os mesmos valores que as fórmulas que eu dei acima. Eu não inventei essas fórmulas, elas são usadas pelo terminal para calcular o TickValue))))

É claro que é mais conveniente tirar o valor do Marketinfo, mas ele estava pedindo fórmulas ou métodos de cálculo.

E sobre o valor que escrevi anteriormente, que não importa, porque em 5 dígitos conta um ponto = 10 pips, e é o mesmo ponto a partir de 4 dígitos.

 
evillive:

Como isso está errado? Marketinfo retorna os mesmos valores que as fórmulas que eu dei acima. Eu não inventei essas fórmulas, elas são usadas pelo terminal para calcular o TickValue))))

É claro que é mais conveniente tirar o valor do Marketinfo, mas ele estava pedindo fórmulas ou métodos de cálculo.

E escrevi anteriormente sobre significação, que não importa, porque em 5 dígitos conta um ponto = 10 pips, e este é o mesmo ponto a partir de 4 dígitos.


É isso que quero dizer comMarketInfo(Symbol(),MODE_TICKVALUE) =1.0/Bid;Talvez apenas para Eurodollar, eu não o pulverizo em outros!
 
borilunad:

É isso que quero dizer comMarketInfo(Symbol(),MODE_TICKVALUE) =1.0/Bid;Talvez, apenas para Euro, não para outros!

Isto é exatamente o que está errado com o Eurodollar, com base na definição dada na ajuda

MODE_TICKVALUE

16

Mudança mínima do preço da segurança na moeda do depósito


E isso significa multiplicar-se

MODE_POINT

11

Tamanho do ponto na moeda de cotação. Pois o símbolo atual é armazenado na variável pré-definida Ponto


por

MODE_LOTSIZE

15

Tamanho do contrato na moeda base do instrumento


Naturalmente, se sua conta está em Euro, você deve usar Euro como moeda base, mas para os comerciantes que têm uma conta em Dólar (na maioria das vezes eles têm), as fórmulas acima são válidas. Como os pares principais e mais negociados são baseados no dólar americano, estas fórmulas são mais freqüentemente utilizadas.

 
evillive:

Isto é exatamente errado, com base na definição dada na ajuda

MODE_TICKVALUE

16

Mudança mínima do preço do símbolo na moeda do depósito


Isso significa que esse valor deve ser multiplicado por

MODE_POINT

11

Tamanho do ponto na moeda de cotação. Pois o símbolo atual é armazenado na variável pré-definida Ponto


em

MODE_LOTSIZE

15

Tamanho do contrato na moeda base do instrumento


É claro, se sua conta está em euros, você deve usar euros, mas a maioria dos comerciantes tem uma conta em dólares.


Bem, então, eu tenho um caso especial, mas para mim que vivo na zona do euro, é mais conveniente fazer todos os cálculos em euros!
 

Senhores, por favor, me dêem um exemplo de código para o seguinte indicador. Não consigo descobrir quantos amortecedores são necessários, que tipo de mapeamento e onde e que propriedades devem ser prescritos para eles.

O indicador é o seguinte:

1 As barras conectam-se pelo menos a cada três barras e barras adjacentes. A linha é vermelha.

2 seções de barra conectam os máximos de cada 5ª barra e barras adjacentes. A linha é azul.

O principal: os segmentos não se cruzam de forma alguma. O início e o fim de cada segmento são independentes dos outros segmentos.

O indicador calcula os valores do início e do fim de cada segmento. Elas devem ser coloridas de forma diferente dependendo das condições.

Isto é mais ou menos o que deveria parecer


 

E outra pergunta.

É normal que eu não possa trabalhar com o indicador no modo Debug.

Quando o programa atinge o ponto de parada, o terminal MT4 fica pendurado e a janela fica branca (em HP) de modo que é impossível ver o que está desenhado na tabela

 
Top2n:

Aqui está o código pronto.

Tarefa: Pesquisar linhas de tendência (OBJ_TREND), registrar valores de preços relativos à barra atual em uma matriz. Com relação à filtragem com respeito à existência de parâmetros de tempo do objeto (OBJ_TREND).

simpleton:Muito obrigado, você mefez sentir o código certo!) (Embora eu não tenha entendido muito))))

Se você praticar, a compreensão virá, cada vez mais e mais. É preciso concentração e atenção. Quando o algoritmo do programa é manchado em uma grande função, é difícil realizá-lo com concentração e atenção - demasiados elos são formados. Mas se um programa é dividido em partes funcionais completas (pequenas funções), é muito mais fácil fazer isto para cada pequena função separada. E assim, em cada nível de função. A propósito:

   if( DiffInSecs(dt,dt2)>MAX_SECS_AFTER_PRICE2 && DiffInSecs(dt2,dt1)> MIN_SECS_BETWEEN_PRICE1_AND_PRICE2){
    if (!AddValue(array, ObjectGetValueByShift(name, 1))) { // Пытаемся добавить
      return false; // Ошибка, значение не добавлено
    }
  }
Eu devo ter dado um nome errado à mnemônica MAX_SECS_AFTER_PRICE2 (porque a princípio entendi que a condição deve ser inversa), o significado provavelmente deveria ser MIN_SECS_AFTER_PRICE2, ou seja, o mínimo permitido, não o máximo.