bleh
[mqlkit.git] / indicators / jkalman.mq4
blob51edb612e0abae1edf6ee682e76e35d7c4e2cde2
1 //+------------------------------------------------------------------+\r
2 //|                                                      jkalman.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_chart_window\r
10 #property indicator_buffers 3\r
11 #property indicator_color1 DeepSkyBlue\r
12 #property indicator_color2 DeepSkyBlue\r
13 #property indicator_color3 DeepSkyBlue\r
14 #property indicator_width1 2\r
15 #property indicator_width2 1\r
16 #property indicator_width3 1\r
17 #property indicator_style2 STYLE_SOLID\r
19 //--- input parameters\r
20 extern double    Q = 0.022;\r
21 extern double    R = 0.617;\r
22 extern int       Num_Bars = 25;\r
23 extern int       Num_Sub_Bars = 64;\r
25 extern int       Sub_Time_Frame = PERIOD_M1;\r
26 extern double    Error_Weight = 2.0;\r
28 extern bool      Self_Correct = true;\r
29 extern int       Num_Cycles_Bar = 4;\r
30 extern double    Scatter = 33.3;\r
32 extern bool      Verbose = false;\r
35 //--- buffers\r
36 double ExtMapBuffer1[];\r
37 double ExtMapBuffer2[];\r
38 double ExtMapBuffer3[];\r
42 double x_est_last;\r
43 double P_last;\r
44 //the noise in the system\r
45     \r
46 double K;\r
47 double P;\r
48 double P_temp;\r
49 double x_temp_est;\r
50 double x_est;\r
52 int iter_ctr;\r
53 double sum_error_kalman;\r
54 double median_error_kalman;\r
55 datetime prev_subbar_time;\r
56 double prev_sum_error_kalman = 0.0;\r
58 double used_q;\r
59 double used_r;\r
60 double next_q;\r
61 double next_r;\r
62 double adj_scatter;\r
64 //+------------------------------------------------------------------+\r
65 //| Custom indicator initialization function                         |\r
66 //+------------------------------------------------------------------+\r
68 double subbars_period;\r
69 double inv_subbars_period;\r
71 int init()\r
72   {\r
73 //---- indicators\r
74    SetIndexStyle(0,DRAW_LINE);\r
75    SetIndexBuffer(0,ExtMapBuffer1);\r
76    SetIndexStyle(1,DRAW_LINE);\r
77    SetIndexBuffer(1,ExtMapBuffer2);\r
78    SetIndexStyle(2,DRAW_LINE);\r
79    SetIndexBuffer(2,ExtMapBuffer3);\r
80    SetIndexEmptyValue(0, 0.0);\r
81    SetIndexEmptyValue(1, 0.0);\r
82    SetIndexEmptyValue(2, 0.0);\r
83 //----\r
84    prev_subbar_time = 0;\r
85  \r
86    used_q = Q;\r
87    used_r = R;\r
88    next_q = Q;\r
89    next_r = R;\r
90   \r
91    // init_kalman( iClose(Symbol(), Period(), Num_Bars * Period() / Sub_Time_Frame) );\r
93    adj_scatter = Scatter;\r
94    \r
95    subbars_period = Period() / Sub_Time_Frame;\r
96    inv_subbars_period = 1.0 / subbars_period;\r
97    \r
98    return(0);\r
99   }\r
100 //+------------------------------------------------------------------+\r
101 //| Custom indicator deinitialization function                       |\r
102 //+------------------------------------------------------------------+\r
103 int deinit()\r
104   {\r
105 //----\r
106      Comment("");\r
107 //---Commen\r
108    return(0);\r
109   }\r
110   \r
112 void\r
113 init_kalman(\r
114      double init_value)\r
116     //initial values for the kalman filter\r
117     \r
118     //initialize with a measurement\r
119     x_est_last = init_value;\r
120     P_last = 0.0;\r
121     \r
122     sum_error_kalman = 0.0;\r
123     median_error_kalman = 0.0;\r
124     iter_ctr = 0; // for median\r
127 double\r
128 do_kalman(\r
129      double value, \r
130      double train_val,\r
131      double q, \r
132      double r)\r
134         //do a prediction\r
135         P_temp = P_last + q;\r
136         \r
137         //calculate the Kalman gain\r
138         K = P_temp / (P_temp + r); \r
140         //correct\r
141         x_est = x_est_last + K * (value - x_est_last); \r
142         P = (1.0 - K) * P_temp;\r
143         //we have our new system\r
145         if (train_val != 0.0) {\r
146           double abserror = MathAbs(train_val - x_est);\r
147           sum_error_kalman += abserror;\r
148           \r
149           median_error_kalman = median_error_kalman * iter_ctr + Error_Weight * abserror;\r
150           median_error_kalman /= (iter_ctr + Error_Weight);\r
151           iter_ctr++;\r
152         }\r
153         \r
154         //update our last's\r
155         P_last = P;\r
156         x_est_last = x_est;\r
158         return (x_est);\r
161 double\r
162 do_cycle(int start_bar, int end_bar, double q, double r, double reference_value)\r
164      double est = 0.0;\r
165      sum_error_kalman = 0.0;\r
166      \r
167      for (int i = start_bar; i >= end_bar; i--) {\r
168           double hist_val = iClose(NULL, Sub_Time_Frame, i);\r
169           est = do_kalman(hist_val, reference_value, q, r);\r
170      }\r
171      \r
172      return (est);\r
176 void\r
177 incr_coef(\r
178      double &qr_coef, \r
179      double &prev_qr_coef)\r
181      if (prev_qr_coef == 0.0) return;\r
182      \r
183      qr_coef = prev_qr_coef + (prev_qr_coef / adj_scatter);\r
186 void\r
187 decr_coef(\r
188      double &qr_coef, \r
189      double &prev_qr_coef)\r
191      if (prev_qr_coef == 0.0) return;\r
193      qr_coef = prev_qr_coef - (prev_qr_coef / adj_scatter);\r
196 #define INCR_R_COEF 0\r
197 #define DECR_R_COEF 1\r
198 #define INCR_Q_COEF 0\r
199 #define DECR_Q_COEF 1\r
201 int last_r_adj = INCR_R_COEF;\r
202 int last_q_adj = INCR_Q_COEF;\r
205 void\r
206 filter_bar(int index)\r
208    double est = 0.0;\r
209    double ref_value = Close[index];\r
211    used_q = next_q;\r
212    used_r = next_r;\r
213    \r
214    est = do_cycle( Num_Sub_Bars + index * subbars_period, index * subbars_period, used_q, used_r, ref_value);\r
215      \r
216    if (Self_Correct == true) {\r
218      if (sum_error_kalman < prev_sum_error_kalman) {\r
219      \r
220           if (last_q_adj == INCR_Q_COEF) incr_coef(next_q, used_q);\r
221           else decr_coef(next_q, used_q);\r
222           \r
223           if (last_r_adj == INCR_R_COEF ) incr_coef(next_r, used_r);\r
224           else decr_coef(next_r, used_r);\r
225           \r
226      } else if (prev_sum_error_kalman < sum_error_kalman) {\r
227      \r
228           if (last_q_adj == INCR_Q_COEF) decr_coef(next_q, used_q);\r
229           else incr_coef(next_q, used_q);\r
230           \r
231           if (last_r_adj == INCR_R_COEF) decr_coef(next_r, used_r);\r
232           else incr_coef(next_r, used_r);\r
233           \r
234      } else {\r
235           next_q = used_q;\r
236           next_r = used_r;\r
237      }\r
238      \r
239      prev_sum_error_kalman = sum_error_kalman;\r
240      \r
241    } \r
242    \r
243    if (est > ref_value) {\r
244      ExtMapBuffer1[index] = est;\r
245      ExtMapBuffer2[index] = est - median_error_kalman;\r
246      ExtMapBuffer3[index] = 0.0;\r
248      if (ExtMapBuffer2[index + 1] == 0.0) {\r
249           double prev_err = ExtMapBuffer3[index + 1] - ExtMapBuffer1[index + 1];\r
250           ExtMapBuffer2[index + 1] = ExtMapBuffer1[index + 1] - prev_err;\r
251      }\r
253    } else {\r
254      ExtMapBuffer1[index] = est;\r
255      ExtMapBuffer2[index] = 0.0;\r
256      ExtMapBuffer3[index] = est + median_error_kalman;\r
257      \r
258      if (ExtMapBuffer3[index + 1] == 0.0) {\r
259           prev_err = ExtMapBuffer1[index + 1] - ExtMapBuffer2[index + 1];\r
260           ExtMapBuffer3[index + 1] = ExtMapBuffer1[index + 1] + prev_err;\r
261      }\r
263    }\r
264    \r
267 //+------------------------------------------------------------------+\r
268 //| Custom indicator iteration function                              |\r
269 //+------------------------------------------------------------------+\r
270 int start()\r
271   {\r
272 //----\r
273   int counted_bars = IndicatorCounted();\r
274   int limit = Bars - counted_bars - 1;\r
275   if (limit < 0) return (0);\r
276   if (limit > Num_Bars) limit = Num_Bars;\r
277  \r
278 //----\r
279   if (limit == 0) { \r
280      if (prev_subbar_time == iTime(NULL, Sub_Time_Frame, 0)) return (0);\r
281      else prev_subbar_time = iTime(NULL, Sub_Time_Frame, 0);\r
282   }\r
284    for (int i = limit; i >= 0; i--) {\r
285      init_kalman( iClose(Symbol(), Sub_Time_Frame, (i + 1) * subbars_period - 1) );\r
286      \r
287      for (int j = 0;j < Num_Cycles_Bar; j++) filter_bar(i);\r
288    }\r
290    if (Verbose == true) {\r
291      Comment(\r
292            "\n\nTotal error this bar: ", sum_error_kalman, " (", iter_ctr," bars) \n",\r
293            "Last bar median weighted Kalman error: ", median_error_kalman, "\n",\r
294            "Q:",used_q," R:",used_r," \n",\r
295            "Prediction: ", x_est, "\n");\r
296    }     \r
298    return(0);\r
299   }\r
300 //+------------------------------------------------------------------+