a trading strategy based on Elliott Wave Theory - page 140

 
Если мы тестируем систему на достаточно длинной истории возникает проблема нормировки (например, кажется очевидным, что 100 пунктов при курсе 0.8 вовсе не эквивалентны 100 пунктам при курсе 1.36).

I think this is a very valuable point!!! Maybe it makes sense to normalize the price spread, for example by the average price for the last month or two and then calculate the normalized value of the spread for a series of bars. I will try to improve the indicator in the nearest future according to this principle.

I have finalized the indicator according to this proposal. I will post it now. If you used an indicator of a previous version, you should perform the forced recalculation of values when you run the new version (force_recalculation=true) not to wait for the next day.
Below are screenshots for the new version of the indicator for comparison with the first version.
//+------------------------------------------------------------------+
//|                                     AMPLITUDE_STAT_LEVELS_v2.mq4 |
//|                                        Copyright © 2006, Solandr |
//|                                                solandr99@mail.ru |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2006, Solandr"
#property link      "solandr99@mail.ru"
#property indicator_chart_window

//В версии 2 происходит относительный расчёт размахов в соответствии со средней ценой за 25 баров.
//В принципе при достаточном количестве баров истории это эквивалентно отношению среднеарифметического значения размаха
//к среднему значению цены на истории, умноженное затем на текущее среднее значение цены (например по последним 25 барам).
//Но решено оставить всё-таки более сложный алгоритм расчёта (нормировка значений амплитуд), поскольку он наверное будет вполне 
//уместен и в случаях когда баров истории совсем немного. 
// ============================================================================================
//"Купи подешевле, продай подороже" - основа, на которой базируется спекуляция на финансовых рынках. 
//Данный индикатор предлагает своё видение этих уровней "подешевле" и "подороже". Он основан на простом 
//статистическом расчёте размахов (амплитуд High-Low) баров по имеющейся истории котировок.
//Расчёт амплитуд происходит по сериям от 1 до 10 баров. То есть в выбранной серии на истории находитcя разница между 
//максимальным и минимальным значением цены. Далее окно серии смещается на 1 бар и получаем следующий размах амплитуды 
//баров для выбранной серии баров. После усреднения значения полученных размахов мы имеем среднее арифметическое диапазона 
//колебания цены для выбранной серии баров. 
//
//Полученное таким образом значение амплитуды откладывается на графике по следующему принципу. К минимуму текущей серии 
//баров прибавляется значение среднеарифметического размаха, посчитанного на истории. Так мы получаем возможный 
//среднестатистический максимум цены для текущей серии баров. То же самое делаем для нахождения среднестатистического 
//минимума для текущей серии баров. То есть от максимума текущей серии баров отнимаем среднеарифметический размах, 
//посчитанный для данной серии баров по историческим данным. Индикатор производит описанные выше действия для серий 
//от 1 до 10 баров. На уровнях присутствуют надписи, поясняющие для какого текущего временного промежутка построен данный 
//уровень. С параметром TF_needed="AUTO" уровни строятся для серий баров текущего таймфрейма. Если требуется зафиксировать
// уровни какого-то таймфрейма на остальных периодах, то необходимо установить это значение в MN, W1, D1, H4, H1, M30, 
//M15, M5, или в M1. Например для значения TF_needed="D1" на всех периодах будут отображаться уровни для временных 
//промежутков от 1 до 10 дней, обозначаемых соответственно как D1,...,D10.
//
//При настройках по умолчанию индикатор производит перерасчёт среднестатистических амплитуд по истории один раз в день 
//с их внесением в глобальные переменные терминала. Если по какой-то причине (например импортирование дополнительных 
//котировок) требуется произвести перерасчёт среднеарифметических значений амплитуд для серий баров не дожидаясь 
//следующего дня, то необходимо установить force_recalculation=true и будет произведён перерасчёт 
//среднеарифметических значений размахов для серий баров при следующей инициализации индикатора.
//
//Данный индикатор может быть полезен при принятии решений о входе в позицию. Может поспособствовать сохранению депозита
//особенно начинающих трейдеров. Продавайте на красных уровнях и покупайте на зелёных и за Вас будет играть математика! ;o))) 
//Если Вы например купили на зелёных уровнях и курс пошёл резко против Вас, то убыточную позицию есть смысл удерживать лишь 
//до тех пор пока красные уровни не окажутся ниже Вашей открытой позиции. И когда цена окажется на этих красных уровнях - 
//закройте убыточную позицию с минимальным убытком, а во многих случаях и с маленьким плюсом. Желаю успехов!:o)
// ============================================================================================
extern string TF_needed="AUTO";
extern bool force_recalculation=false;//принудительный перерасчёт

double average_price;
bool recalculation_needed=false;
bool aver_pr_recalc_needed=true;
int last_aver_pr_recalc_bars;
double delta[11];
string work_symbol;
int TF;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
   int i,k,all_bars,counter_counted_bars;
   string b_str,global_name;
   double average_price_array[10];
 
   work_symbol=Symbol();
   
   //Выбор требуемого тайфрейма для расчёта;
   if(TF_needed=="AUTO" || (TF_needed!="MN" && TF_needed!="W1" && TF_needed!="D1" && TF_needed!="H4" && TF_needed!="H1" && TF_needed!="M30" && TF_needed!="M15" && TF_needed!="M5" && TF_needed!="M1")) TF=Period();
   if(TF_needed=="MN") TF=43200;
   if(TF_needed=="W1") TF=10080;
   if(TF_needed=="D1") TF=1440;
   if(TF_needed=="H4") TF=240;
   if(TF_needed=="H1") TF=60;  
   if(TF_needed=="M30") TF=30;  
   if(TF_needed=="M15") TF=15;  
   if(TF_needed=="M5") TF=5;  
   if(TF_needed=="M1") TF=1;  
      
   //Проверяем наличие посчитанных данных амплитуд для данного TF, а также производим проверку дня, в который был произведен расчёт этих данных
   global_name=work_symbol+"_"+TF+"_counted_day";
   if(GlobalVariableCheck(global_name) && !force_recalculation) 
   {  
      if(MathAbs(GlobalVariableGet(global_name)-DayOfYear())>0) recalculation_needed=true;
   }
   else recalculation_needed=true;
         
   if(recalculation_needed)
   {//Производим расчёт средней амплитуды бара (серии баров) по таймфрейму TF на символе work_symbol
      all_bars=iBars(work_symbol,TF);
      ArrayResize(average_price_array,all_bars);
   
      //Рассчитываем массив средних цен для каждого расчётного момента времени на основе 25 баров
      for(k=all_bars-1;k>=0;k--) 
      {      
            average_price_array[k]=0;
            counter_counted_bars=0;
            for(i=k;i<=k+24;i++)//вычисляем среднюю цену на 25 барах
            {
               if(i<all_bars) 
               {
                  average_price_array[k]=average_price_array[k]+(iOpen(work_symbol,TF,i)+iHigh(work_symbol,TF,i)+iLow(work_symbol,TF,i)+iClose(work_symbol,TF,i))/4;
                  counter_counted_bars++;
               }
            }
            if(counter_counted_bars>0) average_price_array[k]=average_price_array[k]/counter_counted_bars;
      }
   
      for(i=1;i<=10;i++) delta[i]=0;
   
      for(i=1;i<=10;i++)
      {      
         for(k=all_bars-i;k>=0;k--) 
         {  
            if(average_price_array[k]>0) delta[i]=delta[i]+(iHigh(work_symbol,TF,Highest(Symbol(),TF,MODE_HIGH,i,k))-iLow(work_symbol,TF,Lowest(Symbol(),TF,MODE_LOW,i,k)))/average_price_array[k];
            else Print("average_price_array[",k,"]<=0 при i=",i," и k=",k);
         }
         delta[i]=NormalizeDouble(delta[i]/(all_bars-i+1),Digits);   
         global_name=work_symbol+"_"+TF+"_"+i;
         GlobalVariableSet(global_name,delta[i]); 
         //Print("delta",i,"=",delta[i]);
      } 
      global_name=work_symbol+"_"+TF+"_counted_day";
      GlobalVariableSet(global_name,DayOfYear()); 
      recalculation_needed=false;
   }//if(recalculation_needed)
   else
   {//Если данные имеются в глобальных переменных терминала, то берём имеющиеся расчётные данные амплитуд из глобальных переменных терминала
      for(i=1;i<=10;i++)
      {
         global_name=work_symbol+"_"+TF+"_"+i;
         delta[i]=GlobalVariableGet(global_name);
         //Print("Глобал ",i," ",delta[i]);
      }
   }
}   
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
{
//----
   int i;
   string b_str;
   for(i=1;i<=10;i++)
   {
      b_str="up_line"+i;
      ObjectDelete(b_str);
      b_str="down_line"+i;
      ObjectDelete(b_str);
      b_str="up_line_txt"+i;
      ObjectDelete(b_str);      
      b_str="down_line_txt"+i;
      ObjectDelete(b_str);       
   }
}   

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
   int i;
   string line_name;
  
   /*
   for(i=iBars(work_symbol,TF)-1;i>=0;i--) average_price=average_price+(iOpen(work_symbol,TF,i)+iHigh(work_symbol,TF,i)+iLow(work_symbol,TF,i)+iClose(work_symbol,TF,i))/4;
   average_price=average_price/iBars(work_symbol,TF);
   Print("Средняя цена по всей выборке=",NormalizeDouble(average_price,Digits));
   average_price=0;
   */
   
   if(iBars(work_symbol,TF)!=last_aver_pr_recalc_bars) aver_pr_recalc_needed=true;
   
   if(aver_pr_recalc_needed)
   {  
      average_price=0;
      for(i=0;i<=24;i++) average_price=average_price+(iOpen(work_symbol,TF,i)+iHigh(work_symbol,TF,i)+iLow(work_symbol,TF,i)+iClose(work_symbol,TF,i))/4;
      average_price=average_price/25;
      aver_pr_recalc_needed=false;
      last_aver_pr_recalc_bars=iBars(work_symbol,TF);
   }
   //Print("average_price=",NormalizeDouble(average_price,Digits));
   
   for(i=1;i<=10;i++)
   {  
      if(TF==43200) line_name="MN"+i;   
      if(TF==10080) line_name="W"+i;
      if(TF==1440) line_name="D"+i;
      if(TF==240) line_name="H"+4*i;
      if(TF==60) line_name="H"+i;
      if(TF==30) line_name="M"+30*i;
      if(TF==15) line_name="M"+15*i;
      if(TF==5) line_name="M"+5*i;
      if(TF==1) line_name="M"+i;
            
      up_line(i,iLow(NULL,TF,Lowest(work_symbol,TF,MODE_LOW,i,0))+delta[i]*average_price,line_name);
      down_line(i,iHigh(NULL,TF,Highest(work_symbol,TF,MODE_HIGH,i,0))-delta[i]*average_price,line_name);
   }

   return(0);
  }
//+------------------------------------------------------------------+
int up_line(int q_days, double level, string ln)
{
   string b_str="up_line"+q_days;

   if(ObjectFind(b_str) == -1) 
   {
     ObjectCreate(b_str, OBJ_TREND, 0, Time[1], level, Time[1]+2700000,level);
     ObjectSet(b_str, OBJPROP_STYLE, STYLE_DOT);
     ObjectSet(b_str, OBJPROP_COLOR, Brown);
     ObjectSet(b_str, OBJPROP_RAY, true);
     ObjectSet(b_str, OBJPROP_WIDTH, 1);
     ObjectMove(b_str, 0, Time[1],  level);
   }
   else 
   {
      if(MathAbs(level-ObjectGet(b_str, OBJPROP_PRICE1))>0.9*Point) ObjectDelete(b_str);
   }
   
   b_str="up_line_txt"+q_days;
   string b_txt=ln;
   datetime t_bar;
   if(ObjectFind(b_str) == -1) 
   {
     ObjectCreate(b_str, OBJ_TEXT, 0, Time[0], 0);
     ObjectSetText(b_str, b_txt, 8, "Arial", Brown);
     ObjectMove(b_str, 0, Time[0]+2*q_days*Period()*60,  level);
   }
   else 
   {
     ObjectMove(b_str, 0, Time[0]+2*q_days*Period()*60,  level);
   }      
   
   return(0);
}

int down_line(int q_days, double level, string ln)
{
   string b_str="down_line"+q_days;
   
   if(ObjectFind(b_str) == -1) 
   {
     ObjectCreate(b_str, OBJ_TREND, 0, Time[1], level, Time[1]+2700000,level);
     ObjectSet(b_str, OBJPROP_STYLE, STYLE_DOT);
     ObjectSet(b_str, OBJPROP_COLOR, DarkGreen);
     ObjectSet(b_str, OBJPROP_RAY, true);
     ObjectSet(b_str, OBJPROP_WIDTH, 1);
     ObjectMove(b_str, 0, Time[1],  level);
   }
   else 
   {
      if(MathAbs(level-ObjectGet(b_str, OBJPROP_PRICE1))>0.9*Point) ObjectDelete(b_str);
   }
   
   b_str="down_line_txt"+q_days;
   string b_txt=ln;
   if(ObjectFind(b_str) == -1) 
   {
     ObjectCreate(b_str, OBJ_TEXT, 0, Time[0], 0);
     ObjectSetText(b_str, b_txt, 8, "Arial", DarkGreen);
     ObjectMove(b_str, 0, Time[0]+2*q_days*Period()*60,  level);
   }
   else 
   {
     ObjectMove(b_str, 0, Time[0]+2*q_days*Period()*60,  level);
   }      
   
   return(0);
}







 
Maybe I am not explaining correctly. What I say is that using algorithms for graph matching (combinatorial graphs) can be used for pattern recognition. Go to:
http://citeseer.ist.psu.edu/ and search for:
Graph pattern recognition algorithm
 
Let's point it this way (I am not sure it's the scientific way) but...
Elliott Wave Theory is about patterns in price. The price is representing as chart (price in time)-graph.
Elliott Wave Theory identifies patterns-Impulse, ZigZag, Flats... that are within price. How-
Fibonacci retracement. Then found waves are plotted in probability order, but this is very difficult to make (to make a decision witch movement is next or 100% "SURE". So what I suggest is better to solve that problem if consider chart as graph and found patterns according to graph theory. Maybe (?) it will be more accurate and decision will be strictly mathematical?!
 
Maybe (?) it will be more accurate and the decision will be strictly mathematical?!

By the way, a friend of mine from Ireland (she's lived there for five years now) says that native speakers don't say may be, but probably. Is it sure?
 
Candid,I have asked some mathematicians that work in the field of combinatorics and graphs to explain is it possible to use combinatorial graphs to find patterns in data. Here is the answer of Janet M.Six:
"Hi Dave,

I'm sure that combinatorial graphs can be used to find patterns
within market charts. I would also guess that work on this topic has
been done.


Janet Six "
 
2 Dave Mason
What do you call the term combinatorial graphs ? If what Candid wrote
Combinatorial graphs can sometimes be represented pictorially as networks of dots (called vertices) connected by lines (called edges)

you can hardly use this for pattern recognition. A network of vertices can be connected by all sorts of lines, which will form closed loops among other things. Whereas a price chart is a simple single line because there is only one price value for each moment of time. In terms of graph theory (combinatorial graphs), such a line is the most primitive object. I don't think anything can be done about it.

Besides, a graph (combinatorial graphs) has a constant spatial structure. A price chart constantly changes in time.

But this is all IMHO. If this question is relevant to you, you'd better ask specialists in the field of combinatorics and graphs. Janet Six, for example. If she is sure that "that combinatorial graphs can be used to find patterns within market charts" and that "that work on this topic has been done", let her give the link.
 
Dave Mason, no offence, but the situation is somewhat reminiscent of an old sci-fi story: there a group of researchers were convinced that the problem of antigravity had already been solved, and then they did solve it :).
I must say that my ideas about graph theory are rather superficial, and they consist in that this science is interested mainly in the topology of sought objects. The topology of the pattern itself is too simple, i.e. most likely not interesting for graph theory. In principle, we can imagine that we have formalized (encoded) standard patterns and try to look for them on a graph. Specific parts of the graph can be identified with more than one pattern. Further, the patterns themselves, if they are some kind of primitives, can be related to each other. In this way we get an object, perhaps similar to what graph theory does. It's a lot of work, and it's not clear whether such an approach will yield anything
 
Yurixx
What do you call combinatorial graphs ? If what Candid wrote
Combinatorial graphs can sometimes be represented pictorially as networks of dots (called vertices) connected by lines (called edges)

I didn't write that, there's a link :))
Basically yes, it is easy to establish that there is a Janet M. Six and she does deal with graphs. Nevertheless, simple statements are not enough. It would be good to get at least brief considerations that became the basis for the conclusions. Or indeed, a specific reference, if not to a solution, then to a potential "key" to enter the problem.
 
I think you really do not know what Elliott Wave Theory is about!
It is about FRACTALS.
Fractals are part of combinatorial graphs. So you better be more prepared when you speak.
If you want to "scalp" read something before.

http://www.math.utah.edu/vigre/reu/reports/harris_fall2005.pdf#search=%22%20Ralph%20Nelson%20Elliott%20elliott%20wave%20theory%20%22
 
I didn't write that, there's a link :))

No way! Too late to deny it now! :))