C логарифмом не сложилось...

 

#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots 1
//---- plot
#property indicator_label1 "D_1"
#property indicator_type1 DRAW_LINE
#property indicator_color1 RoyalBlue
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1

//---- input parameters
input int pPeriod=200; // Period

double P=0.00001;
//---- indicator buffers
double ExtBuffer[],std,sred,Means;
//--- global variable
int iPeriod;
string sName="D_Vars";
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
void OnInit()
{
//--- check for input value
if(pPeriod<0)
{
iPeriod=14;
Print ("Input parameter Period has wrong value.",
" Indicator will use value ",pPeriod);
}
else iPeriod=pPeriod;
//---- buffers
SetIndexBuffer(0,ExtBuffer,INDICATOR_DATA);

//---- name for DataWindow and indicator subwindow label
sName+="("+string(iPeriod)+ ")";
IndicatorSetString(INDICATOR_SHORTNAME,sName);
//--- sets first bar from what index will be drawn
PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,iPeriod-1);
//--- sets drawing line empty value
PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0);
//--- digits
IndicatorSetInteger(INDICATOR_DIGITS,5);
PlotIndexSetString(0,PLOT_LABEL,sName);
ArraySetAsSeries(ExtBuffer,true);
Print("Init Dvar....");
}
//+------------------------------------------------------------------+
//| Momentu |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const int begin,
const double &price[])
{
//--- start calculation
     int StartCalcPosition=(iPeriod+1)+begin;

//---- insufficient data
    if(rates_total<StartCalcPosition)
    return(0);
//--- correct draw begin

   std=0.1;
   sred=0.001;
   Means=0.001;
   Print(".... start ....iPeriod=",iPeriod);
   for(int i=0;i<iPeriod;i++)
      {
         ExtBuffer[i]=std*MathLog(sred)/(MathLog(price[0])*Means);
         Print (i,"=",ExtBuffer[i]," price[0]=",price[0]);
      }
    Print(".... end....");  
    //--- OnCalculate done. Return new prev_calculated.
   return(rates_total);
}

 

результат

2010.02.13 05:05:55 Access (CHFJPY,M15) Access violation read to 0x00000007 in 'E:\Program Files\MetaTrader 5\MQL5\Indicators\MyMSQL5\errors\Access.ex5 
2010.02.13 05:05:55 Access (CHFJPY,M15) 2 = 0.9559295868397006 price[0]= 87.119
2010.02.13 05:05:55 Access (CHFJPY,M15) 1 = 1.131892665130701 price[0]= 87.119
2010.02.13 05:05:55 Access (CHFJPY,M15) 0 = 1.201220169277647 price[0]= 87.119
2010.02.13 05:05:55 Access (CHFJPY,M15) .... start ....iPeriod= 200
2010.02.13 05:05:55 Access (CHFJPY,M15) Init Dvar....

Получается, что в цикле меняются результаты, или оптимизация кода напартачила? 

В чём ошибка?

 

И еще одна хохма -. последняя цена  на графике 83.689/05!!

что в price[0] - если в параметрах выбрана цена Close? 

 

 

Пока мой пост не замечают решил ответить на свой второй вопрос - взять пример "не кривого" кода (по образному выражению Мегаквотов ;) и  добавить одну странную на мой взгляд проверку...

//+------------------------------------------------------------------+
//|                                                     Momentum.mq5 |
//|                        Copyright 2009, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2009, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
//---- indicator settings
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1
#property indicator_type1   DRAW_LINE
#property indicator_color1  DodgerBlue
//---- input parameters
input int InpMomentumPeriod=14; // Period
//---- indicator buffers
double    ExtMomentumBuffer[];
//--- global variable
int       ExtMomentumPeriod;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void OnInit()
  {
//--- check for input value
   if(InpMomentumPeriod<0)
     {
      ExtMomentumPeriod=14;
      Print("Input parameter InpMomentumPeriod has wrong value. Indicator will use value ",ExtMomentumPeriod);
     }
   else ExtMomentumPeriod=InpMomentumPeriod;
//---- buffers   
   SetIndexBuffer(0,ExtMomentumBuffer,INDICATOR_DATA);
//---- name for DataWindow and indicator subwindow label
   IndicatorSetString(INDICATOR_SHORTNAME,"Momentum"+"("+string(ExtMomentumPeriod)+")");
//--- sets first bar from what index will be drawn 
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,ExtMomentumPeriod-1);
//--- sets drawing line empty value
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
//--- digits
   IndicatorSetInteger(INDICATOR_DIGITS,2);
  }
//+------------------------------------------------------------------+
//|  Momentum                                                        |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {
//--- start calculation
   int StartCalcPosition=(ExtMomentumPeriod-1)+begin;
//---- insufficient data
   if(rates_total<StartCalcPosition)
      return(0);
//--- correct draw begin
   if(begin>0) PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,StartCalcPosition+(ExtMomentumPeriod-1));
//--- start working, detect position
   int pos=prev_calculated-1;
   if(pos<StartCalcPosition)
      pos=begin+ExtMomentumPeriod;
      if(!ArrayGetAsSeries(price)) //          ------ Проверка очевидного !!!!!! 
      ArraySetAsSeries(price,true);//                    но не для всех...
//--- main cycle
   for(int i=pos;i<rates_total;i++)
     {
      ExtMomentumBuffer[i]=price[i]*100/price[i-ExtMomentumPeriod];
     }
     Print (price[0]);
//--- OnCalculate done. Return new prev_calculated.
   return(rates_total);
  }
//+------------------------------------------------------------------+

Естественно получилась небольшая разница в результатах..

 

А в справке написано  

В качестве массива price[] может быть передана одна из ценовых таймсерий либо рассчитанный буфер какого-либо индикатора. Чтобы определить направление индексации в массиве price[], необходимо вызывать функцию ArrayGetAsSeries(). Чтобы не зависеть от умолчаний, необходимо безусловно вызывать функцию ArraySetAsSeries() для тех массивов, с которыми предполагается работать.

Чудно..
 
avatara:

Пока мой пост не замечают решил ответить на свой второй вопрос - взять пример "не кривого" кода (по образному выражению Мегаквотов ;) и  добавить одну странную на мой взгляд проверку...

Естественно получилась небольшая разница в результатах..

 

А в справке написано  

Чудно..

 

 

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

сейчас тело oncalculate выглядит так:

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[]){
                
  ArraySetAsSeries(TDBuffer, true );   
  ArraySetAsSeries(TDDemand, true );   
  ArraySetAsSeries(TDSupport, true );   
  ArraySetAsSeries(high, true );   
  ArraySetAsSeries(TDBreakOutQualifier1, true );
  ArraySetAsSeries(TDBreakOutQualifier2, true );
  ArraySetAsSeries(TDBreakOutQualifier3, true );
  ArraySetAsSeries(BuyStopBuffer, true );
  ArraySetAsSeries(SellStopBuffer, true );

 

 

на каждый индикаторный буфер пишу  ArraySetAsSeries(, true ), чтоб наверняка, а time[], open[], high[], low[], close[] вообще не использую, т.к. они доступны только в OnCalculate,  и для того чтобы их использовать, предположим внутри объектов или фнукций, вызываемых далее (а если алогоритмы сложные, то уровень вложенности вызываемых функции может быть не один и не два), то нужно передавать их в качестве параметров на каждый уровень вложенности, либо копировать специальным образом содержимое этих массивов в глобальные, чтоли переменные, поэтому пришлось написать свои функции Open(), High(), Low(), Close(), Time(). Может быть я мыслю слишком шаблонно и топорно? может разработчики подскажут, как организовать доступ к таймсериям при использовании сложных алогритмов с использованием ооп и большой вложенности вызовов функций?
я лично ждал платформу с ооп, в которой можно было реализовывавать действительно сложные вещи кодируя торговые идей, ооп получилось хорошее, устраивает, а вот кодирование идей- утомляет, погрязаешь в бесконечных проверках, нехватке решений непосредственно поддерживаемых платформой - к примеру я о том же Open[] - почему я должен программировать эту функцию, почему в специализированной торговой платформе ее нет? раз нет этого функционала, может разработчики сами его реализуют уже средствами языка? а то пытаешься сам запрограммирвоать, не получается - и ооказывается, если по простому: я это еще не разу не делал, и опять не получилось.

 
gdtt писал(а)  :

 

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

Зато не криво получится может...

;)

 А пример Моментума и цитату из справки привел для иллюстрации, что проверки не обязательны...

 Правда не всем. 

 
avatara писал(а)  :

И еще одна хохма -. последняя цена  на графике 83.689/05!!

что в price[0] - если в параметрах выбрана цена Close?

Не всегда получается отвечать вовремя. Но ведь можно проверить самостоятельно и убедиться, что самая последняя цена передается в функцию OnCalculate() под индексом rates_total-1. То есть, переданный в функцию массив price[] имеет индексацию из прошлого в будущее.

Вот простой пример индикатора для проверки.

//+------------------------------------------------------------------+
//|                                               CheckDirection.mq5 |
//|                        Copyright 2009, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2009, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1
//---- plot close
#property indicator_label1  "close"
#property indicator_type1   DRAW_LINE
#property indicator_color1  Red
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- indicator buffers
double         closeBuffer[];
bool           firstCalc=true;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,closeBuffer,INDICATOR_DATA);
//---
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate (const int rates_total,      // размер массива price[]
                 const int prev_calculated,  // обработано баров на предыдущем вызове
                 const int begin,            // откуда начинаются значимые данные
                 const double& price[]       // массив для расчета
                 )
  {
  if(firstCalc)
  {
  ArrayInitialize(closeBuffer,EMPTY_VALUE);
  firstCalc=false;
  }
//---
   MqlTick last_tick;
   string com="\r\n";
   if(SymbolInfoTick(Symbol(),last_tick))
     {
      com=com+" Last Bid = "+DoubleToString(last_tick.bid,_Digits);
     }
   com=com+"   price[0]= "+DoubleToString(price[0],_Digits)+
       "   price[rates_total-1]= "+DoubleToString(price[rates_total-1],_Digits);
   Comment(com);
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

Результат:


 
avatara:

Пока мой пост не замечают решил ответить на свой второй вопрос - взять пример "не кривого" кода (по образному выражению Мегаквотов ;) и  добавить одну странную на мой взгляд проверку...

Естественно получилась небольшая разница в результатах..

//+------------------------------------------------------------------+
//|  Momentum                                                        |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {
//--- start calculation
   int StartCalcPosition=(ExtMomentumPeriod-1)+begin;
//---- insufficient data
   if(rates_total<StartCalcPosition)
      return(0);
//--- correct draw begin
   if(begin>0) PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,StartCalcPosition+(ExtMomentumPeriod-1));
//--- start working, detect position
   int pos=prev_calculated-1;
   if(pos<StartCalcPosition)
      pos=begin+ExtMomentumPeriod;
      if(!ArrayGetAsSeries(price)) //          ------ Проверка очевидного !!!!!! 
      ArraySetAsSeries(price,true);//                    но не для всех...

А в справке написано  

Чудно..

Дело в том, что массив price[] не обязательно является таймсерией. В справке есть ArrayGetAsSeries() примечание:

Примечание

Для проверки массива на принадлежность к таймсерии следует применять функцию ArrayIsSeries(). Массивы ценовых данных, переданных в качестве входных параметров в функцию OnCalculate(), не обязательно имеют направление индексации как у таймсерий. Нужное направление индексации можно установить функцией ArraySetAsSeries().


 
Rosh писал(а)  :

Не всегда получается отвечать вовремя. Но ведь можно проверить самостоятельно и убедиться, что самая последняя цена передается в функцию OnCalculate() под индексом rates_total-1. То есть, переданный в функцию массив price[] имеет индексацию из прошлого в будущее.

Вот простой пример индикатора для проверки.

Результат:


Спасибо что нашли время ответить!

Вопрос этот был второстепенным и скорее... хм. - провокационным.

Таймсерия принимается и она не таймсерия. Странно знаете.

Нужно не зависеть от умолчаний и проверять - иначе криво!

Смотрим творения мастеров-создателей - никаких проверок.

"Что позволено Юпитеру..."

;)

 

А вопрос  остался! С сложением или делением логарифма. 

 
gdtt:

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

В стандартной поставке идет библиотека MovingAverages, в которой реализован расчет скользящих средних четырьмя способами. Посмотрите как в ней организован расчет,  независимо от того что подано на вход - таймсерия или обычный массив - данные обрабатываются корректно. И нет никакой зависимости от направления индексации во входных данных.
 
avatara:

Спасибо что нашли время ответить!

Вопрос этот был второстепенным и скорее... хм. - провокационным.

Таймсерия принимается и она не таймсерия. Странно знаете.

Нужно не зависеть от умолчаний и проверять - иначе криво!

Смотрим творения мастеров-создателей - никаких проверок.


Но ведь разработчики не пишут для индикатора Momentum в OnInit как у Вас

void OnInit()
{
//--- check for input value
if(pPeriod<0)
{
iPeriod=14;
Print ("Input parameter Period has wrong value.",
" Indicator will use value ",pPeriod);
}
else iPeriod=pPeriod;
//---- buffers
SetIndexBuffer(0,ExtBuffer,INDICATOR_DATA);

//---- name for DataWindow and indicator subwindow label
sName+="("+string(iPeriod)+ ")";
IndicatorSetString(INDICATOR_SHORTNAME,sName);
//--- sets first bar from what index will be drawn
PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,iPeriod-1);
//--- sets drawing line empty value
PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0);
//--- digits
IndicatorSetInteger(INDICATOR_DIGITS,5);
PlotIndexSetString(0,PLOT_LABEL,sName);
ArraySetAsSeries(ExtBuffer,true);
Print("Init Dvar....");
}

Вы же писали это сознательно, значит понимали что делаете.

 
Rosh писал(а)  :

Но ведь разработчики не пишут для индикатора Momentum в OnInit как у Вас

Вы же писали это сознательно, значит понимали что делаете.

Это затронуло  ExtBuffer[i]=std*MathLog(sred)/(MathLog(price[0])*Means);?

:o))) 

Буду осмотрительней...

Спасибо. 

PS.

SetIndexBuffer

Связывает указанный индикаторный буфер с одномерным динамическим массивом типа double, объявленном на глобальном уровне.

bool  SetIndexBuffer(
   int                    index,         // индекс буфера
   double                 buffer[],      // массив
   ENUM_INDEXBUFFER_TYPE  data_type      // что будем хранить
   );

Примечание

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

 
avatara:

 

А вопрос  остался! С сложением или делением логарифма. 

Логарифм здесь не причем. Компилятор указывает на выход за пределы индексации при доступе к массиву ExtBuffer[]. Вы его объявили на глобальном уровне, но он так и остался нулевого размера. Если бы Вы его привязали к индикаторному буферу, то все было бы нормально.

   SetIndexBuffer(0,ExtBuffer,INDICATOR_CALCULATIONS);