Библиотеки: Библиотека функций и советники для трейлинга / Юрий Дзюбан - страница 5

 
Большое спасибо всем, кто пользуется моими скромными наработками! Весьма надеюсь, что вы находите их полезными. К слову - за 5 месяцев с момента публикации данная библиотека стала 3-й среди всех библиотек по числу скачиваний (притом она самая "молодая" в тройке) и первое - по числу комментариев. Большое спасибо!

К сожалению, сейчас не имею достаточного времени, чтобы часто здесь отписываться. Всем, кто имеет какие-либо идеи в плане улучшения или изменения рассматриваемых функций для трейлинга - you are welcome! пожалуйста, модифицируйте, изменяйте, улучшайте. Добавляйте себя в качестве соавторов. Единственная просьба - не удалять инфо об авторе оригинала :)
 
Idalgo писал(а):

Можно как-то модифицировать функцию KillLoss, чтобы она работала для случаев, когда одновременно открыто более одного ордера? Если, к примеру, два ордера открыто, то не тралится ничего. 

Имхо, вместо модификации функции проще перед её вызовом пересчитать открытые позиции и далее, в зависимости от их числа, либо вызывать, либо нет. Например:

   int iOpenOrdersN; // переменная для подсчета кол-ва открытых позиций
   int i;            // переменная-счетчик для циклов
      
   for (i=0;i<OrdersTotal();i++)
      {
      if ((OrderType()==OP_BUY) || (OrderType()==OP_SELL))
      iOpenOrdersN++;
      }                
   
   if (iOpenOrdersN==1)
   // ну или
   // if ((iOpenOrdersN<=1) && (iOpenOrdersN>0))
      {
      // трейлинг на каждом тике
      for (i=0;i<OrdersTotal();i++)
         {
         if (!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) break;
         if (OrderMagicNumber()!=magic || OrderSymbol()!=Symbol()) continue;
         if ((OrderType()==OP_BUY) || (OrderType()==OP_SELL))
            {
            KillLoss(OrderTicket(),1);
            }
         }
       }
С уважением, Юрий.
 
I_D:
Idalgo писал(а):

Можно как-то модифицировать функцию KillLoss, чтобы она работала для случаев, когда одновременно открыто более одного ордера? Если, к примеру, два ордера открыто, то не тралится ничего. 

Имхо, вместо модификации функции проще перед её вызовом пересчитать открытые позиции и далее, в зависимости от их числа, либо вызывать, либо нет. Например:


 

 Юрий, Вам - большое спасибо за Ваши усилия, выложенные материалы и оперативные ответы на вопросы!

Насчет модификации функции KillLoss, я не совсем то имел в виду. Я создал советника, который открывает одновременно ордера в количестве большем, чем 1, и предполагал вставить в него в качестве опции функцию KillLoss. Замечено, что функция KillLoss корректно работает только при одном открытом в данный момент ордере, а если, скажем, одновременно открыто 2 ордера, то она выключается (не срабатывает), и стоплосс срабатывает там, где он изначально ставится.

Проще говоря, KillLoss не тралит одновременно две позиции, как, например, Udavka.

 
Огромная просьба ткнуть носом куда именно нужно вставить код трала ???
//+------------------------------------------------------------------+
//|                                                         Gray.mq4 |
//|                      Copyright © 2007, MetaQuotes Software Corp. |
//|                                        https://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, MetaQuotes Software Corp."
#property link      "https://www.metaquotes.net/"
 
extern double lot=0.1;
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
 
  {
  
  int tiket=0;
//----
 
if (iVolume(NULL,0,0)==1){
    Print("WATR1="+iCustom( NULL, 0, "WATR", 0, 0) );
    Print("WATR2="+iCustom( NULL, 0, "WATR", 1, 0) );
    
    if (iCustom( NULL, 0, "WATR", 0, 2)<1000 && iCustom( NULL, 0, "WATR", 1, 1)<1000) {tiket =OrderSend(Symbol(),OP_SELL,lot,Bid,3,iCustom( NULL, 0, "WATR", 1, 0),0,NULL,16384,0,Red);}
    if (iCustom( NULL, 0, "WATR", 1, 2)<1000 && iCustom( NULL, 0, "WATR", 0, 1)<1000) {tiket= OrderSend(Symbol(),OP_BUY,lot,Ask,3, iCustom( NULL, 0, "WATR", 0, 0),0,NULL,16384,0,Green);}
    CheckOrders();
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
 
}
void CheckOrders(){
int pos=0;
int total=OrdersTotal();
for (pos=0;pos<total;pos++) {
if (OrderSelect(pos,SELECT_BY_POS,MODE_TRADES)==True){ 
if (OrderType()==OP_BUY && OrderStopLoss()<iCustom( NULL, 0, "WATR", 0, 1))OrderModify(OrderTicket(),OrderOpenPrice(),iCustom( NULL, 0, "WATR", 0, 1),OrderTakeProfit(),0,Green);
if (OrderType()==OP_SELL && OrderStopLoss()>iCustom( NULL, 0, "WATR", 1, 1))OrderModify(OrderTicket(),OrderOpenPrice(),iCustom( NULL, 0, "WATR", 1, 1),OrderTakeProfit(),0,Red);
                                                                                   }
                                                          }
                                      }
 

Я  не программист,  трейдер и наверное  тут я не в "своей компании".  Мне многое не понятно, какой трал в описании, какому соответствует в библиотеке? Зачем их столько много? Почему они не работают одновременно?  Какова результативность их применения? и т.д.

Друзья, а нет ли у Вас, для начала, ОДНОГО максимально простого трала, который при достижении заданного профита устанавливает стоплосс в безубыток?  Причём надо что бы одновременно работало несколко таких тралов на одной валютной паре.    

 

Здравствуйте, Ultramarin.

Извините, что отвечаю с таким запозданием (скорее всего, вопрос либо решен, либо неактуален), но все же - в советнике (в т.ч. приведеннном) функцию трейлинга следует вызывать где-нибудь из стандартной функции start(), напр.:

...
start()
     {
     ...
     ... 
     // другие функции, вызываемые на каждом тике курса
     ...
     // ищем открытые сделки и вызываем соответствующую функцию трейлинга, передав ей тикет открытой позиции
     for (i=0;i<OrdersTotal();i++)
         {
         if (!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) break;
         if (OrderMagicNumber()!=magic || OrderSymbol()!=Symbol()) continue;
         if ((OrderType()==OP_BUY) || (OrderType()==OP_SELL))
            {
            // !!! ПРИМЕР ВЫЗОВА ФУНКЦИЙ ТРЕЙЛИНГА !!!
            // среди возможных вариантов мы, допустим, выбрали трейлинг по фракталам. Трейлингуем по 
            // 5-барным фракталам на дневках, с отступом от экстремума в 3 п., в зоне лоссов не тралим
            TrailingByFractals(OrderTicket(),1440,5,3,false);
            // (как видим, достаточно предварительно выбрать ордер OrderSelect() и вызвать функцию, 
            // передав ей тикет позиции и определив необходимые параметры).
            // При желании Вы можете закоментировать данный вид трейлинга и подключить любой другой 
            // или даже "сконструировать" из них более или менее сложную конструкцию.            
            //TrailingByShadows(OrderTicket(),60,iTrlBars,3,true);            
            //TrailingRatchetB(OrderTicket(),10,25,30,10,25,30,false);
            //TrailingStairs(OrderTicket(),50,10);  
            //TrailingByATR(OrderTicket(),1440,5,1,20,1,1,false); 
            // и т.д.       
            }
         }
return(0);
}
 
YuriF:

Я  не программист,  трейдер и наверное  тут я не в "своей компании".  Мне многое не понятно, какой трал в описании, какому соответствует в библиотеке? Зачем их столько много? Почему они не работают одновременно?  Какова результативность их применения? и т.д.

Друзья, а нет ли у Вас, для начала, ОДНОГО максимально простого трала, который при достижении заданного профита устанавливает стоплосс в безубыток?  Причём надо что бы одновременно работало несколко таких тралов на одной валютной паре.    

Здравствуйте, YuriF.

Ну почему же вы так сразу "противопоставляетесь"? Согласен, иногда можно наблюдать примеры того, когда "кодится скорее ради кода, чем собственно торговли", однако все, что я до сих пор писал, так или иначе было нужно для решения каких-то торговых задач. Не скажу, что использую в своей торговле все представленные трейлинговые функции, однако некоторые - регулярно (трейлинг "по теням" и "по фракталам").  Относительно ваших вопросов:

а) названия тралов в описании и в библиотеке - в описании каждой функции приведено ее конкретное названиие, напр., трейлингу, который я назвал "стандартным-ступенчастым" (из-за особенностей алгоритма, соответствует функция

void TrailingStairs(int ticket,int trldistance,int trlstep);

Я не назвал ее TrejlingStandartnyjStupenchastyj, но указываю конкретное название, мне казалось, что разобраться не так сложно;

б) "Зачем их (функций трейлинга) столько много?" и "Почему они не работают одновременно?" Функций много, чтобы трейдер мог выбрать ту, которая, на его взгляд, наилучшим образом подходит для конкретной торговой системы (советника). Относительно второй части вопроса: YuriF, а как вы представляете себе одновременный трейлинг одной и той же позиции на расстоянии в 30 п. и 15 п.?

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

г) насчет переноса в БУ при определенном профите - пожалуйста, попробуйте;

д) "Причём надо чтобы одновременно работало несколко таких тралов на одной валютной паре". Это как? Одна позиция - один трейлинг (одновременно). Сколько позиций "на одной валютной паре" откроете, столько и тралить можно.

YuriF, желаю вам успеха в торговле и самообразовании! С уважением.
 

Я занялся изучением языка MQL4 относительно недавно (в конце марта 2007). Поэтому с признательностью приму любые конструктивные замечания, советы, предложения, идеи и прочее относительно представленных выше функций. Надеюсь, они будут для Вас полезными.

При работе с Глобальными переменными терминала хорошим тоном является использование разных имен в случае тестирования и работы на реале. Иначе тестируемый советник может нарушить алгоритм работы советника, работающего на реале.

Это конструктивное предложение ;)

 
komposter:

Это конструктивное предложение ;)

И надо бы предусмотреть одновременную работу нескольких экспертов.

Я бы вообще сделал имя переменной, хранящей расстояние до СЛ = тикету ордера. Тогда для каждого ордера была бы своя переменная и не было бы конфликтов.

 
komposter:

И надо бы предусмотреть одновременную работу нескольких экспертов.

Слово за слово, и написал =)

Функция KillLoss выглядит так:

void KillLoss(int iTicket,double dSpeedCoeff)
   {   
   // проверяем переданные значения
   if ((iTicket==0) || (!OrderSelect(iTicket,SELECT_BY_TICKET)) || (dSpeedCoeff<0.1))
      {
      Print("Трейлинг функцией KillLoss() невозможен из-за некорректности значений переданных ей аргументов.");
      return(0);
      }           
   double dStopPriceDiff; // расстояние (пунктов) между курсом и стоплоссом   
   double dToMove; // кол-во пунктов, на которое следует переместить стоплосс   
   // текущий курс
   double dBid = MarketInfo(OrderSymbol(),MODE_BID);
   double dAsk = MarketInfo(OrderSymbol(),MODE_ASK);      
   
   // текущее расстояние между курсом и стоплоссом
   if (OrderType()==OP_BUY) dStopPriceDiff = dBid - OrderStopLoss();
   if (OrderType()==OP_SELL) dStopPriceDiff = (OrderStopLoss() + MarketInfo(OrderSymbol(),MODE_SPREAD)*MarketInfo(OrderSymbol(),MODE_POINT)) - dAsk;                  
   
   string GL_name = StringConcatenate( "KillLossTrailing_", iTicket );
   if ( IsTesting() ) GL_name = StringConcatenate( "_tester_", GL_name );
   if (!GlobalVariableCheck(GL_name))
      {
      GlobalVariableSet(GL_name,dStopPriceDiff);      
      }
   else
      {
      // итак, у нас есть коэффициент ускорения изменения курса
      // на каждый пункт, который проходит курс в сторону лосса, 
      // мы должны переместить стоплосс ему на встречу на dSpeedCoeff раз пунктов
      // (например, если лосс увеличился на 3 пункта за тик, dSpeedCoeff = 1.5, то
      // стоплосс подтягиваем на 3 х 1.5 = 4.5, округляем - 5 п. Если подтянуть не 
      // удаётся (слишком близко), ничего не делаем.            
      
      // кол-во пунктов, на которое приблизился курс к стоплоссу с момента предыдущей проверки (тика, по идее)
      dToMove = (GlobalVariableGet(GL_name) - dStopPriceDiff) / MarketInfo(OrderSymbol(),MODE_POINT);
      
      // записываем новое значение, но только если оно уменьшилось
      if (dStopPriceDiff<GlobalVariableGet(GL_name))
      GlobalVariableSet(GL_name,dStopPriceDiff);
      
      // дальше действия на случай, если расстояние уменьшилось (т.е. курс приблизился к стоплоссу, убыток растет)
      if (dToMove>0)
         {       
         // стоплосс, соответственно, нужно также передвинуть на такое же расстояние, но с учетом коэфф. ускорения
         dToMove = MathRound(dToMove * dSpeedCoeff) * MarketInfo(OrderSymbol(),MODE_POINT);                 
      
         // теперь проверим, можем ли мы подтянуть стоплосс на такое расстояние
         if (OrderType()==OP_BUY)
            {
            if (dBid - (OrderStopLoss() + dToMove)>MarketInfo(OrderSymbol(),MODE_STOPLEVEL)* MarketInfo(OrderSymbol(),MODE_POINT))
            OrderModify(iTicket,OrderOpenPrice(),OrderStopLoss() + dToMove,OrderTakeProfit(),OrderExpiration());            
            }
         if (OrderType()==OP_SELL)
            {
            if ((OrderStopLoss() - dToMove) - dAsk>MarketInfo(OrderSymbol(),MODE_STOPLEVEL) * MarketInfo(OrderSymbol(),MODE_POINT))
            OrderModify(iTicket,OrderOpenPrice(),OrderStopLoss() - dToMove,OrderTakeProfit(),OrderExpiration());
            }      
         }
      }            
   }

После ее использования в тестере необходимо удалить ненужные переменные (иначе при повторном тесте трейлинг будет работать неправильно):

int deinit()
{
	GlobalVariablesDeleteAll( "_tester_" );
	return(0);
}
Причина обращения: