bleh
[mqlkit.git] / indicators / jmarket_sentiment.mq4
blob74f1d0c79e2aab634fa6e55462639fdf040d88c4
1 //+------------------------------------------------------------------+\r
2 //|                                            jmarket_sentiment.mq4 |\r
3 //|                                    Copyright  2011, Zarko Asenov |\r
4 //|                                              http://jaltoh.6x.to |\r
5 //+------------------------------------------------------------------+\r
6 #property copyright "Copyright  2011, Zarko Asenov"\r
7 #property link      "http://jaltoh.6x.to"\r
8 \r
9 #property indicator_separate_window\r
10 #property indicator_buffers 5\r
11 #property indicator_color1 Red\r
12 #property indicator_color2 OrangeRed\r
13 #property indicator_color3 Gold\r
14 #property indicator_color4 SteelBlue\r
15 #property indicator_color5 Lime\r
16 #property indicator_width1 1\r
17 #property indicator_width2 1\r
18 #property indicator_width3 1\r
19 #property indicator_width4 2\r
20 #property indicator_width5 1\r
21 #property indicator_level1 1.0\r
22 #property indicator_level2 -1.0\r
24 #define DEBUG 0\r
27 #define WEIGHT_MOVE 0\r
28 #define ABS_MOVE    1\r
29 #define ABS_PUSH    2\r
30 #define TRENDLINE_NAME "jnextbar_predict"\r
31 #define INVALID_VOLUME 50\r
33 #define NEUTRAL 0\r
34 #define BULLISH 1\r
35 #define BEARISH 2\r
38 extern int MA_Period = 16;\r
39 extern int MA2_Period = 8;\r
40 extern int Time_Frame_Mins = 0;\r
41 extern int Retracement_Look_Back = 12;\r
42 extern double Time_Factor = 0.2;\r
43 extern double Volume_Factor = 0.5;\r
44 extern int Mode_Function = 0;\r
45 extern string _Mode_0 = "Bar to bar weighted hi-lo difference aggregate to volume ratio"; // nakaj stiska\r
46 extern string _Mode_1 = "Bar to bar any tick max difference"; // grid\r
47 extern string _Mode_2 = "Bar to bar tick max difference"; // pletkanje\r
48 extern int Sentiment_Expectation = NEUTRAL;\r
49 extern string _Expectation_0 = "Neutral sentiment";\r
50 extern string _Expectation_1 = "Bullish sentiment";\r
51 extern string _Expectation_2 = "Bearish sentiment";\r
53 //--- buffers\r
54 double ExtMapBuffer1[];\r
55 double ExtMapBuffer2[];\r
56 double ExtMapBuffer3[];\r
57 double ExtMapBuffer4[];\r
58 double ExtMapBuffer5[];\r
59 double ExtMapBuffer6[];\r
63 int time_frame;\r
64 double index_factor = 1.0;\r
65 int hTrendLine = -1;\r
66 int ind_window_handle;\r
67 double prev_best_step;\r
68 datetime prev_calc_time;\r
70 void\r
71 create_trendline()\r
72 {\r
73      ind_window_handle = WindowFind("jmarket_sentiment");\r
74    \r
75      if (hTrendLine == -1 && ind_window_handle > -1) {\r
76      \r
77           hTrendLine = ObjectCreate(\r
78                TRENDLINE_NAME, \r
79                OBJ_TREND, \r
80                ind_window_handle, \r
81                iTime(NULL, time_frame, 0), \r
82                0.0, \r
83                iTime(NULL, time_frame, 0) + Period() * 60, \r
84                0.0);\r
85                \r
86           ObjectSet(TRENDLINE_NAME, OBJPROP_COLOR, indicator_color2);\r
87           ObjectSet(TRENDLINE_NAME, OBJPROP_STYLE, STYLE_SOLID);\r
88           ObjectSet(TRENDLINE_NAME, OBJPROP_WIDTH, indicator_width2);\r
89      }\r
90 }\r
92 void\r
93 remove_trendline()\r
94 {\r
95      ObjectDelete(TRENDLINE_NAME);\r
96 }\r
98 //+------------------------------------------------------------------+\r
99 //| Custom indicator initialization function                         |\r
100 //+------------------------------------------------------------------+\r
101 int init()\r
102   {\r
103    IndicatorBuffers(6);\r
104   \r
105 //---- indicators\r
106    SetIndexStyle(0,DRAW_HISTOGRAM);\r
107    SetIndexBuffer(0,ExtMapBuffer1);\r
108    SetIndexLabel(0,"Movement");\r
109    SetIndexEmptyValue(0, EMPTY_VALUE);\r
110    \r
111    SetIndexStyle(1,DRAW_LINE);\r
112    SetIndexBuffer(1,ExtMapBuffer2);\r
113    SetIndexLabel(1,"Movement Sum");\r
114    SetIndexEmptyValue(1, EMPTY_VALUE);\r
115    \r
116    SetIndexStyle(2,DRAW_LINE);\r
117    SetIndexBuffer(2,ExtMapBuffer3);\r
118    SetIndexLabel(2,"Smoothed "+MA_Period);\r
119    SetIndexEmptyValue(2, EMPTY_VALUE);\r
120    \r
121    SetIndexStyle(3,DRAW_LINE);\r
122    SetIndexBuffer(3,ExtMapBuffer4);\r
123    SetIndexLabel(3,"Trend step");\r
124    SetIndexEmptyValue(3, EMPTY_VALUE);\r
126    SetIndexStyle(4,DRAW_LINE);\r
127    SetIndexBuffer(4,ExtMapBuffer5);\r
128    SetIndexLabel(4,"Smoothed "+MA2_Period);\r
129    SetIndexEmptyValue(4, EMPTY_VALUE);\r
130    \r
131    SetIndexStyle(5,DRAW_LINE);\r
132    SetIndexBuffer(5,ExtMapBuffer6);\r
133    SetIndexLabel(5,"Absolute movement");\r
134    SetIndexEmptyValue(5, EMPTY_VALUE);\r
135    \r
136    if (Time_Frame_Mins == 0)\r
137      time_frame = Period();\r
138    else\r
139      time_frame = Time_Frame_Mins;\r
141    if (time_frame < 1) time_frame = 1;\r
143    index_factor = Period();\r
144    index_factor = index_factor / time_frame;\r
145    \r
146    prev_calc_time = 0;\r
147    prev_best_step = 0;\r
148    \r
149    if (Mode_Function != WEIGHT_MOVE) {\r
150      remove_trendline();\r
151      SetIndexStyle(2, DRAW_LINE, STYLE_SOLID, indicator_width3, indicator_color3);\r
152      SetIndexStyle(4, DRAW_LINE, STYLE_SOLID, indicator_width5, indicator_color5);\r
153    } else {\r
154      create_trendline();   \r
155      SetIndexStyle(2, DRAW_LINE, STYLE_DOT, indicator_width3, CLR_NONE);\r
156      SetIndexStyle(4, DRAW_LINE, STYLE_DOT, indicator_width5, indicator_color5);\r
157    }\r
158 //----\r
159    return(0);\r
160   }\r
161 //+------------------------------------------------------------------+\r
162 //| Custom indicator deinitialization function                       |\r
163 //+------------------------------------------------------------------+\r
164 int deinit()\r
165   {\r
166 //----\r
167    remove_trendline();\r
168 //----\r
169    return(0);\r
170   }\r
172 double\r
173 get_delta_ratio(\r
174      double &SignalBuffer[],\r
175      int SignalBufferLen)\r
177 if (DEBUG == 1)  Print("Debug get_delta_ratio");\r
179      double delta = 0;\r
180      bool going_up = false;\r
181    \r
182      for (int i = 0; i < SignalBufferLen; i++) {\r
183         if (SignalBuffer[i] == 0 || SignalBuffer[i+1] == 0) continue;\r
184         else if (delta != 0 && going_up != (SignalBuffer[i] > SignalBuffer[i+1]) ) break;\r
185         \r
186         if (delta == 0) going_up = (SignalBuffer[i] > SignalBuffer[i+1]);\r
187         \r
188         delta = ( (delta * i) + (SignalBuffer[i] - SignalBuffer[i+1])) / (i + 1.);\r
189      }\r
190    \r
191      return (delta);\r
194 double\r
195 get_time_ratio(bool last_bar)\r
197 if (DEBUG == 1)  Print("Debug get_time_ratio");\r
198      return (1);\r
200      double time_ratio;\r
201      if (last_bar == false) {\r
202           time_ratio = 1;\r
203      } else {\r
204           double frame_delta = TimeCurrent() - (60. * iTime(NULL, time_frame, 0));\r
205           if (frame_delta > 0) time_ratio = (time_frame * 60.) / frame_delta;\r
206           else time_ratio = 0;\r
207      }\r
208           \r
209      return(time_ratio);\r
213 double\r
214 get_weighted_move(\r
215      double &hi, \r
216      double &low, \r
217      double &close, \r
218      double &prevhi, \r
219      double &prevlow, \r
220      double &prevclose,     \r
221      int ix, int prev_ix)\r
222 \r
223 if (DEBUG == 1) Print("Debug get_weighted_move");\r
225      if (hi < prevlow || low > prevhi) return (0); // disconnected bars\r
227       //current weighted high minus previous weighted high\r
228      double hidiff = ((3. * hi + close) / 4.) - ((3. * prevhi + prevclose) / 4.);\r
229      double lowdiff = ((3. * low + close) / 4.) - ((3. * prevlow + prevclose) / 4.);\r
230      double absdiff = hidiff + lowdiff;\r
232      double volume_ratio;\r
233      double vol = iVolume(NULL, time_frame, ix);\r
234      double prevol = iVolume(NULL, time_frame, prev_ix);\r
235      \r
236      if (vol < INVALID_VOLUME) {\r
237           volume_ratio = 0;\r
238      } else if (prevol < INVALID_VOLUME) {\r
239           volume_ratio = 1;\r
240      } else {               \r
241           volume_ratio = MathPow(vol / prevol, Volume_Factor);\r
242      }\r
244      double time_ratio = get_time_ratio( (ix == 0) );\r
245      \r
246      return (absdiff * time_ratio * volume_ratio);\r
250 double\r
251 get_absolute_diff(\r
252      double &hi, \r
253      double &low, \r
254      double &prevhi, \r
255      double &prevlow, \r
256      int ix)\r
257 \r
258 if (DEBUG == 1) Print("Debug get_absolute_diff");\r
260       //current weighted high minus previous weighted high\r
261      double hidiff = MathAbs(hi - prevhi);\r
262      double lowdiff = MathAbs(low - prevlow);\r
263      double absdiff = hidiff + lowdiff;\r
265      double time_ratio = get_time_ratio( (ix == 0) );\r
266      \r
267      return (absdiff * time_ratio);\r
270 /* largest price difference between two bars */\r
271 double\r
272 get_absolute_move(\r
273      double hi, \r
274      double low, \r
275      double close, \r
276      double prevhi, \r
277      double prevlow, \r
278      double prevclose)\r
280 if (DEBUG == 1)  Print("Debug get_absolute_move");\r
282      double abs_move = 0.0;\r
283      \r
284      double cur_hlc[3];\r
285      cur_hlc[0] = hi;\r
286      cur_hlc[1] = low;\r
287      cur_hlc[2] = close;\r
288      \r
289      double prev_hlc[3];\r
290      prev_hlc[0] = prevhi;\r
291      prev_hlc[1] = prevlow;\r
292      prev_hlc[2] = prevclose;\r
294      for (int i = 0; i < 3; i++) \r
295           for (int j = 0; j < 3; j++) \r
296                if ( MathAbs(cur_hlc[i] - prev_hlc[j]) > MathAbs(abs_move) )\r
297                     abs_move = cur_hlc[i] - prev_hlc[j];\r
298           \r
299      if ( (hi - low) > abs_move ) {\r
300           if (close > prevclose) abs_move = hi - low; \r
301                else abs_move = low - hi;\r
302      }\r
303      \r
304      return (abs_move);\r
307 void\r
308 get_bar_move(\r
309           int now_bar, \r
310           int ref_bar, \r
311           double &max_move)\r
313 if (DEBUG == 1) Print("Debug get_bar_move");\r
315      for (int ix = now_bar - 1; ix >= ref_bar; ix--) {\r
316           double now_move = get_absolute_move(\r
317                                    iHigh(NULL, time_frame, ix),\r
318                                    iLow(NULL, time_frame, ix),\r
319                                    iClose(NULL, time_frame, ix),\r
320                                    iHigh(NULL, time_frame, now_bar),\r
321                                    iLow(NULL, time_frame, now_bar),\r
322                                    iClose(NULL, time_frame, now_bar) );\r
323                                    \r
324           if ( MathAbs(now_move) > MathAbs(max_move) ) max_move = now_move;\r
325      }\r
328 /* largest price difference since start_bar trend */\r
329 double\r
330 get_max_move(int ref_bar)\r
332      if (DEBUG == 1) Print("Debug get_max_move");\r
334      double max_move = 0;\r
335      bool ref_bull = (ExtMapBuffer1[ref_bar] > 0);\r
336      \r
337      for (int now_bar = ref_bar + 1; \r
338           (ref_bull == (ExtMapBuffer1[now_bar] > 0)) && (now_bar < Bars); \r
339           now_bar++) {\r
341           get_bar_move(now_bar, ref_bar, max_move);\r
342      }\r
344      get_bar_move(now_bar, ref_bar, max_move);\r
346      return (max_move);\r
349 #define MAXLEN 1024\r
351 double bears_array[MAXLEN];\r
352 double bulls_array[MAXLEN];\r
355 /* sorted arrays expected ! */\r
356 double\r
357 calc_pips(\r
358      double &trending[],\r
359      int trending_len,\r
360      double &retracements[],\r
361      int retracements_len\r
362      )\r
364      if (DEBUG == 1) Print("Debug calc_pips");\r
366      double best_ratio = 0;\r
367      double best_step = 0;\r
369      if ( (TimeCurrent() - prev_calc_time) < (time_frame * Period() * 5) ) return(prev_best_step);\r
371      double step_base = 0;\r
372      for (int ix = 1;\r
373           (step_base == 0) && (ix < Bars);\r
374           ix++) \r
375      {\r
376           step_base = ExtMapBuffer6[ix];\r
377      }\r
378      if (step_base == 0) return (prev_best_step);\r
379      \r
380      double interpolation_step = step_base * 0.0312; // 1/16\r
381      \r
382           \r
383      for (int z = 0; z < 64; z++) {\r
384           \r
385           double cur_step = step_base + (z * interpolation_step);\r
386                \r
387           double won_pips = 0;\r
388           double lost_pips = 0;\r
389                     \r
390           for (int j = 0; j < retracements_len; j++) {\r
391                won_pips += cur_step * MathFloor(retracements[j] / cur_step) / Point;\r
392                if (cur_step >= retracements[j]) lost_pips += 2. * MathMod(retracements[j], cur_step) / Point;\r
393           }\r
394                \r
395           for (j = 0; j < trending_len; j++) {\r
396                won_pips += cur_step * MathFloor(trending[j] / cur_step) / Point;\r
397                if (cur_step >= trending[j]) lost_pips += 1. * MathMod(trending[j], cur_step) / Point;\r
398           }\r
400           if (won_pips == 0) double cur_ratio = 0;\r
401           else if (lost_pips == 0) cur_ratio = won_pips;\r
402           else cur_ratio = won_pips / lost_pips;\r
404           if (cur_ratio > best_ratio) {\r
405                best_step = cur_step;\r
406                best_ratio = cur_ratio;\r
407           }\r
409      }\r
410      \r
411      if (best_step == 0) return (prev_best_step);\r
412      \r
413      prev_best_step = best_step;\r
414      prev_calc_time = TimeCurrent();\r
416      if (DEBUG == 1) Print(\r
417           "Recomended minimal pip step " + best_step + " past " + \r
418           trending_len + " trending blocks, " + retracements_len + " retracements blocks.");\r
419      \r
420      return (best_step);\r
423 int\r
424 gcd(int a, int b)\r
426      if (b == 0) return (a);\r
427      else return ( gcd(b, a % b) );\r
430 //+------------------------------------------------------------------+\r
431 //| Custom indicator iteration function                              |\r
432 //+------------------------------------------------------------------+\r
433 int start()\r
434   {\r
435    int counted_bars = IndicatorCounted();\r
436 //----\r
437    int limit = Bars - counted_bars - 1;\r
438    if (limit < 0) return (0);\r
439    \r
440    for (int i = limit; i >= 0; i--) {\r
441    \r
442      int ix = MathFloor(index_factor * i);\r
443      \r
444      double hi = iHigh(NULL, time_frame, ix);\r
445      double low = iLow(NULL, time_frame, ix);\r
446      double close = iClose(NULL, time_frame, ix);\r
448      double prevhi = iHigh(NULL, time_frame, ix+1);\r
449      double prevlow = iLow(NULL, time_frame, ix+1);\r
450      double prevclose = iClose(NULL, time_frame, ix+1);\r
451      \r
452      if (prevhi == 0 || prevlow == 0 || prevclose == 0) continue;\r
453      if (hi == 0 || low == 0 || close == 0) continue;\r
454      \r
455           switch (Mode_Function) {\r
456           case WEIGHT_MOVE:\r
457                ExtMapBuffer1[i] = 0;\r
458                for (int j = 1; j < MA_Period; j++) {\r
459                     int prev_ix = ix+j;\r
460                     prevhi = iHigh(NULL, time_frame, prev_ix);\r
461                     prevlow = iLow(NULL, time_frame, prev_ix);\r
462                     prevclose = iClose(NULL, time_frame, prev_ix);\r
463                     \r
464                     double time_coef = (1. * j) / MA_Period;\r
465                     time_coef = MathPow(1. - time_coef, Time_Factor);\r
466                     \r
467                     ExtMapBuffer1[i] +=  time_coef * get_weighted_move(hi, low, close, prevhi, prevlow, prevclose, ix, prev_ix);\r
468                }\r
469                ExtMapBuffer2[i] = ExtMapBuffer1[i];\r
470                break;\r
471          \r
472           case ABS_MOVE:\r
473                ExtMapBuffer1[i] = get_absolute_move(hi, low, close, prevhi, prevlow, prevclose);\r
474                ExtMapBuffer2[i] = get_max_move(i);\r
475                ExtMapBuffer6[i] = MathAbs(ExtMapBuffer1[i]);\r
476           \r
477                // fixup previous bars\r
478                for (j = i + 1;\r
479                     ((ExtMapBuffer2[i] > 0) == (ExtMapBuffer2[j] > 0.0)) && (j < Bars);\r
480                     j++)\r
481                     ExtMapBuffer2[j] = ExtMapBuffer2[i];\r
482                break;\r
484           case ABS_PUSH:\r
485                ExtMapBuffer1[i] = get_absolute_diff(hi, low, prevhi, prevlow, i);\r
486                ExtMapBuffer2[i] = ExtMapBuffer1[i];\r
487                break;\r
488           }     \r
490      }\r
491    \r
492      if (Mode_Function == WEIGHT_MOVE) {\r
493           double ma_coef = 1;\r
494           \r
495           for (i = limit; i >= 0; i--) \r
496                ExtMapBuffer3[i] = MathAbs(ExtMapBuffer1[i]);\r
497                \r
498           for (i = limit; i >= 0; i--) \r
499                ExtMapBuffer5[i] = iMAOnArray(ExtMapBuffer3, Bars, MA2_Period, 0, MODE_EMA, i);\r
500                \r
501      } else { \r
502           for (i = limit; i >= 0; i--) {\r
503                ExtMapBuffer3[i] = iMAOnArray(ExtMapBuffer6, Bars, MA_Period, 0, MODE_EMA, i);\r
504                ExtMapBuffer5[i] = (ExtMapBuffer6[i+1] * (MA2_Period - 1) + ExtMapBuffer6[i]) / (1. * MA2_Period);\r
505           }\r
506      }\r
508      if (Mode_Function == ABS_MOVE) {\r
509    \r
510           switch (Sentiment_Expectation) {\r
511           case NEUTRAL:\r
512                bool going_bull = (ExtMapBuffer2[0] > 0);\r
513                break;\r
514           \r
515           case BULLISH:\r
516                going_bull = true;\r
517                break;\r
518           \r
519           case BEARISH:\r
520                going_bull = false;\r
521                break;\r
522           }\r
523                     \r
524           int bulls_len = 0;\r
525           int bears_len = 0;\r
526           double preval = 0;\r
528           /* get unique movements */\r
529           for (i = 0; i < Retracement_Look_Back; i++) {\r
530                if (ExtMapBuffer2[i] == preval) continue;\r
531                preval = ExtMapBuffer2[i];\r
532                \r
533                if (preval > 0) { \r
534                     bulls_array[bulls_len] = preval;\r
535                     bulls_len++;\r
536                } else if (preval < 0) {\r
537                     bears_array[bears_len] = MathAbs(preval);\r
538                     bears_len++;\r
539                }\r
540           }\r
542           if (going_bull == true)\r
543                double pip_step = calc_pips(bulls_array, bulls_len, bears_array, bears_len);\r
544           else\r
545                pip_step = calc_pips(bears_array, bears_len, bulls_array, bulls_len);\r
546           \r
547           ExtMapBuffer4[0] = pip_step;\r
548           SetLevelValue(0, pip_step);\r
549           SetLevelValue(1, -1.0 * pip_step);\r
550        \r
552    } else {\r
553           double delta_sign = get_delta_ratio(ExtMapBuffer1, Bars);\r
554           double predicted_price = delta_sign;\r
555           predicted_price += ExtMapBuffer1[0];\r
556      \r
557           if (hTrendLine != -1) {\r
558                ObjectSet(TRENDLINE_NAME, OBJPROP_TIME1, iTime(NULL, time_frame, 0) );\r
559                ObjectSet(TRENDLINE_NAME, OBJPROP_TIME2, iTime(NULL, time_frame, 0) + Period() * 60);\r
560                ObjectSet(TRENDLINE_NAME, OBJPROP_PRICE1, ExtMapBuffer2[0]);\r
561                ObjectSet(TRENDLINE_NAME, OBJPROP_PRICE2, predicted_price);\r
562           }\r
563    \r
564    }\r
565     \r
566 //----\r
567    return(0);\r
568   }\r
569 //+------------------------------------------------------------------+