Errores, fallos, preguntas - página 442

 
voix_kas:

¿Alguien tiene un código listo para calcular el número de dígitos significativos de un volumen?
Algo como SymbolInfoInteger(_Symbol, SYMBOL_DIGITS), pero sólo para el volumen.
Por ejemplo, para el caso SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_STEP) = "1,0" - la respuesta sería "0", para "0,1" - "1", para "0,01" - "2", etc.

Permítanme aclarar un matiz. Para un paso de volumen como "0,1", "0,01", "0,001" tengo.

El código debería funcionar para los siguientes casos como "0,2", "0,11", 0,023" etc.

No existe un código específicopara el volumen. Hay para todo.

int CountSignedDigits(double x)
{  
  for(int i=0; i<1000; i++,x*=10) if(x-MathFloor(x)<DBL_MIN*2) return i;
  return -1;
}
El guión es para comprobarlo en el tráiler.
Archivos adjuntos:
_UniTest.mq5  2 kb
 
MetaDriver:
Un guión para comprobar en el tráiler.
Quiere decir que..., pensé que debía comprobar el lote aceptable antes de hacer un pedido.
 
sergeev:
Quiere decir que..., y pensé que debía comprobar el lote permitido antes de hacer un pedido.

;)

No sé realmente lo que quiere. Veremos lo que dice. Sólo estoy practicando mi telepatía. ;)

 
voix_kas:

¿Alguien tiene un código listo para calcular el número de cifras significativas de un volumen?
Algo como SymbolInfoInteger(_Symbol, SYMBOL_DIGITS), pero sólo para el volumen.
Por ejemplo, para el caso SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_STEP) = "1.0" - la respuesta sería "0", para "0.1" - "1", para "0.01" - "2", etc.

Permítanme aclarar un matiz. Para un paso de volumen como "0,1", "0,01", "0,001" tengo.
El código debería funcionar para los siguientes casos como "0,2", "0,11", 0,023" etc.

Específicamente para los volúmenes puede ser sencillo:

      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

Una pregunta bien formulada es la mitad de la respuesta. :) Lo siento, ya me he acostado, no he descrito la tarea con precisión. Lo intentaré de nuevo.

Me refiero a pasar un volumen normalizado a una orden de comercio.
Es lo que hacemos con el precio:

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

La normalización de los precios, creo que está claro para todos.

En mi época (desde MT4), leí en algún artículo de MT que sería conveniente normalizar también el volumen.
En realidad, escribí la funciónGetVolumeDigits(string Symbol) para encontrar el menor valor posible de volumen según las condiciones del broker. Hay al menos dos implementaciones (el resultado es el mismo):
Aplicación nº 1.

int GetVolumeDigits(string Symbol) {
  int VolumeDigits = 0;
  double VolumeStep = SymbolInfoDouble(Symbol, SYMBOL_VOLUME_STEP);
  while (VolumeStep < 1) {
    VolumeStep *= 10;
    VolumeDigits++;
  }
  return VolumeDigits;
}
Aplicación №2.

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

Ambos funcionan perfectamente para variantes con paso mínimo = 1,0, 0,1, 0,01, 0,001, etc. Es decir, si el paso mínimo es 1,0, la función devolverá 0; si el paso es 0,1, la función devolverá 1, etc.
¿Y si el paso mínimo es 1,1, o 0,11, o 0,011, por ejemplo? Este algoritmo mostrará incorrectamente el dígito menos significativo.
Por supuesto, se puede afirmar que en la práctica no se dan estos casos. Sólo quiero considerar tal posibilidad hipotética en mi Asesor Experto. Pensé que tal vez alguien podría compartir su experiencia en este asunto...

 
voix_kas:
Sí, lo entiendo, necesito que el resultado sea un múltiplo de VolumeStep. Bueno, no tiene nada que ver con Digits, primero calcula el volumen con Digits y luego lo reduce al múltiplo más cercano de VolumeStep.
 
voix_kas:

Se trata de enviar el volumen normalizado a la orden de comercio.
Sólo quiero considerar esta posibilidad hipotética en nuestro Asesor Experto.

¿de qué herramienta "hipotética" estamos hablando?

1. La variante de MetaDriver es adecuada para usted. CountSignedDigits mostrará el número de caracteres de cualquier lote.

2. Conociendo el número de dígitos se puede hacer la normalización:

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
Gracias por la función de validación del lote. Estoy utilizando una construcción/ramificación de cheques similar.
Mi pregunta se centra en encontrar el lugar más joven del lote, para normalizarlo.
En particular, MetaDriver dio su construcción para "todo". :) Sin embargo, no está exento de defectos (o mi compilador tiene fallos). A continuación se muestra el código y el resultado de la ejecución:

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

Siguiente opción (la función CountSignedDigits es la misma):

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
 

Se ha cambiado la siguiente línea en 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

O bien estoy haciendo algo mal (por favor, corríjanlo), o MetaDriver se equivocó en la teoría (al diseñar el algoritmo).

 
voix_kas:

Mi pregunta se centra en determinar el lugar más bajo del lote para normalizarlo.

No es necesario definir la excavación para el lote, sólo hay que normalizarlo al paso correcto:
   lot = NormalizeDouble( lot / lot_step, 0 ) * lot_step;
   if ( lot < lot_min ) lot = lot_min;
   if ( lot > lot_max ) lot = lot_max;


Incluso, si al enviar una solicitud de operación, la variable lote se pone en blanco (en el segundo decimal), será rechazada por el propio terminal.

Al menos, no he tenido ningún problema durante varios años de uso de este diseño.


Y si se quiere reasegurar, se puede normalizar hasta el octavo decimal (con reserva) - si después de la normalización "correcta" aparece basura, será mucho más.

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