2 #property copyright "Copyleft © 2007, GammaRat Forex"
\r
3 #property link "http://www.gammarat.com/Forex/"
\r
7 //#include <GRFMatrixMath.mqh>
\r
8 #property indicator_chart_window
\r
9 #property indicator_buffers 7
\r
10 #property indicator_color1 Orange
\r
11 #property indicator_color2 Orange
\r
12 #property indicator_color3 Orange
\r
13 #property indicator_color4 Red
\r
14 #property indicator_color5 Red
\r
15 #property indicator_color6 Red
\r
16 #property indicator_color7 Red
\r
17 #property indicator_style1 0
\r
18 #property indicator_style2 0
\r
19 #property indicator_style3 0
\r
20 #property indicator_style4 2
\r
21 #property indicator_style5 2
\r
22 #property indicator_style6 0
\r
23 #property indicator_style7 0
\r
26 //---- input parameters
\r
27 extern double Samples=15;
\r
28 extern double DevLevel1 = 2;
\r
29 extern double DevLevel2 = 0;
\r
30 extern double Suppression_dB = 0;
\r
31 extern double PredictBars1 = 0;
\r
32 extern double PredictBars2 = 0;
\r
33 extern bool PrintCurrentState = true;
\r
34 extern bool AutoGainOn = true;
\r
38 double KalmanBuffer[];
\r
39 double KalmanBufferPlus1[];
\r
40 double KalmanBufferNeg1[];
\r
41 double KalmanBufferPlus2[];
\r
42 double KalmanBufferNeg2[];
\r
43 double KalmanBufferPlus3[];
\r
44 double KalmanBufferNeg3[];
\r
45 double xkk[2][1],xkk1[2][1],xk1k1[2][1],yk[1][1],zk[1][1];
\r
46 double Pkk[2][2],Pkk1[2][2],Pk1k1[2][2],Pkk_inv[2][2];
\r
47 double Qkk[2][2],Hk[1][2],Hk_t[2][1],Sk[1][1],Sk_inv[1][1],Rk[1][1],Kk[2][1];
\r
48 double Fk[2][2],Fk_t[2][2],GGT[2][2];
\r
50 double temp22[2][2],temp21[2][1],temp12[1][2],temp11[1][1];
\r
51 double xp[1][1],xpt[1][1],xpt_t[1][1];
\r
52 double Phi1[1][2],Phi2[1][2];
\r
53 double xdel[1][1],xdel_t[1][1];
\r
55 static bool initiated=false;
\r
56 static double c0_above=0, c0_below = 0;
\r
57 static double c1_above=0, c1_below = 0;
\r
58 static int last_time=-1;
\r
59 static int first_time = -1;
\r
60 static int tick_count=0;
\r
61 static int counted_bars = -1;
\r
62 static double TestGain;
\r
63 static bool PrintOn=false;
\r
64 //+------------------------------------------------------------------+
\r
65 //| Custom indicator initialization function |
\r
66 //+------------------------------------------------------------------+
\r
70 shortname = "KalmanAGAS "+DoubleToStr(Samples,1)+ " ";
\r
72 if(LookAhead <0)LookAhead=0;
\r
73 SetIndexStyle(0,DRAW_LINE);
\r
75 SetIndexBuffer(0,KalmanBuffer);
\r
76 SetIndexShift(0,LookAhead);
\r
77 SetIndexDrawBegin(0,LookAhead);
\r
78 SetIndexLabel(0,shortname);
\r
79 if(MathAbs(DevLevel1) > 0) {
\r
80 SetIndexStyle(1,DRAW_LINE);
\r
81 SetIndexBuffer(1,KalmanBufferPlus1);
\r
83 SetIndexDrawBegin(1,1);
\r
84 SetIndexLabel(1,shortname + DoubleToStr(DevLevel1,1) + " Dev");
\r
85 SetIndexStyle(2,DRAW_LINE);
\r
86 SetIndexBuffer(2,KalmanBufferNeg1);
\r
88 SetIndexDrawBegin(2,1);
\r
89 SetIndexLabel(2,shortname + DoubleToStr(-DevLevel1,1) + " Dev");
\r
91 if(MathAbs(DevLevel2) > 0){
\r
92 SetIndexStyle(3,DRAW_LINE);
\r
93 SetIndexBuffer(3,KalmanBufferPlus2);
\r
95 SetIndexDrawBegin(3,1);
\r
96 SetIndexLabel(3,shortname + DoubleToStr(DevLevel2,1) + " Dev");
\r
97 SetIndexStyle(4,DRAW_LINE);
\r
98 SetIndexBuffer(4,KalmanBufferNeg2);
\r
100 SetIndexDrawBegin(4,1);
\r
101 SetIndexLabel(4,shortname + DoubleToStr(-DevLevel2,1) + " Dev");
\r
103 SetIndexStyle(5,DRAW_LINE);
\r
104 SetIndexBuffer(5,KalmanBufferPlus3);
\r
105 SetIndexShift(5,0);
\r
106 SetIndexDrawBegin(5,1);
\r
107 SetIndexLabel(5,shortname + " Highs " + DoubleToStr(DevLevel2,1) + " Dev");
\r
108 SetIndexStyle(6,DRAW_LINE);
\r
109 SetIndexBuffer(6,KalmanBufferNeg3);
\r
110 SetIndexShift(6,0);
\r
111 SetIndexDrawBegin(6,1);
\r
112 SetIndexLabel(6,shortname + " Lows " + DoubleToStr(-DevLevel2,1) + " Dev");
\r
117 //| Point and figure |
\r
118 //+------------------------------------------------------------------+
\r
122 double TestGain_saved;
\r
124 if(counted_bars == -1 && AutoGainOn){
\r
125 if(Bars<Samples*2)Samples =Bars/4;
\r
128 //first time through
\r
130 TestGain_saved = Suppression_dB;
\r
137 //Print("TestGain ",TestGain," trial ", i);
\r
138 Suppression_dB=TestGain;
\r
139 if(MathAbs(TestGain-TestGain_saved) < 0.5)break;
\r
140 TestGain_saved=TestGain;
\r
147 counted_bars=IndicatorCounted();
\r
148 if( counted_bars<0) counted_bars=0;
\r
158 static double acc_sigma2;
\r
159 static double z_sigma2;
\r
160 static double normalization_time;
\r
161 static double working_samples;
\r
164 static double dev_level1,dev_level2;
\r
165 double temp11a[1][1],temp21a[2][1];
\r
166 double temp22a[2][2];
\r
167 static double ZGain = 0;
\r
168 static double AGain=1;
\r
169 static double tgain=1;
\r
170 static double time_last;
\r
171 static double zk_saved[2][1];
\r
175 //give it some time to warm up
\r
176 if(Bars<Samples*2)
\r
178 //rewrite the last bar
\r
179 //if(counted_bars > Bars-2)return(0);
\r
182 if(Time[1] <= last_time) return(0);
\r
185 //if(tick_count>0)return(0);
\r
187 if(counted_bars<0) counted_bars=0;
\r
189 //if(counted_bars>0)counted_bars--;
\r
191 //if(counted_bars >2) counted_bars -= 2;
\r
196 Phi1[0][1] = PredictBars1;
\r
198 Phi2[0][1] = PredictBars2;
\r
200 dev_level1 = DevLevel1*MathSqrt(2);
\r
201 dev_level2 = DevLevel2*MathSqrt(2);
\r
202 ArrayCopy(KalmanBuffer,High);
\r
203 xkk1[0][0] = get_avg(Bars-1);
\r
205 //MatrixPrint(xkk);
\r
211 MatrixTranspose(Fk,Fk_t);
\r
222 MatrixTranspose(Hk,Hk_t);
\r
227 z_sigma2 = MathPow(10,-ZGain);
\r
228 acc_sigma2 = Point*MathPow(10,-Suppression_dB/20.);//*MathSqrt(0.0001/Point);
\r
229 MatrixScalarMul(acc_sigma2,Pkk1);
\r
230 working_samples = Samples;
\r
231 acc_sigma2 *= acc_sigma2;
\r
232 Rk[0][0] = z_sigma2;
\r
234 MatrixScalarMul(acc_sigma2,Pkk);
\r
235 //Print(1./MathSqrt(acc_sigma2));
\r
238 zk_saved[0][0] = get_avg(Bars-1);
\r
239 zk_saved[1][0] = 0;
\r
240 //double A1[20][2],A1t[2][20],A11[2][2],A11_inv[2][2],X[2],B[20];
\r
241 //for(i=0;i<20;i++){
\r
242 ArrayCopy(xkk1,zk_saved);
\r
246 for(i=Bars-counted_bars-1; i> 0;i--){ //ticks are handled elsewhere
\r
248 //Start the update procedure
\r
251 zk[0][0] = get_avg(i);
\r
252 zk[1][0]= zk[0][0]-zk_saved[0][0];
\r
253 ArrayCopy(zk_saved,zk);
\r
254 diff = (zk[0][0]*Point-xkk1[0][0]*Point);
\r
257 c0_above = (c0_above*(working_samples-1)+MathPow(get_avg(i)*Point-KalmanBuffer[i],2))/working_samples;
\r
258 c0_below = c0_below*(working_samples-1)/working_samples;
\r
259 c1_above = (c1_above*(working_samples-1)+MathPow(High[i]-KalmanBuffer[i],2))/working_samples;
\r
260 c1_below = c1_below*(working_samples-1)/working_samples;
\r
263 c0_below = (c0_below*(working_samples-1)+MathPow(get_avg(i)*Point-KalmanBuffer[i],2))/working_samples;
\r
264 c0_above = c0_above*(working_samples-1)/working_samples;
\r
265 c1_below = (c1_below*(working_samples-1)+MathPow(Low[i]-KalmanBuffer[i],2))/working_samples;
\r
266 c1_above = c1_above*(working_samples-1)/working_samples;
\r
268 if(MathAbs(DevLevel1)>0){
\r
269 KalmanBufferPlus1[i-1] = KalmanBuffer[i]+dev_level1*MathSqrt(c0_above);
\r
270 KalmanBufferNeg1[i-1] = KalmanBuffer[i]-dev_level1*MathSqrt(c0_below);
\r
272 if(MathAbs(DevLevel2)>0){
\r
273 KalmanBufferPlus2[i-1] = KalmanBuffer[i]+dev_level2*MathSqrt(c0_above);
\r
274 KalmanBufferNeg2[i-1] = KalmanBuffer[i]-dev_level2*MathSqrt(c0_below);
\r
275 KalmanBufferPlus3[i-1] = KalmanBuffer[i]+dev_level2*MathSqrt(c1_above);
\r
276 KalmanBufferNeg3[i-1] = KalmanBuffer[i]-dev_level2*MathSqrt(c1_below);
\r
278 //this is always left alone, for now
\r
281 ArrayCopy(Qkk,GGT);
\r
283 // set the auto gain
\r
284 if(AutoGainOn && MathSqrt((c0_above+c0_below)/2)> Point){
\r
285 if(c0_below >0 || c0_above>0)
\r
286 tgain = MathAbs((c0_below)/(c0_below+c0_above));
\r
288 if(tgain< 0.2 || tgain > 0.8)
\r
289 AGain = AGain*MathPow(10,0.001);
\r
290 else if(tgain> 0.45 && tgain < 0.55)
\r
291 AGain=AGain*MathPow(10,-0.001);
\r
295 tgain = AGain*acc_sigma2;
\r
296 TestGain=-20*MathLog(MathSqrt(tgain)/Point)/MathLog(10.);
\r
297 MatrixScalarMul(tgain,Qkk);
\r
298 MatrixMul(Hk,xkk1,temp11);
\r
299 //MatrixPrint(xkk1);
\r
300 MatrixAdd(zk,temp11,yk, -1);
\r
301 MatrixMul(Hk,Pkk1,temp12);
\r
302 MatrixMul(temp12,Hk_t,temp11);
\r
303 MatrixAdd(temp11,Rk,Sk,1);
\r
304 MatrixInvert(Sk,Sk_inv);
\r
305 MatrixMul(Pkk1,Hk_t,temp21);
\r
306 MatrixMul(temp21,Sk_inv,Kk);
\r
307 MatrixMul(Kk,yk,temp21);
\r
308 MatrixAdd(temp21,xkk1,xkk,1);
\r
310 MatrixMul(Kk,Hk,temp22);
\r
311 MatrixAdd(Eye,temp22,temp22a,-1);
\r
312 MatrixMul(temp22a,Pkk1,Pkk);
\r
315 //make copies of the last iteration;
\r
316 ArrayCopy(Pk1k1,Pkk);
\r
317 ArrayCopy(xk1k1,xkk);
\r
318 //g = MathSqrt(MathPow(xkk[0][0]-get_avg(i),2))/Pkk[0][0]*Point;
\r
320 //predict the state
\r
321 //Print("Doing Predict");
\r
322 MatrixMul(Fk,xk1k1,xkk1);
\r
323 //MatrixPrint(xkk1);
\r
324 MatrixMul(Fk,Pk1k1,temp22);
\r
325 MatrixMul(temp22,Fk_t,Pk1k1);
\r
326 MatrixAdd(Pk1k1,Qkk,Pkk1,1);
\r
327 //Print("Predict Ended");
\r
328 KalmanBuffer[i-1] = (xkk1[0][0]*Point);
\r
330 if(i==1 && PrintOn){
\r
331 if(PrintCurrentState){
\r
332 Print("Suppression (dB):", -20*MathLog(MathSqrt(tgain)/Point)/MathLog(10.),"dB; Value:",xkk1[0][0]*Point
\r
333 ,"; Speed (pips/bar):",xkk1[1][0],"; dp/p:"
\r
334 , xkk1[1][0]/xkk1[0][0]*100.*240.*(24.*60.)/Period()
\r
336 ,(KalmanBuffer[i-1]-KalmanBuffer[i])/KalmanBuffer[i]
\r
337 *100.*240.*(24.*60.)/Period());
\r
339 if(PredictBars1 > 0){
\r
340 MatrixMul(Phi1,xkk,xpt);
\r
341 xp[0][0] = xkk[0][0];
\r
343 MatrixTranspose(Phi1,temp21);
\r
344 MatrixMul(Pkk,temp21,temp21a);
\r
345 MatrixMul(Phi1,temp21a,temp11a);
\r
346 MatrixInvert(temp11a,temp11);
\r
347 MatrixAdd(xp,xpt,xdel,-1);
\r
348 MatrixTranspose(xdel,xdel_t);
\r
349 MatrixMul(temp11,xdel,temp11a);
\r
350 MatrixMul(xdel_t,temp11a,temp11);
\r
351 g1=MathSqrt(temp11[0][0]);
\r
352 Print(Phi1[0][1], " bar bounds ",(xpt[0][0]-g1)*Point
\r
353 ,",",(xpt[0][0]+g1)*Point);
\r
354 Print(Phi1[0][1], " bar center, r(t) (in pips) ",(xpt[0][0])*Point
\r
357 if(PredictBars2 > 0){
\r
358 MatrixMul(Phi2,xkk,xpt);
\r
359 xp[0][0] = xkk[0][0];
\r
360 MatrixTranspose(Phi2,temp21);
\r
361 MatrixMul(Pkk,temp21,temp21a);
\r
362 MatrixMul(Phi2,temp21a,temp11a);
\r
363 MatrixInvert(temp11a,temp11);
\r
364 MatrixAdd(xp,xpt,xdel,-1);
\r
365 MatrixTranspose(xdel,xdel_t);
\r
366 MatrixMul(temp11,xdel,temp11a);
\r
367 MatrixMul(xdel_t,temp11a,temp11);
\r
368 g1=MathSqrt(temp11[0][0]);
\r
369 Print(Phi2[0][1], " bar bounds ",(xpt[0][0]-g1)*Point
\r
370 ,",",(xpt[0][0]+g1)*Point);
\r
371 Print(Phi2[0][1], " bar center, r(t) (in pips) ",(xpt[0][0])*Point
\r
379 //Print(Pkk1[0][0]/Point," ",Pkk1[1][0]/Point," ",Pkk1[1][1]/Point);
\r
380 //Print("24 hours:", xpt[0][0]*Point," ,Gate ",g);
\r
381 //Print ("Gate 2 ", MathSqrt(xdel[0][0]*xdel[0][0]*g)*Point," g1 ",g1);
\r
385 double get_avg(int k){
\r
386 return(MathPow((High[k]*Low[k]*Close[k]*Close[k]),1/4.)/Point);
\r
388 //+++++++-----------------------------------------------------+
\r
389 double determinant_fixed(double a[][], int k){
\r
392 case 1: return(a[0][0]);
\r
394 case 2: return( a[0][0]*a[1][1]-a[1][0]*a[0][1]);
\r
397 z = a[0][0]*a[1][1]*a[2][2] + a[0][1]*a[1][2]*a[2][0] +
\r
398 a[0][2]*a[1][0]*a[2][1] -
\r
399 (a[2][0]*a[1][1]*a[0][2] + a[1][0]*a[0][1]*a[2][2] +
\r
400 a[0][0]*a[2][1]*a[1][2]);
\r
404 Print("array_range too large for determinant calculation");
\r
408 double determinant(double a[][]){
\r
410 if(ArrayRange(a,0) != ArrayRange(a,1)){
\r
411 Print("Non-square array entered into determinant");
\r
414 switch(ArrayRange(a,0)){
\r
415 case 1: return(a[0][0]);
\r
417 case 2: return( a[0][0]*a[1][1]-a[1][0]*a[0][1]);
\r
420 z = a[0][0]*a[1][1]*a[2][2] + a[0][1]*a[1][2]*a[2][0] +
\r
421 a[0][2]*a[1][0]*a[2][1] -
\r
422 (a[2][0]*a[1][1]*a[0][2] + a[1][0]*a[0][1]*a[2][2] +
\r
423 a[0][0]*a[2][1]*a[1][2]);
\r
427 Print("array_range too large for determinant calculation");
\r
432 int MatrixAdd(double a[][], double b[][],double & c[][],double w=1){
\r
434 for(i=0;i<ArrayRange(c,0);i++){
\r
435 for(j=0;j<ArrayRange(c,1);j++){
\r
436 c[i][j] = a[i][j]+w*b[i][j];
\r
441 int MatrixMul(double a[][], double b[][],double & c[][]){
\r
443 if(ArrayRange(a,1) != ArrayRange(b,0)){
\r
444 Print("array Range Mismatch in Matrix Mul");
\r
447 for(i=0;i<ArrayRange(a,0);i++){
\r
448 for(j=0;j<ArrayRange(b,1);j++){
\r
450 for(k=0;k<ArrayRange(a,1);k++){
\r
451 c[i][j] += (a[i][k]*b[k][j]);
\r
457 int MatrixScalarMul(double b,double & a[][]){
\r
459 for(i =0;i<ArrayRange(a,0);i++){
\r
460 for(j=0;j<ArrayRange(a,1);j++){
\r
465 int MatrixInvert(double a[][],double & b[][]){
\r
467 double temp1[4][4],temp2[4][4];
\r
470 if(ArrayRange(a,0) != ArrayRange(a,1)){
\r
471 Print("Matrix Inverse attempted on non square matrix. Not implemented yet");
\r
474 if(ArrayRange(a,1) > 3){
\r
475 Print("Bugger off, not implemented yet");
\r
478 d = determinant(a);
\r
479 if(MathAbs(d)<0.000001){
\r
480 Print("unstable matrix");
\r
483 k = ArrayRange(a,0);
\r
485 b[0][0]=1./a[0][0];
\r
488 d = determinant(a);
\r
489 for(i1=0;i1<k;i1++){
\r
490 for(j1=0;j1<k;j1++){
\r
491 temp1[i1][j1] = a[i1][j1];
\r
496 //copy the arry. There must be a better way!!
\r
497 ArrayCopy(temp2,temp1);
\r
498 for(j1=0;j1<k;j1++){
\r
505 b[i][j]=determinant_fixed(temp2,k)/d;
\r
509 int MatrixTranspose(double a[][],double & b[][]){
\r
511 for(i=0;i<ArrayRange(a,0);i++){
\r
512 for(j=0;j<ArrayRange(a,1);j++){
\r
518 int MatrixZero(double & a[][]){
\r
520 for(i= 0;i<ArrayRange(a,0);i++){
\r
521 for(j=0;j<ArrayRange(a,1);j++){
\r
527 int MatrixEye(double & a[][]){
\r
529 for(i= 0;i<ArrayRange(a,0);i++){
\r
530 for(j=0;j<ArrayRange(a,1);j++){
\r
537 int MatrixPrint(double a[][]){
\r
539 for(i= 0;i<ArrayRange(a,0);i++){
\r
540 for(j=0;j<ArrayRange(a,1);j++){
\r
541 Print(i," ,",j," ,",a[i][j]);
\r
546 //+------------------------------------------------------------------+
\r