Мультитаймфреймовые индикаторы - страница 1224

 

Тик эмулируется при помощи ChartSetSymbolPeriod() с указанием текущего символа и периода графика:

ChartSetSymbolPeriod(0,Symbol(),Period());

Из справки:

Примечание

Смена символа/периода влечет за собой переинициализацию эксперта, прикрепленного к соответствующему графику.

Вызов ChartSetSymbolPeriod с тем же символом и таймфреймом можно использовать для обновления графика (аналогично команде Refresh в терминале). Обновление графика в свою очередь запускает перерасчет индикаторов, прикрепленных к нему. Таким образом, вы можете рассчитать индикатор на графике даже при отсутствии тиков (например, в выходные дни).

Документация по MQL5: Операции с графиками / ChartSetSymbolPeriod
Документация по MQL5: Операции с графиками / ChartSetSymbolPeriod
  • www.mql5.com
ChartSetSymbolPeriod - Операции с графиками - Справочник MQL5 - Справочник по языку алгоритмического/автоматического трейдинга для MetaTrader 5
 
Artyom Trishkin #:

Тик эмулируется при помощи ChartSetSymbolPeriod() с указанием текущего символа и периода графика:

Из справки:

Артём, а как для индикатора?

 
Vitaly Muzichenko #:

Артём, а как для индикатора?

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

Тут нужно проверять сколько баров уже просчитано и, если 0, то буферы не инициализировать, а сразу заполнять из массива мультипериодного индикатора, ранее заполненного из CopyBuffer. С учётом смещения баров для "неродного" периода.

 

Сейчас на выходных решил попробовать функцию ChartSetSymbolPeriod() в индикаторе, чтобы эмулировать дополнительный тик.

Увидел, что в справке написано следующее:

ChartSetSymbolPeriod

Вызов ChartSetSymbolPeriod с тем же символом и таймфреймом можно использовать для обновления графика (аналогично команде Refresh в терминале). Обновление графика в свою очередь запускает перерасчет индикаторов, прикрепленных к нему. Таким образом, вы можете рассчитать индикатор на графике даже при отсутствии тиков (например, в выходные дни).


В индикаторе запрашиваю по CopyTime() время открытия с М15. Если данные не получены, то дергаем ChartSetSymbolPeriod().

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[])
{
  
  if(getBarsTimeFrame(PERIOD_M15) <= 0)
  {
    ChartSetSymbolPeriod(0, NULL, 0);
    return 0;
  }

  Print(__FUNCTION__, " successed");

  return rates_total;
}


//+------------------------------------------------------------------------------------------------------------------+
int getBarsTimeFrame(ENUM_TIMEFRAMES tf)
{
  datetime dt[];
  int barsTF = Bars(Symbol(), tf);
 
  int copied = CopyTime(Symbol(), tf, 0, barsTF, dt);
  
  Print(__FUNCTION__, " tf=", EnumToString(tf), " barsTF=", barsTF, " copied=", copied);
  
  return copied;
}

Запуск такого индикатора почему-то зацикливается. Вот вывод в журнал:


Я не совсем понимаю почему так. Если исторические данные уже в какой-то момент получены и доступны по CopyTime(), почему зацикливает и потом CopyTime() возвращает -1?
В справке написано, что функция ассинхронная? Это как-то с этим связано?

Файлы:
 
что я делаю неправильно отображаются только 4 синих линии на любом тайм фрейме 
input ENUM_TIMEFRAMES TimeFrame = PERIOD_H1; // Выбор таймфрейма для анализа
input int BarsCount = 1000;  // Количество баров для анализа
input int SupportRedCount = 4; // Количество линий поддержки
input int ResistanceBlueCount = 4; // Количество линий сопротивления

// Инициализация индикатора
int OnInit()
{
    // Удаление всех горизонтальных линий на текущем графике
    ObjectsDeleteAll(0, "", -1, OBJ_HLINE);
    return(INIT_SUCCEEDED);
}

// Деинициализация индикатора
void OnDeinit(const int reason)
{
    // Удаление всех горизонтальных линий на текущем графике
    ObjectsDeleteAll(0, "", -1, OBJ_HLINE);
}

// Основная функция вычисления индикатора
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[])
{
    if(rates_total < BarsCount) return 0;

    // Создаем динамический массив для цен закрытия
    double prices[];
    ArrayResize(prices, BarsCount);
    if(CopyClose(_Symbol, TimeFrame, 0, BarsCount, prices) <= 0) return 0;

    double minPrice = prices[0];
    double maxPrice = prices[0];

    // Находим минимальное и максимальное значения
    for(int i = 1; i < BarsCount; i++)
    {
        if(prices[i] < minPrice) minPrice = prices[i];
        if(prices[i] > maxPrice) maxPrice = prices[i];
    }

    double priceRange = maxPrice - minPrice;
    double supportRange = priceRange / (SupportRedCount + 1); // Расчет интервала для линий поддержки
    double resistanceRange = priceRange / (ResistanceBlueCount + 1); // Расчет интервала для линий сопротивления

    // Проверка, чтобы новая линия не наслаивалась на существующие линии
    for(int i = 0; i < SupportRedCount; i++)
    {
        double supportLevel = minPrice + supportRange * (i + 1);
        string supportName = "SupportLine_" + IntegerToString(i + 1);

        // Создание или обновление линии поддержки
        if(!ObjectCreate(0, supportName, OBJ_HLINE, 0, 0, supportLevel))
            Print("Failed to create support line: ", GetLastError());
        else {
            ObjectSetInteger(0, supportName, OBJPROP_COLOR, clrRed);
            ObjectSetInteger(0, supportName, OBJPROP_WIDTH, 6);
        }
    }

    // Проверка, чтобы новая линия не наслаивалась на существующие линии
    for(int i = 0; i < ResistanceBlueCount; i++)
    {
        double resistanceLevel = minPrice + resistanceRange * (i + 1);
        string resistanceName = "ResistanceLine_" + IntegerToString(i + 1);

        // Создание или обновление линии сопротивления
        if(!ObjectCreate(0, resistanceName, OBJ_HLINE, 0, 0, resistanceLevel))
            Print("Failed to create resistance line: ", GetLastError());
        else {
            ObjectSetInteger(0, resistanceName, OBJPROP_COLOR, clrBlue);
            ObjectSetInteger(0, resistanceName, OBJPROP_WIDTH, 6);
        }
    }

    return rates_total;
}
 
Oleg Kubenko #:
что я делаю неправильно отображаются только 4 синих линии на любом тайм фрейме 

Скорее всего, ошибка здесь:

double supportLevel = minPrice + supportRange * (i + 1);

double resistanceLevel = minPrice + resistanceRange * (i + 1);


Чем отличаются уровни поддержки от уровней сопротивления?

 
спасибо
 

попытался переписать индикатор новый на MQL5 https://www.mql5.com/en/code/49534?utm_source=mql5.com.tg&utm_medium=message&utm_campaign=articles.codes.repost

но он не отображается , можете помочь?


он в упор не хочет отображаться 

#property version   "1.00"
#property strict
#property indicator_separate_window
#property indicator_buffers 5
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrDeepSkyBlue
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrYellow
#property indicator_type3   DRAW_LINE
#property indicator_color3  clrDeepSkyBlue
#property indicator_type4   DRAW_LINE
#property indicator_color4  clrYellow
#property indicator_type5   DRAW_LINE
#property indicator_color5  clrRed
#property indicator_width5  2

input int                inpRsiPeriod        = 14;          // RSI period
input ENUM_APPLIED_PRICE inpPrice            = PRICE_CLOSE; // RSI price

input int                inpSmoothing        = 14;          // Smoothing period for RSI
input double             inpOverbought       = 70;          // Overbought level %
input double             inpOversold         = 30;          // Oversold level %
input double             inpUpperNeutral     = 55;          // Upper neutral level %
input double             inpLowerNeutral     = 45;          // Lower neutral level %

double bupu[],bupd[],bdnu[],bdnd[],rsi[];
//+------------------------------------------------------------------+
int OnInit() {
   SetIndexBuffer(0,bupu,INDICATOR_DATA);
   SetIndexBuffer(1,bupd,INDICATOR_DATA);
   SetIndexBuffer(2,bdnu,INDICATOR_DATA);
   SetIndexBuffer(3,bdnd,INDICATOR_DATA);
   SetIndexBuffer(4,rsi,INDICATOR_DATA);
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
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[]) {
   
   int limit = prev_calculated>0 ? rates_total - prev_calculated + 1 : rates_total - 1;
   
   for(int i=limit;i>=0;i--) {
      Print(i);
      rsi[i] = iRSI(NULL,PERIOD_CURRENT,inpRsiPeriod,inpPrice);
      double _rsi = (rsi[i]!=EMPTY_VALUE) ? rsi[i] : 0;
      /*
      bupu[i]     = iEma(_rsi-inpOverbought  ,inpSmoothing,index,0);
      bdnu[i]     = iEma(_rsi-inpOversold    ,inpSmoothing,index,1);
      bupd[i]     = iEma(_rsi-inpUpperNeutral,inpSmoothing,index,2);
      bdnd[i]     = iEma(_rsi-inpLowerNeutral,inpSmoothing,index,3);
      */
      double pr=2.0/(inpSmoothing+1.0);
      //bupu[i]     = (_rsi-inpOverbought) * pr + bupu[i+1]*(1-pr);
      if(i<rates_total-1) {
         bupu[i]     = (_rsi-inpOverbought) * pr + bupu[i+1]*(1-pr);
         bdnu[i]     = (_rsi-inpOversold) * pr + bdnu[i+1]*(1-pr);
         bupd[i]     = (_rsi-inpUpperNeutral) * pr + bupd[i+1]*(1-pr);
         bdnd[i]     = (_rsi-inpLowerNeutral) * pr + bdnd[i+1]*(1-pr);
      }else{
         bupu[i]     = (_rsi-inpOverbought);
         bdnu[i]     = (_rsi-inpOversold);
         bupd[i]     = (_rsi-inpUpperNeutral);
         bdnd[i]     = (_rsi-inpLowerNeutral);
      }
      
      rsi[i] -= 50;
   }
   return(rates_total);
}
//+------------------------------------------------------------------+
#define _emaInstances 4
#define _emaRingSize 6
double workEma[_emaRingSize][_emaInstances];
//
//---
//


double iEma(double price, double period,int i, int _inst=0)
{
   int _indCurrent = (i  )%_emaRingSize;
   int _indPrevious = (i-1)%_emaRingSize;

   if(i>0 && period>1)
      workEma[_indCurrent][_inst] = workEma[_indPrevious][_inst] + (2.0/(1.0+period)) * (price-workEma[_indPrevious][_inst]);
   else   workEma[_indCurrent][_inst]=price;
   return(workEma[_indCurrent][_inst]);
}
RSI with channels
RSI with channels
  • www.mql5.com
standart RSI with dynamic levels
 
Oleg Kubenko #:

попытался переписать индикатор новый на MQL5 https://www.mql5.com/en/code/49534?utm_source=mql5.com.tg&utm_medium=message&utm_campaign=articles.codes.repost

но он не отображается , можете помочь?


он в упор не хочет отображаться 

https://www.mql5.com/ru/book/applications/indicators_make/indicators_buffers_plots
Учебник по MQL5: Создание прикладных программ / Создание пользовательских индикаторов / Настройка количества буферов и графических построений
Учебник по MQL5: Создание прикладных программ / Создание пользовательских индикаторов / Настройка количества буферов и графических построений
  • www.mql5.com
Чтобы индикатор мог вывести на график результаты своих расчетов, он должен определить один или несколько массивов и объявить их индикаторными...
 

теперь линии появились но они прямые и горизонтальные

а должны быт ькак у автора оригинала

#property version   "1.00"
#property strict
#property indicator_separate_window
#property indicator_buffers 5
#property indicator_plots   5
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrDeepSkyBlue
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrYellow
#property indicator_type3   DRAW_LINE
#property indicator_color3  clrDeepSkyBlue
#property indicator_type4   DRAW_LINE
#property indicator_color4  clrYellow
#property indicator_type5   DRAW_LINE
#property indicator_color5  clrRed
#property indicator_width5  2
input int                inpRsiPeriod        = 14;          // RSI period
input ENUM_APPLIED_PRICE inpPrice            = PRICE_CLOSE; // RSI price

input int                inpSmoothing        = 14;          // Smoothing period for RSI
input double             inpOverbought       = 70;          // Overbought level %
input double             inpOversold         = 30;          // Oversold level %
input double             inpUpperNeutral     = 55;          // Upper neutral level %
input double             inpLowerNeutral     = 45;          // Lower neutral level %

double bupu[],bupd[],bdnu[],bdnd[],rsi[];
//+------------------------------------------------------------------+
int OnInit()
{
   SetIndexBuffer(0, bupu, INDICATOR_DATA);
   SetIndexBuffer(1, bupd, INDICATOR_DATA);
   SetIndexBuffer(2, bdnu, INDICATOR_DATA);
   SetIndexBuffer(3, bdnd, INDICATOR_DATA);
   SetIndexBuffer(4, rsi, INDICATOR_CALCULATIONS);
   
   PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_LINE);
   PlotIndexSetInteger(0, PLOT_LINE_COLOR, clrDeepSkyBlue);
   PlotIndexSetInteger(0, PLOT_LINE_WIDTH, 1);
     
   PlotIndexSetInteger(1, PLOT_DRAW_TYPE, DRAW_LINE);
   PlotIndexSetInteger(1, PLOT_LINE_COLOR, clrYellow);
   PlotIndexSetInteger(1, PLOT_LINE_WIDTH, 1);
      
   PlotIndexSetInteger(2, PLOT_DRAW_TYPE, DRAW_LINE);
   PlotIndexSetInteger(2, PLOT_LINE_COLOR, clrDeepSkyBlue);
   PlotIndexSetInteger(2, PLOT_LINE_WIDTH, 1);
      
   PlotIndexSetInteger(3, PLOT_DRAW_TYPE, DRAW_LINE);
   PlotIndexSetInteger(3, PLOT_LINE_COLOR, clrYellow);
   PlotIndexSetInteger(3, PLOT_LINE_WIDTH, 1);
      
   PlotIndexSetInteger(4, PLOT_DRAW_TYPE, DRAW_LINE);
   PlotIndexSetInteger(4, PLOT_LINE_COLOR, clrRed);
   PlotIndexSetInteger(4, PLOT_LINE_WIDTH, 2);
   
   return (INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
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[]) {
   
   int limit = prev_calculated > 0 ? rates_total - prev_calculated + 1 : rates_total - 1;
   
   for(int i = limit; i >= 0; i--) {
      Print(i);
      rsi[i] = iRSI(NULL, PERIOD_CURRENT, inpRsiPeriod, inpPrice);
      double _rsi = (rsi[i] != EMPTY_VALUE) ? rsi[i] : 0;
      
      bupu[i] = iEma(_rsi - inpOverbought, inpSmoothing, i, 0);
      bdnu[i] = iEma(_rsi - inpOversold, inpSmoothing, i, 1);
      bupd[i] = iEma(_rsi - inpUpperNeutral, inpSmoothing, i, 2);
      bdnd[i] = iEma(_rsi - inpLowerNeutral, inpSmoothing, i, 3);
      
      double pr = 2.0 / (inpSmoothing + 1.0);
      if(i < rates_total - 1) {
         bupu[i] = (_rsi - inpOverbought) * pr + bupu[i + 1] * (1 - pr);
         bdnu[i] = (_rsi - inpOversold) * pr + bdnu[i + 1] * (1 - pr);
         bupd[i] = (_rsi - inpUpperNeutral) * pr + bupd[i + 1] * (1 - pr);
         bdnd[i] = (_rsi - inpLowerNeutral) * pr + bdnd[i + 1] * (1 - pr);
      } else {
         bupu[i] = (_rsi - inpOverbought);
         bdnu[i] = (_rsi - inpOversold);
         bupd[i] = (_rsi - inpUpperNeutral);
         bdnd[i] = (_rsi - inpLowerNeutral);
      }
      
      rsi[i] -= 50;
   }
   return rates_total;
}
//+------------------------------------------------------------------+
#define _emaInstances 4
#define _emaRingSize 6
double workEma[_emaRingSize][_emaInstances];
//
//---
//


double iEma(double price, double period,int i, int _inst=0)
{
   int _indCurrent = (i  )%_emaRingSize;
   int _indPrevious = (i-1)%_emaRingSize;

   if(i>0 && period>1)
      workEma[_indCurrent][_inst] = workEma[_indPrevious][_inst] + (2.0/(1.0+period)) * (price-workEma[_indPrevious][_inst]);
   else   workEma[_indCurrent][_inst]=price;
   return(workEma[_indCurrent][_inst]);
}
Причина обращения: