Примеры: MetaEditor: Опираясь на силу шаблонов - страница 3

 

Новый шаблон советника. Отличается от оптимизированного варианта, опубликованного как Шаблон советника в Code Base, блоком вывода информации об ордерах из Истории в файл .../tester/files/Имя_файла.csv.




Видео:


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

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

//+------------------------------------------------------------------+
//| результат последнего закрытого ордера в валюте депозита          |
//+------------------------------------------------------------------+
double LastProfit(double & lots)
   {
   double res = 0;
   lots = 0;
   int tickets = OrdersHistoryTotal();
//----
   if (tickets > 0)
      {
      if (OrderSelect(tickets-1,SELECT_BY_POS,MODE_HISTORY)) 
         { 
         res = OrderProfit();
         lots = OrderLots();
         }
      }
//----
   return(res);
   }
 
//+------------------------------------------------------------------+
//| комментарий в тикете последнего закрытого ордера                 |
//+------------------------------------------------------------------+
string LastOrderComment()
   {
   string res = "";
   int pos = OrdersHistoryTotal();
//----
   if (pos > 0)
      {
      if (OrderSelect(pos-1,SELECT_BY_POS, MODE_HISTORY))  res = OrderComment();
      }
//----
   return(res);
   }
 
//+------------------------------------------------------------------+
//| прибыль последних N закрытых ордеров                             |
//+------------------------------------------------------------------+
double SummLastOrder(int N)
   {
   double res = 0;
   int counter =0,pos = OrdersHistoryTotal()-1;
//----
   for (int i = pos ; i > 0;i--)
      {
      if (OrderSelect(pos-1,SELECT_BY_TICKET))  
         {
         res += OrderProfit();
         counter++;
         if (counter >=N) break;
         }
      }
 
//----
   return(res);
   }

В связи с этим, блоки по вычислению параметров для новых ордеров перемещены за блок закрытия рыночных и удаления отложенных ордеров. Теперь структура функции start() выглядит таким образом (нумерация блоков намеренно оне была изменена, чтобы было видно что и куда переехало):


//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
   // всегда обнуляем размер массива перед первым использованием
   InitCounters();
   
   // получим массивы наших ордеров
   PrepareTickets(Tickets,CommentsTicket,ExpertMagicNumber);
   
//----
 
/**
      1. Trade Signals . Получение торговых сигналов
      a) Каждый тик                       (TradeSignalEveryTick=true)
      б) Каждый бар заданного периода     (TradeSignalBarPeriod=...)
      OP_BUY      - в покупку
      OP_SELL     - в продажу
      OP_BALANCE  - нет сигнала
*/
 
 
   int trSignal=getTradeSignal(TradeDay,ReversDay,
                       TradeSignalEveryTick,TradeSignalBarPeriod);
                       
 
/**
      3. 
        а) Модификация каждого открытого ордера на каждый тик (SL и TP)        
               (ModifyMarketOrderEveryTick = true)
               
        б) Модификация каждого отложенного ордера на каждый тик (OpenPrice, SL и TP)
               (ModifyPendingEveryTick = true)
        
        в) Модификация каждого открытого ордера на каждом новом баре выбранного периода (SL и TP)
               (ModifyMarketBarPeriod = ...)
        
        г) Модификация каждого отложенного ордера на каждом новом баре выбранного периода (OpenPrice, SL и TP)
               (ModifyPendingBarPeriod = ...)
        
*/
 
   if(SL_TP_Counter>0) ModifyMarkets(ReversTradeSignal,ModifyMarketOrderEveryTick,ModifyMarketBarPeriod,newSL_and_TP);
   if(SL_TP_Counter>0) ModifyPendings(ReversTradeSignal,ModifyPendingEveryTick,ModifyPendingBarPeriod,newSL_and_TP);
 
/**
      4. 
        а) Закрыть открытый ордер по времени
        б) Закрыть открытый ордер по сигналу
*/
   // тикеты ордеров, которые нужно закрыть
   int ticketsToClose[100][2];
   double lotsToClose[100]; 
   
   
   // приготовим массив тикетов для закрытия
   if (trSignal!=OP_BALANCE) PrepareTicketsToClose(trSignal,ReversTradeSignal,ticketsToClose,lotsToClose,Tickets);
   
   // закроем указанные ордера
   if (OrdersToCloseCounter>0) CloseMarketOrders(ticketsToClose,lotsToClose);
 
/**
      5. 
        а) Удалить отложенный ордер по времени
        б) Удалить отложенный ордер по условию
*/
   // тикеты ордеров, которые нужно удалить
   int ticketsToDelete[100];
 
   // приготовим массив тикетов для удаления
   if (trSignal!=OP_BALANCE) PrepareTicketsToDelete(trSignal,ReversTradeSignal,ticketsToDelete,Tickets);
 
   // удалим указанные ордера
   if (OrdersToDeleteCounter>0) DeletePendingOrders(ticketsToDelete);
 
 
/**
      2. 
        а) Вычислить SL и TP для каждого открытого ордера
        б) Вычислить OpenPrice, SL, TP, и Lots для нового ордера
        в) Вычислить OpenPrice, SL и TP для каждого отложенного ордера
*/
 
   if(OurTicketsCounter>0) CalculateSL_and_TP(ReversTradeSignal,Tickets,newSL_and_TP);
 
 
   double marketLots,marketSL,marketTP;
   int marketType, pendingType;
   string marketComment, pendingComment;
   double pendingOpenPrice, pendingLots, pendingSL, pendingTP;
 
   CalculateNewMarketValues(trSignal, marketType, marketLots,marketSL,marketTP,marketComment);
   CalculateNewPendingValues(trSignal, pendingType, pendingOpenPrice, pendingLots, pendingSL, pendingTP, pendingComment);
 
/**
      6. 
        а) Открыть ордер по рынку
        б) Выставить отложенный ордер без ограничения времени
        в) Выставить отложенный ордер с истечением по времени
*/
 
   if (trSignal!=OP_BALANCE) OpenMarketOrder(ReversTradeSignal,marketType,marketLots,marketSL,marketTP,marketComment);
   if (trSignal!=OP_BALANCE) SendPendingOrder(ReversTradeSignal,pendingType,pendingOpenPrice, pendingLots, pendingSL, pendingTP,pendingComment);
//----
   return(0);
  }
//+------------------------------------------------------------------+
 
Rosh:
rotstern:
Очень полезная статья, возвращаюсь к ней в который раз. Не могли ли Вы немного по подробнее остановиться на функциях принудительного закытия ордеров и и трилингстопе (с примером). Был бы Вам очень благодарен.
Были такие мысли, постараюсь в ближайшие пару месяцев (не могу строго обещать). На данный момент пока есть другие нереализованные статьи, надо с ними сначала закончить.

Сделать Trailing Stop в этом шаблоне очень просто, определите функцию getNewSL(). Вот пример для трейлинга по параболику:

//+------------------------------------------------------------------+
//|  вычисляет уровень Stop Loss                                     |
//+------------------------------------------------------------------+
double getNewSL(int    type,      // тип ордера, для которого вычисляем
                double lots,      // объем, может понадобиться
                double openPrice, // цена открытия
                double stopLoss,  // текущий уровень Stop Loss
                double takeProfit // текущий уровень Take Profit
                )
   {
   double res=-1;
//----
//  здесь код вычисления Stop Loss
   if (type == OP_BUY) res = NormalizeDouble(iSAR(NULL,0,0.02,0.2,1),Digits);
   if (type == OP_SELL) res = NormalizeDouble(iCustom(NULL,0,0.02,0.2,2,1)+MarketInfo(Symbol(),MODE_SPREAD)*Point,Digits);
//----
   return(res);   
   }

Компилируете и запускаете тестирование, все происходит автоматически:




В шаблоне не определена реакция на неправильные значения нового SL (или тейкпрофита), в данном случае видна ошибка #1 на попытку модификации - это означает что новое значение SL не отличается от уже установленного. Но там, где уровень вычислен допустимо, стоплосс подтягивается.

 

Слижком уж сложное написание функции нового бара. Предлагаю так:

Усложненный вариант: Через указатель и подсчет новых баров на любой валюте и ТФ

int D1MaxBars = 0;
int start()
{
if (!IsNewBar("",0,D1MaxBars)) return(0); 
// Время пришло...
}
bool IsNewBar(string vCurrency,int vTimeframe, int &MaxBars)
{
if (vCurrency=="") vCurrency=NULL;
int vBars = iBars(vCurrency, vTimeFrame) 
if ( vBars > vMaxBars)
   {
     vMaxBars = vBars;
     return(true);
   } 
    else
   {
     return(false);
   }
}

Вариант упрощенный: Работает только на текущем ТФ и валюте...

int MaxBars = 0;
int start()
{
if (!IsNewBar()) return(0); 
// Время пришло...
}
bool IsNewBar()
{
  if (Bars > MaxBars) 
    {
      MaxBars = Bars;
      return(true);
    }
  else
    {
      return(false);
    }
}
 
esmaster:

Слижком уж сложное написание функции нового бара. Предлагаю так:

Опечатка...
bool IsNewBar(string vCurrency,int vTimeframe, int &vMaxBars)
 
esmaster:

Слижком уж сложное написание функции нового бара. Предлагаю так:

Усложненный вариант: Через указатель и подсчет новых баров на любой валюте и ТФ

int D1MaxBars = 0;
int start()
{
if (!IsNewBar("",0,D1MaxBars)) return(0); 
// Время пришло...
}
bool IsNewBar(string vCurrency,int vTimeframe, int &MaxBars)
{
if (vCurrency=="") vCurrency=NULL;
int vBars = iBars(vCurrency, vTimeFrame) 
if ( vBars > vMaxBars)
   {
     vMaxBars = vBars;
     return(true);
   } 
    else
   {
     return(false);
   }
}

Тогда все равно придется помнить значение MaxBars для каждого таймфрейма.
 
Rosh:
Rosh:
rotstern:
Очень полезная статья, возвращаюсь к ней в который раз. Не могли ли Вы немного по подробнее остановиться на функциях принудительного закытия ордеров и и трилингстопе (с примером). Был бы Вам очень благодарен.
Были такие мысли, постараюсь в ближайшие пару месяцев (не могу строго обещать). На данный момент пока есть другие нереализованные статьи, надо с ними сначала закончить.

Сделать Trailing Stop в этом шаблоне очень просто, определите функцию getNewSL(). Вот пример для трейлинга по параболику:

//+------------------------------------------------------------------+
//|  вычисляет уровень Stop Loss                                     |
//+------------------------------------------------------------------+
double getNewSL(int    type,      // тип ордера, для которого вычисляем
                double lots,      // объем, может понадобиться
                double openPrice, // цена открытия
                double stopLoss,  // текущий уровень Stop Loss
                double takeProfit // текущий уровень Take Profit
                )
   {
   double res=-1;
//----
//  здесь код вычисления Stop Loss
   if (type == OP_BUY) res = NormalizeDouble(iSAR(NULL,0,0.02,0.2,1),Digits);
   if (type == OP_SELL) res = NormalizeDouble(iCustom(NULL,0,0.02,0.2,2,1)+MarketInfo(Symbol(),MODE_SPREAD)*Point,Digits);
//----
   return(res);   
   }

Компилируете и запускаете тестирование, все происходит автоматически:




В шаблоне не определена реакция на неправильные значения нового SL (или тейкпрофита), в данном случае видна ошибка #1 на попытку модификации - это означает что новое значение SL не отличается от уже установленного. Но там, где уровень вычислен допустимо, стоплосс подтягивается.


У меня не заработал в данном примере трал. Подскажите пожалуйста в чем может быть дело. Можно ли увидеть рабочий пример. А еще нет условия на проверку количества открытых ордеров, тот пример что здесь - при наступлении сигнала ордера открываются до бесконечности. А хотелось бы ограничить как по количеству так и по времени. Например не больше 3 и не ольше одного в час (при работе на минутном графике). Пожалуйста помогите, очень понравилась статья. еще бы до конца довести а то я только учусь программировать.
 
Rosh, помогите пожалуйста, следующее вставить в шаблон советника
        BlueH_0 	= iCustom(Symbol(),workPeriod, "TDI Channel", 13, 0, 34, 2, 0, 7, 0,   1, shift);	// Blue   (H. Vol Band)
	Yellow_0 	= iCustom(Symbol(),workPeriod, "TDI Channel", 13, 0, 34, 2, 0, 7, 0,   2, shift);	// Yellow (Market Base)
	BlueL_0    	= iCustom(Symbol(),workPeriod, "TDI Channel", 13, 0, 34, 2, 0, 7, 0,   3, shift);	// Blue   (L. Vol Band)
	Green_0 	= iCustom(Symbol(),workPeriod, "TDI Channel", 13, 0, 34, 2, 0, 7, 0,   4, shift);	// Green  (RSI Price)
	Red_0 		= iCustom(Symbol(),workPeriod, "TDI Channel", 13, 0, 34, 2, 0, 7, 0,   5, shift);	// Red    (Trade Signal)
	Channel_0	= iCustom(Symbol(),workPeriod, "TDI Channel", 13, 0, 34, 2, 0, 7, 0,   6, shift);	//        (Channel)
	
	// Last Closed Candle...
	BlueH_1 	   = iCustom(Symbol(),workPeriod, "TDI Channel", 13, 0, 34, 2, 0, 7, 0,   1, shift+1);	// Blue   (H. Vol Band)
	Yellow_1 	= iCustom(Symbol(),workPeriod, "TDI Channel", 13, 0, 34, 2, 0, 7, 0,   2, shift+1);	// Yellow (Market Base)
	BlueL_1 	= iCustom(Symbol(),workPeriod, "TDI Channel", 13, 0, 34, 2, 0, 7, 0,   3, shift+1);	// Blue   (L. Vol Band)
	Green_1    	= iCustom(Symbol(),workPeriod, "TDI Channel", 13, 0, 34, 2, 0, 7, 0,   4, shift+1);	// Green  (RSI Price)
	Red_1 		= iCustom(Symbol(),workPeriod, "TDI Channel", 13, 0, 34, 2, 0, 7, 0,   5, shift+1);	// Red    (Trade Signal)
	Channel_1	= iCustom(Symbol(),workPeriod, "TDI Channel", 13, 0, 34, 2, 0, 7, 0,   6, shift+1);	//        (Channel)
	
	// Prev Prev Candle...
	BlueH_2 	   = iCustom(Symbol(),workPeriod, "TDI Channel", 13, 0, 34, 2, 0, 7, 0,   1, shift+2);	// Blue   (H. Vol Band)
	Yellow_2 	= iCustom(Symbol(),workPeriod, "TDI Channel", 13, 0, 34, 2, 0, 7, 0,   2, shift+2);	// Yellow (Market Base)
	BlueL_2    	= iCustom(Symbol(),workPeriod, "TDI Channel", 13, 0, 34, 2, 0, 7, 0,   3, shift+2);	// Blue   (L. Vol Band)
	Green_2    	= iCustom(Symbol(),workPeriod, "TDI Channel", 13, 0, 34, 2, 0, 7, 0,   4, shift+2);	// Green  (RSI Price)
	Red_2 		= iCustom(Symbol(),workPeriod, "TDI Channel", 13, 0, 34, 2, 0, 7, 0,   5, shift+2);	// Red    (Trade Signal)
	Channel_2	= iCustom(Symbol(),workPeriod, "TDI Channel", 13, 0, 34, 2, 0, 7, 0,   6, shift+2);	//        (Channel)
if(Green_1 > Red_1 && Green_2 < Green_1 && Red_1 < Yellow_1 && Yellow_2 < Yellow_1 && Red_2 < Red_1 && Yellow_1 <50 && Channel_1 > 25 )
		res = OP_BUY;
if(Green_1 < Red_1 && Green_2 > Green_1 && Red_2 > Red_1 && Red_1 > Yellow_1 && Yellow_2 > Yellow_1 && Yellow_1 > 50 && Channel_1 < 25 )
		res = OP_SELL;
if(OrderType()==OP_BUY)
        {
         if(Red_1 < Yellow_1 && Red_2 > Yellow_2) 
         OrderClose(........................);
         break;
        }
      if(OrderType()==OP_SELL)
        {
          
          if(Red_1 > Yellow_1 && Red_2 < Yellow_2)
          OrderClose(..........................);
          break;
        }