Скачать MetaTrader 5

Отрисовка n последних баров в индикаторе.

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
Andrey Dik
12053
Andrey Dik  

Просмотрел индикаторы в CodeBase, почитал статьи. Не пойму, как организовать отрисовку индикаторных буферов только заданное количество последних баров и начиная с первого.

Кроме того, не соображу даже как подступится к одной задачке. Прилагаю скрипт, который рисует бары назад в прошлое.

Код скрипта:

//--- input parameters
input int    History=100;
input double Hd     =0.3;
input double Ld     =0.6;
input double Hl     =0.3;
input double Ll     =0.1;

//--------------------
double   Open   [];
double   Hight  [];
double   Low    [];
double   Close  [];
datetime Time   [];
datetime Ti     [];
double   Peaks  [];

double HightBuffer [];
double LowBuffer   [];
int    BWDWT_handle;
//--------------------
//+------------------------------------------------------------------+
void OnStart()
{
  ArraySetAsSeries(Open,true);  CopyOpen (NULL,0,0,History+2,Open);
  ArraySetAsSeries(Hight,true); CopyHigh (NULL,0,0,History+2,Hight);
  ArraySetAsSeries(Low,true);   CopyLow  (NULL,0,0,History+2,Low);
  ArraySetAsSeries(Close,true); CopyClose(NULL,0,0,History+2,Close);
  ArraySetAsSeries(Time,true);  CopyTime (NULL,0,0,History+2,Time);
  //-----------------------------------------------------------
  double DeltaLen=0.0;
  double DeltaAve=0.0;
  double BarLen  =0.0;
  double Hi;
  double Lo;
  double Ave=0.0,AvePrev=0.0;
  double SumAve=0.0;
  double x=0.0;

  ObjectsDeleteAll(0,-1,-1);
  //1-й этап
  SumAve=(Hight[0]+Low[0])/2.0;

  x=Hight[0]-Low[0];
  DeltaLen=((2.0/(1.0+MathPow(2.0,-x*(10/Ll))))-1.0)*Hl/2.0;
  //DeltaLen=x/2.0;
  Hi=NormalizeDouble(SumAve+DeltaLen,Digits());
  Lo=NormalizeDouble(SumAve-DeltaLen,Digits());

  ObjectCreate    (0,"AltBar0",OBJ_TREND,0,Time[0],Hi,Time[0],Lo);
  if(Open[0]>Close[0])
    ObjectSetInteger(0,"AltBar0",OBJPROP_COLOR,Yellow);
  else
    ObjectSetInteger(0,"AltBar0",OBJPROP_COLOR,Green);
  ObjectSetInteger(0,"AltBar0",OBJPROP_SELECTABLE,true);
  ObjectSetInteger(0,"AltBar0",OBJPROP_WIDTH,3);

  //-------
  for(int V=1;V<History;V++)
  {
    //2-й этап
    Ave    =(Hight[V-1]+Low[V-1])/2.0;
    AvePrev=(Hight[V]  +Low[V])  /2.0;
    x=Ave-AvePrev;
    DeltaAve=((2.0/(1.0+MathPow(2.0,-x*(10/Ld))))-1.0)*Hd/2.0;

    SumAve-=DeltaAve;

    x=Hight[V]-Low[V];
    DeltaLen=((2.0/(1.0+MathPow(2.0,-x*(10/Ll))))-1.0)*Hl/2.0;
    Hi=NormalizeDouble(SumAve+DeltaLen,Digits());
    Lo=NormalizeDouble(SumAve-DeltaLen,Digits());

    ObjectCreate      (0,"AltBar"+V,OBJ_TREND,0,Time[V],Hi,Time[V],Lo);

    if(Open[V]>Close[V])
      ObjectSetInteger(0,"AltBar"+V,OBJPROP_COLOR,Yellow);
    else
      ObjectSetInteger(0,"AltBar"+V,OBJPROP_COLOR,Green);
    ObjectSetInteger  (0,"AltBar"+V,OBJPROP_SELECTABLE,true);
    ObjectSetInteger  (0,"AltBar"+V,OBJPROP_WIDTH,3);

    //-------
    ChartRedraw(0);
  }
  ChartRedraw(0);
  //-----------------------------------------------------------
}
//+------------------------------------------------------------------+
Усреднение ценовых рядов без дополнительных буферов для промежуточных расчетов
Усреднение ценовых рядов без дополнительных буферов для промежуточных расчетов
  • 2010.10.25
  • Nikolay Kositsin
  • www.mql5.com
Статья о традиционных и не совсем традиционных алгоритмах усреднения, упакованных в максимально простые и достаточно однотипные классы. Они задумывались для универсального использования в практических разработках индикаторов. Надеюсь, что предложенные классы в определенных ситуациях могут оказаться достаточно актуальной альтернативой громоздким, в некотором смысле, вызовам пользовательских и технических индикаторов.
Andrey Dik
12053
Andrey Dik  
Да уж, на MQL5 форуме, похоже, помощи не дождешся.
Valentin
164
Valentin  
joo:
Да уж, на MQL5 форуме, похоже, помощи не дождешся.

Не понятна цель

При инициализации нарисовать  -это сделано в скрипте уже.

что еще надо? 

Всегда отрисовывать только 100?

вывести в отельную фунцию и вызывать в

void OnStart() // инициализация

  {

// тут вызов
  }
и в  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 &TickVolume[],
                const long &Volume[],
                const int &Spread[])
  {int i;

// тут вызов
  return(i);
}
 - при тике
 

Vasily
1262
Vasily  

может все дело в тайм сериях и организации доступа к данным

тут все немного иначе

Andrey Dik
12053
Andrey Dik  

Пришел к такому, заднепроходному решению. Есть варианты получше?

#property indicator_separate_window
#property indicator_buffers 4
#property indicator_plots   4
//--- plot Source
#property indicator_label1  "Source"
#property indicator_type1   DRAW_HISTOGRAM
#property indicator_color1  Red
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot Etalon
#property indicator_label2  "Etalon"
#property indicator_type2   DRAW_LINE
#property indicator_color2  Yellow
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1
//--- plot Normalised
#property indicator_label3  "Normalised"
#property indicator_type3   DRAW_LINE
#property indicator_color3  DarkGreen
#property indicator_style3  STYLE_SOLID
#property indicator_width3  1
//--- plot Label4
#property indicator_label4  "Label4"
#property indicator_type4   DRAW_LINE
#property indicator_color4  Red
#property indicator_style4  STYLE_SOLID
#property indicator_width4  1
//--- input parameters
input int      Clusters              =100;
input int      History               =1000;
input int      Input3;
input int      Input4;

input double   HdifferenceBetweenBars =0.005;
input double   LdifferenceBetweenBars =0.01;

input double   HBarHeight             =0.005;
input double   LBarHeight             =0.01;
//--- indicator buffers
double         SourceBuffer[];
//double         EtalonBuffer[];
//double         NormalisedBuffer[];
//double         Label4Buffer[];
//double         temp[];
//--------------------
double   Open   [];
double   Hight  [];
double   Low    [];
double   Close  [];
datetime Time   [];
datetime Ti     [];
double   Peaks  [];
int      CLUSTER[];
double   BarLength[];
double   DifferenceOfBars[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{ 
  ArraySetAsSeries(Open,true);  CopyOpen (NULL,0,0,History+2,Open);
  ArraySetAsSeries(Hight,true); CopyHigh (NULL,0,0,History+2,Hight);
  ArraySetAsSeries(Low,true);   CopyLow  (NULL,0,0,History+2,Low);
  ArraySetAsSeries(Close,true); CopyClose(NULL,0,0,History+2,Close);
  ArraySetAsSeries(Time,true);  CopyTime (NULL,0,0,History+2,Time);
  //-----------------------------------------------------------
  ArrayResize(CLUSTER,  Clusters);ArrayInitialize(CLUSTER,  0);
  ArrayResize(BarLength,Clusters);ArrayInitialize(BarLength,0);
//--- indicator buffers mapping
  SetIndexBuffer     (0,SourceBuffer,INDICATOR_DATA);
  PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,2);
  PlotIndexSetString (0,PLOT_LABEL,"SourceBuffer");
/*
  SetIndexBuffer     (1,EtalonBuffer,INDICATOR_DATA);
  PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,2);
  PlotIndexSetString (1,PLOT_LABEL,"EtalonBuffer");

  SetIndexBuffer(2,NormalisedBuffer,INDICATOR_DATA);
  SetIndexBuffer(3,Label4Buffer,INDICATOR_DATA);

  ArrayResize(temp,Clusters);
*/
//---
  return(0);
}
//+------------------------------------------------------------------+
//| 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[])
{
  int i=0;

  while (i<rates_total-1)
  {
    SourceBuffer    [i]=0.0;
    //EtalonBuffer    [i]=0.0;
    //NormalisedBuffer[i]=0.0;
    i++;  
  }

  if (Bars(NULL,PERIOD_CURRENT)== rates_total)
  {
    double DeltaLen=0.0;
    double DeltaAve=0.0;
    double BarLen  =0.0;
    double Hi      =0.0;
    double Lo      =0.0;
    double Ave=0.0,AvePrev=0.0;
    double SumAve=0.0;
    double x=0.0;

    ObjectsDeleteAll(0,-1,-1);
    //1-e yoai
    SumAve=(Hight[1]+Low[1])/2.0;

    x=Hight[1]-Low[1];
    DeltaLen=((2.0/(1.0+MathPow(2.0,-x*(10/LBarHeight))))-1.0)*HBarHeight/2.0;

    Hi=NormalizeDouble(SumAve+DeltaLen,Digits());
    Lo=NormalizeDouble(SumAve-DeltaLen,Digits());
    
    //CLUSTER[];
    //BarLength[1]=Hi-Lo;
    ObjectCreate    (0,"AltBar0",OBJ_TREND,0,Time[1],Hi,Time[1],Lo);
    if (Open[1]>Close[1])
      ObjectSetInteger(0,"AltBar0",OBJPROP_COLOR,Yellow);
    else
      ObjectSetInteger(0,"AltBar0",OBJPROP_COLOR,Green);
    ObjectSetInteger(0,"AltBar0",OBJPROP_SELECTABLE,true);
    ObjectSetInteger(0,"AltBar0",OBJPROP_WIDTH,3);

    //-------
    for (int V=2;V<=Clusters;V++)
    {
      //2-e yoai
      Ave    =(Hight[V-1]+Low[V-1])/2.0;
      AvePrev=(Hight[V]  +Low[V])  /2.0;
      x=Ave-AvePrev;
      DeltaAve=((2.0/(1.0+MathPow(2.0,-x*(10/LdifferenceBetweenBars))))-1.0)*HdifferenceBetweenBars/2.0;

      SumAve-=DeltaAve;

      x=Hight[V]-Low[V];
      DeltaLen=((2.0/(1.0+MathPow(2.0,-x*(10/LBarHeight))))-1.0)*HBarHeight/2.0;
      Hi=NormalizeDouble(SumAve+DeltaLen,Digits());
      Lo=NormalizeDouble(SumAve-DeltaLen,Digits());
      
      //BarLength[V]
      ObjectCreate      (0,"AltBar"+(string)V,OBJ_TREND,0,Time[V],Hi,Time[V],Lo);

      if (Open[V]>Close[V])
        ObjectSetInteger(0,"AltBar"+(string)V,OBJPROP_COLOR,Yellow);
      else
        ObjectSetInteger(0,"AltBar"+(string)V,OBJPROP_COLOR,Green);
      ObjectSetInteger  (0,"AltBar"+(string)V,OBJPROP_SELECTABLE,true);
      ObjectSetInteger  (0,"AltBar"+(string)V,OBJPROP_WIDTH,3);
      //-------
    }
    ChartRedraw(0);
    //-----------------------------------------------------------
    for (i=1;i<=Clusters;i++)
      SourceBuffer[rates_total-i-1]=Hight[i]-Low[i];
  }

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

//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
  ObjectsDeleteAll(0,-1,-1);
  ChartRedraw(0);
}
//+------------------------------------------------------------------+
Vasily
1262
Vasily  

ну да чуствуетсясоль уловил попробуй

сделать тайм сериями буферы

сразу все на место встанет

в отличие от мкл4

тут буферы индексируются от конца к началу

и обязательно надо делать связку 

вот тут почитай

// У меня повилась такая странная ошибка.

Sergey Pavlov
9418
Sergey Pavlov  
CoreWinTT :


вот тут почитай

// У меня повилась такая странная ошибка.

   ArraySetAsSeries(AtrBuffer,true);
   ArraySetAsSeries(TempBuffer,true);
   Print("AtrBuffer до",ArrayGetAsSeries(AtrBuffer));
   Print("TempBuffer до",ArrayGetAsSeries(TempBuffer));
   SetIndexBuffer(0,AtrBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,TempBuffer,INDICATOR_CALCULATIONS);
   Print("AtrBuffer после",ArrayGetAsSeries(AtrBuffer));
   Print("TempBuffer после",ArrayGetAsSeries(TempBuffer));


   ArraySetAsSeries(AtrBuffer,false);
   ArraySetAsSeries(TempBuffer,false);
   Print("AtrBuffer до",ArrayGetAsSeries(AtrBuffer));
   Print("TempBuffer до",ArrayGetAsSeries(TempBuffer));
   SetIndexBuffer(0,AtrBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,TempBuffer,INDICATOR_CALCULATIONS);
   Print("AtrBuffer после",ArrayGetAsSeries(AtrBuffer));
   Print("TempBuffer после",ArrayGetAsSeries(TempBuffer));


Я уже сообщил в сервисдеск об этом не соответствии с текстом справки.






Vasily
1262
Vasily  

в справке все нормально =)

тут дело в головах который привыкли к мкл5

кто сказал что при инициализации буфер должен стать тайм серией...

и ваше что он должен


все дело в головах

Vasily
1262
Vasily  
из справки

Примечание

После связывания динамический массив buffer[]  будет иметь индексацию как в обычных массивах, даже если для связываемого массива будет предварительно установлена индексация как в таймсериях. Если необходимо изменить порядок доступа к элементам индикаторного массива, необходимо применить функцию ArraySetAsSeries() после связывания массива функцией SetIndexBuffer().

Sergey Pavlov
9418
Sergey Pavlov  

Я же привёл пример, что если до связывания была таймсерия, то и после будет таймсерия!


Andrey Dik
12053
Andrey Dik  
DC2008 :

Я же привёл пример, что если до связывания была таймсерия, то и после будет таймсерия!

и

Rosh:

Обратная индексация индикаторных буферов, как это сделано в MQL4, изначально была сделана по традиции, так как на то время было общепринято нумеровать бары задом наперед. Это казалось удобным (и безусловно является удобным и сейчас, если обращаться к барам из экспертов), так как последний незавершенный бар всегда имел нулевой индекс.

Но когда дело доходило до написания экономных по производительности индикаторов, то зачастую можно было мозги свихнуть, так как приходилось организовывать циклы по убыванию с вычислением нетривиальных начальных значений для счетчика в цикле. Поэтому было решено сделать так, чтобы было удобно писать и отлаживать именно индикаторы. Если же Вам привычней обратная индексация, то это всегда можно изменить функцией ArraySetAsSeries. Уверен, после небольшой практики Вы найдете такой способ индексации индикаторных буферов более удобным, сужу по своему опыту.

и

CoreWinTT:

да я немного понял когда немножко задумался про заполнения буферов и организацию доступа данных.

думаю данное примечание стоит написать не только к функции к SetIndexBuffer()

Теперь, люди добрые, объясните мне, что я именно не понимаю.

Вот код индикатора MQL4

#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 DeepSkyBlue
//---- input parameters
extern int       History=100;
//---- buffers
double HiBuffer[];
//-------------------------------------------------------------------
int init()
{
//---- indicators
  SetIndexStyle(0,DRAW_HISTOGRAM);
  SetIndexBuffer(0,HiBuffer);
//----
  return(0);
}
//-------------------------------------------------------------------
int deinit()
{
//----

//----
  return(0);
}
//-------------------------------------------------------------------
int start()
{
  int    counted_bars=IndicatorCounted();
//----
  int i=0;
  while (i<counted_bars)
  {
    if (i<History)
    {
      HiBuffer[i]=High[i];
    } else
    {
      HiBuffer[i]=0.0;
    }

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

он рисует такую картинку:

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

Теперь посмотрим на код MQL5, того же индикатора:

#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot Hi
#property indicator_label1  "Hi"
#property indicator_type1   DRAW_LINE
#property indicator_color1  Red
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//-------------------------------------------------------------------
input int      History               =100;
//-------------------------------------------------------------------
double         HiBuffer[];
//-------------------------------------------------------------------
int OnInit()
{
  SetIndexBuffer     (0,HiBuffer,INDICATOR_DATA);
  PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,1);
  PlotIndexSetString (0,PLOT_LABEL,"HiBuffer");
  return(0);
}
//-------------------------------------------------------------------
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 i=0;
  while (i<rates_total)
  {
    if (i<History)
    {
      HiBuffer[i]=high[i];
    } else
    {
      HiBuffer[i]=0.0;
    }
    i++;
  }
  return(rates_total);
}
//-------------------------------------------------------------------

Он рисует такую картинку:


Обратите внимание, что здесь 0-й индекс буфера индикатора соответствует самому старому бару на графике.

Зачем так? Объясните пожалуйста. Скажете, а в чем проблема, сделай буфер индикатора таймсерией, и всё будет ок.

Ок, делаю:

#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot Hi
#property indicator_label1  "Hi"
#property indicator_type1   DRAW_LINE
#property indicator_color1  Red
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//-------------------------------------------------------------------
input int      History               =100;
//-------------------------------------------------------------------
double         HiBuffer[];
//-------------------------------------------------------------------
int OnInit()
{
  SetIndexBuffer     (0,HiBuffer,INDICATOR_DATA);
  ArraySetAsSeries   (HiBuffer,true);//Сделал как посоветовали. 
  PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,1);
  PlotIndexSetString (0,PLOT_LABEL,"HiBuffer");
  return(0);
}
//-------------------------------------------------------------------
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 i=0;
  while (i<rates_total)
  {
    if (i<History)
    {
      HiBuffer[i]=high[i];
    } else
    {
      HiBuffer[i]=0.0;
    }
    i++;
  }
  return(rates_total);
}
//-------------------------------------------------------------------

Получаем такую картинку:

Что мы видим теперь? 0-й индекс буфера индекатоора будет соответствовать также самому старому бару на графике, только отображаются уже в самом конце истории.


Выше я показывал одно из заднепрходных решений. Но оно Заднепроходное!.

Или я что то не понимаю, объясните пожалуйста, как нужно работать с индикаторами, что бы стало "легче".

123
Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий