function [chains,acceptance,loglikelihood,model] = getChains(modelname,dates,seed)
% This function generates Markov chain that estimates the parameter
% posterior distributions
% INPUTS:   modelname       Name of the model
%           dates           Dates
%           seed            Random seed
%
% OUTPUTS:  chains          Markov chains presenting parameter
%                           distributions
%           acceptance      Acceptance or rejection of samples
%           loglikelihood   Log-likelihood
%           model           Model

rng(seed);

% This switch converts the model name into a integer (from 1 to 4) that
% corresponds to the model
switch modelname
  case 'Wilkie'
    model_restr = 1;
  case 'ExtWilkie'
    model_restr = 2;
  case 'ADG'
    model_restr = 3;
  case 'Begin'
    model_restr = 4;
  otherwise
    error('Model has not been implemented');
end

% We load our different datasets (US data)
FEDTARGET         = loadIntendedFedFundsRate_FRED(dates);
CPI               = loadInflationIndexLevel_FRED(dates);
SHORTRATES        = loadFRBShortRate_FRB(dates);
RATES             = loadFRBOtherRates_FRB(dates);
SPX               = loadSPX_Bloomberg(dates);
SPX.ExcessReturn  = SPX.Return - SHORTRATES.Rate./12;

%% Load and create models
% Monetary policy model
momModel = Monetary('calendar',FEDTARGET.Date, ...
                    'series',  FEDTARGET.Rate, ...
                    'scale_pvalues',false);
                  
% We estimate the monetary model using MLE
momModel.fminsearch(100)

% Inflation model
infModel = Inflation('calendar',      CPI.Date, ...
                     'series',        CPI.Rate, ...
                     'scale_pvalues', false, ...
                     'Monetary',      momModel, ...
                     'model_restr',   model_restr);
                  
% We estimate the inflation model using MLE
infModel.fminsearch(100)
[~,z,sig2] = infModel.getMLEfunction(infModel.getPValues);
zq = z./sqrt(sig2);

% Short rate model
shrModel = ShortRate('calendar',      SHORTRATES.Date, ...
                     'series',        SHORTRATES.Rate, ...
                     'scale_pvalues', false, ...
                     'Monetary',      momModel, ...
                     'Inflation',     infModel, ...
                     'model_restr',   model_restr);
                   
% We estimate the short rate model using MLE
shrModel.fminsearch(100,zq)
[~,z,sig2] = shrModel.getMLEfunction(shrModel.getPValues,zq);
zr = z./sqrt(sig2);
rho_qr = shrModel.params.rho_qr.value;

% Dividend yield model
divModel = Dividends('calendar',      SPX.Date, ...
                     'series',        SPX.DividendYield, ...
                     'scale_pvalues', false, ...
                     'Monetary',      momModel, ...
                     'Inflation',     infModel, ...
                     'ShortRate',     shrModel, ...
                     'model_restr',   model_restr);
                   
% We estimate the dividend yield model using MLE
divModel.fminsearch(100,zq,zr,rho_qr)

% Index return model
retModel = IndexReturns('calendar',     SPX.Date, ...
                        'series',       SPX.ExcessReturn, ...
                        'scale_pvalues',false, ...
                        'Monetary',     momModel, ...
                        'model_restr',  model_restr);
                      
% We estimate the stock index return model using MLE
retModel.fminsearch(100)

% Forward rate model
forModel = ForwardRate('calendar',     RATES.Date, ...
                       'series',       RATES(:,2:end), ...
                       'maturities',   [1,2,3,5,7,10,30], ...
                       'scale_pvalues',false, ...
                       'model_restr',  model_restr);
                     
% We estimate the forward rate model using MLE
forModel.fminsearch(100)

%% Creation of the ESG object
% We combine the different models into an object ESG that combines the six
% different models
model = ESG('name',        modelname, ...
            'Monetary',    momModel, ...
            'Inflation',   infModel, ...
            'ShortRate',   shrModel, ...
            'Dividends',   divModel, ...
            'IndexReturns',retModel, ...
            'ForwardRate', forModel);

% We generate Markov chains for our MCMC-based parameter estimation
[chains,acceptance,~,loglikelihood] = model.runMarkovChain();

end