| 1 | ////////////////////////////////////////////////////////////////////////////// |
|---|
| 2 | // FILE : _posEstimation.tol |
|---|
| 3 | // AUTHOR : Luis Miguel Pérez Liberal (lmperez@bayesinf.com) |
|---|
| 4 | // PURPOSE : Post-Estimation diagnosis functions |
|---|
| 5 | ////////////////////////////////////////////////////////////////////////////// |
|---|
| 6 | |
|---|
| 7 | |
|---|
| 8 | ////////////////////////////////////////////////////////////////////////////// |
|---|
| 9 | Set BPL(Serie serie, Text arima, Real autocorr, Real alpha) |
|---|
| 10 | ////////////////////////////////////////////////////////////////////////////// |
|---|
| 11 | { |
|---|
| 12 | Text label = If(arima=="ARIMA","P1_7DIF0_1AR1_0MA0_7",arima); |
|---|
| 13 | Set arima = GetArimaFromLabel(label); |
|---|
| 14 | |
|---|
| 15 | Real rAR = Card(Monomes(ARIMAGetAR(arima))-[[ Polyn 1 ]]); |
|---|
| 16 | Real rMA = Card(Monomes(ARIMAGetMA(arima))-[[ Polyn 1 ]]); |
|---|
| 17 | Real deg = Degree(ARIMAGetDIF(arima)); |
|---|
| 18 | |
|---|
| 19 | Real bpl = BoxPierceLjung(serie,autocorr,rAR,rMA); |
|---|
| 20 | Real bpl_D = BoxPierceLjung(serie,autocorr*deg,rAR,rMA); |
|---|
| 21 | |
|---|
| 22 | Real gl = autocorr - rAR - rMA; |
|---|
| 23 | Real glD = autocorr*deg - rAR - rMA; |
|---|
| 24 | |
|---|
| 25 | Real chi = DistChiInv(1-alpha/2,gl); |
|---|
| 26 | Real chiD = DistChiInv(1-alpha/2,glD); |
|---|
| 27 | |
|---|
| 28 | Real t_blp = GT( Abs(bpl), chi ); |
|---|
| 29 | Real t_blp_D = GT( Abs(bpl_D),chiD ); |
|---|
| 30 | |
|---|
| 31 | Set Eval("Set _.BPL."+Name(serie)+" = [[ t_blp, t_blp_D ]];") |
|---|
| 32 | }; |
|---|
| 33 | ////////////////////////////////////////////////////////////////////////////// |
|---|
| 34 | PutDescription("Realiza un contraste de hipotesis BoxPierceLjung sobre las |
|---|
| 35 | autocorrelaciones dadas (autocorr) dado un arima (como etiqueta). |
|---|
| 36 | Devuelve verdadero si se rechaza la hipotesis y falso si se acepta. |
|---|
| 37 | t_blp es el resultado para las autocorrelaciones dadas, y t_blp_D es el |
|---|
| 38 | resultado del test para las autocorrelaciones dadas multiplicada por el grado |
|---|
| 39 | de la diferencia del arima.", |
|---|
| 40 | BPL); |
|---|
| 41 | ////////////////////////////////////////////////////////////////////////////// |
|---|
| 42 | |
|---|
| 43 | |
|---|
| 44 | ////////////////////////////////////////////////////////////////////////////// |
|---|
| 45 | Set Analisis.Residuals(Serie serie,Real nParametros, Real nParametrosArima, |
|---|
| 46 | Real alpha) |
|---|
| 47 | ////////////////////////////////////////////////////////////////////////////// |
|---|
| 48 | { |
|---|
| 49 | Real med = AvrS(serie); |
|---|
| 50 | Real sig = StDsS(serie); |
|---|
| 51 | Real asi = AsimetryS(serie); |
|---|
| 52 | Real kur = KurtosisS(serie); |
|---|
| 53 | |
|---|
| 54 | Real asi_teo = AsimetryS(Gaussian(med,sig)); |
|---|
| 55 | Real kur_teo = KurtosisS(Gaussian(med,sig)); |
|---|
| 56 | |
|---|
| 57 | Real t = med/sig; |
|---|
| 58 | Real gl = CountS(serie) - nParametrosArima - nParametros; |
|---|
| 59 | //Real alpha = 0.10; |
|---|
| 60 | Real p_med = DistTInv(1-alpha/2,gl); |
|---|
| 61 | |
|---|
| 62 | Real test_med = GT( Abs(t),p_med ); |
|---|
| 63 | |
|---|
| 64 | Serie uno = Not(serie)+Not(Not(serie)); |
|---|
| 65 | Serie norm = (serie - med*uno)/StDsS(serie); |
|---|
| 66 | Real sig1 = SumS(IfSer(GT(Abs(norm),uno*1),1,0))/SumS(uno); |
|---|
| 67 | Real sig2 = SumS(IfSer(GT(Abs(norm),uno*2),1,0))/SumS(uno); |
|---|
| 68 | Real sig3 = SumS(IfSer(GT(Abs(norm),uno*3),1,0))/SumS(uno); |
|---|
| 69 | Set end = [[ med,sig,asi,asi_teo,kur,kur_teo,test_med,sig1,sig2,sig3 ]]; |
|---|
| 70 | |
|---|
| 71 | Set Eval("Set "+Name(serie)+" = end;") |
|---|
| 72 | }; |
|---|
| 73 | ////////////////////////////////////////////////////////////////////////////// |
|---|
| 74 | PutDescription("Dada una serie de residuos, devuelve: |
|---|
| 75 | Media |
|---|
| 76 | Sigma |
|---|
| 77 | Asimetria y Asimetría teórica |
|---|
| 78 | Kurtosis y Kurtosis teórica |
|---|
| 79 | Test media distinta de cero |
|---|
| 80 | Numero de residuos fuera de una, dos y tres sigmas. |
|---|
| 81 | |
|---|
| 82 | Precisa que le digamos el alpha como el área fuera de la curva para el test |
|---|
| 83 | de la media", |
|---|
| 84 | Analisis.Residuals); |
|---|
| 85 | ////////////////////////////////////////////////////////////////////////////// |
|---|
| 86 | |
|---|
| 87 | |
|---|
| 88 | ////////////////////////////////////////////////////////////////////////////// |
|---|
| 89 | Set Analisis.Rachas(Serie residuos, Real max) |
|---|
| 90 | ////////////////////////////////////////////////////////////////////////////// |
|---|
| 91 | { |
|---|
| 92 | // Crea un polinomio del tipo 1+B+B^2+...+B^k |
|---|
| 93 | Polyn PolAcu_K(Polyn operador,Real k){ |
|---|
| 94 | SetSum( For(0,k,Polyn (Real j){ operador^j }) ) |
|---|
| 95 | }; |
|---|
| 96 | |
|---|
| 97 | // Cuenta las fechas de una serie de rachas, cuenta hacia delante y hacia |
|---|
| 98 | // atras para evitar que se elimine la primera fecha de la racha |
|---|
| 99 | Set DatesRacha(Serie racha) |
|---|
| 100 | { |
|---|
| 101 | Set For(1,max,Set (Real j) |
|---|
| 102 | { |
|---|
| 103 | Serie I = Not(racha)+Not(Not(racha)); |
|---|
| 104 | Serie s1 = IfSer(EQ(PolAcu_K(B,j):racha,I*(j+1)),1,0); |
|---|
| 105 | Serie s2 = IfSer(EQ(PolAcu_K(F,j):racha,I*(j+1)),1,0); |
|---|
| 106 | Set dates = DatesInd(s1+s2) |
|---|
| 107 | }) |
|---|
| 108 | }; |
|---|
| 109 | |
|---|
| 110 | // Calcula el numero de ocurrencias de cada racha |
|---|
| 111 | Set DistRacha(Set datesRacha, Serie residuos, Text signo) |
|---|
| 112 | { |
|---|
| 113 | Real med = AvrS(residuos); |
|---|
| 114 | // cojo la sigma de los residuos porque al caso lo que me interesa es la |
|---|
| 115 | // media, y así no tengo que tener en cuenta la transformación |
|---|
| 116 | Real sig = StDsS(residuos); |
|---|
| 117 | Real prb = Case( |
|---|
| 118 | signo=="+", 1-DistNormal(0,med,sig), |
|---|
| 119 | signo=="-", DistNormal(0,med,sig), |
|---|
| 120 | True,"ERROR" |
|---|
| 121 | ); |
|---|
| 122 | |
|---|
| 123 | Text label = Case( |
|---|
| 124 | signo=="+", "pos", |
|---|
| 125 | signo=="-", "neg", |
|---|
| 126 | True,"ERROR" |
|---|
| 127 | ); |
|---|
| 128 | |
|---|
| 129 | Set For(1,Card(datesRacha)-1,Set (Real j) |
|---|
| 130 | { |
|---|
| 131 | Set dates = datesRacha[j] - datesRacha[j+1]; |
|---|
| 132 | Real observado = Card(dates); |
|---|
| 133 | // No es el número de observaciones, hay que restarle la racha menos 1 |
|---|
| 134 | Real longitud = CountS(residuos)-(j+1-1); |
|---|
| 135 | Real teorico = Round((prb^(j+1))*longitud,2); |
|---|
| 136 | Set Eval("Set rch_"+IntText(j+1)+" = [[ |
|---|
| 137 | Eval(\"Real observado_\"+label+\" = observado;\"), |
|---|
| 138 | Eval(\"Real teorico_\"+label+\" = teorico;\") |
|---|
| 139 | ]];") |
|---|
| 140 | }) |
|---|
| 141 | }; |
|---|
| 142 | |
|---|
| 143 | Serie uno = Not(residuos)+Not(Not(residuos)); |
|---|
| 144 | Serie not = Not(uno); |
|---|
| 145 | |
|---|
| 146 | Serie rch_pos = IfSer(GT(residuos,not),1,0); |
|---|
| 147 | Serie rch_neg = IfSer(LT(residuos,not),1,0); |
|---|
| 148 | |
|---|
| 149 | Set sDtsRchPos = DatesRacha(rch_pos); |
|---|
| 150 | Set sDtsRchNeg = DatesRacha(rch_neg); |
|---|
| 151 | |
|---|
| 152 | Set DistRacha(sDtsRchPos,residuos,"+")|DistRacha(sDtsRchNeg,residuos,"-") |
|---|
| 153 | }; |
|---|
| 154 | ////////////////////////////////////////////////////////////////////////////// |
|---|
| 155 | PutDescription("Devuelve el numero de rachas de residuos de igual signo |
|---|
| 156 | consecutivos junto a la esperada teóricamente.", |
|---|
| 157 | Analisis.Rachas); |
|---|
| 158 | ////////////////////////////////////////////////////////////////////////////// |
|---|
| 159 | |
|---|
| 160 | |
|---|
| 161 | ////////////////////////////////////////////////////////////////////////////// |
|---|
| 162 | Set LookFor.VarianceChanges(Serie serie, Real long) |
|---|
| 163 | ////////////////////////////////////////////////////////////////////////////// |
|---|
| 164 | { |
|---|
| 165 | // Serie serie = var; |
|---|
| 166 | // Real long = 40; |
|---|
| 167 | Date iniDate = First(serie); |
|---|
| 168 | Date endDate = Last(serie); |
|---|
| 169 | TimeSet tms = Dating(serie); |
|---|
| 170 | |
|---|
| 171 | Real card = Floor( |
|---|
| 172 | SumS(Not(serie)+Not(Not(serie)))/long |
|---|
| 173 | ); |
|---|
| 174 | |
|---|
| 175 | Serie null = SubNullSer(tms,Succ(endDate,tms,-(long*card-1)),endDate); |
|---|
| 176 | |
|---|
| 177 | Set sPerform = For(1,card,Serie (Real j) |
|---|
| 178 | {// Real j = 1; |
|---|
| 179 | Date iniPerform = Succ(endDate,tms,-long*(j-1)); |
|---|
| 180 | Date endPerform = Succ(endDate,tms,-(long*j-1)); |
|---|
| 181 | |
|---|
| 182 | //--> Las fechas están cambiadas bien.Es para empezar desde el final |
|---|
| 183 | Serie sub = SubSer(serie,endPerform,iniPerform ); |
|---|
| 184 | Serie ci = SubSer(CalInd(In(endPerform,iniPerform),tms), |
|---|
| 185 | endPerform, |
|---|
| 186 | iniPerform |
|---|
| 187 | ); |
|---|
| 188 | |
|---|
| 189 | //--> Saco la desviacion standard de los no nulos |
|---|
| 190 | Real sig = StDsS(AutoDating(sub)); |
|---|
| 191 | |
|---|
| 192 | Serie end = sig*( null << ci >> null ) |
|---|
| 193 | }); |
|---|
| 194 | |
|---|
| 195 | Serie sum = SetSumC(sPerform); |
|---|
| 196 | Serie dif = (1-B):sum; |
|---|
| 197 | |
|---|
| 198 | //--> Elijo como candidatos a priori los mayores de dos sigmas |
|---|
| 199 | Serie candidates = IfSer(LT(Serie Abs(dif),2*StDsS(AutoDating(dif))),0,dif); |
|---|
| 200 | |
|---|
| 201 | //--> La Kurtosis me dice si la distribucion es una normal, si es una |
|---|
| 202 | // uniforme o en cambio es un pico |
|---|
| 203 | Real rKurtosis = KurtosisS(AutoDating(dif)); |
|---|
| 204 | |
|---|
| 205 | //--> La Kurtosis de una normal es 0, le doy 0.4 más para evitarme problemas |
|---|
| 206 | // de distribuciones muy parecidas a las normales |
|---|
| 207 | Real rCriterium = 0 + 0.4; |
|---|
| 208 | Set sCandidates = If(Real Abs(rKurtosis)>rCriterium, |
|---|
| 209 | DatesInd(candidates), |
|---|
| 210 | Empty |
|---|
| 211 | ); |
|---|
| 212 | |
|---|
| 213 | //--> Me quedo con el último más long |
|---|
| 214 | Date day = If( Card(sCandidates)>0, |
|---|
| 215 | sCandidates[Card(sCandidates)], |
|---|
| 216 | iniDate |
|---|
| 217 | ); |
|---|
| 218 | |
|---|
| 219 | Set [[ sum,dif,candidates,day,rKurtosis ]] |
|---|
| 220 | }; |
|---|
| 221 | ////////////////////////////////////////////////////////////////////////////// |
|---|
| 222 | PutDescription("Busca cambios de varianza en una serie temporal. Recibe la |
|---|
| 223 | serie que queramos estudiar y un numero real, que es un intervalo de dias. A |
|---|
| 224 | continuacion divide la serie en intervalos de longitud \"long\" y estudia los |
|---|
| 225 | cambios de varianza que se producen entre intervalos. Retorna un set con tres |
|---|
| 226 | series. La primera muestra la varianza a intervalos (long), el segundo la |
|---|
| 227 | serie diferenciada y la tercera la serie deiferenciada filtrada de candidatos |
|---|
| 228 | pequeños las que informan sobre los posibles candidatos, junto con una fecha |
|---|
| 229 | del dia más probable donde ocurra un cambio de varianza. Esto siempre y cuando |
|---|
| 230 | la distribucion de los candidatos sea más picuda que una normal, en tal caso se |
|---|
| 231 | considera que no hay cambio de varianza importante.", |
|---|
| 232 | LookFor.VarianceChanges); |
|---|
| 233 | ////////////////////////////////////////////////////////////////////////////// |
|---|
| 234 | |
|---|
| 235 | |
|---|
| 236 | ////////////////////////////////////////////////////////////////////////////// |
|---|
| 237 | Date VarianceChange(Serie serie, Real long) |
|---|
| 238 | ////////////////////////////////////////////////////////////////////////////// |
|---|
| 239 | { |
|---|
| 240 | Real iniTest = Floor(long/20); |
|---|
| 241 | Real endTest = Floor(long/3); |
|---|
| 242 | |
|---|
| 243 | Set test = For(iniTest,endTest,Set (Real j) |
|---|
| 244 | { |
|---|
| 245 | Set research = LookFor.VarianceChanges(serie,10*j); |
|---|
| 246 | Set proof = If(Card(research)>0,research,Empty); |
|---|
| 247 | |
|---|
| 248 | Set PutName("Intervalo_"+IntText(j),proof) |
|---|
| 249 | }); |
|---|
| 250 | |
|---|
| 251 | Set sPulses = For(1,Card(test),Serie (Real k) |
|---|
| 252 | { |
|---|
| 253 | Date d = test[k][4]; |
|---|
| 254 | Serie SubSer(Pulse(d,Diario),First(serie),Last(serie)) |
|---|
| 255 | }); |
|---|
| 256 | |
|---|
| 257 | Serie pulses = SetSum(sPulses); |
|---|
| 258 | Serie select = IfSer(LT(Serie Abs(pulses),StDsS(AutoDating(pulses))),0,pulses); |
|---|
| 259 | |
|---|
| 260 | Set sSelectcandidates = DatesInd(select); |
|---|
| 261 | |
|---|
| 262 | Date DayOfChange = If(Card(sSelectcandidates)>0, |
|---|
| 263 | sSelectcandidates[Card(sSelectcandidates)], |
|---|
| 264 | IniDate |
|---|
| 265 | ) |
|---|
| 266 | }; |
|---|
| 267 | ////////////////////////////////////////////////////////////////////////////// |
|---|
| 268 | PutDescription("Hace un estudio iterativo de la serie que le pasas, y devuelve |
|---|
| 269 | la fecha que estima que se ha producido un cambio de varianza. Si no detecta |
|---|
| 270 | cambio alguno, devuelve la primera fecha de la serie. El campo \"long\" es el |
|---|
| 271 | intervalo de dias en los que divide internamente la serie", |
|---|
| 272 | VarianceChange); |
|---|
| 273 | ////////////////////////////////////////////////////////////////////////////// |
|---|
| 274 | |
|---|
| 275 | |
|---|
| 276 | ////////////////////////////////////////////////////////////////////////////// |
|---|
| 277 | // END |
|---|
| 278 | ////////////////////////////////////////////////////////////////////////////// |
|---|