Работа с техническим индикатором в нескольких таймфреймах одновременно в одном окне.

 

Коллеги, добрый день.

Тема неоднократно мелькала в форуме, но так и не нашел понятного ответа или примера.

Суть вопроса в следующем. Насмотревшись видео по трейдингу захотел сделать индикатор по принципу "трех экранов Элдера". Идея в стратегии разумная, с реализацией, вроде, не должно быть проблем. Но...

В пользовательском индикаторе создаю хэндлы на технические индикаторы с разными таймфреймами (далее в тексте - TF). Код компилируется без ошибок, запускается в окне. И выводит данные. Только не все данные одновременно.

Приведенный ниже код выводит значения ADX только только те, которые совпадают с установленным для окна таймфреймом. Одновременно - никак. ( Можно как-то организовать одновременное получение данных от технических индикаторов?

#property indicator_chart_window

enum TF 
  {
   H1=0,     
   H2=1,    
   H4=2,    
   H8=3,    
   D1=4,   
  };
//--- input parameters
input TF intutTF=H1;
//Work - младший таймфрейм. Main - старший.
ENUM_TIMEFRAMES   MainTF[5]={PERIOD_H1, PERIOD_H2, PERIOD_H4, PERIOD_H8, PERIOD_D1};
ENUM_TIMEFRAMES   WorkTF[5]={PERIOD_M5, PERIOD_M10, PERIOD_M15, PERIOD_M30, PERIOD_H1};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//+------------------------------------------------------------------+
//|                            ADX                                   |
//+------------------------------------------------------------------+
input int                  ADX_period = 14;          // период расчета ADX

//--- индикаторные буферы
double         ADX_BufferMain[], ADX_BufferWork[];
double         ADX_DI_plusBufferMain[], ADX_DI_plusBufferWork[];
double         ADX_DI_minusBufferMain[], ADX_DI_minusBufferWork[];
//--- переменная для хранения хэндла индикатора iADX
int    ADX_handleMain, ADX_handleWork;

//------------------------------- Мои переменные
string   symbol;
ENUM_TIMEFRAMES periodMain, periodWork;
//-------------Конторольки для количества баров
int      calcBarsMain=0; //смотрим по основному TF
int      curBarsMain=0;  //смотрим по основному TF
int      calcBarsWork=0; //смотрим по рабочему TF
int      curBarsWork=0;  //смотрим по рабочему TF
//-------------Массивы для получения данных из буферов индикаторов
double ADXBufferWork[3];
double ADXDiPlusWork[3];
double ADXDiMinusWork[3];
double ADXBufferMain[3];
double ADXDiPlusMain[3];
double ADXDiMinusMain[3];
string mess=""; //Вывод отладочной информации


//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
     periodMain=MainTF[intutTF];
     periodWork=WorkTF[intutTF];
     symbol=_Symbol;
     
     
     
//--------------------------------------------- ADM на два таймфрейма    
                SetIndexBuffer(0,ADX_BufferMain,INDICATOR_CALCULATIONS);
                SetIndexBuffer(1,ADX_DI_plusBufferMain,INDICATOR_CALCULATIONS);
                SetIndexBuffer(2,ADX_DI_minusBufferMain,INDICATOR_CALCULATIONS);
                ADX_handleMain=iADX(symbol,periodMain,ADX_period);
                //--- если не удалось создать хэндл
                
                if(ADX_handleMain==INVALID_HANDLE)
                     {
                      //--- сообщим о неудаче и выведем номер ошибки
                       PrintFormat("Не удалось создать хэндл индикатора iADX для пары %s/%s, код ошибки %d",
                                   symbol,
                                   EnumToString(periodMain),
                                   GetLastError());
                      //--- работа индикатора завершается досрочно
                      return(INIT_FAILED);
                     }                     
                     
                SetIndexBuffer(3,ADX_BufferWork,INDICATOR_CALCULATIONS);
                SetIndexBuffer(4,ADX_DI_plusBufferWork,INDICATOR_CALCULATIONS);
                SetIndexBuffer(5,ADX_DI_minusBufferWork,INDICATOR_CALCULATIONS);
                ADX_handleWork=iADX(symbol,periodWork,ADX_period);
                //--- если не удалось создать хэндл
                
                if(ADX_handleWork==INVALID_HANDLE)
                     {
                      //--- сообщим о неудаче и выведем номер ошибки
                       PrintFormat("Не удалось создать хэндл индикатора iADX для пары %s/%s, код ошибки %d",
                                   symbol,
                                   EnumToString(periodWork),
                                   GetLastError());
                      //--- работа индикатора завершается досрочно
                      return(INIT_FAILED);
                     }
//-----------Необходимость этих 6 строк вызывала сомнение. Но от безысходности поставил уже. Все равно не помогло. (                          
               CopyBuffer(ADX_handleWork,0,0,3,ADXBufferWork);
               CopyBuffer(ADX_handleWork,1,0,3,ADXDiPlusWork);
               CopyBuffer(ADX_handleWork,2,0,3,ADXDiMinusWork); 
        
               CopyBuffer(ADX_handleMain,0,0,3,ADXBufferMain);
               CopyBuffer(ADX_handleMain,1,0,3,ADXDiPlusMain);
               CopyBuffer(ADX_handleMain,2,0,3,ADXDiMinusMain);
   
//---
   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[])
  {
  
    curBarsWork=Bars(symbol, periodWork);//считываем количество баров по младшему (рабочему) таймфрейму
    if (calcBarsWork!=curBarsWork)
      {
         calcBarsWork=curBarsWork;
         CopyBuffer(ADX_handleWork,0,0,3,ADXBufferWork);
         CopyBuffer(ADX_handleWork,1,0,3,ADXDiPlusWork);
         CopyBuffer(ADX_handleWork,2,0,3,ADXDiMinusWork); 
        
         curBarsMain=Bars(symbol, periodMain);
         if (calcBarsMain!=curBarsMain)
            {
               calcBarsMain=curBarsMain;
               CopyBuffer(ADX_handleMain,0,0,3,ADXBufferMain);
               CopyBuffer(ADX_handleMain,1,0,3,ADXDiPlusMain);
               CopyBuffer(ADX_handleMain,2,0,3,ADXDiMinusMain);
           
            }
         
         
         for (int j=2; j>=0; j--)
                    {mess+="\n iDI_plus_Work[" +j+"] = "+DoubleToString(ADXDiPlusWork[2-j])
                         + "   iDI_minus_Main["+j+"] = "+DoubleToString(ADXDiPlusMain[2-j]);                      
                    }
                mess+="\n";
                Comment(mess);
                mess="";      
              
      }   

   return(rates_total);
  }
//+------------------------------------------------------------------+


Вот что видим в окне графика. Меняем TF окна и выводятся данные только того индикатора, который совпадает с окном по TF

При TF = H1


И при TF = M5


 
knodit:

Коллеги, добрый день.

Вроде всё нормально работает, правда в тестере.

В терминале тоже будет работать, но когда откроется рынок.

 

Если добавить такой костыль в OnCalculate, то и в выходные работает.

      ResetLastError();
      if(CopyBuffer(ADX_handleWork, 0, 0, 3, ADXBufferWork) < 3)
        {
         Print(GetLastError());
         ChartSetSymbolPeriod(0, _Symbol, PERIOD_CURRENT);
        }
 
Aleksandr Slavskii #:

Если добавить такой костыль в OnCalculate, то и в выходные работает.

Спасибо!! Действительно, работает.. )) В тестере.