Базовые индикаторы, применяемые к кастомному инструменту - страница 3

 
fxsaber:

Рабочим кодом должен быть этот

Но обнаружился баг в MT5, поэтому до исправления он работать не будет - iMA от iMA через кастомный хэндл.

Локализовали баг, поэтому обходится, и код становится рабочим

// МАшка на двух кастомных данных - DRAW_FILLING
#property indicator_chart_window 
#property indicator_buffers 2 
#property indicator_plots   1 

#property indicator_type1   DRAW_FILLING 
#property indicator_color1  clrRed, clrBlue 
#property indicator_width1  1 

input int CustomData = WRONG_VALUE; // Для кастомного режима iCustom
input int MAPeriod = 5;             // Период МАшки

string GetMyName( void )
{
  const int Length = StringLen(TerminalInfoString(TERMINAL_DATA_PATH) + "\\MQL5\\Indicators\\");
  const string Path = MQLInfoString(MQL_PROGRAM_PATH);
  
  return(StringSubstr(Path, Length, StringLen(Path) - Length - 4));
}

const bool FlagCustomData = (CustomData != WRONG_VALUE);

double Buffer0[], Buffer1[];
const bool Init = SetIndexBuffer(0, Buffer0, INDICATOR_DATA) && (!FlagCustomData) && SetIndexBuffer(1, Buffer1, INDICATOR_DATA);

const int handleMA0 = FlagCustomData ? iMA(NULL, PERIOD_CURRENT, 100, 0, MODE_SMA, CustomData ? PRICE_OPEN : PRICE_CLOSE)
                                     : iMA(NULL, PERIOD_CURRENT, MAPeriod, 0, MODE_SMA, iCustom(_Symbol, PERIOD_CURRENT, GetMyName(), 0));
const int handleMA1 = FlagCustomData ? INVALID_HANDLE
                                     : iMA(NULL, PERIOD_CURRENT, MAPeriod, 0, MODE_SMA, iCustom(_Symbol, PERIOD_CURRENT, GetMyName(), 1));

int Replace( double &Array[], const double NewValue = 1e3, const double PrevValue = EMPTY_VALUE )
{
  for (int i = ArraySize(Array) - 1; i >= 0; i--)
    if (Array[i] == PrevValue)
      Array[i] = NewValue;
      
  return(0);
}

int OnCalculate( const int rates_total,      // размер входных таймсерий 
                 const int prev_calculated,  // обработано баров на предыдущем вызове
                 const datetime& time[],     // Time 
                 const double& open[],       // Open 
                 const double& high[],       // High 
                 const double& low[],        // Low 
                 const double& close[],      // Close 
                 const long& tick_volume[],  // Tick Volume 
                 const long& volume[],       // Real Volume 
                 const int& spread[] )       // Spread 
{
  return(prev_calculated + (FlagCustomData ? CopyBuffer(handleMA0, 0, prev_calculated, rates_total - prev_calculated, Buffer0) + Replace(Buffer0) // обходим баг iMA
                                           : MathMin(CopyBuffer(handleMA0, 0, prev_calculated, rates_total - prev_calculated, Buffer0),
                                                     CopyBuffer(handleMA1, 0, prev_calculated, rates_total - prev_calculated, Buffer1))));
}


 
fxsaber:

Локализовали баг, поэтому обходится, и код становится рабочим


До чего-же тяжёлые для понимания коды вы пишете...

 
Alexey Viktorov:

До чего-же тяжёлые для понимания коды вы пишете...

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

 
fxsaber:

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

А в CodeBase хоть один индикатор смотрел? Если это стандартное написание, то в CodeBase тогда что? :)))))))

Всё равно спасибо. Может быть когда ни будь смогу разобраться в таком стандарте написания.

 
Alexey Viktorov:

А в CodeBase хоть один индикатор смотрел? Если это стандартное написание, то в CodeBase тогда что? :)))))))

КБ не смотрел, т.к. в документации все оказалось.

Сейчас специально посмотрел код нескольких индикаторов в КБ - все так же. Не увидел только такого, но ООП массово не жалуют, видимо.

Если правильно понимаю, после появления Маркета поток немного нестандартных решений в кодобазе сильно уменьшился. ООП-индикаторов не нашел, например.

 
Alexey Viktorov:

А в CodeBase хоть один индикатор смотрел? Если это стандартное написание, то в CodeBase тогда что? :)))))))

Всё равно спасибо. Может быть когда ни будь смогу разобраться в таком стандарте написания.

Использован минималистичный понятный стиль, и десяток строк не растянуты на пять прокруток монитора, как это в кодобазе по-умолчанию

 

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

#property version   "1.00"
#property indicator_chart_window

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   // Здесь все вычисления и заполнение буферов
   return(rates_total);
  }
//+------------------------------------------------------------------+

В вашем-же коде  OnInit() заменён на const bool Init я даже не сразу это увидел.

const int handleMA0 = FlagCustomData..... в глобальной области что я вижу впервые. Всегда объявляли переменную в глобальной области и в OnInit() получали хендл индикатора...

И в конце концов само вычисление индикатора.... надо долго разбираться чтобы что-то сказать об этом. И самое непонятное, зачем так указывать период МА? Просто на столько непривычно, да и за много лет неиспользования знаний полученных в школе, наверное не я один, забыл что такое 1е2

В общем в таком коде для меня разобраться гораздо сложней. Но главное, я понял что можно в индикаторе получить хендл "самого себя".

 
Alexey Viktorov:

Я конечно самоучка и многого не знаю и даже о многом не слышал.

Тоже не программер.

Можно написать любой код, который будет выполняться до OnInit и после OnDeinit. Поэтому эти обе функции совсем не обязательны. Могут совсем отсутствовать индикаторные буферы, при этом не всегда возможно конвертировать такой индикатор в советник с тем же визуальным результатом.

Все скрипты могут быть переписаны с пустой OnStart - не нужна. И т.д.

Все эти утверждения никак не противоречат Документации, а наоборот - вытекают из нее.

В Документации нигде не написано, что надо писать шаблонно. Скорее, это авторы в кодобазе навязывают какое-то шаблонное написание.

В общем, смотрите на MQL-программы несколько шире. А некоторые элементы ООП дают еще больше гибкости.


ЗЫ 1e7 и 10000000 - что понятнее?

ЗЫЫ Если глобальные инициализации пугают, можно все запихать в OnCalculate

// МАшка на двух кастомных данных - DRAW_FILLING
#property indicator_chart_window 
#property indicator_buffers 2 
#property indicator_plots   1 

#property indicator_type1   DRAW_FILLING 
#property indicator_color1  clrRed, clrBlue 
#property indicator_width1  1 

input int CustomData = WRONG_VALUE; // Для кастомного режима iCustom
input int MAPeriod = 5;             // Период МАшки

string GetMyName( void )
{
  const int Length = StringLen(TerminalInfoString(TERMINAL_DATA_PATH) + "\\MQL5\\Indicators\\");
  const string Path = MQLInfoString(MQL_PROGRAM_PATH);
  
  return(StringSubstr(Path, Length, StringLen(Path) - Length - 4));
}

int Replace( double &Array[], const double NewValue = 1e3, const double PrevValue = EMPTY_VALUE )
{
  for (int i = ArraySize(Array) - 1; i >= 0; i--)
    if (Array[i] == PrevValue)
      Array[i] = NewValue;
      
  return(0);
}

int OnCalculate( const int rates_total,      // размер входных таймсерий 
                 const int prev_calculated,  // обработано баров на предыдущем вызове
                 const datetime& time[],     // Time 
                 const double& open[],       // Open 
                 const double& high[],       // High 
                 const double& low[],        // Low 
                 const double& close[],      // Close 
                 const long& tick_volume[],  // Tick Volume 
                 const long& volume[],       // Real Volume 
                 const int& spread[] )       // Spread 
{
  static const bool FlagCustomData = (CustomData != WRONG_VALUE);
  
  static double Buffer0[], Buffer1[];
  static const bool Init = SetIndexBuffer(0, Buffer0, INDICATOR_DATA) && (!FlagCustomData) && SetIndexBuffer(1, Buffer1, INDICATOR_DATA);
  
  static const int handleMA0 = FlagCustomData ? iMA(NULL, PERIOD_CURRENT, 100, 0, MODE_SMA, CustomData ? PRICE_OPEN : PRICE_CLOSE)
                                              : iMA(NULL, PERIOD_CURRENT, MAPeriod, 0, MODE_SMA, iCustom(_Symbol, PERIOD_CURRENT, GetMyName(), 0));
  static const int handleMA1 = FlagCustomData ? INVALID_HANDLE
                                              : iMA(NULL, PERIOD_CURRENT, MAPeriod, 0, MODE_SMA, iCustom(_Symbol, PERIOD_CURRENT, GetMyName(), 1));
  
  return(prev_calculated + (FlagCustomData ? CopyBuffer(handleMA0, 0, prev_calculated, rates_total - prev_calculated, Buffer0) + Replace(Buffer0) // обходим баг iMA
                                           : MathMin(CopyBuffer(handleMA0, 0, prev_calculated, rates_total - prev_calculated, Buffer0),
                                                     CopyBuffer(handleMA1, 0, prev_calculated, rates_total - prev_calculated, Buffer1))));
}
 

Единственная недокументированная возможность, что проскочила в коде

Очень удобная фича в MT4/5, если писать какую-то универсальную штуку к любому индикатору, потому как там подобный макрос
#define AMOUNT_BUFFERS 5
#property indicator_buffers AMOUNT_BUFFERS
#property indicator_plots   AMOUNT_BUFFERS

BUFFER Buffers[AMOUNT_BUFFERS];
не применить - теряется универсальность.
Причина обращения: