Пользовательские индюки

 
Как научить МТ понимать пользовательские индюки?
 
а что его учить? он умеет, главное ему правильно объяснить. фукнкция iCustom поможет.
 
Как быдет выгледеть эта функция для этого индюка?

#property indicator_separate_window
#property indicator_buffers 2
#property indicator_color1 LightSeaGreen
#property indicator_color2 FireBrick

//---- input parameters
extern int EMA_period=3;
extern int MomPeriod=8;

extern int CountBars=999999;
//---- buffers
double Up[];
double Down[];
double Mom;
double e1,e2,e3,e4,e5,e6,e7,e8,e9,e10,e11,e12;
double c1,c2,c3,c4;
double n,n1,w1,w2,b2,b3,w3,w4,b;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- indicator line
IndicatorBuffers(2);
SetIndexStyle(0,DRAW_HISTOGRAM);
SetIndexBuffer(0,Up);
SetIndexStyle(1,DRAW_HISTOGRAM);
SetIndexBuffer(1,Down);
//----
//----
//---- variable reset
/*e1=0; e2=0; e3=0; e4=0; e5=0; e6=0;
c1=0; c2=0; c3=0; c4=0;
n=0;n1=0;
w1=0; w2=0; w3=0; w4=0;
b2=0; b3=0;*/

b = 0.7;
b2=b*b;
b3=b2*b;
c1=-b3;
c2=(3*(b2+b3));
c3=-3*(2*b2+b+b3);
c4=(1+3*b+b3+3*b2);
n=EMA_period;
n1=MomPeriod + MomPeriod + 1;

if (n<1) n=1;
n = 1 + 0.5*(n-1);
w1 = 2 / (n + 1);
w2 = 1 - w1;
if (n1<1) n1=1;
n1 = 1 + 0.5*(n1-1);
w3 = 2 / (n1 + 1);
w4 = 1 - w3;
return(0);
}
//+------------------------------------------------------------------+
//| T3_iAnchMom |
//+------------------------------------------------------------------+
int start()
{
if (CountBars>Bars) CountBars=Bars;
SetIndexDrawBegin(0,Bars-CountBars+(MomPeriod*2)*EMA_period);
SetIndexDrawBegin(1,Bars-CountBars+(MomPeriod*2)*EMA_period);
int i,counted_bars=IndicatorCounted();
double a,c;

if(Bars<=n1) return(0);

//---- initial zero
if(counted_bars<n1)
{
for(i=1;i<=n1;i++) Up[CountBars-i]=0.0;
for(i=1;i<=n1;i++) Down[CountBars-i]=0.0;
}
//----
i=CountBars-1;
// if(counted_bars>=1) i=Bars-counted_bars-1;
while(i>=0)
{

e1 = w1*Close[i] + w2*e1;
e2 = w1*e1 + w2*e2;
e3 = w1*e2 + w2*e3;
e4 = w1*e3 + w2*e4;
e5 = w1*e4 + w2*e5;
e6 = w1*e5 + w2*e6;

a=c1*e6 + c2*e5 + c3*e4 + c4*e3;

e7 = w3*Close[i] + w4*e7;
e8 = w3*e7 + w4*e8;
e9 = w3*e8 + w4*e9;
e10 = w3*e9 + w4*e10;
e11 = w3*e10 + w4*e11;
e12 = w3*e11 + w4*e12;

c=c1*e12 + c2*e11 + c3*e10 + c4*e9;

Mom = 100*((a / c)-1);
if (Mom>0) {Up[i]=Mom;Down[i]=0.0;} else {Down[i]=Mom;Up[i]=0.0;}

i--;
}
return(0);
}
//+------------------------------------------------------------------+
 
Пример: пользовательский индикатор "My_Ind" вызывается на текущем символе, на текущем тайм-фрейме, значение берется на текущем баре сначала из его первого буфера, затем из второго:

Эксперт:
// ...
double some_value_a;
double some_value_b;
// ...
some_value_a = iCustom( NULL, 0, "My_Ind", EMA_period, MomPeriod, 0, 0);
some_value_b = iCustom( NULL, 0, "My_Ind", EMA_period, MomPeriod, 1, 0);
// ...

Особое внимание надо обратить на правильность порядка передачи аргументов и соответствию их типов при вызове iCustom в эксперте, иначе могут получиться чудеса.

См. справку по iCustom:
double iCustom( string symbol, int timeframe, string name, ..., int mode, int shift)
 
Помогите пожалуйста написать советник, который бы работал по этому индюку. Пробовал сам(пробовал переделать MACD Sample), но из за недостаточного знания програмирования и MQ4 в частности он просто отказывается работать.

Этот индюк я хочу взять за основу.
Покупаем если гистограмма выше 0, продаем если гистограмма ниже 0. Закрываем сделку при смене цвета гистограммы. Профит = Х, стоп = У + Возможность оптимизации параметров индюка. Вот и всё. Если что то получится с моей задумкой, с радостью поделюсь своей наработкой.

Зарание спасибо.
 
Переделанный под этот индюк пример Moving Average. Для тестирования годится, для демо и тем более для реала (если до него дойдет) необходимо снабдить "канделябрами" типа IsTradeAllowed( ), IsTradeContextBusy( ) и т.п. См. "Проверка состояния" в хелпе к МЕ. Результаты тестирования, мягко говоря, не впечатляют.

//+------------------------------------------------------------------+
//|                                       MOM_MA_Expert_BareBone.mq4 |
//|                     Copyright © 2006, HolyGrailUnderConstruction |
//|          http://www.holy_grails_huge_choice.lohotron.bazara.net/ |
//+------------------------------------------------------------------+
// ---- properties
#property copyright "Copyright © 2006, HolyGrailUnderConstruction"
#property link      "http://www.holy_grails_huge_choice.lohotron.bazara.net/"
// ---- defines
// ---- input parameters
extern bool   MM_Enabled     = false;
extern double Lots           = 0.1;    //
extern double MaximumRisk    = 0.02;   //
extern double DecreaseFactor = 3;      //
extern int    EMA_period     = 3;      //
extern int    MomPeriod      = 8;      //
extern int    CountBars      = 999999; // obsolete
extern int    Threshold      = 0;      // filter
// ---- variables
int    MAGICMA;
double mom_up; // indicator value "up" (when ind_value > 0)
double mom_dw; // indicator value "down" (when ind_value < 0)
//+------------------------------------------------------------------+
//| Calculate open positions                                         |
//+------------------------------------------------------------------+
int CalculateCurrentOrders(string symbol)
 {
  int buys=0,sells=0;
 //----
  for(int i=0;i<OrdersTotal();i++)
   {
    if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
    if(OrderSymbol()==Symbol() && OrderMagicNumber()==MAGICMA)
     {
      if(OrderType()==OP_BUY)  buys++;
      if(OrderType()==OP_SELL) sells++;
     }
   }
 //---- return orders volume
  if(buys>0) return(buys);
  else       return(-sells);
 }
//+------------------------------------------------------------------+
//| Calculate optimal lot size                                       |
//+------------------------------------------------------------------+
double LotsOptimized()
  {
   double lot=Lots;
   int    orders=HistoryTotal();     // history orders total
   int    losses=0;                  // number of losses orders without a break
//----    
   if (!MM_Enabled) return(Lots); // if MM disabled, return input lots value
//---- select lot size, if MM enabled
   lot=NormalizeDouble(AccountFreeMargin()*MaximumRisk/1000.0,1);
//---- calculate number of losses orders without a break
   if(DecreaseFactor>0)
     {
      for(int i=orders-1;i>=0;i--)
        {
         if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==false) { Print("Error in history!"); break; }
         if(OrderSymbol()!=Symbol() || OrderType()>OP_SELL) continue;
         //----
         if(OrderProfit()>0) break;
         if(OrderProfit()<0) losses++;
        }
      if(losses>1) lot=NormalizeDouble(lot-lot*losses/DecreaseFactor,1);
     }
//---- return lot size
   if(lot<0.1) lot=0.1;
   return(lot);
  }
/* 
custom indicator external variables:
//
extern int    EMA_period     = 3;      //
extern int    MomPeriod      = 8;      //
extern int    CountBars      = 999999; //
*/
//+------------------------------------------------------------------+
//| Check for open order conditions                                  |
//+------------------------------------------------------------------+
void CheckForOpen()
  {
   int    res;
//---- go trading only for first tiks of new bar
   if(Volume[0]>1) return;
//---- get MOM Up and Down 
   mom_up = iCustom( NULL, 0, "MOM", EMA_period, MomPeriod, CountBars, 0, 0);
   mom_dw = iCustom( NULL, 0, "MOM", EMA_period, MomPeriod, CountBars, 1, 0);
//---- buy conditions
   if(mom_up > Threshold*Point) // filter mom_up
     {
      res=OrderSend(Symbol(),OP_BUY,LotsOptimized(),Ask,3,0,0,"",MAGICMA,0,Blue);
      return;
     }
//---- sell conditions
   if(mom_dw < -Threshold*Point) // filter mom_dw
     {
      res=OrderSend(Symbol(),OP_SELL,LotsOptimized(),Bid,3,0,0,"",MAGICMA,0,Red);
      return;
     }
//----
  }
//+------------------------------------------------------------------+
//| Check for close order conditions                                 |
//+------------------------------------------------------------------+
void CheckForClose()
  {
//---- go trading only for first tiks of new bar
   if(Volume[0]>1) return;
//---- get MOM Up and Down 
   mom_up = iCustom( NULL, 0, "MOM", EMA_period, MomPeriod, CountBars, 0, 0);
   mom_dw = iCustom( NULL, 0, "MOM", EMA_period, MomPeriod, CountBars, 1, 0);
//----
   for(int i=0;i<OrdersTotal();i++)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false)        break;
      if(OrderMagicNumber()!=MAGICMA || OrderSymbol()!=Symbol()) continue;
      //---- check order type 
      if(OrderType()==OP_BUY)
        {
         if(mom_dw < -Threshold*Point) // filter mom_dw
          OrderClose(OrderTicket(),OrderLots(),Bid,3,White);
          break;
        }
      if(OrderType()==OP_SELL) // filter mom_up
        {
         if(mom_up > Threshold*Point) OrderClose(OrderTicket(),OrderLots(),Ask,3,White);
         break;
        }
     }
//----
   return;
  }
//+------------------------------------------------------------------+
//| Start function                                                   |
//+------------------------------------------------------------------+
void start()
  {
//---- check for history and trading
   if(Bars<100 || IsTradeAllowed()==false) return;
//---- calculate open orders by current symbol
   if(CalculateCurrentOrders(Symbol())==0) CheckForOpen();
   else                                    CheckForClose();
//----
   return;
  }
//+------------------------------------------------------------------+
//| Init function                                                    |
//+------------------------------------------------------------------+
void init()
   {
    MAGICMA = AccountNumber();
    // TODO: add your code here
    return;
   }
//+------------------------------------------------------------------+
//| DeInit function                                                  |
//+------------------------------------------------------------------+
void deinit()
   {
    // TODO: add your code here
    return;
   }
//+------------------------------------------------------------------+



Вот сам индюк:

//+------------------------------------------------------------------+
//|                                                          MOM.mq4 |
//|                     Copyright © 2006, HolyGrailUnderConstruction |
//|          http://www.holy_grails_huge_choice.lohotron.bazara.net/ |
//+------------------------------------------------------------------+
// ---- properties
#property copyright "Copyright © 2006, HolyGrailUnderConstruction"
#property link      "http://www.holy_grails_huge_choice.lohotron.bazara.net/"
// ---- indicator properties
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_color1 LightSeaGreen
#property indicator_color2 FireBrick
//---- input parameters
extern int EMA_period=3;
extern int MomPeriod=8;
extern int CountBars=999999;
//---- buffers
double Up[];
double Down[];
double Mom;
double e1,e2,e3,e4,e5,e6,e7,e8,e9,e10,e11,e12;
double c1,c2,c3,c4;
double n,n1,w1,w2,b2,b3,w3,w4,b;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- indicator line
IndicatorBuffers(2);
SetIndexStyle(0,DRAW_HISTOGRAM);
SetIndexBuffer(0,Up);
SetIndexStyle(1,DRAW_HISTOGRAM);
SetIndexBuffer(1,Down);
//----
//----
//---- variable reset
/*e1=0; e2=0; e3=0; e4=0; e5=0; e6=0;
c1=0; c2=0; c3=0; c4=0; 
n=0;n1=0; 
w1=0; w2=0; w3=0; w4=0; 
b2=0; b3=0;*/

b = 0.7;
b2=b*b;
b3=b2*b;
c1=-b3;
c2=(3*(b2+b3));
c3=-3*(2*b2+b+b3);
c4=(1+3*b+b3+3*b2);
n=EMA_period;
n1=MomPeriod + MomPeriod + 1;

if (n<1) n=1;
n = 1 + 0.5*(n-1);
w1 = 2 / (n + 1);
w2 = 1 - w1;
if (n1<1) n1=1;
n1 = 1 + 0.5*(n1-1);
w3 = 2 / (n1 + 1);
w4 = 1 - w3;
return(0);
}
//+------------------------------------------------------------------+
//| T3_iAnchMom |
//+------------------------------------------------------------------+
int start()
{
if (CountBars>Bars) CountBars=Bars;
SetIndexDrawBegin(0,Bars-CountBars+(MomPeriod*2)*EMA_period);
SetIndexDrawBegin(1,Bars-CountBars+(MomPeriod*2)*EMA_period);
int i,counted_bars=IndicatorCounted();
double a,c;

if(Bars<=n1) return(0);

//---- initial zero
if(counted_bars<n1)
{
for(i=1;i<=n1;i++) Up[CountBars-i]=0.0;
for(i=1;i<=n1;i++) Down[CountBars-i]=0.0;
}
//----
i=CountBars-1;
// if(counted_bars>=1) i=Bars-counted_bars-1;
while(i>=0)
{

e1 = w1*Close[i] + w2*e1;
e2 = w1*e1 + w2*e2;
e3 = w1*e2 + w2*e3;
e4 = w1*e3 + w2*e4;
e5 = w1*e4 + w2*e5;
e6 = w1*e5 + w2*e6;

a=c1*e6 + c2*e5 + c3*e4 + c4*e3;

e7 = w3*Close[i] + w4*e7;
e8 = w3*e7 + w4*e8;
e9 = w3*e8 + w4*e9;
e10 = w3*e9 + w4*e10;
e11 = w3*e10 + w4*e11;
e12 = w3*e11 + w4*e12;

c=c1*e12 + c2*e11 + c3*e10 + c4*e9;

Mom = 100*((a / c)-1);
if (Mom>0) {Up[i]=Mom;Down[i]=0.0;} else {Down[i]=Mom;Up[i]=0.0;} 

i--;
}
return(0);
}
//+------------------------------------------------------------------+ 



Успехов!



 
Замена

mom_up = iCustom( NULL, 0, "MOM", EMA_period, MomPeriod, CountBars, 0, 0);
mom_dw = iCustom( NULL, 0, "MOM", EMA_period, MomPeriod, CountBars, 1, 0);

на

mom_up = iCustom( NULL, 0, "MOM", EMA_period, MomPeriod, CountBars, 0, 1);
mom_dw = iCustom( NULL, 0, "MOM", EMA_period, MomPeriod, CountBars, 1, 1);

к радикальным изменениям и сверхприбыли не приводит.
 
А можно сделать, что бы советник совершал одну сделку по сигналу. А то их просто миллион. Можно было бы попробовать отфильтровать сигналы походим на него индюком. Эксперт вообщето мне нужен для подбора наилучших параметров индюков.

//+------------------------------------------------------------------+
//|                                                       iTrend.mq4 |
//|                      Copyright © 2004, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "unknown"
#property link      "unknown"

#property indicator_separate_window
#property indicator_buffers 2
#property indicator_color1 LimeGreen
#property indicator_color2 Red

//---- input parameters
extern int Bands_Period=    20;
extern int Bands_Deviation= 2;
extern int Power_Period=    13;

extern int Bands_Mode_0_2=  0;  // =0-2 MODE_MAIN, MODE_LOW, MODE_HIGH
extern int Power_Price_0_6= 0;  // =0-6 PRICE_CLOSE,PRICE_OPEN,PRICE_HIGH,PRICE_LOW,PRICE_MEDIAN,PRICE_TYPICAL,PRICE_WEIGHTED
extern int Price_Type_0_3=  0;  // =0-3 PRICE_CLOSE,PRICE_OPEN,PRICE_HIGH,PRICE_LOW


//---- buffers
double TrendBuf1[];
double TrendBuf2[];

#include "fxoe-lib.mqh"


//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
   //   string short_name;
   //---- indicator line
   IndicatorBuffers(2);
   SetIndexStyle(0,DRAW_HISTOGRAM);
   SetIndexBuffer(0,TrendBuf1);
   SetIndexDrawBegin(0, Bands_Period+1);

   SetIndexStyle(1,DRAW_HISTOGRAM);
   SetIndexBuffer(1,TrendBuf2);
   SetIndexDrawBegin(1, Bands_Period+1);

   IndicatorShortName("FXOE-ITrendHistogram(" + Bands_Period + ", " + Bands_Deviation + ", " + Power_Period + ")= ");
   
   //----
   return(0);
}


//+------------------------------------------------------------------+
//| Trend                                                            |
//+------------------------------------------------------------------+
int start()
{
   double dummy1[], dummy2[];
   int counted_bars= IndicatorCounted(),
         lastbar;

   if (Bars<=Bands_Period) 
      return(0);
      
   if (counted_bars>0)
      counted_bars--;
      
   lastbar= Bars - counted_bars;

   ITrend(0, lastbar, dummy1, dummy2, TrendBuf1, TrendBuf2, Bands_Period, Bands_Deviation, Power_Period);
   
   return (0);
}



Может быть сюда можно было бы приписать АС. Точно не знаю. Пока еще тестирую

 
Еще хотелось бы, что бы сделки совершались либо по закрытию бара, либо по его открытию, т.е. сигналы индикаторов внутри бара не учитываются.
 
if(Volume[0]>1) return;
- это и есть торговля при открытии нового бара.

Лучше сделать так (советуют разработчики):
// ...
datetime prev_bar_time;
// ...
int init()
 {
// ...
  prev_bar_time =  LocalTime();
// ...
 return(0);
 }
// ...
int start()
 {
// ...
  if (prev_bar_time == Time[0]) 
   { return(0); }
  else
   { prev_bar_time = Time[0]; }
// ... TODO what we ought to
  return(0);
 }



Твори, выдумывай, пробуй! (с) Удачи и успехов.