www.gusucode.com > 基于matlab编程kalman滤波处理源码程序 > 基于matlab编程kalman滤波处理源码程序/code/MainSS.m

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This Matlab Script estimates the parameters of the model presented in Schwartz-Smith 
% (2000) paper(Short-Term Variations and Long-Term Dynamics in Commodity Prices).
% NOTE: it can take up to 10 minutes for the estimation to complete.
% 
% Produced by Dominice Goodwin (May 2013) to conduct the empirical study in
% master thesis D. Goodwin (2013):
% (http://www.lunduniversity.lu.se/o.o.i.s?id=24965&postid=3809118)
% 
% Contact: dominice.goodwin@gmail.com
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clc; clear; format short; load data; % Spot data in first column. All prices in log.

which_model = 1;
% [1 = Schwartz-Smith (2000) Model on the approximately the same Crude Oil
% data as used in this article.]

if which_model == 1 % Schwartz-Smith (2000) on crude oil data
    
    %%% INPUT SETTINGS %%%
    data = ss2000OilData;                   % Specify which variable that contains data for estimation (Column1 = Spot, Column2 = Future(Shortest Maturity)...) 
    include_spot_in_estimation = 0;         % [0 = No, 1 = Yes (Include the first column of Spot data in estimation)]
    Num_Contracts = 5;                      % # of future contracts in data to use
    matur = [1/12,5/12,9/12,13/12,17/12];   % Maturities of included contracts
    frequency = 1;                          % [1 = all observations in data variables are considered, 2 = every second observation is considered, ...] (This data is weekly .. so frequency = 1 -> weekly frequency. 
    dt = 7/360;                             % Time step size (Since weekly data) to get parameters on per year basis.
    start_obs = 1;                          % Start at first observation in data.
    end_obs = 268;                          % End at last observation in data.
    
% The standard errors are obtained from the hessian. However, since the model estimates the parameters 
% so that the one or a couple of futures contracts are matched with close to zero measurement errors, 
% leading to that the measurement error covariance matrix (usually) is positive semi-defined.
% --> Matlab error: Warning: Matrix is close to singular or badly scaled. Results may be inaccurate.

% To be able to invert the hessian and obtain standard errors the following
% ad hoc approach can be used:
%  - Once it is known which of the future contracts is matched with close to zero measurement errors 
% the estimation can be redone with the corresponding elements in measurement error covariance matrix 
% restricted to zero and thus excluded from the estimation. In this way measurement error covariance matrix 
% is positive defined and invertible.
    locked_parameters = 4;                  % [ 0 = No parameter locked, 1 to ... = Forces a measurement error parameter to be Zero] 
                                            % OBS: This data requiers locked_parameters = 4; 
                                            
    %%% SELECT INITIAL VALUES %%%
    k       = 2;                            % NOTE: These initial values have to be changed manually in order to find a Global Maximum Log-Likelihood Score
    sigmax  = 0.2;
    lambdax = 0.2;
    mu      = 0.02;
    sigmae  = 0.2;
    rnmu    = 0.02;
    pxe     = 0.2;
    s_guess = 0.01;
    initial_statevector = [0;3.1307];       % Initial state vector m(t)=E[xt;et] 
    initial_dist = [0.01,0.01;0.01,0.01];   % Initial covariance matrix for the state variables C(t)=cov[xt,et]
end  


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% ADJUSTING DATA ACCORDING TO INPUTS %%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
data_SelectedPeriod = data(start_obs:end_obs,1:end);
num_obs = size(data_SelectedPeriod,1);
if frequency ~= 1
    new_num_obs = floor((num_obs-1)/frequency);
    data_SelectedPeriod_SelectedFrequency = zeros(new_num_obs,size(data_SelectedPeriod,2));
    data_SelectedPeriod_SelectedFrequency(1,:) = data_SelectedPeriod(1,:);
    for t = 1:new_num_obs
        data_SelectedPeriod_SelectedFrequency(t+1,:) = data_SelectedPeriod((t*frequency)+1,:);
    end
else
    data_SelectedPeriod_SelectedFrequency = data_SelectedPeriod;
end


St = data_SelectedPeriod_SelectedFrequency(1:end,1);
if include_spot_in_estimation == 1
    y  = data_SelectedPeriod_SelectedFrequency(1:end,1:Num_Contracts);                 
else
    y  = data_SelectedPeriod_SelectedFrequency(1:end,2:Num_Contracts+1); 
end

% y is a {nobs x N} Matrix, N = number of future contracts, nobs = number of observations
nobs = size(y,1);
N    = size(y,2);
num_locked_parameters = size(locked_parameters,1);



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Optimizing the parameters with the Kalman filter & MLE
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Placeholders & Variable def.
global save_att save_vtt save_vt  save_dFtt_1 save_vFv save_Ptt_1 save_Ftt_1 save_Ptt
lnL_scores = zeros(3,1);
boundary = Inf;

% Running the estimation for The S&S 2 factor model and two benchmark
% models (The GBM model and the Ornstein-Uhlenbeck model).
for model = 1:3 % [1 = The S&S 2 factor model, 2 = The GBM modell, 3 = The Ornstein-Uhlenbeck model.]
    if model == 1 % The S&S 2 factor model
        if sum(locked_parameters) == 0
     
            psi = zeros(7+N,1);
            psi(1:7,1) = [k, sigmax, lambdax, mu, sigmae, rnmu, pxe]';
            psi(8:end,1) = s_guess;
            
            lb = zeros(7+N,1);
            lb(1:7,1) = [0, 0, -boundary, -boundary, 0, -boundary, -1]';
            lb(8:end,1) = 0.0000001;
            
            ub = zeros(7+N,1);
            ub(1:7,1) = [boundary, boundary, boundary, boundary, boundary, boundary, 1]';
            ub(8:end,1) = boundary;
        else
            psi = zeros(7+N-num_locked_parameters,1);
            psi(1:7,1) = [k, sigmax, lambdax, mu, sigmae, rnmu, pxe]';
            psi(8:end,1) = s_guess;
            
            lb = zeros(7+N-num_locked_parameters,1);
            lb(1:7,1) = [0, 0, -boundary, -boundary, 0, -boundary, -1]';
            lb(8:end,1) = 0.0000001;
            
            ub = zeros(7+N-num_locked_parameters,1);
            ub(1:7,1) = [boundary, boundary, boundary, boundary, boundary, boundary, 1]';
            ub(8:end,1) = boundary;         
        end
        a0 = initial_statevector;
        P0 = initial_dist;
    end
    if model == 2 % The GBM model
       locked_parameters(1:end,1) = 0;
        
       psi = zeros(7+N,1);
       psi(1:7,1) = [k, sigmax, lambdax, mu, sigmae, rnmu, pxe]';
       psi(8:end,1) = s_guess;
        
       lb = zeros(7+N,1);
       lb(1:7,1) = [0, 0, 0, -boundary, 0, -boundary, -1]';
       lb(8:end,1) = 0;
            
       ub = zeros(7+N,1);
       ub(1:7,1) = [0.0001, 0, 0, boundary, boundary, boundary, 1]';
       ub(8:end,1) = boundary;
        
        a0 = [0;initial_statevector(1) + initial_statevector(2)];
        P0 = [0,0;0,initial_dist(2,2)];
    end
    if model == 3 % The Ornstein-Uhlenbeck model
        locked_parameters(1:end,1) = 0;
        
        psi = zeros(7+N,1);
        psi(1:7,1) = [k, sigmax, lambdax, mu, sigmae, rnmu, pxe]';
        psi(8:end,1) = s_guess;
        
        lb = zeros(7+N,1);
        lb(1:7,1) = [0, 0, -boundary, 0, 0, 0, -1]';
        lb(8:end,1) = 0;
            
        ub = zeros(7+N,1);
        ub(1:7,1) = [5, boundary, boundary, 0, 0, 0, 1]';
        ub(8:end,1) = boundary;
        
        a0 = [initial_statevector(1,1); mean(ss_att(1:end,2))];
        P0 = [initial_dist(1,1),0;0,0];
    end
    
    % Running estimation
    options = optimset('Algorithm','interior-point','Display','off'); %interior-point active-set
    MaxlnL_Kalman = @(psi) Kalman_Estimation(y, psi, matur, dt, a0, P0, N, nobs, locked_parameters);
    [psi_optimized, log_L,exitflag,output,lambda,grad,hessian] = fmincon(MaxlnL_Kalman, psi, [], [],[], [], lb, ub, [], options);

    % Saving estimation output
    lnL_scores(model,1) = -log_L;

    if model == 1
        ss_att = save_att;
        ss_vtt = save_vtt;
        ss_vt = save_vt;
        ss_dFtt_1 = save_dFtt_1;
        ss_vFv = save_vFv;
        ss_Ptt_1 = save_Ptt_1;
        ss_Ftt_1 = save_Ftt_1;
        ss_Ptt = save_Ptt;
        
        if sum(locked_parameters) == 0
             ss_psi_estimate = [psi_optimized(1:7,1);sqrt(psi_optimized(8:end,1))];
             ss_SE = sqrt(diag(inv(hessian)));
        else      
            prel_SE = sqrt(diag(inv(hessian)));
            prel_ss_psi_estimate = zeros(size(psi,1)+size(locked_parameters,1),1);
            ss_SE = zeros(size(psi,1)+size(locked_parameters,1),1);
            j = 1;
            for i = 1:size(prel_ss_psi_estimate,1)
                 if all(abs(i-(locked_parameters+7))) == 1
                     prel_ss_psi_estimate(i,1) = psi_optimized(j,1);
                     ss_SE(i,1) = prel_SE(j,1);
                     j = j+1;
                 else
                     prel_ss_psi_estimate(i,1) = 0;
                     ss_SE(i,1) = 0;
                 end
            end
            ss_psi_estimate = [prel_ss_psi_estimate(1:7,1);sqrt(prel_ss_psi_estimate(8:end,1))];
         end
    end
       
   
    if model == 2
        gbm_att = save_att;
        gbm_vtt = save_vtt;
        gbm_psi_estimate = [psi_optimized(1:7,1);sqrt(psi_optimized(8:end,1))];
    end
    if model == 3
        ou_att = save_att;
        ou_vtt = save_vtt;
        ou_psi_estimate = [psi_optimized(1:7,1);sqrt(psi_optimized(8:end,1))];
    end
end


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Calculating/outputing key statistics
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Output
ss_psi_estimate
ss_SE
gbm_psi_estimate
ou_psi_estimate

% S&S Model fit 
ss_Mean_Error = mean(ss_vtt)'
ss_Std_of_Error = std(ss_vtt)'
ss_MAE = mean(abs(ss_vtt))'

% GBM Model fit 
GBM_Mean_Error = mean(gbm_vtt)'
GBM_Std_of_Error = std(gbm_vtt)'
GBM_MAE = mean(abs(gbm_vtt))'

% OU Model fit 
OU_Mean_Error = mean(ou_vtt)'
OU_Std_of_Error = std(ou_vtt)'
OU_MAE = mean(abs(ou_vtt))'

% Performance
lnL_scores

LR_SSvsGBM = -2*(lnL_scores(2,1)-lnL_scores(1,1))
p_value_SSvsGBM = 1-chi2cdf(LR_SSvsGBM, 2) %(Value, DF)

LR_SSvsOU = -2*(lnL_scores(3,1)-lnL_scores(1,1))
p_value_OU = 1-chi2cdf(LR_SSvsOU, 3) %(Value, DF)


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Outputing Graph
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
figure(1);
set(figure(1), 'Position', [100 100 400 1000])

subplot(3,1,1);
hold on
plot(exp(St),'k','linewidth',1);
plot(exp(ss_att(:,1)+ss_att(:,2)),'r','linewidth',1); 
plot(exp(ss_att(:,2)),'b','linewidth',1);
h = legend('Observed Price','Estimated Price','Equilibrium Price');
title('Schwartz-Smith 2-factor model')
hold off

subplot(3,1,2);
hold on
plot(exp(St),'k','linewidth',1);
plot(exp(gbm_att(:,1)+gbm_att(:,2)),'--r','linewidth',1); 
plot(exp(gbm_att(:,2)),'b','linewidth',1);
h = legend('Observed Price','Estimated Price','Equilibrium Price');
title('geometric Brownian motion')
hold off

subplot(3,1,3);
hold on
plot(exp(St),'k','linewidth',1);
plot(exp(ou_att(:,1)+ou_att(:,2)),'r','linewidth',1); 
plot(exp(ou_att(:,2)),'b','linewidth',1);
h = legend('Observed Price','Estimated Price','Equilibrium Price');
title('Ornstein-Uhlenbeck')
hold off