Erros, bugs, perguntas - página 442

 
voix_kas:

Alguém tem um código pronto para calcular o número de dígitos significativos para um volume?
Algo como SymbolInfoInteger(_Symbol, SYMBOL_DIGITS), mas apenas para volume.
Por exemplo, para o caso SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_STEP) = "1.0" - a resposta seria "0", para "0.1" - "1", para "0.01" - "2", etc.

Deixem-me esclarecer uma nuance. Para um passo de volume como "0.1", "0.01", "0.001" eu tenho.

O código deve funcionar para os seguintes casos como "0.2", "0.11", 0.023", etc.

Não existe um código específicopara o volume. Há para tudo.

int CountSignedDigits(double x)
{  
  for(int i=0; i<1000; i++,x*=10) if(x-MathFloor(x)<DBL_MIN*2) return i;
  return -1;
}
O guião é para verificação no reboque.
Arquivos anexados:
_UniTest.mq5  2 kb
 
MetaDriver:
Um guião para verificar no reboque.
Quer dizer que..., eu pensei que devia verificar o lote aceitável antes de fazer uma encomenda.
 
sergeev:
Quer dizer que..., e eu pensei que devia verificar o lote admissível antes de fazer uma encomenda.

;)

Eu não sei realmente o que ele quer. Vamos ver o que ele diz. Estou apenas a praticar a minha telepatia. ;)

 
voix_kas:

Alguém tem um código pronto para calcular o número de dígitos significativos para um volume?
Algo como SymbolInfoInteger(_Symbol, SYMBOL_DIGITS), mas apenas para volume.
Por exemplo, para o caso SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_STEP) = "1.0" - a resposta seria "0", para "0.1" - "1", para "0.01" - "2", etc.

Deixem-me esclarecer uma nuance. Para um passo de volume como "0.1", "0.01", "0.001" eu tenho.
O código deve funcionar para os seguintes casos como "0.2", "0.11", 0.023", etc.

Especificamente para volumes pode ser simples:

      int N=0;
      double step=SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP);
      if(step-1.0<0)  N++;
      if(step-0.1<0)  N++;
      if(step-0.01<0) N++;
 

sergeev
MetaDriver
Valmars

A pergunta bem formulada é metade da resposta. :) Desculpe, já fui para a cama, não consegui descrever a tarefa com precisão. Vou tentar novamente.

Estou a falar de passar um volume normalizado para uma ordem comercial.
É o que fazemos com o preço:

MqlTradeRequest TradeRequest;
...
TradeRequest.volume = NormalizeDouble(Volume, GetVolumeDigits(_Symbol));
TradeRequest.price  = NormalizeDouble(Price, SymbolInfoInteger(_Symbol, SYMBOL_DIGITS));
...

Normalização dos preços - penso que é claro para todos.

Na minha época (desde MT4), li algures nos artigos de MT que seria desejável normalizar também o volume.
Na verdade, escrevi a funçãoGetVolumeDigits(string Symbol) para encontrar o menor valor de volume possível, de acordo com as condições do corretor. Há pelo menos duas implementações (o resultado é o mesmo):
Implementação #1.

int GetVolumeDigits(string Symbol) {
  int VolumeDigits = 0;
  double VolumeStep = SymbolInfoDouble(Symbol, SYMBOL_VOLUME_STEP);
  while (VolumeStep < 1) {
    VolumeStep *= 10;
    VolumeDigits++;
  }
  return VolumeDigits;
}
Implementação №2.

int GetVolumeDigits(string Symbol) {
  return (int)MathLog10(1.0 / SymbolInfoDouble(Symbol, SYMBOL_VOLUME_STEP));
}

Ambos funcionam perfeitamente para variantes com passo min = 1,0, 0,1, 0,01, 0,001, etc. Isto é, se o passo mínimo for 1,0, a função retornará 0; se o passo for 0,1, a função retornará 1, etc.
E se o passo mínimo for 1,1, ou 0,11, ou 0,011, por exemplo? Este algoritmo irá mostrar incorrectamente o dígito menos significativo.
É claro que se pode afirmar que não existem tais casos na prática. Quero apenas considerar tal possibilidade hipotética no meu Conselheiro Especialista. Pensei que talvez alguém partilhasse a sua experiência nesta matéria.

 
voix_kas:
Sim, já percebi, preciso que o resultado seja um múltiplo do VolumeStep. Bem, não tem nada a ver com Dígitos, primeiro calcule o volume com Dígitos e depois reduza-o para o múltiplo mais próximo de VolumeStep.
 
voix_kas:

Trata-se de enviar o volume normalizado para a ordem de comércio.
Quero apenas considerar esta possibilidade hipotética no nosso Consultor Especialista.

de que ferramenta "hipotética" estamos a falar?

1. A variante do MetaDriver é adequada para si. CountSignedDigits mostrará o número de caracteres em qualquer lote.

2. Conhecendo o número de dígitos, pode fazer a normalização desta forma:

double MinLot; // минимальный лот по символу
double MaxLot; // максимальный лот по символу
double LotStep; // шаг лота по символу
int dig; // знаковость лота узнали из функции CountSignedDigits

double NL(double lot)
{
  if (lot<=MinLot) return(MinLot); // проверка на минимальный
  double d=MathFloor((lot-MinLot)/StepLot); // сколько ЦЕЛЫХ шагов умещается в проверяемом лоте
  lot=MinLot+StepLot*d; // рассчитали по этому целому числу
  lot=MathMin(lot, MaxLot);  lot=NormalizeDouble(lot, dig);// не забыли проверить на максимальный // нормализовали
  return(lot); // вернули
}
 

sergeev
Obrigado pela função de validação do lote. Estou a utilizar uma construção/branqueamento de cheques semelhante.
A minha pergunta centra-se em encontrar o lugar mais novo no lote, para o normalizar.
Em particular, o MetaDriver deu a sua construção para "tudo". :) No entanto, não está sem falhas (ou o meu compilador está com falhas). Abaixo está o código e o resultado da execução:

void OnStart() {
  Print(CountSignedDigits(110.0));
  Print(CountSignedDigits(11.0));
  Print(CountSignedDigits(1.1));
  Print(CountSignedDigits(0.11));
  Print(CountSignedDigits(0.011));
  Print(CountSignedDigits(0.0011));
  Print(CountSignedDigits(0.00011));
}

int CountSignedDigits(double x) {  
  for (int i = 0; i < 1000; i++, x *= 10)
    if (x - MathFloor(x) < DBL_MIN * 2)
      return i;
  return -1;
}

Resultado:

2011.07.03 13:15:21     test (EURUSD,M5)        5
2011.07.03 13:15:21     test (EURUSD,M5)        4
2011.07.03 13:15:21     test (EURUSD,M5)        18      -    Здесь только у меня бяка вылазиет?
2011.07.03 13:15:21     test (EURUSD,M5)        2
2011.07.03 13:15:21     test (EURUSD,M5)        1
2011.07.03 13:15:21     test (EURUSD,M5)        0
2011.07.03 13:15:21     test (EURUSD,M5)        0

A opção seguinte (a função CountSignedDigits é a mesma):

void OnStart() {
  double value = 110.0;
  int count = 9;
  while (count) {
    Print(DoubleToString(value), " - ", CountSignedDigits(value));
    value /= 10;
    count--;
  }
}

Resultado:

2011.07.03 13:23:32     test (EURUSD,M5)        0.00000110 - 22       -   Почему-то здесь бяка...
2011.07.03 13:23:32     test (EURUSD,M5)        0.00001100 - 21       -
2011.07.03 13:23:32     test (EURUSD,M5)        0.00011000 - 5
2011.07.03 13:23:32     test (EURUSD,M5)        0.00110000 - 4
2011.07.03 13:23:32     test (EURUSD,M5)        0.01100000 - 3        - Здесь уже все нормально. Почему результаты разные?!
2011.07.03 13:23:32     test (EURUSD,M5)        0.11000000 - 2
2011.07.03 13:23:32     test (EURUSD,M5)        1.10000000 - 1
2011.07.03 13:23:32     test (EURUSD,M5)        11.00000000 - 0
2011.07.03 13:23:32     test (EURUSD,M5)        110.00000000 - 0
 

Mudou a seguinte linha no OnStart:

double value = 210.0;

Resultado:

2011.07.03 13:28:01     test (EURUSD,M5)        0.00000021 - 23
2011.07.03 13:28:01     test (EURUSD,M5)        0.00000210 - 22
2011.07.03 13:28:01     test (EURUSD,M5)        0.00002100 - 21
2011.07.03 13:28:01     test (EURUSD,M5)        0.00021000 - 20
2011.07.03 13:28:01     test (EURUSD,M5)        0.00210000 - 19
2011.07.03 13:28:01     test (EURUSD,M5)        0.02100000 - 3
2011.07.03 13:28:01     test (EURUSD,M5)        0.21000000 - 2
2011.07.03 13:28:01     test (EURUSD,M5)        2.10000000 - 1
2011.07.03 13:28:01     test (EURUSD,M5)        21.00000000 - 0
2011.07.03 13:28:01     test (EURUSD,M5)        210.00000000 - 0

Ou estou a fazer algo errado (por favor, corrigir), ou o MetaDriver cometeu um erro em teoria (ao conceber o algoritmo).

 
voix_kas:

A minha pergunta centra-se em determinar o lugar mais baixo do lote para normalizá-lo.

Não é preciso definir cavar para o lote, apenas normalizá-lo para o passo certo:
   lot = NormalizeDouble( lot / lot_step, 0 ) * lot_step;
   if ( lot < lot_min ) lot = lot_min;
   if ( lot > lot_max ) lot = lot_max;


Mesmo que ao enviar um pedido comercial, o lote variável receba lixo (na segunda casa decimal), ele será rejeitado pelo próprio terminal.

Pelo menos, não tive quaisquer problemas durante vários anos de utilização deste desenho.


E se quiser ressegurá-lo, pode normalizá-lo até à 8ª casa decimal (com reserva) - se depois de aparecer o lixo "correcto" da normalização, será muito mais longe.

Документация по MQL5: Стандартные константы, перечисления и структуры / Структуры данных / Структура торгового запроса
Документация по MQL5: Стандартные константы, перечисления и структуры / Структуры данных / Структура торгового запроса
  • www.mql5.com
Стандартные константы, перечисления и структуры / Структуры данных / Структура торгового запроса - Документация по MQL5