forked from cab79/Matlab_files
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathboxcox.m
127 lines (96 loc) · 3.88 KB
/
boxcox.m
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
function [bct, bclambda] = boxcox(varargin)
%BOXCOX transforms non-normally distributed data to normally distributed data.
%
% [TRANSDAT, LAMBDA] = boxcox(DATA) transforms the data vector DATA using
% the Box-Cox Transformation method into the vector TRANSDAT. It also
% calculates the transformation parameter LAMBDA. DATA must be positive.
% The Box-Cox Transformation is the family of power transformation:
%
% DATA(LAMBDA) = ((DATA^LAMBDA) - 1) / LAMBDA; if LAMBDA ~= 0,
%
% or
%
% DATA(LAMBDA) = log(DATA); if LAMBDA == 0.
%
% Here, 'log' is the natural logarithm (log base e). The algorithm calls
% for finding the LAMBDA value that maximizes the Log-Likelihood Function
% (LLF). The search is conducted using FMINSEARCH.
%
% TRANSDAT = boxcox(LAMBDA, DATA) transforms the data vector DATA using
% a certain specified LAMBDA for the Box-Cox Transformation. This syntax
% does not find the optimum LAMBDA that maximizes the LLF. DATA must be
% positive.
%
% Example:
%
% load disney.mat
% % Look at the non-NaN data only
% X = dis_CLOSE(~isnan(dis_CLOSE));
% [Xbc, lambdabc] = boxcox(X);
% hist(Xbc);
%
% See also FMINSEARCH.
% Copyright 1995-2013 The MathWorks, Inc.
% Input checks.
switch nargin
case 1
% Syntax: BCT = boxcox(DATA);
% Find the maximum log-likelihood lambda and compute the transform
% Get the data vector.
x = varargin{1};
if ~isvector(x)
error(message('finance:ftseries:ftseries_boxcox:InputMustBeVector'));
end
if any(x <= 0)
error(message('finance:ftseries:ftseries_boxcox:DataMustBePositive'));
end
% Find the lambda that minimizes of the Log-Likelihood function;
% FMINSEARCH is used here so that we don't need to provide a set
% of boundary initial conditions. We only need a number as the
% starting point of search.
objectiveFun = @(l) logLikelihood(l,x);
options = optimset('MaxFunEvals', 2000, 'Display', 'off');
bclambda = fminsearch(objectiveFun, 0, options);
% Generate the transformed data using the optimal lambda.
bct = bcTransform(bclambda,x);
case 2
% Syntax: BCT = boxcox(LAMBDA, DATA);
% Compute the transform for a given lambda
% Get the lambda and data vectors.
lambda = varargin{1};
x = varargin{2};
bct = bcTransform(lambda,x);
otherwise
error(message('finance:ftseries:ftseries_boxcox:TooManyInputArguments'));
end
function llf = logLikelihood(lambda,x)
% Compute the log likelihood function for a given lambda and x
% Get the length of the data vector.
n = length(x);
% Transform data using a particular lambda.
xhat = bcTransform(lambda,x);
% The algorithm calls for maximizing the LLF; however, since we
% have only functions that minimize, the LLF is negated so that we
% can minimize the function instead of maximixing it to find the
% optimum lambda.
llf = -(n/2) .* log(std(xhat, 1, 1)' .^ 2) + (lambda-1)*(sum(log(x)));
llf = -llf;
function bct = bcTransform(lambda,x)
% Perform the actual box-cox transform.
% Get the length of the data vector.
n = length(x);
% Make sure that the lambda vector is a column vector.
lambda = lambda(:);
% Find where the non-zero and zero lambda's are.
nzlambda = find(lambda ~= 0);
zlambda = find(lambda == 0);
% Create a matrix of the data by replicating the data vector
% columnwise.
mx = x * ones(1, length(lambda));
% Create a matrix of the lambda by replicating the lambda vector
% rowwise.
mlambda = (lambda * ones(1, n))';
% Calculate the transformed data vector, xhat.
bct(:, nzlambda) = ((mx(:, nzlambda).^mlambda(:, nzlambda))-1) ./ ...
mlambda(:, nzlambda);
bct(:, zlambda) = log(mx(:, zlambda));