Создатель сетки 1.1

 
Здесь представлена версия 1.1 "Grid maker"... скрипт или советник, который устанавливает и поддерживает серию равномерно распределенных ордеров на покупку или продажу.
Эта версия является либо скриптом, либо советником, вы можете изменить частоту обновления, выбрать лонги и/или шорты, и т.д... см. параметры для объяснения.

Я думаю, что протестировал большинство вариантов, но нет никаких гарантий, что это работает во всех случаях! Если вы попробуете и найдете проблемы, дайте мне знать.

Возможно, это последняя версия, которую я выкладываю. Я разработал ее для тестирования MT4. Будущие версии будут более сложными, требующими внешних данных, таких как уровни поддержки и сопротивления, поэтому выкладывать их будет нецелесообразно.



//+------------------------------------------------------------------+
//|                                                     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);
  }
//+------------------------------------------------------------------+
 
Привет, hdb,

Я слежу за этой идеей с давних пор на форумах MoneyTec (Simspeed), ET (ElectricSavant) и Oanda (MarkVH и Sympatico) и я думал о том, как разработать эксперта для улучшения первого скрипта, который Вы послали на форум, возможно, мы могли бы работать вместе, чтобы достичь чего-то быстрее :) Пожалуйста, дайте мне знать, если вы заинтересованы, мой e-mail: artefactodigital@gmail.com.

С наилучшими пожеланиями,
Фернандо.

Здесь представлена версия 1.1 "Grid maker"... скрипт или советник, который устанавливает и поддерживает серию равномерно распределенных ордеров на покупку или продажу. <br / translate="no"> Эта версия является либо скриптом, либо советником, вы можете изменить частоту обновления, выбрать лонги и/или шорты, и т.д... см. параметры для объяснения.

Я думаю, что протестировал большинство вариантов, но нет никаких гарантий, что это работает во всех случаях! Если вы попробуете и найдете проблемы, дайте мне знать.

Возможно, это последняя версия, которую я выкладываю. Я разработал ее для тестирования MT4. Будущие версии будут более сложными, требующими внешних данных, таких как уровни поддержки и сопротивления, поэтому выкладывать их будет нецелесообразно.
 
Хорошо, звучит неплохо... см. мой e-mail...
 
кстати, вы можете пробовать, использовать, менять его, но, пожалуйста, не продавайте его!

Я не даю никаких гарантий относительно его эффективного рабочего состояния и любые торговые операции, которые вы можете проводить с ним, вы осуществляете на свой страх и риск.
Я не несу никакой ответственности за прямые или косвенные убытки, связанные с этим скриптом.


Если вы используете его, пожалуйста, периодически оставляйте отзывы - результаты, настройки, ошибки, наблюдения и т.д.

наслаждайтесь
 
ок, поехали... одно крупное движение рынка спустя, сетка выжила!!! Я открыл демо-счет две недели назад с 50k.
Я потерял 1k, тестируя гридмейкер, а затем, прямо перед падением евро, я поставил эксперта GridMaker по умолчанию на 9 валютных пар:
EUR/CHF, USD/JPY, GBP/JPY, EUR/GBP, USD/CHF, AUD/USD, GBP/USD, EUR/USD, EUR/JPY.

Расстояние между сетками составляет 6 тиков для всех валют, а TP на уровне 6 тиков. Я установил размер лота 0,1. Я выставлял длинные и короткие позиции каждые 6 тиков для каждой валютной пары.
Обновление происходило каждые 15 минут (т.е. сетка регенерировалась каждые 15 минут), за исключением EUR/USD и GBP/USD с интервалом 5 минут.

Баланс увеличился на 10 тыс. (20%), использованная маржа - 13 тыс. (26%), свободная маржа - 26 тыс. (52%), нереализованный доход от прибыли и убытков -19 тыс.

Чистый результат евро-бана (пока что) заключается в том, что я потерял -9k. Я ожидал гораздо худшего!

Сетка пополняет баланс со скоростью от 600 до 2000 в день!

Я с нетерпением жду, как это будет выглядеть на следующей неделе.

Да здравствует сетка!!!
 
Так, так, неделя прошла, а сетка действительно пострадала! Моя вина, потому что я не сделал необходимые расчеты размера лота / расстояния между сетками.
необходимых для того, чтобы понять, какой удар можно принять с имеющимся капиталом.

В любом случае, баланс развивается довольно хорошо: от 700 до 1800 в день прирост - баланс сейчас 65k (начинал с 49k, так что это +16k).
Использованная маржа сейчас 15k, доступная маржа 21k - все еще много места для добавления позиций, когда это необходимо.
Нереализованный доход -29k, что дает чистый убыток в 13k, на 4 хуже, чем на прошлой неделе.

Положительным моментом является то, что я изменил настройки, чтобы избежать встречных сделок (флаг CounterTrade false), и нереализованный p&l, кажется, стабилизировался.
На одном этапе он был на уровне -36k.

Что мне нравится в этом форвард-тесте, так это то, что он начался с большого удара - падения евро на прошлой неделе - так что теперь будет интересно посмотреть, как и когда система восстановится.
система восстановится. Я не сомневаюсь, что так и будет.

Я просто не могу дождаться результатов на следующей неделе!!!

ps. У меня есть версия 1.2 с возможностью изменения TP и добавления SL. Напишите здесь, если хотите.
 
Я немного поиграл с этой программой. Просто запустил все по умолчанию на всех парах...
Должен сказать, что я был очень впечатлен его работой.

Есть только один большой нюанс.

Давайте возьмем только короткие позиции... по мере падения цены активируются короткие ордера... но много раз вы можете получить 2 ордера на короткой стороне, прежде чем цена решит развернуться.

т.е. тейк-профит находится по той же цене, что и следующий короткий, который будет инициирован, и не учитывает спред, т.е. цены покупки и продажи.

поэтому для того, чтобы предотвратить открытие 2 ордеров до того, как цена развернется в длинную сторону, TP должен произойти в то же время, когда будет размещен следующий короткий ордер.

Я думаю, если это возможно, моя просадка в настоящее время может быть сокращена вдвое...

Я предполагаю, что ваша последняя версия этой системы решит эту проблему.

Так что если бы вы могли опубликовать его, это было бы замечательно...
 
Привет,

Я рад, что ты находишь это интересным. Я тоже.

я никак не могу одновременно иметь TP = размер сетки и исключить возможность иметь 2 открытые позиции на развороте.
Это не проблема программного обеспечения, а просто связано со спредами.

Единственная возможность теоретически полностью исключить это - терять спред каждый раз:
т.е. при спреде в 4 тика вы выходите в короткую позицию по 1.2006 (бид), TP по 1.2000 (аск) и короткую позицию по 1.1996 (бид).
Вы просто теряете 4/10 диапазона.

В новой версии можно установить размер сетки и TP на разные числа, так что можно реализовать то, что вы ищете.
можно установить сетку на 10, а TP на 6, если спред 4 пункта.

Я не уверен, что это уменьшит dd в два раза - но это определенно значительно уменьшит вашу прибыль.

Дайте мне знать.

ps. v1.2 в следующем посте
 
вот версия 1.2 гридмейкера.

единственные отличия:
1) я добавил опциональный стоплосс, если он вам нужен. 0 означает отсутствие стоплосса, любое положительное число означает стоплосс.
Если вы используете стоплосс в сетке, вы должны сделать его большим.
2) вы можете указать TP, отличный от размера сетки. darkstonexa, в предыдущем сообщении, хочет устранить двойные "висячие" позиции.
Моим первоначальным намерением было попробовать большие ТП относительно размера сетки.

сохраните его в папке советника (что-то вроде C:\Program Files\MetaTrader 4\experts\) и, по желанию, скопируйте в папку scripts
, если хотите использовать его как скрипт (C:\Program Files\MetaTrader 4\experts\scripts\).

У меня есть скрипт для удаления открытых ордеров сетки, если вы хотите... это довольно полезно, если вы хотите изменить настройки.

ПРИМЕЧАНИЕ: настройки по умолчанию могли измениться со времен последней версии. убедитесь, что вы установили ваши предпочтительные настройки перед перекомпиляцией.

ВОПРОС к администратору: возможно, я должен поместить подобные вещи в библиотеку советников... это правильно?

//+------------------------------------------------------------------+
//|                                                     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);
  }
//+------------------------------------------------------------------+
 
Это здорово...

Это просто решение проблемы, когда есть опция TP.

Возможно, я переоценил размер просадки... но это, надеюсь, остановит многие случаи, когда я видел 2 ордера в конце диапазона.
каждый с убытком в $2000+ уйдут в прошлое :)

Теперь последнее, что может быть полезным, это разработка опции истечения срока действия лимитных ордеров...
Сейчас у вас установлено, что они не истекают...
поэтому приходится удалять вручную.

В настоящее время у меня есть куча ордеров, которым около 3 дней и которые вряд ли будут исполнены в ближайшее время...

Что ж, я хотел бы сказать, что это отличная работа... :)
 
вот скрипт для удаления всех открытых ордеров для определенной валютной пары. код немного неприятный, но, кажется, работает.

//+------------------------------------------------------------------+
//|                                                   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);
  }
//+------------------------------------------------------------------+
Причина обращения: