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
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
27 #define WEIGHT_MOVE 0
\r
30 #define TRENDLINE_NAME "jnextbar_predict"
\r
31 #define INVALID_VOLUME 50
\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
54 double ExtMapBuffer1[];
\r
55 double ExtMapBuffer2[];
\r
56 double ExtMapBuffer3[];
\r
57 double ExtMapBuffer4[];
\r
58 double ExtMapBuffer5[];
\r
59 double ExtMapBuffer6[];
\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
73 ind_window_handle = WindowFind("jmarket_sentiment");
\r
75 if (hTrendLine == -1 && ind_window_handle > -1) {
\r
77 hTrendLine = ObjectCreate(
\r
81 iTime(NULL, time_frame, 0),
\r
83 iTime(NULL, time_frame, 0) + Period() * 60,
\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
95 ObjectDelete(TRENDLINE_NAME);
\r
98 //+------------------------------------------------------------------+
\r
99 //| Custom indicator initialization function |
\r
100 //+------------------------------------------------------------------+
\r
103 IndicatorBuffers(6);
\r
106 SetIndexStyle(0,DRAW_HISTOGRAM);
\r
107 SetIndexBuffer(0,ExtMapBuffer1);
\r
108 SetIndexLabel(0,"Movement");
\r
109 SetIndexEmptyValue(0, EMPTY_VALUE);
\r
111 SetIndexStyle(1,DRAW_LINE);
\r
112 SetIndexBuffer(1,ExtMapBuffer2);
\r
113 SetIndexLabel(1,"Movement Sum");
\r
114 SetIndexEmptyValue(1, EMPTY_VALUE);
\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
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
131 SetIndexStyle(5,DRAW_LINE);
\r
132 SetIndexBuffer(5,ExtMapBuffer6);
\r
133 SetIndexLabel(5,"Absolute movement");
\r
134 SetIndexEmptyValue(5, EMPTY_VALUE);
\r
136 if (Time_Frame_Mins == 0)
\r
137 time_frame = Period();
\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
146 prev_calc_time = 0;
\r
147 prev_best_step = 0;
\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
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
161 //+------------------------------------------------------------------+
\r
162 //| Custom indicator deinitialization function |
\r
163 //+------------------------------------------------------------------+
\r
167 remove_trendline();
\r
174 double &SignalBuffer[],
\r
175 int SignalBufferLen)
\r
177 if (DEBUG == 1) Print("Debug get_delta_ratio");
\r
180 bool going_up = false;
\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
186 if (delta == 0) going_up = (SignalBuffer[i] > SignalBuffer[i+1]);
\r
188 delta = ( (delta * i) + (SignalBuffer[i] - SignalBuffer[i+1])) / (i + 1.);
\r
195 get_time_ratio(bool last_bar)
\r
197 if (DEBUG == 1) Print("Debug get_time_ratio");
\r
201 if (last_bar == false) {
\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
209 return(time_ratio);
\r
220 double &prevclose,
\r
221 int ix, int prev_ix)
\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
236 if (vol < INVALID_VOLUME) {
\r
238 } else if (prevol < INVALID_VOLUME) {
\r
241 volume_ratio = MathPow(vol / prevol, Volume_Factor);
\r
244 double time_ratio = get_time_ratio( (ix == 0) );
\r
246 return (absdiff * time_ratio * volume_ratio);
\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
267 return (absdiff * time_ratio);
\r
270 /* largest price difference between two bars */
\r
280 if (DEBUG == 1) Print("Debug get_absolute_move");
\r
282 double abs_move = 0.0;
\r
287 cur_hlc[2] = close;
\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
299 if ( (hi - low) > abs_move ) {
\r
300 if (close > prevclose) abs_move = hi - low;
\r
301 else abs_move = low - hi;
\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
324 if ( MathAbs(now_move) > MathAbs(max_move) ) max_move = now_move;
\r
328 /* largest price difference since start_bar trend */
\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
337 for (int now_bar = ref_bar + 1;
\r
338 (ref_bull == (ExtMapBuffer1[now_bar] > 0)) && (now_bar < Bars);
\r
341 get_bar_move(now_bar, ref_bar, max_move);
\r
344 get_bar_move(now_bar, ref_bar, 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
358 double &trending[],
\r
360 double &retracements[],
\r
361 int retracements_len
\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
373 (step_base == 0) && (ix < Bars);
\r
376 step_base = ExtMapBuffer6[ix];
\r
378 if (step_base == 0) return (prev_best_step);
\r
380 double interpolation_step = step_base * 0.0312; // 1/16
\r
383 for (int z = 0; z < 64; z++) {
\r
385 double cur_step = step_base + (z * interpolation_step);
\r
387 double won_pips = 0;
\r
388 double lost_pips = 0;
\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
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
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
411 if (best_step == 0) return (prev_best_step);
\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
420 return (best_step);
\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
435 int counted_bars = IndicatorCounted();
\r
437 int limit = Bars - counted_bars - 1;
\r
438 if (limit < 0) return (0);
\r
440 for (int i = limit; i >= 0; i--) {
\r
442 int ix = MathFloor(index_factor * i);
\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
452 if (prevhi == 0 || prevlow == 0 || prevclose == 0) continue;
\r
453 if (hi == 0 || low == 0 || close == 0) continue;
\r
455 switch (Mode_Function) {
\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
464 double time_coef = (1. * j) / MA_Period;
\r
465 time_coef = MathPow(1. - time_coef, Time_Factor);
\r
467 ExtMapBuffer1[i] += time_coef * get_weighted_move(hi, low, close, prevhi, prevlow, prevclose, ix, prev_ix);
\r
469 ExtMapBuffer2[i] = ExtMapBuffer1[i];
\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
477 // fixup previous bars
\r
479 ((ExtMapBuffer2[i] > 0) == (ExtMapBuffer2[j] > 0.0)) && (j < Bars);
\r
481 ExtMapBuffer2[j] = ExtMapBuffer2[i];
\r
485 ExtMapBuffer1[i] = get_absolute_diff(hi, low, prevhi, prevlow, i);
\r
486 ExtMapBuffer2[i] = ExtMapBuffer1[i];
\r
492 if (Mode_Function == WEIGHT_MOVE) {
\r
493 double ma_coef = 1;
\r
495 for (i = limit; i >= 0; i--)
\r
496 ExtMapBuffer3[i] = MathAbs(ExtMapBuffer1[i]);
\r
498 for (i = limit; i >= 0; i--)
\r
499 ExtMapBuffer5[i] = iMAOnArray(ExtMapBuffer3, Bars, MA2_Period, 0, MODE_EMA, i);
\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
508 if (Mode_Function == ABS_MOVE) {
\r
510 switch (Sentiment_Expectation) {
\r
512 bool going_bull = (ExtMapBuffer2[0] > 0);
\r
520 going_bull = false;
\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
534 bulls_array[bulls_len] = preval;
\r
536 } else if (preval < 0) {
\r
537 bears_array[bears_len] = MathAbs(preval);
\r
542 if (going_bull == true)
\r
543 double pip_step = calc_pips(bulls_array, bulls_len, bears_array, bears_len);
\r
545 pip_step = calc_pips(bears_array, bears_len, bulls_array, bulls_len);
\r
547 ExtMapBuffer4[0] = pip_step;
\r
548 SetLevelValue(0, pip_step);
\r
549 SetLevelValue(1, -1.0 * pip_step);
\r
553 double delta_sign = get_delta_ratio(ExtMapBuffer1, Bars);
\r
554 double predicted_price = delta_sign;
\r
555 predicted_price += ExtMapBuffer1[0];
\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
569 //+------------------------------------------------------------------+