Zero Divide (Encontrado el tema - pero ¿por qué?) - página 2

 
RaptorUK:

Si usted quiere pasar días ordenando esta simple cuestión, entonces por todos los medios siéntase libre.... Yo no lo haría.

Si sabe cuándo ocurre durante su prueba retrospectiva, entonces es fácil de encontrar... comience la prueba retrospectiva un día antes de la fecha en que ocurre... averigüe exactamente, al minuto, cuándo va a ocurrir... para todas las divisiones en su código... sí, todas ellas, añada un Print() antes de la línea que contiene la división que imprime el código... . sí, todas ellas, añada un Print() antes de la línea que contiene la división que imprime el divisor y una referencia a la línea de código en cuestión .

Por ejemplo:

Cuando tu código termine con el error de división por cero revisa el archivo de registro y en las últimas impresiones estará la impresión que muestra la línea de código que produjo el error y qué variable se puso a cero. . .

. . aprende a trabajar de forma más inteligente y persigue tus problemas de forma lógica y eficiente.


Os agradezco que me ayudéis y me indiquéis la dirección correcta para solucionar esto. He encontrado el problema (¡después de pasar un buen rato pegando huellas por todas partes!)

En realidad se debe al hecho de que mi corredor (ILQ) utiliza una alimentación nocional y la ayuda de un miembro de este foro en mi hilo con respecto a esto. En una cáscara de nuez este es el código de abajo - Con ILQ puede operar tan bajo como 1 unidad. Dentro de la ventana de transacciones de MT4 usted pondría el tamaño preciso de la unidad que desea (es decir, 0,01 || 874 unidades).

¿Puedes ayudarme a entender qué parte de esta fórmula va mal donde he puesto la flecha? La matemática se ve bien desde donde la estoy viendo?

//+------------------------------------------------------------------+
//| Order Enter Function                                             |
//+------------------------------------------------------------------+
void OrderEntry(int direction)
{
   //Padding for the stop and padding for the entry too. 
   double ATR_Pad = iATR(NULL,60,14,1)/2;
      if(ATR_Pad == 0.0)Print(" ATR_Pad = ", ATR_Pad); 
   double Buy_Pad = NormalizeDouble(ATR_Pad,Digits);
   double Sell_Pad = NormalizeDouble(ATR_Pad,Digits);
   
   //Get Highest Price in our lookback range and set buy price above it.
   int iTBT = iBarShift(NULL,60, triggerBarTime, true),
   iHH = iHighest(NULL,60, MODE_HIGH, iTBT + CandlesBeforeBiasObtained, 0);
   double Buy_Here = High[iHH] + Buy_Pad;
   double buyPrice= NormalizeDouble(Buy_Here,Digits);

   //Get Lowest Price in our lookback range and set sell price below it.
   int iTBT_1 = iBarShift(NULL, 60, triggerBarTime, true),
   iLL = iLowest(NULL, 60, MODE_LOW, iTBT_1 + CandlesBeforeBiasObtained, 0);
   double Sell_Here =Low[iLL] - Sell_Pad;
   double sellPrice = NormalizeDouble(Sell_Here,Digits);
   
   //Stop calculations.    
   double ATR = iATR(NULL,60,14,1);
   double MA = iMA(NULL,60,MA_Period,0,1,0,1);
   double BuyStopPriceMath = MA - ATR;
   double SellStopPriceMath = MA + ATR;
   double BuyStopPrice = NormalizeDouble(BuyStopPriceMath,Digits);
   double SellStopPrice = NormalizeDouble(SellStopPriceMath,Digits);

   //get our buystop price from below the ma and our takeprofit based on our r:r ratio.
   double pips_to_bsl = buyPrice-BuyStopPrice;
   double buy_tp_price=(pips_to_bsl*RewardRatio)+buyPrice;
   double buy_takeprofit_price= NormalizeDouble(buy_tp_price, Digits);

   //get our sellstop price from below the ma and our takeprofit based on our r:r ratio.
   double pips_to_ssl=SellStopPrice-sellPrice;
   double sell_tp_price=sellPrice-(pips_to_ssl*RewardRatio);
   double sell_takeprofit_price= NormalizeDouble(sell_tp_price, Digits);
   
   //Lot calculation - Facilitates Notional and Lots within MT4 - As well as find the tick value relative to the account denomination.   
   double risk_amount = AccountEquity( )*RiskPercent/100;
      if( risk_amount == 0.0 )Print(" risk_amount = ", risk_amount);
   double Lot_Step = MarketInfo(Symbol(), MODE_LOTSTEP);
   double ts = MarketInfo(Symbol(), MODE_TICKSIZE);
   double tv = MarketInfo(Symbol(), MODE_TICKVALUE);
   double minlot = MarketInfo(Symbol(), MODE_MINLOT);
         
   double loss_for_1_lot = pips_to_bsl/ ts * tv ; //<<<<<<<<<<<<<<<<<<<<<<<<<<< This is giving me a "0" randomly sometimes?
      if( loss_for_1_lot == 0.0 )Print(" loss_for_1_lot = ", loss_for_1_lot);
   //Alert(loss_for_1_lot);
   double LotSize_Buy = MathFloor( risk_amount / loss_for_1_lot/ Lot_Step) * Lot_Step ;
      if( LotSize_Buy == 0.0 )Print(" LotSize_Buy = ", LotSize_Buy);
   //Alert(LotSize_Buy);
      
   double loss_for_1_lot1 = pips_to_ssl/ ts * tv ;  //<<<<<<<<<<<<<<<<<<<<<<<<<<< This is giving me a "0" randomly sometimes?
      if( loss_for_1_lot1 == 0.0 )Print(" loss_for_1_lot1 = ", loss_for_1_lot1);
   //Alert(loss_for_1_lot1);
   double LotSize_Sell = MathFloor( risk_amount / loss_for_1_lot1/ Lot_Step) * Lot_Step ;
      if( LotSize_Sell == 0.0 )Print(" LotSize_Sell = ", LotSize_Sell);
   //Alert(LotSize_Sell);
 
DomGilberto:


Os agradezco que me ayudéis y me indiquéis cómo solucionar esto. He encontrado el problema (¡después de pasar un buen rato pegando huellas por todas partes!)

En realidad se debe al hecho de que mi corredor (ILQ) utiliza una alimentación nocional y la ayuda de un miembro de este foro en mi hilo con respecto a esto. En una cáscara de nuez este es el código de abajo - Con ILQ puede operar tan bajo como 1 unidad. Dentro de la ventana de transacciones de MT4 usted pondría el tamaño preciso de la unidad que desea (es decir, 0,01 || 874 unidades).

¿Puedes ayudarme a entender qué parte de esta fórmula va mal donde he puesto la flecha? La matemática se ve bien desde donde la estoy viendo?

Vale, he leído brevemente tu otro hilo sobre el cálculo alternativo del tamaño del lote pero no con suficiente detalle, pero en términos generales para solucionar este problema esto es lo que podría hacer....

¿Qué está causando el problema? ¿TS? ¿TV? ¿o ambos? Si cualquiera de ellos es 0.0 entonces el producto de TS y TV será 0.0... pero si sólo uno de ellos es devuelto ocasionalmente como 0.0 entonces sólo necesita abordar el problema con uno de ellos...


TickSize no cambiará (hasta donde yo sé)... no necesita seguir leyéndolo, léalo en init() pero compruebe que no está obteniendo un valor devuelto de 0.0, o siga leyéndolo si quiere pero sólo use lo que se devuelve si no es 0.0

TickValue puede cambiar, pero nunca debería ser 0.0, así que si lo lees y es 0.0 no actualices su valor... o inténtalo de nuevo y luego actualízalo.

No es ciencia de cohetes. . .

 

No entiendo por qué necesitas seguir preguntando sobre esto, el simple sentido común debería decirte que hagas lo que Raptor acaba de decir. Si resulta que ts*tv no es el problema imprime todas las demás variables que se utilizan como divisor.

 

@SDC - Ya lo he hecho lol? Ya he identificado de dónde viene, todo lo que estaba diciendo es que la fórmula para el tamaño del lote se ve bien para mí, y en lugar de ir por las ramas he publicado el código para ver si me estoy perdiendo algo?

Usted se dará cuenta en el código de la "<<<<" que indica lo que está imprimiendo un "0" o cero divide....

@ RaptorUK - gracias compañero, agradezco que lo hayas desglosado. Creo que sé cómo funciona de lo que estás diciendo - Voy a tener un juego con él en un poco y el informe para confirmar el problema se resuelve :)

 
Ok por lo que su "TickValue" que está regresando un "0".

He tratado de usar "static double tv = 0;" y luego asignar el valor de la garrapata dentro de "int init", y luego actualizar ese doble estático en cada nueva vela H1 si "tv==0", pero todavía no produce nada más que "0"? El par de divisas en cuestión es GBPJPY (Todo esto es dentro de Strategy Tester)

Perdón si estoy siendo lento...?
 
DomGilberto:
Ok por lo que su "TickValue" que está regresando un "0".

He intentado utilizar "static double tv = 0;" y luego asignar el valor de la garrapata dentro de "int init", y luego actualizar ese doble estático en cada nueva vela H1 si "tv==0", pero todavía no produce nada más que "0"? El par de divisas en cuestión es GBPJPY (Todo esto es dentro de Strategy Tester)

Perdón si estoy siendo lento...?
¿Por qué actualizaría el valor de tv si TICKVALUE ha devuelto un valor incorrecto de 0,0? sólo debería actualizar tv si TICKVALUE devuelve un valor distinto de cero...
 

Perdón, quería decir que básicamente he probado las dos formas. Así que he intentado hacer simplemente "tv = MarketInfo(Symbol(), MODE_TICKVALUE);" dentro de la sección "int init"... (y "static double tv = 0;")

Básicamente el valor del tick es siempre "0"? (Lo tengo imprimiendo para mí, por supuesto)

Del mismo modo, cuando paso al backtest en el EURUSD el valor del tick también me dice "0", sin embargo se las arregla para ejecutar con éxito todo el backtest sin error de división en cero desde 2001-2013?

ACTUALIZACIÓN: Hice una prueba en un corredor normal en los mercados en vivo que tiene una alimentación basada en el lote, y el valor de la garrapata estaba devolviendo una cifra > 0. Sin embargo, cuando dejé caer este mismo script en el mismo corredor de mercado en vivo que tiene una alimentación nocional, el valor de la garrapata regresó como "0"? ¿Alguna idea de cómo puedo evitar este error de tamaño de lote cuando se utiliza la opción de alimentación nocional (comercio tan bajo como 1 unidad)?

 
DomGilberto:

Perdón, quería decir que básicamente he probado de las dos maneras. Así que he intentado hacer simplemente "tv = MarketInfo(Symbol(), MODE_TICKVALUE);" dentro de la sección "int init"... (y "static double tv = 0;")

Básicamente el valor del tick es siempre "0"? (Lo tengo imprimiendo para mí, por supuesto)

Asimismo, cuando paso al backtest del EURUSD el valor del tick también me dice "0", sin embargo consigue ejecutar con éxito todo el backtest sin error de división en cero desde el 2001 al 2013 ?

Por el código que has mostrado... eso no es posible, a no ser que no estés llamando a la función que has mostrado...

   double ts = MarketInfo(Symbol(), MODE_TICKSIZE);
   double tv = MarketInfo(Symbol(), MODE_TICKVALUE);
   double minlot = MarketInfo(Symbol(), MODE_MINLOT);
         
   double loss_for_1_lot = pips_to_bsl/ ts * tv ;

si TICKVALUE es siempre 0.0 entonces tv es 0.0 por lo que ts * tv = 0.0 por lo que siempre obtendrá un error de división por cero. . .

¿Esta su terminal conectada a su Broker? o esta corriendo con ella desconectada?

 

Espero que este video que he hecho (40 segundos más o menos) ilustre lo que estoy hablando ( ya que no estoy seguro de si lo estoy dejando claro o no).

Video: http://screencast.com/t/uMHY5DpM

Verás que la primera parte cuando suelto el script en el gráfico en vivo (cuenta real) que el valor del tick y el tamaño del tick devuelven "0" en esa "cuenta nocional", que ilustro en la ventana de lotes (unidades).

La segunda parte es con el mismo broker pero en un feed basado en lotes y esta vez devuelve un valor de tick y un tamaño de tick. De nuevo, ilustro que se opera con lotes....

Así que con respecto al probador de estrategias, no tengo ni idea de por qué ha estado trabajando y a veces no lo hace. La cuenta ha estado conectada mientras ejecutaba las pruebas retrospectivas también (en una cuenta demo nocional alimentada (unidades)).

Mi siguiente pregunta sería, si esta es la respuesta típica que obtendré de la cuenta alimentada nocional, ¿podrían sugerirme cómo corregir mi cálculo de tamaño de posición en esta circunstancia? Funciona perfectamente para una alimentación basada en lotes... Espero que eso lo explique un poco mejor?

 
DomGilberto:
Ok, así que su "TickValue" que está devolviendo un "0".

He tratado de usar "static double tv = 0;" y luego asignar el valor de la garrapata dentro de "int init", y luego actualizar ese doble estático en cada nueva vela H1 si "tv==0", pero todavía no produce nada más que "0"? El par de divisas en cuestión es GBPJPY (Todo esto es dentro de Strategy Tester)

Perdón si estoy siendo lento...?


¿Cómo está imprimiendo TickValue?

Como los dígitos de GBPJPY suelen ser 3, es muy posible que TickValue esté imprimiendo cero porque no hay suficientes decimales.

Para estar absolutamente seguro, puede ser una idea ampliar los decimales impresos

DoubleToStr(MarketInfo(Symbol(),MODE_TICKVALUE),8)

Tenga en cuenta que

double loss_for_1_lot = pips_to_bsl/ ts * tv ; //<<<<<<<<<<<<<<<<<<<<<<<<<<< This is giving me a "0" randomly sometimes?

también dará como resultado cero si pips_to_bsl es cero. ¿Es esto posible?