-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathAugmentedDickeyFuller.java
174 lines (155 loc) · 5.3 KB
/
AugmentedDickeyFuller.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
package tests;
import java.util.List;
import org.apache.commons.math3.linear.MatrixUtils;
import org.apache.commons.math3.linear.RealMatrix;
import org.apache.commons.math3.linear.RealVector;
public class AugmentedDickeyFuller {
private List<Double> ts;
private int lag;
private boolean needsDiff = true;
private double adfStat;
private double[] zeroPaddedDiff;
private double ADF_THRESHOLD = -3.45;
/**
* Uses the Augmented Dickey Fuller test to determine
* if ts is a stationary time series
* @param ts
* @param lag
*/
public AugmentedDickeyFuller(List<Double> ts, int lag) {
this.ts = ts;
this.lag = lag;
computeADFStatistics();
}
/**
* Uses the Augmented Dickey Fuller test to determine
* if ts is a stationary time series
* @param ts
*/
public AugmentedDickeyFuller(List<Double> ts) {
this.ts = ts;
this.lag = (int) Math.floor(Math.cbrt((ts.size() - 1)));
computeADFStatistics();
}
private void computeADFStatistics() {
double[] y = diff(ts);
RealMatrix designMatrix = null;
int k = lag+1;
int n = ts.size() - 1;
RealMatrix z = MatrixUtils.createRealMatrix(laggedMatrix(y, k)); //has rows length(ts) - 1 - k + 1
RealVector zcol1 = z.getColumnVector(0); //has length length(ts) - 1 - k + 1
double[] xt1 = subsetArray(ts, k-1, n-1); //ts[k:(length(ts) - 1)], has length length(ts) - 1 - k + 1
double[] trend = sequence(k,n); //trend k:n, has length length(ts) - 1 - k + 1
if (k > 1) {
RealMatrix yt1 = z.getSubMatrix(0, ts.size() - 1 - k, 1, k-1); //same as z but skips first column
//build design matrix as cbind(xt1, 1, trend, yt1)
designMatrix = MatrixUtils.createRealMatrix(ts.size() - 1 - k + 1, 3 + k - 1);
designMatrix.setColumn(0, xt1);
designMatrix.setColumn(1, ones(ts.size() - 1 - k + 1));
designMatrix.setColumn(2, trend);
designMatrix.setSubMatrix(yt1.getData(), 0, 3);
} else {
//build design matrix as cbind(xt1, 1, tt)
designMatrix = MatrixUtils.createRealMatrix(ts.size() - 1 - k + 1, 3);
designMatrix.setColumn(0, xt1);
designMatrix.setColumn(1, ones(ts.size() - 1 - k + 1));
designMatrix.setColumn(2, trend);
}
RidgeRegression regression = new RidgeRegression(designMatrix.getData(), zcol1.toArray());
regression.updateCoefficients(.0001);
double[] beta = regression.getCoefficients();
double[] sd = regression.getStandarderrors();
double t = beta[0] / sd[0];
adfStat = t;
if (t <= ADF_THRESHOLD) {
this.needsDiff = true;
} else {
this.needsDiff = false;
}
}
/**
* Takes finite differences of x
* @param x
* @return Returns an array of length x.length-1 of
* the first differences of x
*/
private double[] diff(List<Double> x) {
double[] diff = new double[x.size() - 1];
double[] zeroPaddedDiff = new double[x.size()];
zeroPaddedDiff[0] = 0;
for (int i = 0; i < diff.length; i++) {
double diff_i = x.get(i + 1) - x.get(i);
diff[i] = diff_i;
zeroPaddedDiff[i+1] = diff_i;
}
this.zeroPaddedDiff = zeroPaddedDiff;
return diff;
}
/**
* Equivalent to matlab and python ones
* @param n
* @return an array of doubles of length n that are
* initialized to 1
*/
private double[] ones(int n) {
double[] ones = new double[n];
for (int i = 0; i < n; i++) {
ones[i] = 1;
}
return ones;
}
/**
* Equivalent to R's embed function
* @param x time series vector
* @param lag number of lags, where lag=1 is the same as no lags
* @return a matrix that has x.length - lag + 1 rows by lag columns.
*/
private double[][] laggedMatrix(double[]x, int lag) {
double[][] laggedMatrix = new double[x.length - lag + 1][lag];
for (int j = 0; j < lag; j++) { //loop through columns
for (int i = 0; i < laggedMatrix.length; i++) {
laggedMatrix[i][j] = x[lag - j - 1 + i];
}
}
return laggedMatrix;
}
/**
* Takes x[start] through x[end - 1]
* @param x
* @param start
* @param end
* @return
*/
private double[] subsetArray(List<Double> x, int start, int end) {
double[] subset = new double[end - start + 1];
for (int i = 0; i < subset.length && i + start < x.size(); i += 1) {
subset[i] = x.get(i + start);
}
return subset;
}
/**
* Generates a sequence of ints [start, end]
* @param start
* @param end
* @return
*/
private double[] sequence(int start, int end) {
double[] sequence = new double[end - start + 1];
for (int i = start; i <= end; i++) {
sequence[i - start] = i;
}
return sequence;
}
public boolean isNeedsDiff() {
return needsDiff;
}
public double getAdfStat() {
return adfStat;
}
public double[] getZeroPaddedDiff() {
return zeroPaddedDiff;
}
public int getLag(){
return lag;
}
}