Cálculo correcto del lote a partir del % de la fianza - página 5

 
EverAlex:

Por lo tanto lSL es cuántos puntos a SL

Punto = 0,00001 (en citas de 5 dígitos)

dLotStep = 0,01


La fórmula (lSL*dLotCost*dLotStep))*dLotStep es incorrecta

Debería ser algo así como (lSL*dLotCost*Point))*dLotStep


No tienes que inventarte nada. El tamaño del lote es diferente para cada empresa de corretaje y hay que ajustarlo al tamaño adecuado. Los puntos no tienen nada que ver
 
Vinin:

No hay que inventar nada. El tamaño del lote es diferente en cada empresa de corretaje y tenemos que llevarlo al tamaño adecuado. Los puntos no tienen nada que ver.


En nuestro caso, lSL es el tamaño del drawdown en puntos de las cotizaciones pero no en puntos del lote.

Es decir, los puntos no tienen nada que ver.

Así, en la fórmula para calcularlo, multiplica (lo que está entre paréntesis) por Punto, no por dLotStep.

Otra cosa es que esto ya se haga a expensas de dLotCost (junto con la conversión a la moneda del depósito)...

Es decir, somos los primeros en el

MathRound(AccountFreeMargin()*lRisk*0.01/(lSL*dLotCost*dLotStep))

Obtener un número entero y luego recalcular de nuevo a las unidades correctas del lote multiplicando por dLotStep ?

 
double lotSize(double deposSize=1000.0, string currName="USDCHF", double proc=2.0, int pipsLoss=1000)// функция лота
{  
   //проверка достаточности средств 
   if(deposSize < 
   MarketInfo(currName,MODE_MARGINREQUIRED)*MarketInfo(currName,MODE_MINLOT))
   //для проведения торговли
   {
      Alert("Величина вашего депозита недостаточна \nдля торговли на инструменте\""+currName+"\" \nc минимальнодопустимым лотом");
      return 0.0;
   }
   //проверка, на стоп-аут
   ENUM_ACCOUNT_STOPOUT_MODE stopOutMode=(ENUM_ACCOUNT_STOPOUT_MODE)AccountInfoInteger(ACCOUNT_MARGIN_SO_MODE);
   double procUsed;
   if(stopOutMode==ACCOUNT_STOPOUT_MODE_PERCENT)//если стоп-аут в процентах
     {
         if(proc > AccountInfoDouble(ACCOUNT_MARGIN_SO_SO))
           {
               Alert("Потеря выше уровня STOPOUT!\nРасчет лота производиться по величине STOPOUT.");
               procUsed=AccountInfoDouble(ACCOUNT_MARGIN_SO_SO)/100;
               //Print(MarketInfo(currName,MODE_MARGINREQUIRED)," ",procUsed);
               return deposSize/(pipsLoss+procUsed*MarketInfo(currName,MODE_MARGINREQUIRED));               
           }
     }
     //а вот здесь нужна доработка, для платформ, где стоп-аут в пунктах
     //как сказал один наш товарищ "у кого идеи ростут из нужного места".. доделает
     
   double currMove=deposSize*proc/100;// расчет процента от величины депозита
   double lotCount=currMove/(pipsLoss*MarketInfo(currName,MODE_TICKVALUE));//ну а тут и ведеться сам расчет лота

   if(lotCount<MarketInfo(currName,MODE_MINLOT))
   {
      return MarketInfo(currName,MODE_MINLOT);
   }
   if(lotCount>MarketInfo(currName,MODE_MAXLOT))
   {
      return MarketInfo(currName,MODE_MAXLOT);  
   }
   return NormalizeDouble(lotCount,2);
   //return lotCount;
}

También hay una opción con un depósito de 3 libras para operar con el EURUSD y poner el 30% en el lado perdedor... pero esto está fuera de una serie de perversiones

 
EverAlex:


En cuanto al problema lSL es el tamaño de la reducción en puntos de las cotizaciones, no en puntos del lote.

Es decir, los puntos no tienen nada que ver.

Así, en la fórmula de cálculo debemos multiplicar (lo que está entre paréntesis) por Punto, no por dLotStep.

Otra cosa es que esto ya se haga a expensas de dLotCost (junto con la conversión a la moneda del depósito)...

Es decir, primero en

obtener un número entero, y luego recalcular de nuevo a las unidades correctas del lote multiplicando por dLotStep ?




 
Vinin:


La fórmula sigue siendo errónea (para un bloque de iSL>0).

TICKVALUE da el precio de TICKSIZE.

Y el lSL se da en puntos POINT.

ElPOINT no siempre coincide con el TICKSIZE (ver el par de 3 dígitos XAUUSD en Alpari).

Así que debe convertir lSL de POINT a TICKSIZE.

De lo contrario, obtendremos un lote 10 veces sobreestimado (eso es lo que observé en el par XAUUSD hasta que añadí el recálculo).

si (lSL>0){

lSL= (int)(MarketInfo(lSymbol,MODE_TICKSIZE) / MarketInfo(lSymbol,MODE_POINT) )* lSL; // TICKSIZE/POINT dará un número entero (1 o 10), podemos usar lSL de tipo int

// esto es lo que era.

 double dLotCost=MarketInfo(lSymbol,MODE_TICKVALUE);
 dLot=MathRound(AccountFreeMargin()*lRisk*0.01/(lSL*dLotCost*dLotStep))*dLotStep;
}

PD: para el TC optimizado para muchas pasadas (>10mln) todos los parámetros no modificables del símbolo(TICKSIZE, POINT, TICKVALUE, LOTSTEP, MINLOT, MAXLOT etc.) deben ser asignados a variables en la funcióninit() y utilizar estas variables en los cálculos.

Incluyendo poner el valor de TickSize/Point en una variable.

 
EverAlex:

La fórmula sigue siendo errónea (para un bloque de iSL>0).

TICKVALUE da el precio de TICKSIZE.

Y el lSL se da en puntos POINT.

ElPOINT no siempre coincide con el TICKSIZE (ver el par de 3 dígitos XAUUSD en Alpari).

Por lo tanto, debe convertir lSL de POINT a TICKSIZE.

De lo contrario, obtendremos un lote 10 veces sobreestimado (eso es lo que observé en el par XAUUSD hasta que añadí el recálculo).

si (lSL>0){

lSL= (int)(MarketInfo(lSymbol,MODE_TICKSIZE) / MarketInfo(lSymbol,MODE_POINT) )* lSL; // TICKSIZE/POINT dará un número entero (1 o 10), podemos usar lSL de tipo int

// esto es lo que era.

PD: para los TS que optimizan muchas pasadas (>10mln) todos los parámetros no modificables del símbolo(TICKSIZE, POINT, TICKVALUE, LOTSTEP, MINLOT, MAXLOT etc.) deben ser asignados a variables en la funcióninit() y utilizar las variables en los cálculos.

Incluyendo poner el valor de TickSize/Point en una variable.




Gracias
 
Vinin:

Gracias

El tópico envió sus respetos en la primera página y nunca volvió.

Hace unos años se discutió este tema en algún foro. Lo volveré a contar de memoria, pero sin fórmulas.

Supongamos que operamos con el par AUDCHF. Se ha tomado de forma bastante arbitraria para explicar cómo se forman los beneficios o las pérdidas en una posición. Aproximadamente el mismo tema se planteó en https://www.mql5.com/ru/forum/150912

Si operamos un solo lote de 100000 AUD, entonces ( en un cinco dígitos) cada pip hace 1 CHF (denominador del par) de ganancia o pérdida (depende de la dirección que hayamos tomado y hacia dónde va el precio).

Por lo tanto, en cualquier momento, sabemos cuántos CHF hemos ganado/perdido. La ganancia/pérdida se convierte a la moneda del depósito, utilizando el tipo de cambio USDCHF del momento, si la moneda del depósito es el USD, o EURCHF, si la moneda del depósito es el EUR. Por analogía, para todos los pares y monedas de depósito.

Esta es la respuesta: no siempre podemos estimar el tamaño exacto del lote. MarketInfo() con el parámetro de solicitud MODE_TICKVALUE puede servir de guía.

 
Mislaid:

De ahí la respuesta: no siempre podemos estimar el tamaño exacto del lote. MarketInfo() con el parámetro de solicitud MODE_TICKVALUE puede servir de guía.


Así es como se ha contabilizado durante mucho tiempo. Al menos en el bonito post de Vinin (con un cálculo de lote erróneo por TICKSIZE c POINT no coincidente) y en el antiguo post de Martingeil (con un cálculo de lote correcto, pero sin posibilidad de establecer drawdown ==0).

Lo principal es que el valor correcto de TICKVALUE debe llegar desde la empresa de corretaje (o calculado correctamente en el cliente, si se calcula en MT).


Cuando este tema comenzó, no había TICKVALUE .

Y con su llegada, todo se simplificó y este tema languideció durante un tiempo.

PD: pronto publicaré mi versión - un híbrido de la versión de Vinin (tiene una fórmula más simple e iSL==0) y la de Martingeil (control de fondos insuficientes incluso para el lote mínimo).

Características: 1) cálculo del saldo desde AccountFreeMargin(), no desde AccountBalance().

2) Y (para los cambiadores) se tiene en cuenta que el saldo disminuirá en una cierta cantidad cuando una operación abierta se cierre en SL.

Si no hay suficiente dinero ni siquiera para el balance mínimo - mostrará el volumen del lote -134 (error 134 - no hay suficiente dinero para abrir una operación)

En este sentido, la pregunta a Vinin (y a otros compañeros experimentados): ¿este código se colorea solo o lo haces tú mismo? Intenté poner el estilo de fragmento "código", pero no lo coloreó. ¿O sólo se colorea después de enviar el mensaje?

 
EverAlex:

Una pregunta para Vinin (y otros compañeros experimentados): ¿el código se colorea solo, o lo haces tú mismo? He intentado poner el estilo de fragmento "código", pero no está coloreado. ¿O sólo se colorea después de enviar el mensaje?

Está coloreado por mí. Pero no siempre.
 

he finalizado mi idea (para plataformas con porcentaje de stop-out)... compartiendo el código... se aceptan críticas constructivas

double lotSize(double deposSize=1000.0, string currName="USDCHF", double proc=2.0, int pipsLoss=1000)
{  
   double lotCount=0;
   //1) проверка достаточности средств для проведения торговли
   if(deposSize < 
   MarketInfo(currName,MODE_MARGINREQUIRED)*MarketInfo(currName,MODE_MINLOT))
   {
      //Alert("Величина вашего депозита недостаточна \nдля торговли на инструменте\""+currName+"\" \nc минимальнодопустимым лотом");
      return 0.0;
   }
   
   double currMove=deposSize*proc/100;// расчет процента от величины депозита
   
  
   //расчивываем максимально допустимый лот, до стоп-аута
   double SOlot = deposSize/(pipsLoss*MarketInfo(currName,MODE_TICKVALUE)+
   MarketInfo(currName,MODE_MARGINREQUIRED)*AccountInfoDouble(ACCOUNT_MARGIN_SO_SO)/100);     
   //расчет величины депозита, при котором сработает стоп-аут
   double SOval = SOlot*pipsLoss*MarketInfo(currName,MODE_TICKVALUE);
   
   
   ENUM_ACCOUNT_STOPOUT_MODE stopOutMode=(ENUM_ACCOUNT_STOPOUT_MODE)AccountInfoInteger(ACCOUNT_MARGIN_SO_MODE);
   
   if(stopOutMode==ACCOUNT_STOPOUT_MODE_PERCENT)//если стоп-аут в процентах
   {  
     
     if((deposSize-currMove)<SOval)//проверяем остаток на депозите на превышение значения стоп-аут
     {     
         if(SOlot<MarketInfo(currName,MODE_MINLOT))//если лот стоп-аута меньше минимального лота
         {
             lotCount = MarketInfo(currName,MODE_MINLOT);
             //находим количесвто пунктов до вылета по стоп-ауту и выбрасываем предупреждение
             int pipsSO=(int)round((deposSize - SOval)/(lotCount * MarketInfo(currName,MODE_TICKVALUE)));
             Print("При прохождении ценой больше ", pipsSO," пп.- \nторговля будет прекращена по STOP OUT!");             
             
             
         }
         else//если наш стоп-аут лот больше равно минимального
         {
              lotCount = SOlot;              
              int pipsSO=(int)round((deposSize - SOval)/(lotCount * MarketInfo(currName,MODE_TICKVALUE)));
              Print("Достижение STOP OUT, произойдет через ", pipsSO, " и работа будет проведена с максимальнодоступимым лотом до STOP OUT");
                           
         }
     }
     else//если же остаток на депозите будет меньше стоп-аута
     {     
     lotCount = currMove/(pipsLoss*MarketInfo(currName,MODE_TICKVALUE));
         if(lotCount<MarketInfo(currName,MODE_MINLOT))//если лот меньше минимального лота
         {            
            int pipsProc=(int)round(currMove/(MarketInfo(currName,MODE_MINLOT)*MarketInfo(currName,MODE_TICKVALUE)));
            Print(proc,"%-й уровень депозита будет достигнут, з минимальнолопустимым лотом, за ",pipsProc," пп.");
            lotCount=MarketInfo(currName,MODE_MINLOT);      
         }         
     }     
     
   }
   else{
   //а вот здесь нужна доработка, для платформ, где стоп-аут в пунктах
   //как сказал один наш товарищ "у кого идеи ростут из нужного места".. доделает
   /*
   */}      
  
   //"прическа" для лота   
   lotCount = MathFloor(lotCount/MarketInfo(currName,MODE_MINLOT))*MarketInfo(currName,MODE_MINLOT);   

   if(lotCount<MarketInfo(currName,MODE_MINLOT))
   {
      return MarketInfo(currName,MODE_MINLOT);
   }
   if(lotCount>MarketInfo(currName,MODE_MAXLOT))
   {
      return MarketInfo(currName,MODE_MAXLOT);  
   }   
   return lotCount;
}