Discusión sobre el artículo "Escribir un Expert Advisor mediante la programación orientada a objetos de MQL5" - página 2

 
Yedelkin:
Si el Bid en la apertura estará en 1.2695, ya tenemos 5 pips de pérdida automáticamente. Si al mismo tiempo el SL es de 50 pips según la idea del desarrollador, entonces tienen que pasar 45 pips más en la dirección desfavorable antes de que se active. Es decir, cuando se activa el stop loss, Bid no debería estar en 1,2645, sino en 1,2650; y Ask, respectivamente, en 1,2655.

1. Sobre la pérdida de 5 pips en la apertura.

Tienes razón sobre la pérdida, si cerramos la posición en el mismo momento (condicionalmente) obtendremos una pérdida por el importe del spread, los propios 5 pips.

Ya que los largos se cierran al precio Bid (contra).

Al menos lógicamente en este caso deberíamos obtener esta pérdida (y es correcto).

Lo mismo ocurre si cerramos con una orden contraria. ¿Qué resultado cree que obtendremos cuando la contraorden se active al precio de 1,2695 (que es donde está el Bid en este momento)?

Bueno, ¿no afirmarás que el precio de apertura de las posiciones CORTAS es Ask?

2. Tratemos el cierre en BU

Recordemos que abrimos en Buy a 1,27 (este precio es ahora un nivel BU para nosotros).

Es razonable suponer que el cierre BU se producirá si el precio Bid alcanza 1,27 (es decir, subirá exactamente 5 pips).

Comprobemos nuestra afirmación cerrando en la CU con la ayuda de una contraorden. El precio de apertura de dicha posición debe estar en 1,27, y como sabemos las órdenes de venta se colocan en Bid. Actualmente Bid está en 1,2695. Por lo tanto, para cerrar en la BU necesita pasar 5 pips, por lo que no hay error en los cálculos y la afirmación es correcta.

3. sobre SL y TP

Aquí rigen dos afirmaciones:

а. Los largos se abren en el Ask y se cierran en el Bid; los cortos se abren en el Bid y se cierran en el Ask.

б. La distancia a TP y SL se calculan a partir del Precio de Apertura, el cálculo tiene en cuenta la dirección de la posición.


Exactamente de acuerdo con la segunda afirmación, determinaremos los precios SL y TP para nuestro ejemplo. Al precio de apertura 1,27 SL = 1,2650 y TP = 1,28 (según las condiciones descritas anteriormente).

3. De acuerdo con la primera afirmación, el LARGO (y en el ejemplo es el LARGO) se abrirá con la condición de que el Ask sea igual a 1,27 (y el Bid sea igual a 1,2695, basándonos en el spread de 5 pips). 4. Ahora vamos a determinar bajo el precio de apertura 1,27 el SL = 1,2650 y el TP = 1,28 (de acuerdo con las condiciones descritas anteriormente).

4. Ahora vamos a determinar en qué condiciones se activarán nuestro SL y TP.

Nuestra posición se cerrará cuando se cumpla una de las condiciones (si no hay otros factores):

En TP - Si Bid alcanza 1.28 (100 pips desde 1.27), Ask en este momento estará en 1.2805 (la primera declaración y el tamaño de la regla de spread aquí).

Comprobemos nuestra afirmación cerrando en TP utilizando una posición contraria. El precio de apertura de dicha posición debería estar en 1,28, y como sabemos las órdenes de venta se colocan en la oferta. Actualmente Bid está en 1.2695. Por lo tanto, para cerrar en TP es necesario pasar 5 pips (para cubrir pérdidas en el spread) + 100 pips para fijar el beneficio.

En SL - Si el precio alcanza el nivel de SL, igual a 1.2650 como recordamos.


Ahora vamos a entender qué precio será. Lógicamente, debería ser el precio Bid (que corresponde al precio de apertura de la contraorden).

Recordemos que actualmente (según la condición de apertura de la posición) Bid está en 1,2695. Por lo tanto, el precio tiene que pasar 45 pips antes de que se active el SL.

Por lo tanto, registraremos una pérdida igual al spread (5 pips) + 45 pips que el precio ha tenido tiempo de pasar antes de que se active el SL.

Desde este punto de vista tienes razón

Comprobemos nuestra afirmación cerrando en SL utilizando una posición contraria. El precio de apertura de dicha posición debería estar en 1.2650, y como sabemos las órdenes de venta se abren en Bid. Actualmente Bid está en 1.2695. Por lo tanto, para cerrar en SL es necesario pasar 45 pips. Cuando se active el SL, se registrará una pérdida de 50 pips (5 pips en el spread + 45 pips en el movimiento en nuestra contra).

PS

Pero desde este punto de vista, este ejemplo para MQL4 no me queda muy claro.

int ticket;

  if(iRSI(NULL,0,14,PRICE_CLOSE,0)<25)
    {
     ticket=OrderSend(Symbol(),OP_BUY,1,Ask,3,Bid-25*Point,Ask+25*Point,"My order #"+counter,16384,0,Green);
     if(ticket<0)
       {
        Print("OrderSend failed with error #",GetLastError());
        return(0);
       }
    }

Más precisamente, no estoy muy claro sobre la base de qué lógica y qué declaraciones SL y sólo se considera.

Pero sobre la base de este ejemplo (y sólo de ella) me sale lo siguiente

//Ejemplo básico
ticket=OrderSend(Symbol(),OP_BUY,1,Ask,3,SL = Bid-Loss*Point,TP = Ask+Profit*Point,"My order #"+counter,16384,0,Green);
//Orden de apertura de una posición de mercado
ticket=OrderSend(Symbol(),OP_BUY,1,1.27,3,1.2645 = 1.2695-50*Point,1.28 = 1.27+100*Point);

En base a los valores Open = 1,27, SL = 1,2645 y TP = 1,28 entiendo lo siguiente:

1. La posición se abre cuando Ask alcanza el precio de 1,27 (en nuestro caso ya está ahí);

2. El nivel BU se sitúa en el precio de 1,27 y para cerrar sobre él el tipo del símbolo (en nuestro caso EUR) debe crecer en el tamaño del spread (en nuestro caso 5 pips);

3. En el momento de la apertura, inmediatamente obtenemos una pérdida en la cantidad del spread (en caso de que cerremos la posición INMEDIATAMENTE), porque la posición abierta, basada en declaraciones lógicas, debe cerrarse con una contraorden. En el código MQL4, tal operación tendrá el siguiente aspecto

//Ejemplo básico
ticket=OrderSend(Symbol(),OP_SELL,1,Bid,3,0,0);
//Cerrar una posición en el mercado con una contraorden
ticket=OrderSend(Symbol(),OP_SELL,1,1.2695,3,0,0);

4. TP se activa después de que el precio alcance el nivel de 1,28. Lógicamente, este debería ser el precio Bid, ya que la contraorden se abre a este precio (la operación se ejecuta cuando el precio Bid alcanza el valor de 1,28). En base a esto, el cierre en el código MQL4 debería tener el siguiente aspecto

//Cierre de una posición TP con una orden de mercado (contraorden)
ticket=OrderSend(Symbol(),OP_SELL,1,1.28,3,0,0);
//Cierre de una posición con una orden pendiente de contador (limitador)
ticket=OrderSend(Symbol(),OP_SELLLIMIT,1,1.28,3,0,0);

5. SL se activará después de que el tipo de cambio del símbolo que se está negociando (en nuestro caso EUR) caiga 50 pips desde el momento de la apertura.


Ahora lo más interesante

Vamos a comprobar la apertura de una posición de mercado basándonos en el mismo ejemplo de la Ayuda del MQL4 (un ejemplo clásico, que probablemente ha sido utilizado por miles de personas).

Utilizaremos este código para comprobarlo

//+------------------------------------------------------------------+
double PriceOpen,PriceSL,PriceTP;
int ticket;
//+------------------------------------------------------------------+
//Formular precios para el pedido
PriceOpen = Ask;
PriceSL   = Bid-500*Point;
PriceTP   = PriceOpen+1000*Point;
//Orden de apertura de una posición de mercado
ticket = OrderSend(Symbol(),OP_BUY,0.10,PriceOpen,5,PriceSL,PriceTP);
//+------------------------------------------------------------------+

Ejecutando este código en el servidor de Alpari (utilizando cotizaciones reales) se obtiene el siguiente resultado

2010.08.24 09:12:47 '******': instant order buy 0.10 EURUSD at 1.26292 sl: 1.25776 tp: 1.27292

Es fácil adivinar que en este caso obtendremos los siguientes tamaños SL = 516 (o 51 pips por 4 dígitos) TP = 1000 (o 100 pips por 4 dígitos)

PPS

Veamos la ayuda del MQL4:

Parámetros:
símbolo - Nombre del instrumento financiero con el que se realiza la operación comercial.
cmd - Operación comercial. Puede ser cualquiera de los valores de la operación.
volumen - Número de lotes.
precio - Precio de apertura.
deslizamiento - Desviación máxima permitida del precio para órdenes de mercado (órdenes de compra o venta).
stoploss - Precio de cierre de la posición cuando se alcanza el nivel de pérdida (0 en caso de no existir nivel de pérdida).
takeprofit - Precio de cierre de la posición cuando se alcanza el nivel de rentabilidad (0 en caso de ausencia de nivel de rentabilidad).
comentario - Texto del comentario de la orden. La última parte del comentario puede ser modificada por el servidor de operaciones.
magia - Número mágico de la orden. Puede utilizarse como identificador definido por el usuario.
caducidad - Periodo de expiración de la orden pendiente.
color_flecha - Color de la flecha de apertura en el gráfico. Si el parámetro está ausente o su valor es CLR_NONE, la flecha de apertura no se muestra en el gráfico.
Ejemplo:
  int ticket; if(iRSI(NULL,0,14,PRECIO_CIERRE,0)<25) { ticket=OrderSend(Symbol(),OP_BUY,1,Ask,3,Bid-25*Point,Ask+25*Point, "Mi orden #"+contador,16384,0,Verde); if(ticket<0) { Print("OrderSend falló con error #",GetLastError()); return(0); } }

¿"Aquí dime dónde está la verdad hermano"?

OrderSend - Документация на MQL4
  • docs.mql4.com
OrderSend - Документация на MQL4
 
Yedelkin:

No entiendo la siguiente parte del código:

// Copia el precio de cierre de la barra anterior (barra 1) a la variable correspondiente del Asesor Experto
   Cexpert.setCloseprice(mrate[1].close);  // precio de cierre de la barra 1
//--- Comprobar si hay una posición de compra
   if (Cexpert.checkBuy()==true)
   {
      if (Buy_opened) 
         {
            Alert("¡¡¡Ya tenemos una posición de compra!!!"); 
            return;    // No añadir a la posición larga
         }
      double aprice = NormalizeDouble(latest_price.ask,_Digits);
      double stl    = NormalizeDouble(latest_price.ask - STP*_Point,_Digits);
      double tkp    = NormalizeDouble(latest_price.ask + TKP*_Point,_Digits);
      int    mdev   = 100;
      // realizar el pedido
      Cexpert.openBuy(ORDER_TYPE_BUY,Lot,aprice,stl,tkp,mdev);
   }
Si vamos a abrir una posición de compra, debemos centrarnos en el precio latest_price.ask, pero al establecer un Stop Loss y Take Profit para dicha posición - en el precio latest_price.bid. ¿Es esto correcto? ¿Por qué el Stop Loss y Take Profit se establecen en base al precio ask en el texto del código? ¿Es un error tipográfico o una peculiaridad de una estrategia en particular (el código tiene una construcción similar para la apertura de una posición de venta)?

Esta parte del código debe entenderse sobre la base de las siguientes afirmaciones:

а. Largo - abrir en Ask y cerrar en Bid; Corto - abrir en Bid y cerrar en Ask;

б. Las posiciones se cierran mediante contraórdenes;

в. El nivel BU está en el Precio de Apertura;

г. La distancia a TP y SL se calculan a partir del Precio Abierto (nivel CU);

д. El TP se activará cuando el precio de la Oferta alcance un nivel igual al Precio Abierto + el tamaño del Beneficio;

e. SL se activará cuando el valor alcance el nivel de Oferta igual al Precio Abierto - tamaño de la Pérdida.

Lo más probable es que el autor del Asesor Experto se guiara por afirmaciones similares en su trabajo. Para que todo quede lo más claro posible, ofrezco una ilustración de lo anterior con la ayuda de la siguiente pantalla (nos interesa el rectángulo rojo).


 
Interesting:

e. SL se activará cuando el precio Bid alcance un nivel igual a Open Price - Loss size.

Gracias, entiendo la lógica. Pero aún así, de acuerdo con el punto "e" resulta que cuando se activa el stoploss, Bid no debería estar en 1,2645, sino en 1,2650; y Ask, respectivamente, en 1,2655.

 
Yedelkin:

Gracias, entiendo la lógica. Pero aún así, según el punto "e" resulta que cuando se dispara un stop-loss, Bid no debería estar en 1,2645, sino en 1,2650; y Ask, respectivamente, en 1,2655.

Puede ser así, hay que comprobar qué ocurre exactamente cuando se dispara un stop-loss por el mercado (bueno, o ajustar el modelo matricial teniendo en cuenta todas las posibilidades de cierre disponibles)....


Para el punto "e" (como yo lo entiendo)

En caso de contar desde Open (Ask) será 1.27-50 = 1.2650 (el precio pasará 45 pips y la pose se cerrará), si he entendido bien. En este caso creo que SL debería funcionar en Bid 1.2650 y Ask 1.2655.

Otra cosa, si contamos desde Bid, entonces obtendremos el precio 1.2695-50 - 1.2645 (no se puede discutir con las matemáticas). Si calculamos SL desde Bid obtendremos 1.27-1.2645 = 55 pips (que según tengo entendido no entraba en nuestros planes).

PS

Al menos, este modelo nos permite romper correctamente los niveles SL y TP a partir del precio Open (en mi opinión correctamente)...

Por supuesto, sería interesante conocer la opinión oficial de los desarrolladores sobre cómo deberían calcularse los precios en la realidad (no sólo SL y TP).

 

Pregunta.


100 billetes verdes - ¿es en rublo o e.u.? ;)

 
que se prometió desaparecer.
 
Jager:

Pregunta.


100 billetes verdes - ¿es en rublo o e.u.? ;)

Este es el valor del tiempo de espera en milisegundos. Este parámetro ya ha sido eliminado de todas las funciones de negociación.
 

Hola gracias por el ejemplo tan bien expuesto.

Pero tengo que preguntar ¿es correcto?

En el EA está comprobando si hay una oportunidad de comercio en el inicio de cada nueva barra.

En la función getbuffers() de la clase recupera los datos de las 3 últimas barras empezando por la barra 0 actual que acaba de formarse y por lo tanto el valor es erróneo.

void MiExperto::getBuffers()
{
if(CopyBuffer(ADX_handle,0,0,3,ADX_val)<0 || CopyBuffer(ADX_handle,1,0,3,plus_DI)<0
|| CopyBuffer(ADX_handle,2,0,3,minus_DI)<0 || CopyBuffer(MA_handle,0,0,3,MA_val)<0)

¿No debería estar recuperando los datos del indicador de las 3 últimas barras empezando por la posición 1?

gracias

 

Gran artículo Samuel

Gracias de antemano por este inestimable artículo,

Entonces basado en este articulo, podriamos incluir funciones como IsNewBar o Buy_opened a la clase y solo llamarla desde EA.

Gracias de nuevo,

Espero ver más artículo de usted,

Hamed,

 

Por favor, ayúdame a entender algo que no entiendo:

Al principio del EA se llama a la función:

  Cexpert.doInit(ADX_Period,MA_Period);
при этом для ее корректного выполнения требуются уже установленные параметры symbol  и period :
//+-----------------------------------------------------------------------+
// FUNCIONES PÚBLICAS DE NUESTRA CLASE 
//+-----------------------------------------------------------------------+
/*
 Inicializando 
*/
void MyExpert::doInit(int adx_period,int ma_period)
{
   //--- Obtener el indicador ADX
   ADX_handle=iADX(symbol,period,adx_period);
  //--- Obtener el manejador del indicador de Media Móvil
   MA_handle=iMA(symbol,period,ma_period,0,MODE_EMA,PRICE_CLOSE);
однако, заполнение этих параметров конкретными значениями происходит позже, уже после Cexpert.doInit :
//--- iniciar la función de inicialización
   Cexpert.doInit(ADX_Period,MA_Period);
//--- establecer todas las variables necesarias para nuestro objeto de clase
   Cexpert.setPeriod(_Period);     // fija el período
   Cexpert.setSymbol(_Symbol);     // especifica el símbolo (par de divisas)
   
   Никак не пойму, как может правильно выполниться Cexpert.doInit, если переменной symbol пока не присвоено
значение (или как-то присвоено ?) Застрял тут и дальше никак . Спасибо.