Merge branch 'master' of git://repo.or.cz/mqlkit
[mqlkit.git] / indicators / jmarket_sentiment.mq4.LOCAL.4229.mq4
blob98ab530100e65bac27cd03697a50bc993750c53c
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 4\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_width1 1\r
16 #property indicator_width2 1\r
17 #property indicator_width3 2\r
18 #property indicator_width4 2\r
19 #property indicator_level1 1.0\r
20 #property indicator_level2 -1.0\r
22 #define DEBUG 1\r
25 #define WEIGHT_MOVE 0\r
26 #define ABS_MOVE    1\r
27 #define ABS_PUSH    2\r
28 #define TRENDLINE_NAME "jnextbar_predict"\r
29 #define INVALID_VOLUME 50\r
31 #define NEUTRAL 0\r
32 #define BULLISH 1\r
33 #define BEARISH 2\r
36 extern int MA_Period = 32;\r
37 extern int Time_Frame_Mins = 0;\r
38 extern int Retracement_Look_Back = 32;\r
39 extern int Mode_Function = ABS_MOVE;\r
40 extern string _Mode_0 = "Bar to bar weighted hi-lo difference aggregate to volume ratio"; // nakaj stiska\r
41 extern string _Mode_1 = "Bar to bar any tick max difference"; // grid\r
42 extern string _Mode_2 = "Bar to bar tick max difference"; // pletkanje\r
43 extern int Sentiment_Expectation = NEUTRAL;\r
44 extern string _Expectation_0 = "Neutral sentiment";\r
45 extern string _Expectation_1 = "Bullish sentiment";\r
46 extern string _Expectation_2 = "Bearish sentiment";\r
48 //--- buffers\r
49 double ExtMapBuffer1[];\r
50 double ExtMapBuffer2[];\r
51 double ExtMapBuffer3[];\r
52 double ExtMapBuffer4[];\r
53 double ExtMapBuffer5[];\r
57 int time_frame;\r
58 double index_factor = 1.0;\r
59 int hTrendLine = -1;\r
60 int ind_window_handle;\r
61 double prev_best_step;\r
62 datetime prev_calc_time;\r
64 void\r
65 create_trendline()\r
66 {\r
67      ind_window_handle = WindowFind("jmarket_sentiment");\r
68    \r
69      if (hTrendLine == -1 && ind_window_handle > -1) {\r
70      \r
71           hTrendLine = ObjectCreate(\r
72                TRENDLINE_NAME, \r
73                OBJ_TREND, \r
74                ind_window_handle, \r
75                iTime(NULL, time_frame, 0), \r
76                0.0, \r
77                iTime(NULL, time_frame, 0) + Period() * 60, \r
78                0.0);\r
79                \r
80           ObjectSet(TRENDLINE_NAME, OBJPROP_COLOR, indicator_color2);\r
81           ObjectSet(TRENDLINE_NAME, OBJPROP_STYLE, STYLE_SOLID);\r
82           ObjectSet(TRENDLINE_NAME, OBJPROP_WIDTH, indicator_width2);\r
83      }\r
84 }\r
86 void\r
87 remove_trendline()\r
88 {\r
89      ObjectDelete(TRENDLINE_NAME);\r
90 }\r
92 //+------------------------------------------------------------------+\r
93 //| Custom indicator initialization function                         |\r
94 //+------------------------------------------------------------------+\r
95 int init()\r
96   {\r
97    IndicatorBuffers(5);\r
98   \r
99 //---- indicators\r
100    SetIndexStyle(0,DRAW_HISTOGRAM);\r
101    SetIndexBuffer(0,ExtMapBuffer1);\r
102    SetIndexLabel(0,"Movement");\r
103    SetIndexEmptyValue(0, EMPTY_VALUE);\r
104    \r
105    SetIndexStyle(1,DRAW_LINE);\r
106    SetIndexBuffer(1,ExtMapBuffer2);\r
107    SetIndexLabel(1,"Movement Sum");\r
108    SetIndexEmptyValue(1, EMPTY_VALUE);\r
109    \r
110    SetIndexStyle(2,DRAW_LINE);\r
111    SetIndexBuffer(2,ExtMapBuffer3);\r
112    SetIndexLabel(2,"Smoothed "+MA_Period);\r
113    SetIndexEmptyValue(2, EMPTY_VALUE);\r
114    \r
115    SetIndexStyle(3,DRAW_LINE);\r
116    SetIndexBuffer(3,ExtMapBuffer4);\r
117    SetIndexLabel(3,"Trend step");\r
118    SetIndexEmptyValue(3, EMPTY_VALUE);\r
119    \r
120    SetIndexStyle(4,DRAW_LINE);\r
121    SetIndexBuffer(4,ExtMapBuffer5);\r
122    SetIndexLabel(4,"Absolute movement");\r
123    SetIndexEmptyValue(4, EMPTY_VALUE);\r
124    \r
125    if (Time_Frame_Mins == 0)\r
126      time_frame = Period();\r
127    else\r
128      time_frame = Time_Frame_Mins;\r
130    if (time_frame < 1) time_frame = 1;\r
132    index_factor = Period();\r
133    index_factor = index_factor / time_frame;\r
134    \r
135    prev_calc_time = 0;\r
136    prev_best_step = 0;\r
137    \r
138    if (Mode_Function == ABS_MOVE) remove_trendline();\r
139    else create_trendline();   \r
140    \r
141 //----\r
142    return(0);\r
143   }\r
144 //+------------------------------------------------------------------+\r
145 //| Custom indicator deinitialization function                       |\r
146 //+------------------------------------------------------------------+\r
147 int deinit()\r
148   {\r
149 //----\r
150    remove_trendline();\r
151 //----\r
152    return(0);\r
153   }\r
155 double\r
156 get_delta_ratio(\r
157      double &SignalBuffer[],\r
158      int SignalBufferLen)\r
160 if (DEBUG == 1)  Print("Debug get_delta_ratio");\r
162      double delta = 0.0;\r
163      bool going_up = false;\r
164    \r
165      for (int i = 0; i < SignalBufferLen; i++) {\r
166         if (SignalBuffer[i] == 0. || SignalBuffer[i+1] == 0.) continue;\r
167         else if (delta != 0. && going_up != (SignalBuffer[i] > SignalBuffer[i+1]) ) break;\r
168         \r
169         if (delta == 0.) going_up = (SignalBuffer[i] > SignalBuffer[i+1]);\r
170         \r
171         delta = (delta * i + (SignalBuffer[i] - SignalBuffer[i+1])) / (i + 1.);\r
172      }\r
173    \r
174      return (delta);\r
177 double\r
178 get_time_ratio(bool last_bar)\r
180 if (DEBUG == 1)  Print("Debug get_time_ratio");\r
182      double time_ratio;\r
183      if (last_bar == false) {\r
184           time_ratio = 1;\r
185      } else {\r
186           double frame_delta = TimeCurrent() - iTime(NULL, time_frame, 0);\r
187           if (frame_delta > 0) time_ratio = time_frame * 60. / frame_delta;\r
188           else time_ratio = 0;\r
189      }\r
190           \r
191      return(time_ratio);\r
194 double\r
195 get_weighted_move(\r
196      double &hi, \r
197      double &low, \r
198      double &close, \r
199      double &prevhi, \r
200      double &prevlow, \r
201      double &prevclose,     \r
202      int ix)\r
203 \r
204 if (DEBUG == 1) Print("Debug get_weighted_move");\r
206      if (hi < prevlow || low > prevhi) return (0); // disconnected bars\r
208       //current weighted high minus previous weighted high\r
209      double hidiff = ((2. * hi + close) / 3.) - ((2. * prevhi + prevclose) / 3.);\r
210      double lowdiff = ((2. * low + close) / 3.) - ((2. * prevlow + prevclose) / 3.);\r
211      double absdiff = hidiff + lowdiff;\r
213      double volume_ratio;\r
214      double vol = iVolume(NULL, time_frame, ix);\r
215      double prevol = iVolume(NULL, time_frame, ix+1);\r
216      \r
217      if (vol < INVALID_VOLUME) {\r
218           volume_ratio = 0;\r
219      } else if (prevol < INVALID_VOLUME) {\r
220           volume_ratio = 1;\r
221      } else {               \r
222           volume_ratio = vol / prevol;\r
223      }\r
225      double time_ratio = get_time_ratio( (ix == 0) );\r
226      \r
227      return (absdiff * time_ratio * volume_ratio);\r
231 double\r
232 get_absolute_diff(\r
233      double &hi, \r
234      double &low, \r
235      double &prevhi, \r
236      double &prevlow, \r
237      int ix)\r
238 \r
239 if (DEBUG == 1) Print("Debug get_absolute_diff");\r
241       //current weighted high minus previous weighted high\r
242      double hidiff = MathAbs(hi - prevhi);\r
243      double lowdiff = MathAbs(low - prevlow);\r
244      double absdiff = hidiff + lowdiff;\r
246      double time_ratio = get_time_ratio(ix);\r
247      \r
248      return (absdiff * time_ratio);\r
251 /* largest price difference between two bars */\r
252 double\r
253 get_absolute_move(\r
254      double hi, \r
255      double low, \r
256      double close, \r
257      double prevhi, \r
258      double prevlow, \r
259      double prevclose)\r
261 if (DEBUG == 1)  Print("Debug get_absolute_move");\r
263      double abs_move = 0.0;\r
264      \r
265      double cur_hlc[3];\r
266      cur_hlc[0] = hi;\r
267      cur_hlc[1] = low;\r
268      cur_hlc[2] = close;\r
269      \r
270      double prev_hlc[3];\r
271      prev_hlc[0] = prevhi;\r
272      prev_hlc[1] = prevlow;\r
273      prev_hlc[2] = prevclose;\r
275      for (int i = 0; i < 3; i++) \r
276           for (int j = 0; j < 3; j++) \r
277                if ( MathAbs(cur_hlc[i] - prev_hlc[j]) > MathAbs(abs_move) )\r
278                     abs_move = cur_hlc[i] - prev_hlc[j];\r
279           \r
280      if ( (hi - low) > abs_move ) {\r
281           if (close > prevclose) abs_move = hi - low; \r
282                else abs_move = low - hi;\r
283      }\r
284      \r
285      return (abs_move);\r
288 void\r
289 get_bar_move(\r
290           int now_bar, \r
291           int ref_bar, \r
292           double &max_move)\r
294 if (DEBUG == 1) Print("Debug get_bar_move");\r
296      for (int ix = now_bar - 1; ix >= ref_bar; ix--) {\r
297           double now_move = get_absolute_move(\r
298                                    iHigh(NULL, time_frame, ix),\r
299                                    iLow(NULL, time_frame, ix),\r
300                                    iClose(NULL, time_frame, ix),\r
301                                    iHigh(NULL, time_frame, now_bar),\r
302                                    iLow(NULL, time_frame, now_bar),\r
303                                    iClose(NULL, time_frame, now_bar) );\r
304                                    \r
305           if ( MathAbs(now_move) > MathAbs(max_move) ) max_move = now_move;\r
306      }\r
309 /* largest price difference since start_bar trend */\r
310 double\r
311 get_max_move(int ref_bar)\r
313      if (DEBUG == 1) Print("Debug get_max_move");\r
315      double max_move = 0;\r
316      bool ref_bull = (ExtMapBuffer1[ref_bar] > 0);\r
317      \r
318      for (int now_bar = ref_bar + 1; \r
319           (ref_bull == (ExtMapBuffer1[now_bar] > 0)) && (now_bar < Bars); \r
320           now_bar++) {\r
322           get_bar_move(now_bar, ref_bar, max_move);\r
323      }\r
325      get_bar_move(now_bar, ref_bar, max_move);\r
327      return (max_move);\r
330 #define MAXLEN 1024\r
332 double bears_array[MAXLEN];\r
333 double bulls_array[MAXLEN];\r
336 /* sorted arrays expected ! */\r
337 double\r
338 calc_pips(\r
339      double &trending[],\r
340      int trending_len,\r
341      double &retracements[],\r
342      int retracements_len\r
343      )\r
345      if (DEBUG == 1) Print("Debug calc_pips");\r
347      double best_ratio = 0;\r
348      double best_step = 0;\r
350      if ( (TimeCurrent() - prev_calc_time) < (time_frame * Period() * 5) ) return(prev_best_step);\r
352      double step_base = 0;\r
353      for (int ix = 1;\r
354           (step_base == 0) && (ix < Bars);\r
355           ix++) \r
356      {\r
357           step_base = ExtMapBuffer5[ix];\r
358      }\r
359      if (step_base == 0) return (prev_best_step);\r
360      \r
361      double interpolation_step = step_base * 0.0312; // 1/16\r
362      \r
363           \r
364      for (int z = 0; z < 64; z++) {\r
365           \r
366           double cur_step = step_base + (z * interpolation_step);\r
367                \r
368           double won_pips = 0;\r
369           double lost_pips = 0;\r
370                     \r
371           for (int j = 0; j < retracements_len; j++) {\r
372                lost_pips += cur_step * MathFloor(retracements[j] / cur_step) / Point;\r
373                if (cur_step >= retracements[j]) lost_pips += 1. * MathMod(retracements[j], cur_step) / Point;\r
374           }\r
375                \r
376           for (j = 0; j < trending_len; j++) {\r
377                won_pips += cur_step * MathFloor(trending[j] / cur_step) / Point;\r
378                if (cur_step >= trending[j]) lost_pips += 1. * MathMod(trending[j], cur_step) / Point;\r
379           }\r
381           if (won_pips == 0) double cur_ratio = 0;\r
382           else if (lost_pips == 0) cur_ratio = won_pips;\r
383           else cur_ratio = won_pips / lost_pips;\r
385           if (cur_ratio > best_ratio) {\r
386                best_step = cur_step;\r
387                best_ratio = cur_ratio;\r
388           }\r
390      }\r
391      \r
392      if (best_step == 0) return (prev_best_step);\r
393      \r
394      prev_best_step = best_step;\r
395      prev_calc_time = TimeCurrent();\r
397      if (DEBUG == 1) Print(\r
398           "Recomended minimal pip step " + best_step + " past " + \r
399           trending_len + " trending blocks, " + retracements_len + " retracements blocks.");\r
400      \r
401      return (best_step);\r
404 int\r
405 gcd(int a, int b)\r
407      if (b == 0) return (a);\r
408      else return ( gcd(b, a % b) );\r
411 //+------------------------------------------------------------------+\r
412 //| Custom indicator iteration function                              |\r
413 //+------------------------------------------------------------------+\r
414 int start()\r
415   {\r
416    int counted_bars = IndicatorCounted();\r
417 //----\r
418    int limit = Bars - counted_bars - 1;\r
419    if (limit < 0) return (0);\r
420    \r
421    for (int i = limit; i >= 0; i--) {\r
422    \r
423      int ix = MathFloor(index_factor * i);\r
424      \r
425      double hi = iHigh(NULL, time_frame, ix);\r
426      double low = iLow(NULL, time_frame, ix);\r
427      double close = iClose(NULL, time_frame, ix);\r
429      double prevhi = iHigh(NULL, time_frame, ix+1);\r
430      double prevlow = iLow(NULL, time_frame, ix+1);\r
431      double prevclose = iClose(NULL, time_frame, ix+1);\r
432      \r
433      if (prevhi == 0 || prevlow == 0 || prevclose == 0) continue;\r
434      if (hi == 0 || low == 0 || close == 0) continue;\r
435      \r
436           switch (Mode_Function) {\r
437           case WEIGHT_MOVE:\r
438                ExtMapBuffer1[i] = get_weighted_move(hi, low, close, prevhi, prevlow, prevclose, ix);\r
439                ExtMapBuffer2[i] = ExtMapBuffer1[i];\r
440                break;\r
441          \r
442           case ABS_MOVE:\r
443                ExtMapBuffer1[i] = get_absolute_move(hi, low, close, prevhi, prevlow, prevclose);\r
444                ExtMapBuffer2[i] = get_max_move(i);\r
445                ExtMapBuffer5[i] = MathAbs(ExtMapBuffer1[i]);\r
446           \r
447                // fixup previous bars\r
448                for (int j = i + 1;\r
449                     ((ExtMapBuffer2[i] > 0) == (ExtMapBuffer2[j] > 0.0)) && (j < Bars);\r
450                     j++)\r
451                     ExtMapBuffer2[j] = ExtMapBuffer2[i];\r
452                break;\r
454           case ABS_PUSH:\r
455                ExtMapBuffer1[i] = get_absolute_diff(hi, low, prevhi, prevlow, i);\r
456                ExtMapBuffer2[i] = ExtMapBuffer1[i];\r
457                break;\r
458           }     \r
460      }\r
461    \r
462      if (Mode_Function == WEIGHT_MOVE) {\r
463           double ma_coef = 10.0;\r
464           for (i = limit; i >= 0; i--) \r
465                ExtMapBuffer3[i] = ma_coef * iMAOnArray(ExtMapBuffer1, Bars, MA_Period, 0, MODE_EMA, i);\r
466      } else { \r
467           ma_coef = 1;\r
468           for (i = limit; i >= 0; i--) \r
469                ExtMapBuffer3[i] = ma_coef * iMAOnArray(ExtMapBuffer5, Bars, MA_Period, 0, MODE_EMA, i);\r
470      }\r
472      if (Mode_Function == ABS_MOVE) {\r
473    \r
474           switch (Sentiment_Expectation) {\r
475           case NEUTRAL:\r
476                bool going_bull = (ExtMapBuffer2[0] > 0);\r
477                break;\r
478           \r
479           case BULLISH:\r
480                going_bull = true;\r
481                break;\r
482           \r
483           case BEARISH:\r
484                going_bull = false;\r
485                break;\r
486           }\r
487                     \r
488           int bulls_len = 0;\r
489           int bears_len = 0;\r
490           double preval = 0;\r
492           /* get unique movements */\r
493           for (i = 0; i < Retracement_Look_Back; i++) {\r
494                if (ExtMapBuffer2[i] == preval) continue;\r
495                preval = ExtMapBuffer2[i];\r
496                \r
497                if (preval > 0) { \r
498                     bulls_array[bulls_len] = preval;\r
499                     bulls_len++;\r
500                } else if (preval < 0) {\r
501                     bears_array[bears_len] = MathAbs(preval);\r
502                     bears_len++;\r
503                }\r
504           }\r
506           if (going_bull == true)\r
507                double pip_step = calc_pips(bulls_array, bulls_len, bears_array, bears_len);\r
508           else\r
509                pip_step = calc_pips(bears_array, bears_len, bulls_array, bulls_len);\r
510           \r
511           ExtMapBuffer4[0] = pip_step;\r
512           SetLevelValue(0, pip_step);\r
513           SetLevelValue(1, -1.0 * pip_step);\r
514        \r
516    } else {\r
517           double delta_sign = get_delta_ratio(ExtMapBuffer1, Bars);\r
518           double predicted_price = delta_sign;\r
519           predicted_price += ExtMapBuffer1[0];\r
520      \r
521           if (hTrendLine != -1) {\r
522                ObjectSet(TRENDLINE_NAME, OBJPROP_TIME1, iTime(NULL, time_frame, 0) );\r
523                ObjectSet(TRENDLINE_NAME, OBJPROP_TIME2, iTime(NULL, time_frame, 0) + Period() * 60);\r
524                ObjectSet(TRENDLINE_NAME, OBJPROP_PRICE1, ExtMapBuffer2[0]);\r
525                ObjectSet(TRENDLINE_NAME, OBJPROP_PRICE2, predicted_price);\r
526           }\r
527    \r
528    }\r
529     \r
530 //----\r
531    return(0);\r
532   }\r
533 //+------------------------------------------------------------------+