Свечной индикатор – определяем какой по отношению к выборке является свеча

21.12.2016 в 1:51
admin
Регистрация: 17.02.2011
Сообщений: 4483
Рейтинг: 2841

Несколько раз на одном из форумов мне приходилось помогать форумчанам в написании свечных индикаторов. Имея некоторый опыт в написании программ для Метатрейдера и в программировании на языках, основанных на концепции СИ++, я уже могу мысленно представить какой объем работы предстоит при реализации того или иного пользовательского индикатора, советника либо скрипта. Конечно, порой изначальная задача кажется простой, но приступая к ее реализации в коде, либо сталкиваешься с какими-либо изначально скрытыми трудностями, либо сам наворачиваешь по ходу кодинга к “велосипеду” реактивный двигатель. А вот самое сложное состоит в том, чтобы “вытащить” из потенциального обладателя индикатора, точную формулировку задания, так называемое техническое задание на разработку свечного индикатора.

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

Итак, изначально одной девушке понадобился свечной индикатор, который показывает размер свечи, но “не тела свечи, а вместе с хвостами”. Реализация заняла несколько минут:

//+------------------------------------------------------------------+ 
//|                               candle_size_for_Natashika_mmgp.mq4 | 
//|                                 Vlad Sergeev aka moneyinnetwork  | 
//+------------------------------------------------------------------+ 
#property copyright "http://moneyinnetwork.ru"
#property link "http://moneyinnetwork.ru" 
#property version   "1.00" 
#property strict 
#property indicator_chart_window 
 
input int      TextSize = 8; //размер шрифта 
input color    TextColor = clrYellow; //цвет текста 
input int      TextAngle = 90; //угол поворота текста 
input int      MaxBar = 100;  //количество баров, начиная с 0, для которых вычисляется размер свечей 
 
int OnInit() 
{ 
   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 i; 
   for ( i = 0; i < MaxBar; i++ )   { 
      if ( ObjectFind ("candlesize"+ IntegerToString(i)) >=0 )   { 
             ObjectDelete("candlesize"+ IntegerToString(i)); 
      } 
      ObjectCreate ("candlesize"+ IntegerToString(i),  
                    OBJ_TEXT,  
                    0,  
                    time[i],  
                    high[i]+StepPer()*Point); 
      ObjectSet (  "candlesize"+IntegerToString(i),  
                    OBJPROP_ANGLE,  
                    TextAngle 
                 ); 
      ObjectSetText ( "candlesize"+IntegerToString(i),  
                      DoubleToStr(NormalizeDouble((high[i]-low[i]+Point)/Point, 0), 0),  
                      TextSize,  
                      NULL,  
                      TextColor 
                     ); 
   } 
   return(rates_total); 
} 
 
int StepPer () 
{ 
     int i = 0; 
     switch (Period()) 
     { 
          case PERIOD_M1: 
          i = 5; 
          break; 
          case PERIOD_M5: 
          i = 15; 
          break; 
          case PERIOD_M15: 
          i = 25; 
          break; 
          case PERIOD_M30: 
          i = 40; 
          break; 
          case PERIOD_H1: 
          i = 60; 
          break; 
          case PERIOD_H4: 
          i = 90; 
          break; 
          case PERIOD_D1: 
          i = 220; 
          break; 
          case PERIOD_W1: 
          i = 500; 
          break; 
          case PERIOD_MN1: 
          i = 2000; 
          break; 
          default:  
          break; 
     } 
     return (i); 
}

И этот простейший индикатор, написанный на коленках, скачало 468 человек.

Потом первоначальная идея была направленна в несколько иное русло. Требовался индикатор, который указывает в отдельной строке размер тела уже сформированной свечи, причем, в определенной позиции экрана и определенным шрифтом, при этом индикатор “не должен оставлять следов” после удаления его с графика. Выводить информацию должен в виде строки, например, “Свеча: 50″. Решение было найдено достаточно быстро:

//+------------------------------------------------------------------+ 
//|                                 candle_size_for_Retrade_mmgp.mq4 | 
//|                                 Vlad Sergeev aka moneyinnetwork  | 
//+------------------------------------------------------------------+ 
#property copyright "http://moneyinnetwork.ru" 
#property link "http://moneyinnetwork.ru" 
#property version   "2.00" 
#property strict 
#property indicator_chart_window 
 
input int      TextSize = 10; //размер шрифта 
input string   FontName = "Verdana"; //наименование шрифта 
input color    TextColor = clrWhite; //цвет текста 
input int      PosX = 0;  //координата текста по x 
input int      PosY = 50; //координата текста по у 
 
int OnInit() 
{ 
   return(INIT_SUCCEEDED); 
} 
 
void OnDeinit(const int reason) 
{ 
   if ( ObjectFind ("candlesizeXX") >=0 )   { 
             ObjectDelete("candlesizeXX"); 
   } 
} 
 
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 ( ObjectFind ("candlesizeXX") >=0 )   { 
             ObjectDelete("candlesizeXX"); 
      } 
      ObjectCreate ("candlesizeXX", OBJ_LABEL, 0, 0, 0); 
      ObjectSet ("candlesizeXX", OBJPROP_ANGLE, 0); 
      ObjectSet("candlesizeXX", OBJPROP_CORNER, 0); 
      ObjectSet("candlesizeXX", OBJPROP_BACK, FALSE); 
      ObjectSet("candlesizeXX", OBJPROP_XDISTANCE, PosX); 
      ObjectSet("candlesizeXX", OBJPROP_YDISTANCE, PosY); 
      ObjectSetText ( "candlesizeXX",  
                      "Свеча: "+DoubleToStr(NormalizeDouble((high[1]-low[1]+Point)/Point, 0), 0),  
                      TextSize,  
                      FontName,  
                      TextColor 
                     ); 
   return(rates_total); 
}

Сколько человек скачало этот индикатор не знаю, поскольку, он был выложен в виде текста (как и здесь, впрочем).

Потом разные люди хотели разных реализаций. Сколько людей, столько и реализаций свечных индикаторов :)

Спустя какое-то время меня попросили изменить индикатор Bar Value так, чтобы он выдавал алерт сразу, как только тело текущей свечи достигнет нужного размера. Мной был реализован вариант, который выдает только один алерт для текущей свечи, поскольку в ином случае, на каждом тике при выполнении заданного условия мы получали бы сигнал алерта. В общем, была бы просто чума (а именно, так, кстати, и “голосил” первейший вариант):

//+------------------------------------------------------------------+  
//|                                              body_size_alert.mq4 |  
//|                                 Vlad Sergeev aka moneyinnetwork  |  
//+------------------------------------------------------------------+  
#property copyright "http://moneyinnetwork.ru"  
#property link "http://moneyinnetwork.ru"  
#property version   "4.00"  
#property strict  
#property indicator_chart_window  
 
input int      TextSize = 10; //размер шрифта  
input string   FontName = "Verdana"; //наименование шрифта  
input color    TextColor = clrWhite; //цвет текста  
input int      PosX = 0;  //координата текста по x  
input int      PosY = 50; //координата текста по у  
input int      Max_Bar = 20; //размер бара при котором выдается Alert 
bool  no_alert; 
datetime time_old; 
 
int OnInit()  
{  
   no_alert = false; 
   time_old = 0; 
   return(INIT_SUCCEEDED);  
}  
 
void OnDeinit(const int reason)  
{  
   if ( ObjectFind ("candlesizeXX") >=0 )   {  
             ObjectDelete("candlesizeXX");  
   }  
}  
 
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[])  
{  
   double bar_size = MathAbs(close[0]-open[0])/Point; 
   if ( ObjectFind ("candlesizeXX") >=0 )   {  
             ObjectDelete("candlesizeXX");  
      }  
      ObjectCreate ("candlesizeXX", OBJ_LABEL, 0, 0, 0);  
      ObjectSet ("candlesizeXX", OBJPROP_ANGLE, 0);  
      ObjectSet("candlesizeXX", OBJPROP_CORNER, 0);  
      ObjectSet("candlesizeXX", OBJPROP_BACK, FALSE);  
      ObjectSet("candlesizeXX", OBJPROP_XDISTANCE, PosX);  
      ObjectSet("candlesizeXX", OBJPROP_YDISTANCE, PosY);  
      ObjectSetText ( "candlesizeXX",   
                      "Размер тела текущей свечи: "+DoubleToStr(bar_size, 0)+" пунктов",   
                      TextSize,   
                      FontName,   
                      TextColor  
                     );  
   if ( time_old != time[0] )  { 
      no_alert = false; 
      time_old = time[0]; 
   } 
   if ( bar_size > Max_Bar && !no_alert ) { 
      Alert("Размер тела свечи превысил заданный уровень в ", Max_Bar, " пунктов!");    
      no_alert = true; 
   } 
   return(rates_total);  
}

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

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

Итак, поступила очередная просьба сделать версию индикатора, который помимо определения размера последней свечи (от high до low) мог бы сопоставлять также её размеры с размерами предыдущих свечей (выборка глубиной, задаваемой пользователем индикатора). При наведении курсора мыши на свечу, индикатор должен показывать это значение (сопоставляемое) словами “широкий”, “средний” или “узкий”.

В силу вышеуказанных причин, заниматься этой несложной работой у меня желания не возникло и я ответил, что, мол, с удовольствием переделывал все и подо всех, если бы только этим с утра и до вечера занимался и не делал бы более ничего. Однако, у меня, к счастью, есть свои интересы, дела… тянуть этот раздел (программирование и т.п.) лично у меня желания нет. Выразил недовольство тем, что народ днюет и ночует в новостях, занявшись набиванием платных постов… “Если интересуют разработки “под Вас”, то обращайтесь в личку: будет время сделаю, естественно, не бесплатно…”

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

Пишу:

Ну, начнем с того, что Вы сами не указали, например, какие свечи считать: широкими (может, те, которые больше среднего на 20% за выборку), узкими (может те, которые меньше среднего на 20% за выборку), и с каким отклонением допустимым отклонением от среднего – среднее (если, скажем, свеча имеет размер с отклонением +- 5% от размера средней по выборке, то она считается средней).
Дальше, размер берем все-таки свечи (high-low), а не тела (close-open)?
С индикацией все понятно.

В ответе опять требуемых данных не получил. Клиенту нужно было,чтобы ширина последней свечи (или бара, как удобно) определялась методом сравнения с предыдущими 20 – 30 свечами (барами), как это будет делаться технически, он не знает и ссылается на то, что я программист и мне решать эту задачу. Далее уточнил, что размер свечи (бара) берем от хая до лоу и размер должен показываться на графике словами “широкий”, “узкий”, “средний” при наведении мышкой на свечу, чтобы не захламлять график.

Тут я понял, что мы с оппонентом находимся на “разных волнах”. Меня интересовали именно параметры, относящиеся к формулировкам: “широкие”, “узкие” и “средние”. А клиент опять, очевидно, решил, что я вытягиваю из него методы реализации индикатора в коде. Пишу, объясняя на пальцах:

Правильная постановка условия задачи – это 50% ее решения.
Сравнивать можно хоть с 300 свечами из истории. Суть-то в том, что Вы не определили:
1. Какие свечи считать “широкими”.
2. Какие свечи считать “узкими”
3. Какие свечи считать “средними”.
Т.е. я из Вас “выжимаю” критерии сравнения, в то время, как, Вы хотите их от меня, но задача-то Ваша, а не моя.
Давайте на пальцах.
Есть в истории 10 свечей размерами от хая до лоу: 20,30,25,60,40,25,50,40,20,60 пунктов. Средний арифметический размер бара из этой выборки: 37 пунктов.
Закрылась новая свеча размером 30 пунктов. Какой ее считать? Узкой или средней?
Закрылась свеча 62 пункта. Широкая? (т.е. больше максимальной в выборке)
Закрылась свеча 18 пунктов. Узкая? (т.е. меньше минимальной в выборке)
А, может, средней будем считать свечу, которая укладывается в диапазон размеров всех свечей в выборке, т.е. в интервале от 20 до 60 средняя?
Вот о чем я речь вел.
А то получается так, взял учитель учебник по математике и прочитал слово “Задача”, а потом попросил ее решить не дав исходных данных.

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

Я понял мысль. Посидел – посчитал. У меня получилось, что средней будет считаться свеча, которая попадает в диапазон +/- 25% от размера средней по выборке из количества последних 20 – 30 свечей. Теперь более детально, как я это понимаю.За основу взял Ваш вышеизложенный пример.
Есть в истории 10 свечей: 20, 30, 25, 60, 40, 25, 50, 40, 20, 60 пунктов. Средний размер их равен 37 пунктов. У следующей свечи (одиннадцатой) размер 30 пунктов. 37 п. = 100%, отклонение 25% от 37 пунктов равно 9 пунктам Значит, среднее значение размера свечи в 30 пунктов должно лежать в диапазоне от 28 до 46 пунктов (+/- 9 пунктов от 37 пунктов). Следовательно, наша свеча в 30 пунктов средняя.
Следующая свеча (двенадцатая) у нас 62 пункта. Так как по формуле нашего примера мы берем последние 10 свечей, следовательно первую свечу в нашем примере в 20 пунктов мы исключаем, а вместо нее подставляем нашу последнюю (одиннадцатую) свечу в 30 пунктов.
Теперь последние свечи берем 30, 25, 60, 40, 25, 50, 40, 20, 60, 30. Их средний размер равен 38 пунктов. 38 п. = 100 %, отклонение 25% от 38 пунктов равно тоже 9 пунктам. Значит, среднее размера свечи в 62 пункта должно лежать в диапазоне от 29 до 47 пунктов (+/- 9 пунктов от 38 пунктов). Так как наша свеча в 62 пункта не попадает в этот диапазон, следовательно она широкая. Здесь хочу ОБРАТИТЬ ВНИМАНИЕ, что дроби от 0,1 до 0,5 округляем в меньшую сторону, а от 0,6 до 1,0 – в большую).
Ну и так далее…… Я думаю теперь Вы поняли ход моих мыслей.

Итак, реализация:

//+------------------------------------------------------------------+ 
//|                                    wide_medium_narrow_candle.mq4 | 
//|                                         http://moneyinnetwork.ru | 
//+------------------------------------------------------------------+ 
#property copyright "(c) 2016 moneyinnetwork.ru" 
#property link "http://moneyinnetwork.ru" 
#property version   "1.00" 
#property strict 
#property indicator_chart_window 
 
//всего потребуется 6 индикаторных буферов
#property indicator_buffers 6
 
//делаем индикаторные линии невидимыми, чтобы не захламлять график
#property indicator_color1 clrNONE
#property indicator_color2 clrNONE
#property indicator_color3 clrNONE
#property indicator_color4 clrNONE
#property indicator_color5 clrNONE
#property indicator_color6 clrNONE
 
//объявим массивы 
double wide_buf[], wide_buf1[], medium_buf[], medium_buf1[], narrow_buf[], narrow_buf1[];  
 
input int      TextSize = 10; //размер шрифта 
input string   FontName = "Verdana"; //наименование шрифта 
input color    TextColor = clrWhite; //цвет текста 
input int      PosX = 0;   //координата текста по x 
input int      PosY = 50;  //координата текста по у 
input int      Depth = 30; //глубина выборки для определения средней свечи
input double   Delta = 25; //допустимое отклонение от среднего, в процентах
input bool     Alert_S = true;//разрешение/запрет оповещения как только текущая свеча становится широкой
input int      All_Bars = 250; //Количество последних баров, для которых производиться расчет индикатора  
 
bool  no_alert;
datetime time_old;
 
int OnInit() 
{ 
   no_alert = false;
   time_old = 0;  
 
   //имя индикатора (в сплывающем окне)
   IndicatorShortName ("Свечной индикатор");
 
   //привяжем наши массивы к индикаторным буферам
   SetIndexBuffer (0, wide_buf);   SetIndexBuffer (1, wide_buf1);
   SetIndexBuffer (2, medium_buf); SetIndexBuffer (3, medium_buf1);
   SetIndexBuffer (4, narrow_buf); SetIndexBuffer (5, narrow_buf1);
 
   //зададим пустое значение для индикаторных буферов
   SetIndexEmptyValue (0, EMPTY_VALUE); SetIndexEmptyValue (1, EMPTY_VALUE);
   SetIndexEmptyValue (2, EMPTY_VALUE); SetIndexEmptyValue (3, EMPTY_VALUE);
   SetIndexEmptyValue (4, EMPTY_VALUE); SetIndexEmptyValue (5, EMPTY_VALUE);
 
   //определим тип индикаторных линий - гистограмма
   SetIndexStyle (0, DRAW_HISTOGRAM); SetIndexStyle (1, DRAW_HISTOGRAM);
   SetIndexStyle (2, DRAW_HISTOGRAM); SetIndexStyle (3, DRAW_HISTOGRAM);
   SetIndexStyle (4, DRAW_HISTOGRAM); SetIndexStyle (5, DRAW_HISTOGRAM);
 
   //наименование характерных свечей (в сплывающем окне)
   SetIndexLabel(0, "Широкая"); SetIndexLabel(1, "Широкая");
   SetIndexLabel(2, "Средняя"); SetIndexLabel(3, "Средняя");
   SetIndexLabel(4, "Узкая");   SetIndexLabel(5, "Узкая");
 
   if ( ObjectFind ("candlesizeXX") < 0 )   
   { 
       ObjectCreate ("candlesizeXX", OBJ_LABEL, 0, 0, 0); 
       ObjectSet ("candlesizeXX", OBJPROP_ANGLE, 0); 
       ObjectSet("candlesizeXX", OBJPROP_CORNER, 0); 
       ObjectSet("candlesizeXX", OBJPROP_BACK, FALSE); 
   }
 
   return(INIT_SUCCEEDED); 
} 
 
void OnDeinit(const int reason) 
{ 
   //"подчистим" за собой при деинициализации индикатора
   if ( ObjectFind ("candlesizeXX") >=0 )   { 
             ObjectDelete("candlesizeXX"); 
   } 
} 
 
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, j, k;
   double max_bar, min_bar, sum_bar, bar_size, Max_Bar = 0;
   //проходим по каждой из последних All_Bars, для расчета индикатора
   for ( k = 0; k < All_Bars; k++ )
   {
      //проходим по каждой свече в выборке глубиной Depth предшествующей k-ой свече
      j = k + 1;
      max_bar = 0; min_bar = 0; sum_bar = 0;
      for ( i = 0; i < Depth; i++ )
      {
         //размер бара
         bar_size = high[j]-low[j];
         //определение минимального и максимального баров
         if ( max_bar < bar_size ) max_bar = bar_size;
         if ( min_bar > bar_size ) min_bar = bar_size;
         sum_bar+=bar_size;
         j++;
      }
      //определяем среднюю высоту бара из выборки глубиной Depth
      sum_bar = sum_bar/Depth;
      wide_buf[k] = EMPTY_VALUE;    wide_buf1[k] = EMPTY_VALUE;
      medium_buf[k] = EMPTY_VALUE;  medium_buf1[k] = EMPTY_VALUE; 
      narrow_buf[k] = EMPTY_VALUE;  narrow_buf1[k] = EMPTY_VALUE;  
      //проверка на узкий, средний, широкий бары и заполнение индикаторных буферов размера баров (пункты).
      //бар средний
      if ( high[k]-low[k] >= (100-Delta)*sum_bar/100 && high[k]-low[k] <= (100+Delta)*sum_bar/100 )  { 
         medium_buf[k] = low[k]; medium_buf1[k] = high[k]; 
      }
      //бар широкий
      if ( high[k]-low[k] > (100+Delta)*sum_bar/100 ) {
         wide_buf[k] = low[k]; wide_buf1[k] = high[k];
 
      }
      //бар узкий
      if ( high[k]-low[k] < (100-Delta)*sum_bar/100 )  {
         narrow_buf[k] = low[k]; narrow_buf1[k] = high[k];
      }
      if ( k == 0 ) Max_Bar = sum_bar;
   }
   //проверка на разрешение оповещения
   if ( Alert_S ) 
   {
      if ( time_old != time[0] )  
      {
         no_alert = false;
         time_old = time[0];
      }
      //условия для оповещения выполнены - оповещаем
      if ( high[0]-low[0] > (100+Delta)*Max_Bar/100 && !no_alert ) 
      {
         Alert("Текущая свеча широкая для выборки из предыдущих ", Depth, " свечей!");   
         no_alert = true;
      }
   }
   //переводим пипсы в пункты для 5-ти значных котировок
   double dec = 1;
   if ( Digits==5 ) dec = 10;
   ObjectSet("candlesizeXX", OBJPROP_XDISTANCE, PosX); 
   ObjectSet("candlesizeXX", OBJPROP_YDISTANCE, PosY); 
   ObjectSetText ( "candlesizeXX", "Свеча: "+DoubleToStr((high[0]-low[0])/Point/dec, 1)+" п." + 
                   " Средняя в глубину: " + DoubleToStr(Max_Bar/Point/dec, 1) + " п.",  
                   TextSize, FontName, TextColor ); 
   return(rates_total); 
}

Скачать свечной индикатор

Cвечной индикатор, начиная с текущей свечи, сравнивает ее размер со средним значением из выборки предыдущих ей свечей на глубину, определенную параметром Depth, и при наведении курсора мыши на любую из последних All_Bars свечей текущего графика появляется всплывающее сообщение с указанием, какой именно по соотношению размеров является данная свеча к средней из выборки:

  • Средней, если размер свечи не отклоняется от среднего из выборки более чем на 25%;
  • Широкой, если размер свечи больше среднего из выборки на 25% и более;
  • Узкой, если размер свечи меньше среднего из выборки на 25% и более.

Кроме того, индикатор в отдельной строке (в левом верхнем углу графика) должен указывать размер текущей свечи.

Вот, собственно, именно такое техническое задание мне хотелось увидеть в самом первом обращении :) Решив пойти немного дальше, сделал оповещение сигналом (алертом) в том случае, когда размер текущей свечи станет “широким” по отношению к среднему размеру из выборки.

Пишите свечные индикаторы хорошие и разные. И маленькое пожелание тем, кто сам писать их не может: четко формулируйте техническое задание на разработку пользовательского индикатора – это ускоряет процесс.

Поделиться в соц. сетях:
Ответов в теме: 19 Просмотров темы: 2652

21.12.2016, в 19:05
Aleks132016
Регистрация: нет
Сообщений: 1
Рейтинг: 2
#1

Огромное спасибо admin за проделанную работу!!!
Индикатор установил, он работает, как и требовалось.
По его просьбе расскажу, для чего он нужен.
Есть такой метод торговли по объемам. VSA называется. Метод строится на анализе объема,открытии/закрытии свечи, ширине свечи от хая до лоу и предшествующему фону (т.е. тому, что было на графике слева от последней свечи на глубину 20 – 30 баров.
Этот индикатор просто уменьшает время для анализа графика и убирает чисто человеческий фактор в определении ширины свечей (лично моя точка зрения!!!).
Вот так как-то.

+2 + -
Цитировать Ответить

06.05.2017, в 10:16
Андрей
Регистрация: нет
Сообщений: 4
Рейтинг: 0
#2

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

+ -
Цитировать Ответить

07.05.2017, в 15:48
admin
Регистрация: 17.02.2011
Сообщений: 4483
Рейтинг: 2841
#3

Андрей, попробуйте вот этот код:

//+------------------------------------------------------------------+  
//|                                            two_candles_alert.mq4 |  
//|                                 Vlad Sergeev aka moneyinnetwork  |  
//+------------------------------------------------------------------+  
#property copyright "moneyinnetwork.ru"  
#property link "http://moneyinnetwork.ru"  
#property version   "1.00"  
#property strict  
#property indicator_chart_window  
 
bool  no_alert; 
datetime time_old; 
 
int OnInit()  
{  
   no_alert = false; 
   time_old = 0; 
   return(INIT_SUCCEEDED);  
}  
 
void OnDeinit(const int reason)  
{  
}  
 
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 ( time_old != time[1] )  { 
      no_alert = false; 
      time_old = time[1]; 
   } 
   if ( close[2] > open[2] && close[1] > open[1] && !no_alert ) { 
      Alert("Покупка!");    
      no_alert = true; 
   }
   if ( close[2] < open[2] && close[1] < open[1] && !no_alert ) { 
      Alert("Продажа!");    
      no_alert = true; 
   } 
   return(rates_total);  
}

Работу проверить не могу, т.к. функция Alert не работает в тестере стратегий терминала МТ4.

+ -
Цитировать Ответить

08.05.2017, в 00:42
Андрей
Регистрация: нет
Сообщений: 4
Рейтинг: 0
#4

Спасибо, буду тестить! *DRINK*

+ -
Цитировать Ответить

09.05.2017, в 12:12
admin
Регистрация: 17.02.2011
Сообщений: 4483
Рейтинг: 2841
#5

Работает, но сделал небольшой апгрейд, чтобы информировал по типу строки, например:

2017.05.09 12:12 CADJPY Продажа! период M1

//+------------------------------------------------------------------+  
//|                                            two_candles_alert.mq4 |  
//|                                 Vlad Sergeev aka moneyinnetwork  |  
//+------------------------------------------------------------------+  
#property copyright "moneyinnetwork.ru"  
#property link "http://moneyinnetwork.ru"  
#property version   "2.00"  
#property strict  
#property indicator_chart_window  
 
bool  no_alert; 
datetime time_old; 
 
int OnInit()  
{  
   no_alert = false; 
   time_old = 0; 
   return(INIT_SUCCEEDED);  
}  
 
void OnDeinit(const int reason)  
{  
}  
 
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 ( time_old != time[1] )  { 
      no_alert = false; 
      time_old = time[1]; 
   } 
   if ( close[2] > open[2] && close[1] > open[1] && !no_alert ) { 
      Alert(TimeToStr(time[0])+" "+Symbol()+" Покупка! период "+Period1());    
      no_alert = true; 
   }
   if ( close[2] < open[2] && close[1] < open[1] && !no_alert ) { 
      Alert(TimeToStr(time[0])+" "+Symbol()+" Продажа! период "+Period1());    
      no_alert = true; 
   } 
   return(rates_total);  
}
 
string Period1()
{
   switch (Period())
   {
      case PERIOD_M1:  return "M1";  break;
      case PERIOD_M5:  return "M5";  break;
      case PERIOD_M15: return "M15"; break;
      case PERIOD_M30: return "M30"; break;
      case PERIOD_H1:  return "H1";  break;
      case PERIOD_H4:  return "H4";  break;
      case PERIOD_D1:  return "D1";  break;
      case PERIOD_W1:  return "W1";  break;
      case PERIOD_MN1: return "MN";  break;
   }
   return "unknow";
}
+ -
Цитировать Ответить

10.05.2017, в 10:07
Андрей
Регистрация: нет
Сообщений: 4
Рейтинг: 0
#6

Спасибо, скажите пожалуйста, а можно сделать что бы звуком (мне нужным) информировал за 60 секунд до закрытия свечи начиная с 5 минутного тайм фрейма?, или куда и что добавить надо? =)

+ -
Цитировать Ответить

10.05.2017, в 11:21
admin
Регистрация: 17.02.2011
Сообщений: 4483
Рейтинг: 2841
#7

Андрей Сегодня, в 10:07:
информировал за 60 секунд до закрытия свечи

За минуту на рынке может многое измениться. В момент подачи сигнала ситуация может быть одна, а в следующую секунду этого сигнала уже не будет.
Т.е. речи не идет о работе по закрытым свечам? Сигнал определяется по одному направлению у текущей и предыдущей ей свечи? Добавлено сообщение 10.05.2017, в 11:37

Андрей Сегодня, в 10:07:
а можно сделать что бы звуком (мне нужным)

В функции MQL4 Alert() встроен свой специфичный звуковой сигнал, который нельзя изменить программным способом. Есть функция PlaySound(), которая воспроизводит wav файлы, но она не будет работать не перед, не после Alert().
Если вместо функции Alert() для создания информационного окна и информирования использовать функцию MessageBox() в связке с функцией PlaySound(), то такой “союз” не будет работать в индикаторе, т.к. функция MessageBox() не работает в индикаторах, поскольку индикаторы исполняются в интерфейсном потоке и не должны его тормозить. Т.е. придется писать индикатор в форме советника. Добавлено сообщение 10.05.2017, в 11:57Но у такого способа свой главный недостаток: каждый раз (с новым сигналом) будет открываться новое информационное окно, которое надо будет закрывать иначе нет возможности получить новый сигнал пока открыто это информационное окно (тормозится интерфейсный поток). В случае же с функцией Alert все информационные сообщения выводятся в одно окно и оно может быть открыто, т.к. интерфейсный поток не тормозится. Добавлено сообщение 10.05.2017, в 12:01

Андрей Сегодня, в 10:07:
начиная с 5 минутного тайм фрейма

Т.е. перебирать в коде все таймфреймы, проверяя на наличие сигнала… Не проще ли просто открыть несколько нужных графиков. Добавлено сообщение 10.05.2017, в 12:03

admin Сегодня, в 11:21:
придется писать индикатор в форме советника.

//+------------------------------------------------------------------+
//|                               two_candles_informer_as_expert.mq4 |
//|                                                moneyinnetwork.ru |
//|                                         http://moneyinnetwork.ru |
//+------------------------------------------------------------------+
#property copyright "moneyinnetwork.ru"
#property link      "http://moneyinnetwork.ru"
#property version   "3.00"
#property strict
 
bool  no_alert; 
datetime time_old; 
 
int OnInit()
{
   no_alert = false; 
   time_old = 0; 
   return(INIT_SUCCEEDED);
}
 
void OnDeinit(const int reason)
{
}
 
void OnTick()
{
   double close1, open1, close2, open2;
   close1 = iClose(Symbol(),Period(),1);
   close2 = iClose(Symbol(),Period(),2);
   open1 = iOpen(Symbol(),Period(),1);
   open2 = iOpen(Symbol(),Period(),2);
   if ( time_old != iTime(Symbol(),Period(),1) )  { 
      no_alert = false; 
      time_old = iTime(Symbol(),Period(),1); 
   } 
   if ( close2 > open2 && close1 > open1 && !no_alert ) { 
      PlaySound("news.wav");
      MessageBox(TimeToStr(iTime(Symbol(),Period(),0))+" "+Symbol()+" Покупка! период "+Period1(),"Сигнал на покупку - "+Symbol());    
      no_alert = true; 
   }
   if ( close2 < open2 && close1 < open1 && !no_alert ) { 
      PlaySound("news.wav");
      MessageBox(TimeToStr(iTime(Symbol(),Period(),0))+" "+Symbol()+" Продажа! период "+Period1(),"Сигнал на продажу - "+Symbol());    
      no_alert = true; 
   }   
}
 
string Period1()
{
   switch (Period())
   {
      case PERIOD_M1:  return "M1";  break;
      case PERIOD_M5:  return "M5";  break;
      case PERIOD_M15: return "M15"; break;
      case PERIOD_M30: return "M30"; break;
      case PERIOD_H1:  return "H1";  break;
      case PERIOD_H4:  return "H4";  break;
      case PERIOD_D1:  return "D1";  break;
      case PERIOD_W1:  return "W1";  break;
      case PERIOD_MN1: return "MN";  break;
   }
   return "unknow";
}

Добавлено сообщение 10.05.2017, в 12:07

PlaySound("news.wav");

В PlaySound указать свое имя проигрываемого wav файла. Файл положить в директорию: Каталог терминала/Sounds

+ -
Цитировать Ответить

11.05.2017, в 14:34
Андрей
Регистрация: нет
Сообщений: 4
Рейтинг: 0
#8

Спасибо админ, выручил! *DRINK*

+ -
Цитировать Ответить

14.05.2017, в 00:27
Artemii
Регистрация: 13.05.2017
Сообщений: 2
Рейтинг: 0
#9

Здравствуйте, знаю что вас завалили прозьбами но все равно напишу, вдруг *PARDON* ) Возможно ли написать такой индикатор который бы выдавал сигнал по определенному значению размера свечи после закрытия? Ну вот допустим, 5м тйфрейм, мое значение поставленое в индикаторе 30 пунктов, я хотел бы что бы выдался сигнал по закрытию этой свечи на 30 пунктах и более пунктов? И что бы была возможность ставки различной “музыки” в сигнал аллерта. надеюсь мою мысль поняли, заранее спасибо, сайт у вас класный!)

+ -
Цитировать Ответить

14.05.2017, в 12:02
admin
Регистрация: 17.02.2011
Сообщений: 4483
Рейтинг: 2841

Как и в предыдущем случае, реализация индикатора при таких условиях возможна в форме советника.
Код для размера тела свечи (цена открытия минус цена закрытия свечи):

//+------------------------------------------------------------------+
//|                                           body_size_informer.mq4 |
//|                                                moneyinnetwork.ru |
//|                                         http://moneyinnetwork.ru |
//+------------------------------------------------------------------+
#property copyright "moneyinnetwork.ru"
#property link      "http://moneyinnetwork.ru"
#property version   "1.00"
#property strict
#property description "В момент закрытия свечи информирует о превышении тела текущей свечи заданного размера в пунктах."
 
input long Candle_Size=30;//предел размера тела свечи, пунктов
input string Sound="news.wav";//имя файла звукового оповещения;
 
bool no_alert; 
datetime time_old; 
 
int OnInit()
{
   no_alert = false; 
   time_old = 0; 
   return(INIT_SUCCEEDED);
}
 
void OnDeinit(const int reason)
{
}
 
void OnTick()
{
   double close1, open1;
   close1 = iClose(Symbol(),Period(),1);
   open1 = iOpen(Symbol(),Period(),1);
   if ( time_old != iTime(Symbol(),Period(),0) )  { 
      no_alert = false; 
      time_old = iTime(Symbol(),Period(),0); 
   } 
   if ( MathAbs(close1-open1)/Point()>=Candle_Size && !no_alert ) { 
      PlaySound(Sound);
      MessageBox(TimeToStr(iTime(Symbol(),Period(),0))+" "+Symbol()+" Сигнал поступил: на периоде "+Period1()+
      "!\nТело свечи превысило "+IntegerToString(Candle_Size)+" пунктов("+DoubleToStr(MathAbs(close1-open1)/Point(),0)+")"+
      "\nЗакройте это окно, чтобы не пропустить новый сигнал!","Сигнал поступил - "+Symbol());    
      no_alert = true; 
   }   
}
 
string Period1()
{
   switch (Period())
   {
      case PERIOD_M1:  return "M1";  break;
      case PERIOD_M5:  return "M5";  break;
      case PERIOD_M15: return "M15"; break;
      case PERIOD_M30: return "M30"; break;
      case PERIOD_H1:  return "H1";  break;
      case PERIOD_H4:  return "H4";  break;
      case PERIOD_D1:  return "D1";  break;
      case PERIOD_W1:  return "W1";  break;
      case PERIOD_MN1: return "MN";  break;
   }
   return "unknow";
}

Код для размера свечи (максимальная цена свечи минус минимальная цена свечи):

//+------------------------------------------------------------------+
//|                                         candle_size_informer.mq4 |
//|                                                moneyinnetwork.ru |
//|                                         http://moneyinnetwork.ru |
//+------------------------------------------------------------------+
#property copyright "moneyinnetwork.ru"
#property link      "http://moneyinnetwork.ru"
#property version   "1.00"
#property strict
#property description "В момент закрытия свечи информирует о превышении размера текущей свечи заданного размера в пунктах."
 
input long Candle_Size=30;//предел размера свечи, пунктов
input string Sound="news.wav";//имя файла звукового оповещения;
 
bool no_alert; 
datetime time_old;
 
int OnInit()
{
   no_alert = false; 
   time_old = 0; 
   return(INIT_SUCCEEDED);
}
 
void OnDeinit(const int reason)
{
}
 
void OnTick()
{
   double high1, low1;
   high1 = iHigh(Symbol(),Period(),1);
   low1 = iLow(Symbol(),Period(),1);
   if ( time_old != iTime(Symbol(),Period(),0) )  { 
      no_alert = false; 
      time_old = iTime(Symbol(),Period(),0); 
   } 
   if ( MathAbs(high1-low1)/Point()>=Candle_Size && !no_alert ) { 
      PlaySound(Sound);
      MessageBox(TimeToStr(iTime(Symbol(),Period(),0))+" "+Symbol()+" Сигнал поступил: на периоде "+Period1()+
      "!\nРазмер свечи превысил "+IntegerToString(Candle_Size)+" пунктов("+DoubleToStr(MathAbs(high1-low1)/Point(),0)+")"+
      "\nЗакройте это окно, чтобы не пропустить новый сигнал!","Сигнал поступил - "+Symbol());    
      no_alert = true; 
   }   
}
 
string Period1()
{
   switch (Period())
   {
      case PERIOD_M1:  return "M1";  break;
      case PERIOD_M5:  return "M5";  break;
      case PERIOD_M15: return "M15"; break;
      case PERIOD_M30: return "M30"; break;
      case PERIOD_H1:  return "H1";  break;
      case PERIOD_H4:  return "H4";  break;
      case PERIOD_D1:  return "D1";  break;
      case PERIOD_W1:  return "W1";  break;
      case PERIOD_MN1: return "MN";  break;
   }
   return "unknow";
}

Работу не проверял.
Два параметра, которые указывают:
1. Размер тела свечи (либо размер свечи по “хвостам”, как во втором случае), в пунктах, исходя из точности котирования. Учитывайте, например, что на пяти знаках 300 пунктов соответствуют 30 пунктам на четырех знаках.
2. Имя wav файла, проигрываемого при получении сигнала. Файл с заданным именем необходимо положить в директорию: Каталог терминала/Sounds

+ -
Цитировать Ответить

14.05.2017, в 15:45
Artemii
Регистрация: 13.05.2017
Сообщений: 2
Рейтинг: 0

Большое спасибо за такую быструю работу, честно даже не ожидал) В понедельник будим тэстить) *OK*

+ -
Цитировать Ответить

15.05.2017, в 08:57
admin
Регистрация: 17.02.2011
Сообщений: 4483
Рейтинг: 2841

Artemii Вчера, в 15:45:
В понедельник будим тэстить)

Работает вроде.
информер размера свечи

+ -
Цитировать Ответить

15.05.2017, в 23:21
Сергей
Регистрация: нет
Сообщений: 4
Рейтинг: 0

Добрый день, уважаемый Влад. Помогите сделать индикатор.
candle_volime_1_tic_mmgp.mq4 |
Суть – цифровой индикатор, значение volime: (open – close)
Цвет – жёлтый
Размер шрифта 10
Размещение – в таблице слева в верхнем углу, последние 15 значений или непосредственно под свечой.
Замечание – если значение (open – close) = 0, то пусть будет 0 или поставить по умолчанию 0=1
Заранее спасибо. Добавлено сообщение 15.05.2017, в 23:34

Сергей Сегодня, в 23:21:
Добрый день, уважаемый Влад. Помогите сделать индикатор.
candle_volime_1_tic_mmgp.mq4 |

Суть – цифровой индикатор, значение volime: (open – close)
Цвет – жёлтый
Размер шрифта 10
Размещение – в таблице слева в верхнем углу, последние 15 значений или непосредственно под свечой.
Замечание – если значение (open – close) = 0, то пусть будет 0 или поставить по умолчанию 0=1
Заранее спасибо.

P.S. Полученные значения по формуле сократить до одной десятой, т.е. после запятой 1 число.

+ -
Цитировать Ответить

16.05.2017, в 11:08
Сергей
Регистрация: нет
Сообщений: 4
Рейтинг: 0

Добрый день. Помогите с индикатором. Очень нужен.
Название – candle_volime 1 pips.mq4 |
Sergey Kyznetcov aka sergionnik
Суть индикатора – цифровой, расчёт по формуле volime : (open – close)
если значение open – close = 0, по умолчанию 0=1, если это невозможно, то пусть будет 0
Цвет – жёлтый
После запятой в цифрах два знака
Размещение – под свечой вертикально или в таблице слева в верхнем углу 30 значений.
Если без общего доступа, то будет оплата работы.

+ -
Цитировать Ответить

16.05.2017, в 16:27
admin
Регистрация: 17.02.2011
Сообщений: 4483
Рейтинг: 2841

Сергей, а вот в простейшем случае Вам бы подошел самый первый индикатор из этой темы. Просто в нем надо заменить расчет размера свечи (high-low) на расчет размера тела свечи (close-open) и ввести т.н. условие 0=1, когда close=open.
А если немного усложнить, введя автоматическое вычислением масштаба для привязки текста к нижним теням свечей, то вот так, например, можно:

//+------------------------------------------------------------------+
//|                                       candle_size_for_Sergey.mq4 |
//|                                                moneyinnetwork.ru |
//|                                         http://moneyinnetwork.ru |
//+------------------------------------------------------------------+
#property copyright "moneyinnetwork.ru"
#property link      "http://moneyinnetwork.ru"
#property version   "1.00"
#property strict
#property indicator_chart_window
 
input int      TextSize = 8; //размер шрифта 
input color    TextColor = clrYellow; //цвет текста 
input int      TextAngle = 90; //угол поворота текста 
input int      MaxBar = 30;  //количество баров, начиная с текущего, для которых вычисляется размер свечей 
input int      Exp = 1;      //точность - количество знаков после запятой 
int OnInit() 
{ 
   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 i; 
   double candle_len;
   long chart_ID = ChartID(), height_in_pixels;
   double max_price, min_price;
   ChartGetDouble(chart_ID,CHART_PRICE_MAX,0,max_price);
   ChartGetDouble(chart_ID,CHART_PRICE_MIN,0,min_price);
   double height_in_price = max_price-min_price;
   ChartGetInteger(chart_ID,CHART_HEIGHT_IN_PIXELS,0,height_in_pixels);
   double mast = height_in_price/(double)height_in_pixels;//масштаб
   for ( i = 0; i < MaxBar; i++ )   { 
      candle_len = MathAbs(close[i]-open[i]);
      if ( NormalizeDouble(close[i],Digits)==NormalizeDouble(open[i],Digits) )
         candle_len = Point();
      if ( ObjectFind ("candlesize"+ IntegerToString(i)) >= 0 )   { 
             ObjectDelete("candlesize"+ IntegerToString(i)); 
      } 
      ObjectCreate ("candlesize"+ IntegerToString(i),  
                    OBJ_TEXT,  
                    0,  
                    time[i],  
                    low[i]-(double)(TextSize-1)*mast*(double)StringLen(DoubleToStr(candle_len/Point(), Exp))); 
      ObjectSet (  "candlesize"+IntegerToString(i),  
                    OBJPROP_ANGLE,  
                    TextAngle 
                 ); 
      ObjectSetText ( "candlesize"+IntegerToString(i),  
                      DoubleToStr(candle_len/Point(), Exp),  
                      TextSize,  
                      NULL,  
                      TextColor 
                     ); 
   } 
   return(rates_total); 
}

Параметры можно указывать:

TextSize = 8; //размер шрифта 
TextColor = clrYellow; //цвет текста 
TextAngle = 90; //угол поворота текста 
MaxBar = 30;  //количество баров, начиная с текущего, для которых вычисляется размер свечей 
Exp = 1;      //точность - количество знаков после запятой

Индикатор размера последних 30 тел свечей с вертикальными подписями на свечном графике
Добавлено сообщение 16.05.2017, в 16:30Правда, надписи под свечками иногда не все будут видны. Придется время от времени изменять масштаб графика, удерживая нажатой левую кнопку мышки и перемещая мышь в поле цен (всплывает надпись “Вертикальный масштаб”).

+ -
Цитировать Ответить

16.05.2017, в 22:34
Сергей
Регистрация: нет
Сообщений: 4
Рейтинг: 0

В чистом виде, не считая шапки, получилось следующее, но индикатор не открывается в терминале. Где ошибка?

input int      TextSize = 8; 
input color    TextColor = clrYellow;  
input int      TextAngle = 90;  
input int      MaxBar = 50;
input int      Exp = 1;      
int OnInit() 
{ 
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 i; 
double candle_len;
long chart_ID = ChartID(), height_in_pixels;
double max_price, min_price;
ChartGetDouble(chart_ID,CHART_PRICE_MAX,0,max_price);
ChartGetDouble(chart_ID,CHART_PRICE_MIN,0,min_price);
double height_in_price = max_price-min_price;
ChartGetInteger(chart_ID,CHART_HEIGHT_IN_PIXELS,0,height_in_pixels);
double mast = height_in_price/(double)height_in_pixels;//масштаб
for ( i = 0; i = 0 ) 
{ 
ObjectDelete("candlesize"+ IntegerToString(i)); 
}
ObjectCreate ("candlesize"+ IntegerToString(i),  
OBJ_TEXT,  
0,  
time[i],  
low[i]-(double)(TextSize-1)*mast*(double)StringLen(DoubleToStr(candle_len/Point(), Exp))); 
ObjectSet (  "candlesize"+IntegerToString(i),  
OBJPROP_ANGLE,  
TextAngle 
); 
ObjectSetText ( "candlesize"+IntegerToString(i),  
DoubleToStr(candle_len/Point(), Exp
TextSize,  
NULL,  
TextColor 
); 
} 
return(rates_total); 
}
+ -
Цитировать Ответить

16.05.2017, в 22:51
admin
Регистрация: 17.02.2011
Сообщений: 4483
Рейтинг: 2841

Сергей, я Вам код рабочий дал.
Скачать candle_size_for_Sergey.mq4

+ -
Цитировать Ответить

16.05.2017, в 23:29
Сергей
Регистрация: нет
Сообщений: 4
Рейтинг: 0

admin Сегодня, в 22:51:
17.02.2011
Сообщений: 4479
Рейтинг: 2821
#17
Сергей, я Вам код рабочий дал.
Скачать candle_size_for_Sergey.mq4

Спасибо, оно конечно, но это немного, а точней совсем не то, что подразумевалось. Нет деления на значение volime…..

+ -
Цитировать Ответить

16.05.2017, в 23:48
admin
Регистрация: 17.02.2011
Сообщений: 4483
Рейтинг: 2841

Сергей Сегодня, в 23:29:
Нет деления на значение volime…..

Тогда уж не нет деления на volime, а нет деления volume (объем) на close-open, может быть. Volume выступает в роли делимого =)
И, наверное, close-open надо бы будет поделить на Point(), т.е. close-open перевести в пункты.
В любом случае скелет есть, а свои выражения в него легко подставить.

//+------------------------------------------------------------------+
//|                                    volume_to_body_for_Sergey.mq4 |
//|                                                moneyinnetwork.ru |
//|                                         http://moneyinnetwork.ru |
//+------------------------------------------------------------------+
#property copyright "moneyinnetwork.ru"
#property link      "http://moneyinnetwork.ru"
#property version   "1.00"
#property strict
#property indicator_chart_window
 
input int      TextSize = 8; //размер шрифта 
input color    TextColor = clrYellow; //цвет текста 
input int      TextAngle = 90; //угол поворота текста 
input int      MaxBar = 30;  //количество баров, начиная с текущего, для которых вычисляется размер свечей 
input int      Exp = 1;      //точность - количество знаков после запятой 
int OnInit() 
{ 
   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 i; 
   double candle_len;
   long chart_ID = ChartID(), height_in_pixels;
   double max_price, min_price;
   ChartGetDouble(chart_ID,CHART_PRICE_MAX,0,max_price);
   ChartGetDouble(chart_ID,CHART_PRICE_MIN,0,min_price);
   double height_in_price = max_price-min_price;
   ChartGetInteger(chart_ID,CHART_HEIGHT_IN_PIXELS,0,height_in_pixels);
   double mast = height_in_price/(double)height_in_pixels;//масштаб
   for ( i = 0; i < MaxBar; i++ )   { 
      candle_len = MathAbs(close[i]-open[i]);
      if ( NormalizeDouble(close[i],Digits)==NormalizeDouble(open[i],Digits) )
         candle_len = Point();
      if ( ObjectFind ("candlesize"+ IntegerToString(i)) >= 0 )   { 
             ObjectDelete("candlesize"+ IntegerToString(i)); 
      } 
      ObjectCreate ("candlesize"+ IntegerToString(i),  
                    OBJ_TEXT,  
                    0,  
                    time[i],  
                    low[i]-(double)(TextSize-1)*mast*(double)StringLen(DoubleToStr(volume[i]/candle_len/Point(), Exp))); 
      ObjectSet (  "candlesize"+IntegerToString(i),  
                    OBJPROP_ANGLE,  
                    TextAngle 
                 ); 
      ObjectSetText ( "candlesize"+IntegerToString(i),  
                      DoubleToStr(volume[i]/candle_len/Point(), Exp),  
                      TextSize,  
                      NULL,  
                      TextColor 
                     ); 
   } 
   return(rates_total); 
}
+ -
Цитировать Ответить

Подписаться без комментирования



amarkets