Creador de cuadrículas 1.1

 
Aquí está la versión 1.1 del 'Grid maker'... un script o asesor experto que establece y mantiene una serie de órdenes de compra o venta uniformemente espaciadas.
Esta versión es un script o un asesor experto, u puede cambiar la frecuencia de actualización, seleccionar largos y/o cortos, etc.. ver los parámetros para una explicación.

Creo que he probado la mayoría de las variantes, pero no hay garantías de que funcione en todos los casos. Si lo pruebas y encuentras problemas, házmelo saber.

Esta es probablemente la última versión que publique. La desarrollé para probar MT4. Futuras versiones serán más complejas, necesitando datos externos como niveles de soporte y resistencia, por lo que no será apropiado publicarlas.



//+------------------------------------------------------------------+
//|                                                     MakeGrid.mq4 |
//|                                            Copyright © 2005, hdb |
//|                                       http://www.dubois1.net/hdb |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2005, hdb"
#property link      "http://www.dubois1.net/hdb"
//#property version      "1.1beta"

extern string GridName = "Grid";       // identifies the grid. allows for several co-existing grids
extern double Lots = 0.1;              // 
extern double GridSize = 6;            // pips between orders - grid or mesh size
extern double GridSteps = 10;          // total number of orders to place
extern double UpdateInterval = 15;     // update orders every x minutes
extern bool   wantLongs = true;        //  do we want long positions
extern bool   wantShorts = true;       //  do we want short positions
extern bool   wantBreakout = true;     // do we want longs above price, shorts below price
extern bool   wantCounter = true;      // do we want longs below price, shorts above price
extern bool   limitEMA34 = false;      // do we want longs above ema only, shorts below ema only
extern double LastUpdate = 0;          // counter used to note time of last update
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//---- 
 #property show_inputs              // shows the parameters - thanks Slawa...    
//----
   return(0);
  }
//+------------------------------------------------------------------------+
//| test if there is an open position or order in the region of atRate     |
//|     will check for longs if checkLongs is true, else will check        |
//|     for shorts                                                         |
//+------------------------------------------------------------------------+

bool IsPosition(double atRate, double inRange, bool checkLongs )
  {
  
     int totalorders = OrdersTotal();
     for(int j=0;j<totalorders;j++)                                // scan all orders and positions...
      {
        OrderSelect(j, SELECT_BY_POS);
        if ( OrderSymbol()==Symbol() && OrderComment() == GridName )  // only look if mygrid and symbol...
         {  int type = OrderType();
            if (MathAbs( OrderOpenPrice() - atRate) < inRange) // dont look for exact price but price proximity (less than gridsize)
              { if ( ( checkLongs && ( type == OP_BUY || type == OP_BUYLIMIT  || type == OP_BUYSTOP ) )  || (!checkLongs && ( type == OP_SELL || type == OP_SELLLIMIT  || type == OP_SELLSTOP ) ) )
                 { return(true); }
              }
         }
      } 

   return(false);
  }
//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int start()
  {
//---- 
   int    i, j,k, ticket, entermode, totalorders;
   bool   doit;
   double point, startrate, traderate;
 
//----
  if (MathAbs(CurTime()-LastUpdate)> UpdateInterval*60)           // we update the first time it is called and every UpdateInterval minutes
   {
   LastUpdate = CurTime();
   Print("Updating");
   point = MarketInfo(Symbol(),MODE_POINT);
   startrate = ( Ask + point*GridSize/2 ) / point / GridSize;    // round to a number of ticks divisible by GridSize
   k = startrate ;
   k = k * GridSize ;
   startrate = k * point - GridSize*GridSteps/2*point ;          // calculate the lowest entry point
   
   double EMA34=iMA(NULL,0,34,0,MODE_EMA,PRICE_CLOSE,0);
   
   for( i=0;i<GridSteps;i++)
   {
     traderate = startrate + i*point*GridSize;
     if ( wantLongs && (!limitEMA34 || traderate > EMA34))
       {
         if (!IsPosition(traderate,point*GridSize,true) )           // test if i have no open orders close to my price: if so, put one on
          {
             if ( traderate > Ask ) 
              { entermode = OP_BUYSTOP; } 
              else 
              { entermode = OP_BUYLIMIT ; } 
             if ( (traderate > Ask ) && (wantBreakout) || ((traderate < Ask ) && (wantCounter)) ) 
              { ticket=OrderSend(Symbol(),entermode,Lots,traderate,0,0,traderate+point*GridSize,GridName,16384,0,Green); }
          }
       }

     if ( wantShorts && (!limitEMA34 || traderate < EMA34))
       {
         if (!IsPosition(traderate,point*GridSize,false) )           // test if i have no open orders close to my price: if so, put one on
          {
             if ( traderate > Bid ) 
              { entermode = OP_SELLLIMIT; } 
              else 
              { entermode = OP_SELLSTOP ; } 
              
              if ( (traderate < Bid ) && (wantBreakout) || ((traderate > Bid ) && (wantCounter)) ) 
                { ticket=OrderSend(Symbol(),entermode,Lots,traderate,0,0,traderate-point*GridSize,GridName,16384,0,Red); }
          }
       }

    }
   }
   return(0);
  }
//+------------------------------------------------------------------+
 
Hola hdb,

He estado siguiendo esta idea desde hace mucho tiempo en los foros de MoneyTec (Simspeed), ET (ElectricSavant) y Oanda (MarkVH y Sympatico) y he estado pensando en cómo desarrollar algún experto para mejorar el primer script que enviaste al foro, quizás podríamos trabajar juntos para llegar a algo más rápido :) Por favor, hágamelo saber si usted está interesado mi correo electrónico es artefactodigital@gmail.com

Un saludo,
Fernando.

Aquí está la versión 1.1 del 'Grid maker'... un script o asesor experto que establece y mantiene una serie de órdenes de compra o venta uniformemente espaciadas. <br / translate="no"> Esta versión es una secuencia de comandos o un asesor experto, u puede cambiar la frecuencia de actualización, seleccione largos y / o cortos, etc. ver los parámetros para una explicación.

¡Creo que he probado la mayoría de las variantes, pero no hay garantías de que funciona en todos los casos! Si lo pruebas y encuentras problemas, házmelo saber.

Esta es probablemente la última versión que publique. La desarrollé para probar MT4. Futuras versiones serán más complejas, necesitando datos externos como niveles de soporte y resistencia, por lo que no será apropiado publicarlas.
 
ok suena bien.. ver mi correo electrónico...
 
¡por cierto, eres libre de probarlo, usarlo, cambiarlo pero por favor no lo vendas!

No proporciono ninguna garantía en cuanto a su condición de trabajo efectivo y cualquier comercio que pueda hacer con él es bajo su propio riesgo.
No asumo ninguna responsabilidad por pérdidas directas o indirectas debidas a este script.


Si lo usas, por favor publica tus comentarios de vez en cuando - resultados, ajustes, errores, observaciones, etc.

Disfrute de
 
Ok, aquí va... un movimiento importante del mercado después, ¡la red sobrevive! Empecé una cuenta demo hace dos semanas con 50k.
Perdí 1k probando el gridmaker y luego, justo antes de la caída del euro, puse el experto GridMaker por defecto en 9 pares de divisas:
EUR/CHF, USD/JPY, GBP/JPY, EUR/GBP, USD/CHF, AUD/USD, GBP/USD, EUR/USD, EUR/JPY.

El espacio de la rejilla es de 6 ticks para todas las divisas, y el TP a 6 ticks. Coloqué un tamaño de lote de 0,1. Me puse largo y corto cada 6 ticks para cada par de divisas.
El refresco fue cada 15 minutos (es decir, la rejilla se regerera cada 15 minutos) excepto para el EUR/USD y el GBP/USD a 5 minutos.

El saldo ha subido 10k (20%), el margen utilizado es de 13k (26%), el margen libre es de 26k (52%) y las pérdidas y ganancias no realizadas son de -19k.

El resultado neto de la explosión del euro (hasta ahora) es que he perdido -9k. Esperaba algo mucho peor que esto.

¡La red está añadiendo a la Balanza a un ritmo de 600 a 2000 por día!

Estoy deseando ver cómo queda esto la semana que viene.

¡¡Viva la red!!
 
¡Bueno, bueno, una semana más tarde y la rejilla realmente tomó una paliza! La culpa es mía porque no hice los cálculos necesarios de tamaño de lote/espacio de la rejilla
necesarios para ver cuánto se puede golpear con el capital disponible.

De todas formas, el balance está funcionando bastante bien: aumento de 700 a 1800 por día - el balance es ahora de 65k (comenzó con 49k, así que esto es +16k )
El margen utilizado es ahora de 15k, el margen disponible de 21k - todavía hay mucho espacio para añadir posiciones cuando sea necesario.
El margen no realizado es de -29k, lo que supone una pérdida neta de 13k, 4 peor que la semana pasada.

El lado positivo es que he cambiado la configuración para evitar las contraoperaciones (CounterTrade flag false) y la PyG no realizada parece haberse estabilizado.
Estaba en -36k en un momento dado.

Lo que me gusta de esta prueba a futuro es que comenzó con un gran golpe - la caída del euro de la semana pasada - por lo que ahora será interesante ver cómo y cuándo el
sistema se recupera. No tengo ninguna duda de que lo hará.

¡No puedo esperar a ver los resultados de la próxima semana!

ps. Tengo una v1.2 con la posibilidad de cambiar el TP y añadir un SL. Postea aquí si lo quieres.
 
He estado jugando con este un poco. simplemente ejecutando todo por defecto en todos los pares..
Tengo que decir que he estado muy impresionado por cómo se realiza.

Sólo hay un gran problema con esto.

permite tomar positins corto sólo.. como el precio cae las órdenes cortas se activan.. pero muchas veces usted puede conseguir 2 órdenes en el lado corto antes de que el precio decide invertir.

es decir, la toma de beneficios está en el mismo precio que el próximo corto que se iniciará y no tiene en cuenta la propagación es decir, los precios de compra y venta.

así que para ayudar a evitar tener 2 órdenes abiertas antes de que los precios se invierten en el lado largo TP tiene que ocurrir al mismo tiempo que la siguiente orden corta se coloca.

Creo que si esto es posible mi drawdown actualmente podría reducirse a la mitad..

Supongo que su última versión de esto resolvería este problema.

Así que si usted podría publicar que sería fantástico ...
 
Hola,

Me alegro de que lo encuentres divertido... yo también...

no hay manera de que pueda tener al mismo tiempo un TP = tamaño de la rejilla y eliminar la posibilidad de tener 2 posiciones abiertas en una inversión.
esto no es un problema de software sino simplemente relacionado con los spreads.

la unica posibilidad de eliminar teoricamente esto es perder el spread cada vez:
es decir, ir en corto a 1,2006 (bid), TP a 1,2000 (ask) y en corto a 1,1996 (bid) si se tiene un spread de 4 ticks.
simplemente pierdes 4/10 del rango.

en la nueva versión, se puede establecer el tamaño de la rejilla y el TP a diferentes números para que pueda implementar lo que usted está
lo que está buscando: establezca la rejilla a 10 y el TP a 6 si tiene un margen de 4 puntos.

no estoy seguro de que reduzca la dd a la mitad - pero ciertamente reducirá su ganancia significativamente.

Házmelo saber.

ps.. v1.2 en el próximo post
 
aquí está la v1.2 de gridmaker.

las únicas diferencias son:
1) he añadido un stoploss opcional si quieres uno. 0 significa que no hay stop loss, cualquier número positivo significa un stoploss.
si usas un stop loss en una cuadrícula, debes hacerlo grande...
2) puedes especificar un TP diferente al tamaño de la cuadrícula. darkstonexa , en el post anterior, quiere eliminar las posiciones dobles 'colgadas'.
mi intención inicial era probar TPs más grandes en relación con el tamaño de la rejilla.

guardarlo en la carpeta de asesor experto ( algo así como C:\Program Files\MetaTrader 4\experts\ ) y una copia opcional a la carpeta de scripts
si lo quieres como un script (C:\Program Files\MetaTrader 4\experts\scripts\).

Tengo un script para eliminar las órdenes de rejilla abierta si quieres.. es bastante útil si quieres cambiar la configuración.

NOTA: la configuración por defecto puede haber cambiado desde la última versión. asegúrese de poner su configuración preferida antes de volver a compilar.

PREGUNTA A UN ADMINISTRADOR: tal vez debería poner este tipo de cosas en la biblioteca de asesores expertos... ¿es esto correcto?

//+------------------------------------------------------------------+
//|                                                     MakeGrid.mq4 |
//|                                            Copyright © 2005, hdb |
//|                                       http://www.dubois1.net/hdb |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2005, hdb"
#property link      "http://www.dubois1.net/hdb"
//#property version      "1.2beta"

extern string GridName = "Grid";       // identifies the grid. allows for several co-existing grids
extern double Lots = 0.1;              // 
extern double GridSize = 6;            // pips between orders - grid or mesh size
extern double GridSteps = 10;          // total number of orders to place
extern double TakeProfit = 6 ;         // number of ticks to take profit. normally is = grid size but u can override
extern double StopLoss = 0;            // if u want to add a stop loss. normal grids dont use stop losses
extern double UpdateInterval = 15;     // update orders every x minutes
extern bool   wantLongs = true;        //  do we want long positions
extern bool   wantShorts = true;       //  do we want short positions
extern bool   wantBreakout = true;     // do we want longs above price, shorts below price
extern bool   wantCounter = false;      // do we want longs below price, shorts above price
extern bool   limitEMA34 = false;      // do we want longs above ema only, shorts below ema only
extern double LastUpdate = 0;          // counter used to note time of last update
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//---- 
 #property show_inputs                  // shows the parameters - thanks Slawa...    
 if ( TakeProfit <= 0 )                 // 
   { TakeProfit = GridSize; }
//----
   return(0);
  }
//+------------------------------------------------------------------------+
//| tests if there is an open position or order in the region of atRate    |
//|     will check for longs if checkLongs is true, else will check        |
//|     for shorts                                                         |
//+------------------------------------------------------------------------+

bool IsPosition(double atRate, double inRange, bool checkLongs )
  {
  
     int totalorders = OrdersTotal();
     for(int j=0;j<totalorders;j++)                                // scan all orders and positions...
      {
        OrderSelect(j, SELECT_BY_POS);
        if ( OrderSymbol()==Symbol() && OrderComment() == GridName )  // only look if mygrid and symbol...
         {  int type = OrderType();
            if (MathAbs( OrderOpenPrice() - atRate) < inRange) // dont look for exact price but price proximity (less than gridsize)
              { if ( ( checkLongs && ( type == OP_BUY || type == OP_BUYLIMIT  || type == OP_BUYSTOP ) )  || (!checkLongs && ( type == OP_SELL || type == OP_SELLLIMIT  || type == OP_SELLSTOP ) ) )
                 { return(true); }
              }
         }
      } 

   return(false);
  }
//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int start()
  {
//---- 
   int    i, j,k, ticket, entermode, totalorders;
   bool   doit;
   double point, startrate, traderate;
 
//----
  if (MathAbs(CurTime()-LastUpdate)> UpdateInterval*60)           // we update the first time it is called and every UpdateInterval minutes
   {
   LastUpdate = CurTime();
   Print("Updating");
   point = MarketInfo(Symbol(),MODE_POINT);
   startrate = ( Ask + point*GridSize/2 ) / point / GridSize;    // round to a number of ticks divisible by GridSize
   k = startrate ;
   k = k * GridSize ;
   startrate = k * point - GridSize*GridSteps/2*point ;          // calculate the lowest entry point
   
   double EMA34=iMA(NULL,0,34,0,MODE_EMA,PRICE_CLOSE,0);
   
   for( i=0;i<GridSteps;i++)
   {
     traderate = startrate + i*point*GridSize;
     if ( wantLongs && (!limitEMA34 || traderate > EMA34))
       {
         if (!IsPosition(traderate,point*GridSize,true) )           // test if i have no open orders close to my price: if so, put one on
          {
             double myStopLoss = 0;
             if ( StopLoss > 0 )
               { myStopLoss = traderate-point*StopLoss ; }
               
             if ( traderate > Ask ) 
              { entermode = OP_BUYSTOP; } 
              else 
              { entermode = OP_BUYLIMIT ; } 
             if ( (traderate > Ask ) && (wantBreakout) || ((traderate < Ask ) && (wantCounter)) ) 
              { ticket=OrderSend(Symbol(),entermode,Lots,traderate,0,myStopLoss,traderate+point*TakeProfit,GridName,16384,0,Green); }
          }
       }

     if ( wantShorts && (!limitEMA34 || traderate < EMA34))
       {
         if (!IsPosition(traderate,point*GridSize,false) )           // test if i have no open orders close to my price: if so, put one on
          {
             myStopLoss = 0;
             if ( StopLoss > 0 )
               { myStopLoss = traderate+point*StopLoss ; }
             if ( traderate > Bid ) 
              { entermode = OP_SELLLIMIT; } 
              else 
              { entermode = OP_SELLSTOP ; } 
              
              if ( (traderate < Bid ) && (wantBreakout) || ((traderate > Bid ) && (wantCounter)) ) 
                { ticket=OrderSend(Symbol(),entermode,Lots,traderate,0,myStopLoss,traderate-point*TakeProfit,GridName,16384,0,Red); }
          }
       }

    }
   }
   return(0);
  }
//+------------------------------------------------------------------+
 
Eso es genial...

Sólo la solución al problema en el momento de tener una opción de TP.

Puede que haya sobreestimado la cantidad de drawdown.. pero es de esperar que deje de haber muchos casos en los que he visto 2 órdenes al final de un rango
cada uno con una pérdida de $ 2000 + será una cosa del pasado :)

Ahora la última cosa que podría ser de utilidad es trabajar para establecer la opción de caducidad en las órdenes de límite...
actualmente lo tienes configurado para que no expiren ..
por lo que tienes que eliminar manualmente.

Actualmente tengo un montón de órdenes que son alrededor de 3 días de edad y no es probable que sea golpeado en cualquier momento pronto ..

Bueno me gustaría decir un gran trabajo .. :)
 
aquí hay un script para eliminar todas las órdenes abiertas para un par de divisas en particular. el código es un poco desagradable, pero parece que funciona...

//+------------------------------------------------------------------+
//|                                                   RemoveGrid.mq4 |
//|                                            Copyright © 2005, hdb |
//|                                       http://www.dubois1.net/hdb |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2005, hdb"
#property link      "http://www.dubois1.net/hdb"

extern string GridName = "Grid";

//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int start()
  {

 #property show_inputs              // shows the parameters - thanks Slawa... 

//---- 
  int total = OrdersTotal();
  int i ;
  
      for(i=total-1; i>=0;i--)
 
      {
        OrderSelect(i, SELECT_BY_POS);
        int type   = OrderType();

        if ( OrderSymbol()==Symbol() && OrderComment() == GridName )
        {
          bool result = false;
    
          switch(type)
          {
             case OP_BUY       : result = true ;
      
            case OP_SELL      : result = true ;

            //Close pending orders
            case OP_BUYLIMIT  : result = OrderDelete( OrderTicket() ); 
            case OP_BUYSTOP   : result = OrderDelete( OrderTicket() ); 
            case OP_SELLLIMIT : result = OrderDelete( OrderTicket() ); 
            case OP_SELLSTOP  : result = OrderDelete( OrderTicket() ); 
          }
    
          if(result == false)
          {
     //       Alert("Order " , OrderTicket() , " failed to close. Error:" , GetLastError() );
     //       Sleep(3000);
          }  
        }
      }
 
//----
   return(0);
  }
//+------------------------------------------------------------------+
Razón de la queja: