l1 trend filtering

% Written for CVX by Kwangmoo Koh - 12/10/07
%
% The problem of estimating underlying trends in time series data arises in
% a variety of disciplines. The l1 trend filtering method produces trend
% estimates x that are piecewise linear from the time series y.
%
% The l1 trend estimation problem can be formulated as
%
%    minimize    (1/2)*||y-x||^2+lambda*||Dx||_1,
%
% with variable x , and problem data y and lambda, with lambda >0.
% D is the second difference matrix, with rows [0... -1 2 -1 ...0]
%
% CVX is not optimized for the l1 trend filtering problem.
% For large problems, use l1_tf (www.stanford.edu/~boyd/l1_tf/).

% load time series data
y = csvread('snp500.txt'); % log price of snp500
n = length(y);

% form second difference matrix
e = ones(n,1);
D = spdiags([e -2*e e], 0:2, n-2, n);

% set regularization parameter
lambda = 50;

% solve l1 trend filtering problem
cvx_begin
    variable x(n)
    minimize( 0.5*sum_square(y-x)+lambda*norm(D*x,1) )
cvx_end

% plot estimated trend with original signal
figure(1);
plot(1:n,y,'k:','LineWidth',1.0); hold on;
plot(1:n,x,'b-','LineWidth',2.0); hold off;
xlabel('date'); ylabel('log price');
 
Calling sedumi: 5998 variables, 1999 equality constraints
------------------------------------------------------------
SeDuMi 1.21 by AdvOL, 2005-2008 and Jos F. Sturm, 1998-2003.
Alg = 2: xz-corrector, Adaptive Step-Differentiation, theta = 0.250, beta = 0.500
eqs m = 1999, order n = 3999, dim = 5999, blocks = 2000
nnz(A) = 7993 + 1, nnz(ADA) = 9985, nnz(L) = 5992
Handling 1 + 1 dense columns.
 it :     b*y       gap    delta  rate   t/tP*  t/tD*   feas cg cg  prec
  0 :            1.96E+05 0.000
  1 :  -4.26E+00 5.27E+03 0.000 0.0269 0.9900 0.9900   1.88  1  1  7.9E-01
  2 :  -1.09E-01 2.08E+02 0.000 0.0395 0.9900 0.9900   1.02  1  1  7.0E-01
  3 :   3.55E-01 1.14E+02 0.000 0.5465 0.9000 0.9000   1.00  1  1  6.9E-01
  4 :   6.72E-01 6.41E+01 0.000 0.5632 0.9000 0.9000   1.00  1  1  6.9E-01
  5 :   7.94E-01 3.14E+01 0.000 0.4891 0.9000 0.9000   1.00  1  1  6.8E-01
  6 :   9.32E-01 1.41E+01 0.000 0.4508 0.9134 0.9000   1.00  1  1  6.5E-01
  7 :   1.03E+00 8.94E+00 0.000 0.6322 0.9000 0.9111   1.00  1  1  6.2E-01
  8 :   1.14E+00 6.39E+00 0.151 0.7149 0.9000 0.9597   1.00  1  1  5.9E-01
  9 :   1.21E+00 4.49E+00 0.000 0.7029 0.9000 0.8678   1.00  1  1  5.5E-01
 10 :   1.27E+00 1.36E+00 0.000 0.3019 0.9403 0.9000   1.00  1  1  3.6E-01
 11 :   1.32E+00 9.01E-01 0.000 0.6647 0.9000 0.9198   1.00  1  1  2.8E-01
 12 :   1.36E+00 6.26E-01 0.000 0.6942 0.9000 0.9524   1.00  1  1  2.2E-01
 13 :   1.38E+00 3.63E-01 0.000 0.5795 0.9000 0.9118   1.00  1  1  1.4E-01
 14 :   1.39E+00 2.27E-01 0.000 0.6255 0.9000 0.9468   1.00  1  1  9.7E-02
 15 :   1.40E+00 8.23E-02 0.000 0.3629 0.9247 0.9000   1.00  1  1  3.9E-02
 16 :   1.40E+00 4.59E-02 0.000 0.5571 0.9000 0.9336   1.00  2  2  2.2E-02
 17 :   1.40E+00 2.26E-02 0.000 0.4938 0.9000 0.9390   1.00  2  2  1.1E-02
 18 :   1.40E+00 9.78E-03 0.000 0.4317 0.9000 0.9188   1.00  2  2  4.8E-03
 19 :   1.40E+00 3.91E-03 0.000 0.4000 0.9020 0.9000   1.00  1  2  1.9E-03
 20 :   1.40E+00 9.12E-04 0.000 0.2333 0.9027 0.9000   1.00  1  2  4.5E-04
 21 :   1.40E+00 1.53E-04 0.000 0.1681 0.9107 0.9000   1.00  2  2  7.6E-05
 22 :   1.40E+00 1.17E-05 0.000 0.0764 0.9903 0.9900   1.00  2  2  5.8E-06
 23 :   1.40E+00 3.46E-06 0.000 0.2956 0.9000 0.9047   1.00  2  2  1.7E-06
 24 :   1.40E+00 1.22E-06 0.000 0.3516 0.9000 0.9049   1.00  2  2  6.0E-07
 25 :   1.40E+00 4.79E-07 0.008 0.3937 0.9000 0.9086   1.00  2  2  2.4E-07
 26 :   1.40E+00 1.86E-07 0.000 0.3889 0.9000 0.9178   1.00  2  2  9.2E-08
 27 :   1.40E+00 6.34E-08 0.004 0.3401 0.9000 0.9203   1.00  2  2  3.1E-08
 28 :   1.40E+00 1.87E-08 0.160 0.2950 0.9000 0.9156   1.00  2  2  9.2E-09

iter seconds digits       c*x               b*y
 28      1.0   7.9  1.4016181717e+00  1.4016181530e+00
|Ax-b| =   1.3e-13, [Ay-c]_+ =   0.0E+00, |x|=  2.1e+00, |y|=  1.5e+03

Detailed timing (sec)
   Pre          IPM          Post
3.000E-02    1.000E+00    0.000E+00    
Max-norms: ||b||=1, ||c|| = 50,
Cholesky |add|=0, |skip| = 0, ||L.L|| = 1.99236.
------------------------------------------------------------
Status: Solved
Optimal value (cvx_optval): +1.40162