Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • Dynare/dseries
  • sebastien/dseries
  • houtanb/dseries
  • wmutschl/dseries
  • DoraK/dseries
  • JohannesPfeifer/dseries
6 results
Show changes
Commits on Source (633)
*~
externals
.DS_Store
externals/*
m-unit-tests/*
src/git.info
src/git.last-commit-hash
\ No newline at end of file
src/git.last-commit-hash
variables:
GIT_SUBMODULE_STRATEGY: normal
TERM: linux
MATLAB_VERSION: R2024b
OLD_MATLAB_VERSION: R2018b
# To ensure that "false && true" fails, see https://gitlab.com/gitlab-org/gitlab-runner/-/issues/25394#note_412609647
FF_ENABLE_BASH_EXIT_CODE_CHECK: 'true'
before_script:
- git clone https://git.dynare.org/Dynare/m-unit-tests
test_matlab:
stage: test
script:
- make check-matlab MATLAB=/opt/MATLAB/$MATLAB_VERSION/bin/matlab
test_old_matlab:
stage: test
script:
- make check-matlab MATLAB=/opt/MATLAB/$OLD_MATLAB_VERSION/bin/matlab
test_octave:
stage: test
variables:
OPENBLAS_NUM_THREADS: 1
script:
- make check-octave
[submodule "src/modules/matlab-fame-io"]
path = src/modules/matlab-fame-io
url = ../../Dynare/matlab-fame-io.git
> Copyright (C) 2014 Dynare Team
> Copyright © 2014-2018 Dynare Team
>
> The dseries Matlab/Octave class is licensed under GNU GPL as published by
> The dseries and dates MATLAB/Octave classes are licensed under GNU GPL as published by
> the Free Software Foundation, either version 3 of the License, or (at
> your option) any later version.
>
......@@ -10,4 +10,4 @@
> General Public License for more details.
> A copy of the GNU General Public License is available here
> <http://www.gnu.org/licenses/>.
> <https://www.gnu.org/licenses/>.
OCTAVE=octave-cli
MATLAB=`which matlab`
OCTAVE ?= octave-cli
MATLAB ?= matlab
all: check-octave check-matlab
check-octave:
m-unit-tests/src/mtest.m:
git clone https://git.dynare.org/Dynare/m-unit-tests
check-octave: m-unit-tests/src/mtest.m
@cd tests ;\
$(OCTAVE) --no-init-file --silent --no-history runalltests.m
$(OCTAVE) --no-init-file --silent --no-history --eval "addpath([pwd() '/../m-unit-tests/src']); runalltests" && [ ! -f ./failed ] && [ -f ./pass ]
check-matlab:
@$(MATLAB) -nosplash -nodisplay -r "cd tests; runalltests; quit"
check-matlab: m-unit-tests/src/mtest.m
@$(MATLAB) -batch "addpath([pwd '/m-unit-tests/src']); cd tests; runalltests; quit" && [ ! -f ./tests/failed ] && [ -f ./tests/pass ]
check-clean:
rm -f tests/*_test_*.m tests/*.csv tests/*.xls tests/*.xlsx tests/*.mat tests/failed tests/datafile_for_test
rm -f git.info git.last-commit-hash tests/pass tests/failed tests/*.spc
rm -rf m-unit-tests
[![pipeline status](https://git.dynare.org/Dynare/dseries/badges/master/pipeline.svg)](https://git.dynare.org/Dynare/dseries/commits/master)
This MATLAB/Octave toolbox comes with three classes:
- `@dates` which is used to handle dates.
- `@dseries` which is used to handle time series data.
- `@x13` which provides an interface to X13-ARIMEA-SEATS.
The package is a dependence of
[Dynare](https=//git.dynare.org/Dynare/dynare), but can also be used
as a standalone package without Dynare. The package is
compatible with MATLAB 2008a and following versions, and (almost
compatible with) the latest Octave version.
## Installation
The toolbox can be installed by cloning the Git repository:
~$ git clone https://git.dynare.org/Dynare/dseries.git
or downloading a zip archive:
~$ wget https://git.dynare.org/Dynare/dseries/-/archive/master/dseries-master.zip
~$ unsip dseries-master.zip
-$ mv dseries-master dseries
## Usage
Add the `dseries/src` folder to the MATLAB/Octave path, and run the following command (on MATLAB/Octave) prompt:
>> initialize_dseries_class
which, depending on your system, will add the necessary subfolders to
the MATLAB/Octave path.
You are then ready to go. A full documentation is available in the Dynare
reference manual.
Note that [X13-ARIMA-SEATS](https://www.census.gov/srd/www/x13as/) is required
for accessing all the features of the toolbox. On Windows and macOS, an
X13-ARIMA-SEATS binary is included in standalone dseries packages and in Dynare
packages. On Debian and Ubuntu it is possible to install X13-ARIMA-SEATS with
`apt install x13as` (on Debian, you must have the non-free archive area listed
in package sources).
## Examples
### Instantiate a dseries object from an array
>> A = randn(50, 3);
>> d = dseries(A, dates('2000Q1'), {'A1', 'A2', 'A3'});
The first argument of the `dseries` constructor is an array of data,
observations and variables are respectively along the rows and
columns. The second argument is the initial period of the dataset. The
last argument is a cell array of row character arrays for the names of
the variables.
>> d
d is a dseries object:
| A1 | A2 | A3
2000Q1 | -1.0891 | -2.1384 | -0.29375
2000Q2 | 0.032557 | -0.83959 | -0.84793
2000Q3 | 0.55253 | 1.3546 | -1.1201
2000Q4 | 1.1006 | -1.0722 | 2.526
2001Q1 | 1.5442 | 0.96095 | 1.6555
2001Q2 | 0.085931 | 0.12405 | 0.30754
2001Q3 | -1.4916 | 1.4367 | -1.2571
2001Q4 | -0.7423 | -1.9609 | -0.86547
2002Q1 | -1.0616 | -0.1977 | -0.17653
2002Q2 | 2.3505 | -1.2078 | 0.79142
| | |
2009Q4 | -1.7947 | 0.96423 | 0.62519
2010Q1 | 0.84038 | 0.52006 | 0.18323
2010Q2 | -0.88803 | -0.020028 | -1.0298
2010Q3 | 0.10009 | -0.034771 | 0.94922
2010Q4 | -0.54453 | -0.79816 | 0.30706
2011Q1 | 0.30352 | 1.0187 | 0.13517
2011Q2 | -0.60033 | -0.13322 | 0.51525
2011Q3 | 0.48997 | -0.71453 | 0.26141
2011Q4 | 0.73936 | 1.3514 | -0.94149
2012Q1 | 1.7119 | -0.22477 | -0.16234
2012Q2 | -0.19412 | -0.58903 | -0.14605
>>
### Instantiate a dseries object from a file
It is possible to instantiate a `dseries` object from a `.csv`,
`.xls`, `.xlsx`, `.mat` or `m` file, see the Dynare reference manual
for a complete description of the constraints on the content of these
files.
>> websave('US_CMR_data_t.csv', 'https://www.dynare.org/Datasets/US_CMR_data_t.csv');
>> d = dseries('US_CMR_data_t.csv');
>> d
d is a dseries object:
| gdp_rpc | conso_rpc | inves_rpc | defgdp | ... | networth_rpc | re | slope | creditspread
1980Q1 | 47941413.1257 | NaN | NaN | 0.40801 | ... | 33.6814 | 0.15047 | -0.0306 | 0.014933
1980Q2 | 46775570.3923 | NaN | NaN | 0.41772 | ... | 32.2721 | 0.12687 | -0.0221 | 0.028833
1980Q3 | 46528261.9561 | NaN | NaN | 0.42705 | ... | 36.6499 | 0.098367 | 0.011167 | 0.022167
1980Q4 | 47249592.2997 | NaN | NaN | 0.43818 | ... | 39.4069 | 0.15853 | -0.0343 | 0.022467
1981Q1 | 48059176.868 | NaN | NaN | 0.44972 | ... | 37.9954 | 0.1657 | -0.0361 | 0.0229
1981Q2 | 47531422.174 | NaN | NaN | 0.45863 | ... | 38.6262 | 0.1778 | -0.0403 | 0.0202
1981Q3 | 47951509.5055 | NaN | NaN | 0.46726 | ... | 36.3246 | 0.17577 | -0.0273 | 0.016333
1981Q4 | 47273009.6902 | NaN | NaN | 0.47534 | ... | 34.8693 | 0.13587 | 0.005 | 0.025933
1982Q1 | 46501690.1111 | NaN | NaN | 0.48188 | ... | 32.0964 | 0.14227 | 0.00066667 | 0.027367
1982Q2 | 46525455.3206 | NaN | NaN | 0.48814 | ... | 31.6967 | 0.14513 | -0.0058333 | 0.0285
| | | | | ... | | | |
2016Q1 | 85297205.4011 | 51926452.5716 | 21892729.0934 | 1.0514 | ... | 420.7154 | 0.0016 | 0.0203 | 0.0323
2016Q2 | 85407205.5913 | 52096454.9154 | 21824323.7487 | 1.0506 | ... | 398.7084 | 0.0036 | 0.0156 | 0.0339
2016Q3 | 85796604.1157 | 52436447.9843 | 21874814.014 | 1.0578 | ... | 424.8703 | 0.0037333 | 0.0138 | 0.029167
2016Q4 | 86101149.6919 | 52595613.0404 | 22010921.8985 | 1.0617 | ... | 444.622 | 0.0039667 | 0.011667 | 0.026967
2017Q1 | 86376652.4732 | 52795431.0988 | 22399301.0801 | 1.0672 | ... | 450.8777 | 0.0045 | 0.0168 | 0.0251
2017Q2 | 86982016.8089 | 53164725.076 | 22671020.5449 | 1.0728 | ... | 481.8778 | 0.007 | 0.017433 | 0.022167
2017Q3 | 87605975.0339 | 53451779.0342 | 23033324.7981 | 1.0758 | ... | 496.3342 | 0.0095 | 0.013133 | 0.022367
2017Q4 | 88111231.6601 | 53601437.7291 | 23477516.6946 | 1.081 | ... | 509.1968 | 0.011533 | 0.0109 | 0.020867
2018Q1 | 88557263.9759 | 53960814.0875 | 23726936.444 | 1.0882 | ... | 536.4746 | 0.012033 | 0.011667 | 0.019
2018Q2 | 88817646.3122 | 53931032.9449 | 23989494.0402 | 1.0937 | ... | 560.3093 | 0.014467 | 0.013133 | 0.0171
2018Q3 | 89689102.8539 | 54343965.1391 | 24123408.6269 | 1.1027 | ... | 554.472 | 0.017367 | 0.011833 | 0.0186
>>
### Create time series
Using an existing `dseries` object it is possible to create new time series:
>> d.cy = d.conso_rpc/d.gdp_rpc
d is a dseries object:
| conso_rpc | creditspread | cy | defgdp | ... | pinves_defl | re | slope | wage_rph
1980Q1 | NaN | 0.014933 | NaN | 0.40801 | ... | 145.6631 | 0.15047 | -0.0306 | 65.0376
1980Q2 | NaN | 0.028833 | NaN | 0.41772 | ... | 145.6095 | 0.12687 | -0.0221 | 65.1872
1980Q3 | NaN | 0.022167 | NaN | 0.42705 | ... | 145.3811 | 0.098367 | 0.011167 | 65.3858
1980Q4 | NaN | 0.022467 | NaN | 0.43818 | ... | 144.3745 | 0.15853 | -0.0343 | 65.5028
1981Q1 | NaN | 0.0229 | NaN | 0.44972 | ... | 144.6055 | 0.1657 | -0.0361 | 65.4385
1981Q2 | NaN | 0.0202 | NaN | 0.45863 | ... | 145.6512 | 0.1778 | -0.0403 | 65.3054
1981Q3 | NaN | 0.016333 | NaN | 0.46726 | ... | 144.7545 | 0.17577 | -0.0273 | 65.5074
1981Q4 | NaN | 0.025933 | NaN | 0.47534 | ... | 145.4748 | 0.13587 | 0.005 | 65.4142
1982Q1 | NaN | 0.027367 | NaN | 0.48188 | ... | 144.924 | 0.14227 | 0.00066667 | 66.1617
1982Q2 | NaN | 0.0285 | NaN | 0.48814 | ... | 144.4647 | 0.14513 | -0.0058333 | 65.8827
| | | | | ... | | | |
2016Q1 | 51926452.5716 | 0.0323 | 0.60877 | 1.0514 | ... | 98.7988 | 0.0016 | 0.0203 | 102.4176
2016Q2 | 52096454.9154 | 0.0339 | 0.60998 | 1.0506 | ... | 98.2923 | 0.0036 | 0.0156 | 102.5282
2016Q3 | 52436447.9843 | 0.029167 | 0.61117 | 1.0578 | ... | 98.1811 | 0.0037333 | 0.0138 | 102.0061
2016Q4 | 52595613.0404 | 0.026967 | 0.61086 | 1.0617 | ... | 98.0833 | 0.0039667 | 0.011667 | 102.1861
2017Q1 | 52795431.0988 | 0.0251 | 0.61122 | 1.0672 | ... | 97.8223 | 0.0045 | 0.0168 | 102.8336
2017Q2 | 53164725.076 | 0.022167 | 0.61122 | 1.0728 | ... | 97.6873 | 0.007 | 0.017433 | 103.4761
2017Q3 | 53451779.0342 | 0.022367 | 0.61014 | 1.0758 | ... | 97.8137 | 0.0095 | 0.013133 | 103.5137
2017Q4 | 53601437.7291 | 0.020867 | 0.60834 | 1.081 | ... | 97.4819 | 0.011533 | 0.0109 | 104.3091
2018Q1 | 53960814.0875 | 0.019 | 0.60933 | 1.0882 | ... | 97.4234 | 0.012033 | 0.011667 | 104.1112
2018Q2 | 53931032.9449 | 0.0171 | 0.60721 | 1.0937 | ... | 97.5643 | 0.014467 | 0.013133 | 104.5487
2018Q3 | 54343965.1391 | 0.0186 | 0.60591 | 1.1027 | ... | 97.8751 | 0.017367 | 0.011833 | 103.7128
>>
Recursive definitions for new time series are also possible. For
instance one can create a sample from an ARMA(1,1) stochastic process
as follows:
>> e = dseries(randn(100, 1), '2000Q1', 'e', '\varepsilon');
>> y = dseries(zeros(100, 1), '2000Q1', 'y');
>> from 2000Q2 to 2024Q4 do y(t)=.9*y(t-1)+e(t)-.4*e(t-1);
>> y
y is a dseries object:
| y
2000Q1 | 0
2000Q2 | -0.95221
2000Q3 | -0.6294
2000Q4 | -1.8935
2001Q1 | -1.1536
2001Q2 | -1.5905
2001Q3 | 0.97056
2001Q4 | 1.1409
2002Q1 | -1.9255
2002Q2 | -0.29287
|
2022Q2 | -1.4683
2022Q3 | -1.3758
2022Q4 | -1.2218
2023Q1 | -0.98145
2023Q2 | -0.96542
2023Q3 | -0.23203
2023Q4 | -0.34404
2024Q1 | 1.4606
2024Q2 | 0.901
2024Q3 | 2.4906
2024Q4 | 0.79661
>>
Any univariate nonlinear recursive model can be simulated with this approach.
classdef arima<handle
% Class for ARIMA models (interface to X13).
% Copyright © 2017-2023 Dynare Team
%
% This code is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare dseries submodule is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <https://www.gnu.org/licenses/>.
properties
y = []; % dseries object with a single variable.
p = []; % Number of lags on the autoregressive part.
d = []; % Order of differenciation.
q = []; % Number of lags on the moving average part.
P = []; % Seasonal component autoregressive part number of lags.
D = []; % Seasonal component order of differenciation.
Q = []; % Seasonal component moving average part number of lags.
S = []; % Seasonal component period.
ar = []; % Autoregressive parameters.
ma = []; % Moving arverage parameters.
AR = []; % Seasonal component autoregressive parameters.
MA = []; % Seasonal component moving average parameters.
ar_std = []; % Autoregressive parameters estimator std.
ma_std = []; % Moving arverage parameters estimator std.
AR_std = []; % Seasonal component autoregressive parameters estimator std.
MA_std = []; % Seasonal component moving average parameters estimator std.
sigma = []; % Standard deviation of the schock.
estimation = []; % Structure gathering informations related to the estimation of the model.
end
methods
function o = arima(y, model)
% Constructor for the arma class.
%
% INPUTS
% - y [dseries] Data.
% - model [string] Specification of the model of the form '(p, d, q)(P,D,Q)S', See X-13ARIMA-SEATS manual.
%
% OUPUTS
% - o [arima] ARIMA model object.
switch nargin
case 0
% Return empty object.
o.y = []; % dseries object with a single variable.
o.p = []; % Number of lags on the autoregressive part.
o.d = []; % Order of differenciation.
o.q = []; % Number of lags on the moving average part.
o.P = []; % Seasonal component autoregressive part number of lags.
o.D = []; % Seasonal component order of differenciation.
o.Q = []; % Seasonal component moving average part number of lags.
o.S = []; % Seasonal component period.
o.ar = []; % Autoregressive parameters.
o.ma = []; % Moving arverage parameters.
o.AR = []; % Seasonal component autoregressive parameters.
o.MA = []; % Seasonal component moving average parameters.
o.ar_std = []; % Autoregressive parameters estimator std.
o.ma_std = []; % Moving arverage parameters estimator std.
o.AR_std = []; % Seasonal component autoregressive parameters estimator std.
o.MA_std = []; % Seasonal component moving average parameters estimator std.
o.sigma = []; % Standard deviation of the schock.
o.estimation = []; % Structure gathering informations related to the estimation of the model.
return
case 2
if ~isdseries(y)
error('arima::WrongInputArguments', 'First input argument must be a dseries object!')
end
if ~ischar(model)
error('arima::WrongInputArguments', 'Second input argument must be a string!')
end
o.y = y;
o.estimation = struct();
% Read the description of the ARIMA model.
model = regexprep(model,'(\s)',''); % Removes all spaces.
description = regexp(model, '(\([0-9],[0-9],[0-9]\)([0-9]+)?)', 'tokens');
% First cell is the non seasonal component.
ns_arima = description{1}{1};
ns_arima_specification = regexp(ns_arima, '([0-9]*)', 'tokens');
o.p = str2num(ns_arima_specification{1}{1});
o.d = str2num(ns_arima_specification{2}{1});
o.q = str2num(ns_arima_specification{3}{1});
% Set default values for parameters and estimate std.
if o.p
o.ar = zeros(o.p, 1);
o.ar_std = zeros(o.p, 1);
else
o.ar = [];
o.ar_std = [];
end
if o.q
o.ma = zeros(o.q, 1);
o.ma_std = zeros(o.q, 1);
else
o.ma = [];
o.ma_std = [];
end
% Following cells are the ARIMA models on the seasonal components.
number_of_seasonal_components = length(description)-1;
if number_of_seasonal_components
o.P = zeros(number_of_seasonal_components, 1);
o.D = zeros(number_of_seasonal_components, 1);
o.Q = zeros(number_of_seasonal_components, 1);
o.S = zeros(number_of_seasonal_components, 1);
for i=1:number_of_seasonal_components
s_arima = description{i+1}{1};
s_arima_specification = regexp(s_arima, '([0-9]*)', 'tokens');
if isequal(i, 1) && isequal(length(s_arima_specification), 3)
o.S(i) = y.init.freq;
else
o.S(i) = str2num(s_arima_specification{4}{1});
end
o.P(i) = str2num(s_arima_specification{1}{1});
o.D(i) = str2num(s_arima_specification{2}{1});
o.Q(i) = str2num(s_arima_specification{3}{1});
end
end
% Set default values for parameters and estimate std.
o.AR = {};
o.MA = {};
o.AR_std = {};
o.MA_std = {};
for i=1:number_of_seasonal_components
if o.P(i)
o.AR{i} = zeros(o.P(i), 1);
o.AR_std{i} = zeros(o.P(i), 1);
else
o.AR{i} = [];
o.AR_std{i} = [];
end
if o.Q(i)
o.MA{i} = zeros(o.Q(i), 1);
o.MA_std{i} = zeros(o.Q(i), 1);
else
o.MA{i} = [];
o.MA_std{i} = [];
end
end
% Set default value for the size of the innovation.
o.sigma = std(y.data);
otherwise
error('arima::WrongInputArguments', 'Two input argument are mandatory!')
end
end % arima
end % methods
end % classdef --*-- Unit tests --*--
%@test:1
%$ try
%$ data = dseries(cumsum(randn(200, 1)), '1990Q1', 'Output');
%$ arma = arima(data, '(1,1,1)(0,0,1)');
%$ t(1) = true;
%$ catch
%$ t(1) = false;
%$ end
%$
%$ T = all(t);
%@eof:1
function estimate(o, varargin)
% Estimate method for arima class.
% Copyright © 2017-2021 Dynare Team
%
% This code is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare dseries submodule is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <https://www.gnu.org/licenses/>.
% Set default values for options.
options.tol = 1e-5;
options.exact = 'arma';
options.maxiter = 1500;
options.outofsample = false;
options.print='none';
options.save = 'estimates lkstats residuals';
% Update options.
if length(varargin)
if mod(length(varargin), 2)
error('arima:estimate:WrongInputArguments', 'Number of input should be even (option name, option value)!')
else
for option_id = 1:2:length(varargin)
if ismember(varargin{option_id}, {'tol', 'exact', 'maxiter', 'outofsample', 'print', 'save'})
eval(sprintf('options.%s = %s;', varargin{option_id}, varargin{option_id+1}))
else
warning('arima:estimate: Unknown option %s!', varargin{option_id})
end
end
end
end
model = sprintf('(%i,%i,%i)', o.p, o.d, o.q);
for i = 1:length(o.P)
model = sprintf('%s(%i,%i,%i)%i', model, o.P(i), o.D(i), o.Q(i), o.S(i));
end
% Set random name for temporary *.spc file.
basefilename = randomstring(10);
% Write *.spc file for estimation.
fid = fopen([basefilename '.spc'], 'w');
fprintf(fid, '# File created on %s by Dynare.\n\n', datetime());
fprintf(fid, 'series {\n');
fprintf(fid, ' title = "%s"\n', o.y.name{1});
fprintf(fid, ' start = %i.%i\n', o.y.init.year, o.y.init.subperiod);
fprintf(fid, ' period = %i\n', o.y.init.freq);
fprintf(fid, ' data = %s', sprintf(data2txt(o.y.data)));
fprintf(fid, '}\n\n');
fprintf(fid, 'arima{ Model = %s }\n\n', model);
fprintf(fid, 'estimate{\n');
fprintf(fid, ' tol = %d\n', options.tol);
fprintf(fid, ' maxiter = (%i)\n', options.maxiter);
fprintf(fid, ' exact = %s\n', options.exact);
if options.outofsample
fprintf(fid, ' outofsample = yes\n');
else
fprintf(fid, ' outofsample = no\n');
end
fprintf(fid, ' print = (%s)\n', options.print);
fprintf(fid, ' save = (%s)\n', options.save);
fprintf(fid, '}\n');
fclose(fid);
% Run estimation of the ARIMA model
system(sprintf('%s %s', select_x13_binary(), basefilename));
% Get the content of the generated *.est file
fid = fopen(sprintf('%s.est', basefilename), 'r');
if fid<=0, error('arima:estimate: Unable to find %.est', basefilename); end
txt = textscan(fid, '%s', 'delimiter', '\n');
txt = txt{1};
fclose(fid);
% Locate the lines where the estimates are reported.
l0 = find(strncmp(txt, '$arima$estimates$:',7))+3;
l1 = find(strncmp(txt, '$variance$:',7))-1;
% Read and store the estimation results.
for l = l0:l1
linea = textscan(txt{l}, '%s %s %d %d %f %f');
switch linea{1}{1}
case 'AR'
switch linea{2}{1}
case 'Nonseasonal'
o.ar(linea{4}) = linea{5};
o.ar_std(linea{4}) = linea{6};
case 'Seasonal'
i = find(linea{3}==o.S);
o.AR{i}(linea{4}) = linea{5};
o.AR_std{i}(linea{4}) = linea{6};
otherwise
% For seasonal factors for wich the period is not matching the data frequency.
linea = textscan(txt{l}, '%s %s %d %d %d %f %f');
i = find(linea{4}==o.S);
o.AR{i}(linea{5}) = linea{6};
o.AR_std{i}(linea{5}) = linea{7};
end
case 'MA'
switch linea{2}{1}
case 'Nonseasonal'
o.ma(linea{4}) = linea{5};
o.ma_std(linea{4}) = linea{6};
case 'Seasonal'
i = find(linea{4}==o.S);
o.MA{i}(linea{4}) = linea{5};
o.MA_std{i}(linea{4}) = linea{6};
otherwise
% For seasonal factors for wich the period is not matching the data frequency.
linea = textscan(txt{l}, '%s %s %d %d %d %f %f');
i = find(linea{4}==o.S);
o.MA{i}(linea{5}) = linea{6};
o.MA_std{i}(linea{5}) = linea{7};
end
otherwise
error('arima:estimate: Unable to interpret line %i line in %s.est!', l, basefilename)
end
end
l2 = find(strncmp(txt, '$variance$:',7))+2;
% Get the estimated standard error of the innovations.
linea = textscan(txt{l2}, '%s %f');
if isequal(linea{1}{1}, 'mle')
o.estimation.sigma = linea{2};
else
error('arima:estimate: Unable to find the estimated standard error of the innovations in %s.est', basefilename)
end
% TODO Figure out what is se
% linea = textscan(txt{l2+1}, '%s %f');
% if isequal(linea{1}{1}, 'se')
% o.sigma = linea{2}
% else
% error()
%end
% Get the content of the generated *.rsd file
fid = fopen(sprintf('%s.rsd', basefilename), 'r');
if fid<=0, error('arima:estimate: Unable to find %.rsd', basefilename); end
txt = textscan(fid, '%s', 'delimiter', '\n');
txt = txt{1}(3:end);
fclose(fid);
% Read and store the estimated innovations.
data = cellfun(@(x) x{2}, cellfun(@(x) [textscan(x, '%d %f')], txt, 'UniformOutput', false), 'UniformOutput', false);
data = transpose([data{:}]);
o.estimation.e = dseries(data, o.y.init, {'innovations'}, {'\hat{\varepsilon}'});
% Get the content of the generated *.lks file
fid = fopen(sprintf('%s.lks', basefilename), 'r');
if fid<=0, error('arima:estimate: Unable to find %.lks', basefilename); end
txt = textscan(fid, '%s', 'delimiter', '\n');
fclose(fid);
linea = textscan(txt{1}{2}, '%s %d');
if isequal(linea{1}{1}, 'nobs')
o.estimation.number_of_observations = linea{2};
end
linea = textscan(txt{1}{3}, '%s %d');
if isequal(linea{1}{1}, 'nefobs')
o.estimation.effective_number_of_observations = linea{2};
end
linea = textscan(txt{1}{5}, '%s %d');
if isequal(linea{1}{1}, 'np')
o.estimation.number_of_estimated_parameters = linea{2};
end
% TODO Check the meaning of lnlkhd (versus mle)
% linea = textscan(txt{1}{8}, '%s %d');
% if isequal(linea{1}{1}, 'lnlkhd')
% o.estimation.log_likelihood = linea{2};
% end
linea = textscan(txt{1}{9}, '%s %d');
if isequal(linea{1}{1}, 'aic')
o.estimation.information_criteria.Akaike = linea{2};
end
linea = textscan(txt{1}{10}, '%s %d');
if isequal(linea{1}{1}, 'Aicc')
% Akaike with correction for finite sample size.
o.estimation.information_criteria.CorrectedAkaike = linea{2};
end
linea = textscan(txt{1}{11}, '%s %d');
if isequal(linea{1}{1}, 'hnquin')
o.estimation.information_criteria.HannanQuinn = linea{2};
end
linea = textscan(txt{1}{12}, '%s %d');
if isequal(linea{1}{1}, 'bic')
o.estimation.information_criteria.Schwarz = linea{2};
end
return
%@test:1
try
y = dseries([0; 0], '1938Q3', 'y')
e = dseries(randn(201,1),'1938Q4','e');
from from 1939Q1 to 1988Q4 do y(t) = .8*y(t-1) - .2*y(t-2) + e(t) - .15*e(t-1)
model = arima(y, '(2,0,1)');
estimate(model);
catch
t(1) = false;
end
T = all(t);
%@eof:1
function o = append(o, d)
% append method for dates class.
%
% INPUTS
% - o [dates]
% - d [dates,char] date to be appended (if not a dates object, it must be a row char array that can be interpreted as a date).
%
% OUTPUTS
% - o [dates] containing dates defined in o and d.
% Copyright © 2012-2022 Dynare Team
%
% This code is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare dates submodule is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <https://www.gnu.org/licenses/>.
if isa(d, 'dates')
if ~isequal(length(d), 1)
error('dates:append:ArgCheck','Input argument %s has to be a dates object with one element.', inputname(2))
end
if isempty(d)
return
end
elseif isdate(d)
d = dates(d);
end
if ~isequal(o.freq, d.freq)
error('dates:append:ArgCheck','dates must have common frequency!')
end
o = copy(o);
o.append_(d);
return % --*-- Unit tests --*--
%@test:1
% Define some dates
B1 = '1953Q4';
B2 = '1950Q2';
B3 = '1950Q1';
B4 = '1945Q3';
B5 = '2009Q2';
% Define expected results.
e.time = [1945*4+3; 1950*4+1; 1950*4+2; 1953*4+4];
e.freq = 4;
% Call the tested routine.
d = dates(B4, B3, B2, B1);
try
d.append(dates(B5));
t(1) = true;
catch
t(1) = false;
end
% Check the results.
if t(1)
t(2) = isequal(d.time,e.time);
t(3) = isequal(d.freq,e.freq);
end
T = all(t);
%@eof:1
%@test:2
% Define some dates
B1 = '1953Q4';
B2 = '1950Q2';
B3 = '1950Q1';
B4 = '1945Q3';
B5 = '2009q2';
% Define expected results.
e.time = [1945*4+3; 1950*4+1; 1950*4+2; 1953*4+4; 2009*4+2];
f.time = [1945*4+3; 1950*4+1; 1950*4+2; 1953*4+4];
e.freq = 4;
% Call the tested routine.
d = dates(B4,B3,B2,B1);
try
c = d.append(B5);
t(1) = true;
catch
t(1) = false;
end
% Check the results.
if t(1)
t(2) = isequal(d.time,f.time);
t(3) = isequal(c.time,e.time);
t(4) = isequal(c.freq,e.freq);
t(5) = isequal(d.freq,e.freq);
end
T = all(t);
%@eof:2
%@test:3
% Define some dates
B1 = '1953Q4';
B2 = '1950Q2';
B3 = '1950Q1';
B4 = '1945Q3';
B5 = '2009q2';
% Define expected results.
e.time = [1945*4+3; 1950*4+1; 1950*4+2; 1953*4+4; 2009*4+2];
f.time = [1945*4+3; 1950*4+1; 1950*4+2; 1953*4+4];
e.freq = 4;
% Call the tested routine.
d = dates(B4,B3,B2,B1);
try
c = append(d, B5);
t(1) = true;
catch
t(1) = false;
end
% Check the results.
if t(1)
t(2) = isequal(d.time,f.time);
t(3) = isequal(c.time,e.time);
t(4) = isequal(c.freq,e.freq);
t(5) = isequal(d.freq,e.freq);
end
T = all(t);
%@eof:3
function o = append_(o, d)
% append method for dates class (in place modification).
%
% INPUTS
% - o [dates]
% - d [dates,char] date to be appended (if not a dates object, it must be a row char array that can be interpreted as a date).
%
% OUTPUTS
% - o [dates] dates object containing dates defined in o and d.
% Copyright © 2012-2022 Dynare Team
%
% This code is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare dates submodule is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <https://www.gnu.org/licenses/>.
if isa(d, 'dates')
if ~isequal(length(d), 1)
error('dates:append_:ArgCheck','Input argument %s has to be a dates object with one element.', inputname(2))
end
if isempty(d)
return
end
elseif isdate(d)
d = dates(d);
end
if ~isequal(o.freq, d.freq)
error('dates:append_:ArgCheck','dates must have common frequency!')
end
o.time = [o.time; d.time];
return % --*-- Unit tests --*--
%@test:1
% Define some dates
B1 = '1953Q4';
B2 = '1950Q2';
B3 = '1950Q1';
B4 = '1945Q3';
B5 = '2009Q2';
% Define expected results.
e.time = [1945*4+3; 1950*4+1; 1950*4+2; 1953*4+4; 2009*4+2];
e.freq = 4;
% Call the tested routine.
d = dates(B4,B3,B2,B1);
try
d.append_(dates(B5));
t(1) = true;
catch
t(1) = false;
end
% Check the results.
if t(1)
t(2) = isequal(d.time,e.time);
t(3) = isequal(d.freq,e.freq);
end
T = all(t);
%@eof:1
%@test:2
% Define some dates
B1 = '1953Q4';
B2 = '1950Q2';
B3 = '1950Q1';
B4 = '1945Q3';
B5 = '2009Q2';
% Define expected results.
e.time = [1945*4+3; 1950*4+1; 1950*4+2; 1953*4+4; 2009*4+2];
e.freq = 4;
% Call the tested routine.
d = dates(B4,B3,B2,B1);
try
d.append_(B5);
t(1) = true;
catch
t(1) = false;
end
% Check the results.
if t(1)
t(2) = isequal(d.time,e.time);
t(3) = isequal(d.freq,e.freq);
end
T = all(t);
%@eof:2
%@test:3
% Define some dates
B1 = '1953Q4';
B2 = '1950Q2';
B3 = '1950Q1';
B4 = '1945Q3';
B5 = '2009Q2';
% Define expected results.
e.time = [1945*4+3; 1950*4+1; 1950*4+2; 1953*4+4; 2009*4+2];
e.freq = 4;
% Call the tested routine.
d = dates(B4,B3,B2,B1);
try
c = d.append_(B5);
t(1) = true;
catch
t(1) = false;
end
% Check the results.
if t(1)
t(2) = isequal(d.time,e.time);
t(3) = isequal(c.time,e.time);
t(4) = isequal(d.freq,e.freq);
t(5) = isequal(c.freq,e.freq);
end
T = all(t);
%@eof:3
%@test:4
% Define some dates
B1 = '1953Q4';
B2 = '1950Q2';
B3 = '1950Q1';
B4 = '1945Q3';
B5 = '2009Q2';
% Call the tested routine.
d = dates(B4,B3);
e = dates(B1,B2,B5);
try
d.append_(e);
t(1) = false;
catch
t(1) = true;
end
T = all(t);
%@eof:4
%@test:5
% Define some dates
B = '1950Q2';
% Call the tested routine.
d = dates(B);
try
d.append_('1950Q3');
t(1) = true;
catch
t(1) = false;
end
if t(1)
t(2) = isequal(d.time, [1950*4+2; 1950*4+3]);
end
T = all(t);
%@eof:5
%@test:6
% Define some dates
B = '1950Q2';
% Call the tested routine.
d = dates(B);
try
d.append_('1950Z3');
t(1) = false;
catch
t(1) = true;
end
T = all(t);
%@eof:6
%@test:7
% Define some dates
B1 = '2020-01-01';
B2 = '2020-01-02';
B3 = '2020-01-03';
B4 = '2020-01-04';
B5 = '2020-01-05';
% Call the tested routine.
d = dates(B4,B3);
e = dates(B1,B2,B5);
try
d.append_(e);
t(1) = false;
catch
t(1) = true;
end
T = all(t);
%@eof:7
%@test:8
% Define some dates
B1 = '2020-01-01';
B2 = '2020-01-02';
B3 = '2020Q1';
% Call the tested routine.
d = dates(B1,B2);
e = dates(B3);
try
d.append_(e);
t(1) = false;
catch
t(1) = true;
end
T = all(t);
%@eof:8
%@test:9
% Define some dates
B1 = '2020W1';
B2 = '2020W2';
B3 = '2020W3';
B4 = '2020W4';
% Call the tested routine.
try
d1 = dates(B1,B2,B3);
d2 = dates(B4);
d1.append_(d2);
t(1) = true;
catch
t(1) = false;
end
if t(1)
t(2) = isequal(d1, dates(B1, B2, B3, B4));
end
T = all(t);
%@eof:9
\ No newline at end of file
function s = char(o)
% Given a one element dates object, returns a string with the formatted date.
%
% INPUTS
% - o [dates]
%
% OUTPUTS
% - s [string]
% Copyright © 2014-2023 Dynare Team
%
% This code is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare dates submodule is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <https://www.gnu.org/licenses/>.
if length(o)>1
error('dates:char:ArgCheck', 'The input argument must be a dates object with one element!')
end
s = date2string(o.time, o.freq);
return % --*-- Unit tests --*--
%@test:1
% Define a dates object
o = dates('1950Q1');
% Call the tested routine.
try
str = char(o);
t(1) = true;
catch
t(1) = false;
end
if t(1)
t(2) = isequal(str,'1950Q1');
end
T = all(t);
%@eof:1
%@test:2
% Define a dates object
o = dates('1950M1');
% Call the tested routine.
try
str = char(o);
t(1) = true;
catch
t(1) = false;
end
if t(1)
t(2) = isequal(str,'1950M1');
end
T = all(t);
%@eof:2
%@test:3
% Define a dates object
o = dates('2020-10-01');
% Call the tested routine.
try
str = char(o);
t(1) = true;
catch
t(1) = false;
end
if t(1)
t(2) = isequal(str,'2020-10-01');
end
T = all(t);
%@eof:3
%@test:4
% Define a dates object
o = dates('1950Y');
% Call the tested routine.
try
str = char(o);
t(1) = true;
catch
t(1) = false;
end
if t(1)
t(2) = isequal(str,'1950Y');
end
T = all(t);
%@eof:4
%@test:5
% Define a dates object
o = dates('1950A');
% Call the tested routine.
try
str = char(o);
t(1) = true;
catch
t(1) = false;
end
if t(1)
t(2) = isequal(str,'1950Y');
end
T = all(t);
%@eof:5
%@test:6
% Define a dates object
o = dates('1950W1');
% Call the tested routine.
try
str = char(o);
t(1) = true;
catch
t(1) = false;
end
if t(1)
t(2) = isequal(str,'1950W1');
end
T = all(t);
%@eof:6
function q = colon(varargin)
% Overloads the colon operator (:). This method can be used to create ranges of dates.
%
% INPUTS
% o o [dates] Initial date.
% o d [integer] Number of periods between each date (default value, if nargin==2, is one)
% o p [dates] Terminal date.
%
% OUTPUTS
% o q [dates] Object with length(p-o) elements (if d==1).
%
% REMARKS
% 1. p must be greater than o if d>0.
% 2. p and q are dates objects with one element.
% Copyright © 2013-2023 Dynare Team
%
% This code is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare dates submodule is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <https://www.gnu.org/licenses/>.
% Check the input arguments.
if isequal(nargin, 2)
o = varargin{1};
p = varargin{2};
d = 1;
if ~(isa(o, 'dates') && isa(p, 'dates') && isequal(o.length(), 1) && isequal(p.length(), 1))
error('dates:colon:ArgCheck', 'In an expression like A:B, A and B must be one element dates objects.')
end
elseif isequal(nargin,3)
o = varargin{1};
p = varargin{3};
d = varargin{2};
if ~(isa(o, 'dates') && isa(p, 'dates') && isequal(o.length(), 1) && isequal(o.length(), 1) && isscalar(d) && isint(d))
error('dates:colon:ArgCheck', 'In an expression like A:d:B, A and B must be one element dates objects and d a scalar integer.')
end
if isequal(d, 0)
error('dates:colon:ArgCheck', 'In an expression like A:d:B, d (the incremental number of periods) must nonzero.')
end
else
error('dates:colon:ArgCheck', 'See the manual for the colon (:) operator and dates objects.')
end
if ~isequal(o.freq, p.freq)
error('dates:colon:ArgCheck', 'Input arguments %s and %s must have common frequency.', inputname(1), inputname(2))
end
if o>p && d>0
error('dates:colon:ArgCheck', 'First date must preceed the second one.')
end
if p>o && d<0
error('dates:colon:ArgCheck', 'Second date must preceed the first one.')
end
% Initialize the output argument.
q = dates();
% Set the frequency in q
q.freq = o.freq;
% Set time
q.time = transpose(o.time:d:p.time);
return % --*-- Unit tests --*--
%@test:1
% Define two dates
date_1 = '1950Q2';
date_2 = '1951Q4';
% Define expected results.
e.freq = 4;
e.time = [1950*4+2; 1950*4+3; 1950*4+4; 1951*4+1; 1951*4+2; 1951*4+3; 1951*4+4];
% Call the tested routine.
d1 = dates(date_1);
d2 = dates(date_2);
d3 = d1:d2;
% Check the results.
t(1) = isequal(d3.time, e.time);
t(2) = isequal(d3.freq, e.freq);
T = all(t);
%@eof:1
%@test:2
% Define expected results.
e.freq = 4;
e.time = [1950*4+2; 1950*4+3; 1950*4+4; 1951*4+1; 1951*4+2; 1951*4+3; 1951*4+4];
% Call the tested routine.
d = dates('1950Q2'):dates('1951Q4');
% Check the results.
t(1) = isequal(d.time, e.time);
t(2) = isequal(d.freq, e.freq);
T = all(t);
%@eof:2
%@test:3
% Define expected results.
e.freq = 4;
e.time = [1950*4+2; 1950*4+4; 1951*4+2; 1951*4+4];
% Call the tested routine.
d = dates('1950Q2'):2:dates('1951Q4');
% Check the results.
t(1) = isequal(d.time, e.time);
t(2) = isequal(d.freq, e.freq);
T = all(t);
%@eof:3
%@test:4
% Create an empty dates object for quaterly data
qq = dates('Q');
% Define expected results.
e.freq = 4;
e.time = [1950*4+2; 1950*4+3; 1950*4+4; 1951*4+1; 1951*4+2; 1951*4+3; 1951*4+4];
% Call the tested routine.
d = qq(1950,2):qq(1951,4);
% Check the results.
t(1) = isequal(d.time, e.time);
t(2) = isequal(d.freq, e.freq);
T = all(t);
%@eof:4
%@test:5
% Create an empty dates object for quaterly data
qq = dates('Q');
% Define expected results.
e.freq = 4;
e.time = [1950*4+1; 1950*4+2; 1950*4+3];
% Call the tested routine.
d = qq(1950,1):qq(1950,3);
% Check the results.
t(1) = isequal(d.time, e.time);
t(2) = isequal(d.freq, e.freq);
T = all(t);
%@eof:5
%@test:6
% Create an empty dates object for daily data
dd = dates('D');
% Define expected results.
e.freq = 365;
e.time = [712251; 712252; 712253];
% Call the tested routine.
d = dd(1950, 01, 28):dd(1950, 01, 30);
% Check the results.
t(1) = isequal(d.time(:,1), e.time(:,1));
t(2) = isequal(d.freq, e.freq);
T = all(t);
%@eof:6
function p = copy(o)
% Do a copy of a dates object.
%
% INPUTS
% - o [dates]
%
% OUTPUTS
% - p [dates]
% Copyright © 2014-2023 Dynare Team
%
% This code is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare dates submodule is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <https://www.gnu.org/licenses/>.
p = dates();
p.freq = o.freq;
p.time = o.time;
return % --*-- Unit tests --*--
%@test:1
% Define a dates object
o = dates('1945Q3','1944Q4');
q = dates('1945Q3','1944Q4');
% Call the tested routine.
try
p = copy(o);
t(1) = true;
catch
t(1) = false;
end
if t(1)
o.sort_();
t(2) = dassert(p, q);
end
T = all(t);
%@eof:1
classdef dates<handle
% Copyright © 2014-2023 Dynare Team
%
% This code is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare dates submodule is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <https://www.gnu.org/licenses/>.
properties
freq = []; % Frequency (integer scalar)
time = []; % One dimensional array of integers (counts subperiods since year 0)
end
methods
function o = dates(varargin)
if ~nargin
% Returns empty dates object.
o.freq = NaN(0);
o.time = NaN(0,1);
return
end
if all(cellfun(@isdates, varargin))
% Concatenates dates objects in a dates object.
o = horzcat(varargin{:});
return
end
if all(cellfun(@isstringdate, varargin))
% Concatenates dates in a dates object.
tmp = cellfun(@string2date, varargin);
if all([tmp.freq]-tmp(1).freq==0)
o.freq = tmp(1).freq;
else
error('dates:ArgCheck', 'All dates passed as inputs must have the same frequency!')
end
o.time = transpose([tmp.time]);
return
end
if isequal(nargin,1) && isfreq(varargin{1})
% Instantiate an empty dates object (only set frequency)
o.time = NaN(0,1);
if ischar(varargin{1})
o.freq = string2freq(varargin{1});
else
o.freq = varargin{1};
end
return
end
if isequal(nargin, 3) && isfreq(varargin{1})
o.time = NaN(0, 1);
if ischar(varargin{1})
o.freq = string2freq(varargin{1});
else
o.freq = varargin{1};
end
if o.freq==365
error('dates:ArgCheck', 'Requires four inputs for daily dates.')
end
if (isnumeric(varargin{2}) && isvector(varargin{2}) && all(isint(varargin{2})))
if isnumeric(varargin{3}) && isvector(varargin{3}) && all(isint(varargin{3}))
if o.freq==52
if all(varargin{3}>=1)
if any(islongyear(varargin{2}(:))) && any(varargin{3}(islongyear(varargin{2}(:)))>53)
error('dates:ArgCheck', 'Third input specifies non existing ISO weeks (argument cannot be greater than 53).')
end
if any(~islongyear(varargin{2}(:))) && any(varargin{3}(~islongyear(varargin{2}(:)))>52)
error('dates:ArgCheck', 'Third input specifies non existing ISO weeks (argument cannot be greater than 52 except in long years).')
end
else
error('dates:ArgCheck', 'Third input must contain strictly positive integers.')
end
else
if all(varargin{3}>=1) && all(varargin{3}<=o.freq)
o.time = varargin{2}(:)*o.freq+varargin{3}(:);
else
error('dates:ArgCheck', 'Third input must contain integers between 1 and %i.', o.freq)
end
end
else
error('dates:ArgCheck', 'Third input must be a vector of integers.')
end
else
error('dates:ArgCheck', 'Second input must be a vector of integers.')
end
return
end
if isequal(nargin,2) && isfreq(varargin{1})
o.time = NaN(0, 1);
if ischar(varargin{1})
o.freq = string2freq(varargin{1});
else
o.freq = varargin{1};
end
if isequal(o.freq, 1)
if (isnumeric(varargin{2}) && isvector(varargin{2}) && all(isint(varargin{2})))
o.time = varargin{2}(:);
return
else
error('dates:ArgCheck','Second input must be a vector of integers.')
end
elseif ismember(o.freq, [2,4,12])
if isequal(size(varargin{2}, 2), 2)
if all(all(isint(varargin{2})))
if all(varargin{2}(:,2)>=1) && all(varargin{2}(:,2)<=o.freq)
o.time = varargin{2}(:,1)*o.freq+varargin{2}(:,2);
else
error('dates:ArgCheck', 'Second column of the last input must contain integers between 1 and %i.', o.freq)
end
else
error('dates:ArgCheck', 'Second input argument must be an array of integers.')
end
else
error('dates:ArgCheck', 'The second input must be a n*2 array of integers.')
end
elseif isequal(o.freq, 365)
if isequal(size(varargin{2}, 2), 3)
if all(all(isint(varargin{2})))
if all(varargin{2}(:,2)>=1) && all(varargin{2}(:,2)<=12)
if all(varargin{2}(:,3)>=1) && all(varargin{2}(:,2)<=31)
o.time = datenum(varargin{2}(:,1), varargin{2}(:,2), varargin{2}(:,3));
else
error('dates:ArgCheck', 'Third column of the last input must contain integers between 1 and 31 (days).')
end
else
error('dates:ArgCheck', 'Second column of the last input must contain integers between 1 and 12 (months).')
end
else
error('dates:ArgCheck', 'Second input argument must be an array of integers.')
end
else
error('dates:ArgCheck', 'For daily dates the second input must be a n*3 array of integers.')
end
end
return
end
if isequal(nargin,4) && isfreq(varargin{1}) && ( isequal(varargin{1}, 365) || strcmpi(varargin{1}, 'D'))
o.time = NaN(0,1);
if ischar(varargin{1})
o.freq = string2freq(varargin{1});
else
o.freq = varargin{1};
end
if (isnumeric(varargin{2}) && isvector(varargin{2}) && all(isint(varargin{2})))
if isnumeric(varargin{3}) && isvector(varargin{3}) && all(isint(varargin{3}))
if isnumeric(varargin{4}) && isvector(varargin{4}) && all(isint(varargin{4}))
if all(varargin{3}>=1) && all(varargin{3}<=12)
if all(varargin{4}>=1) && all(varargin{3}<=31)
if length(varargin{2})==length(varargin{3}) && length(varargin{2})==length(varargin{4})
o.time = datenum(varargin{2}(:), varargin{3}(:), varargin{4}(:));
else
error('dates:ArgCheck', 'Vectors passed as second, third, and fourth arguments must have the same number of elements.')
end
else
error('dates:ArgCheck', 'Fourth input must contain integers between 1 and 31 (days).')
end
else
error('dates:ArgCheck', 'Third input must contain integers between 1 and 12 (days).')
end
else
error('dates:ArgCheck','Fourth input must be a vector of integers.')
end
else
error('dates:ArgCheck','Third input must be a vector of integers.')
end
else
error('dates:ArgCheck','Second input must be a vector of integers.')
end
return
end
error('dates:ArgCheck','The input cannot be interpreted as a date. You should first read the manual!')
end % dates constructor.
% Other methods
p = sort(o);
o = sort_(o);
p = unique(o);
o = unique_(o);
p = append(o, d);
o = append_(o, d);
p = pop(o, d);
o = pop_(o, d);
p = remove(o, d);
o = remove_(o, d);
s = char(o);
a = double(o);
n = ndat(o);
n = length(o);
end % methods
end % classdef --*-- Unit tests --*--
%@test:1
%$ % Define some dates
%$ B1 = '1945Q3';
%$ B2 = '1950Q2';
%$ B3 = '1950q1';
%$ B4 = '1953Q4';
%$
%$ % Define expected results.
%$ e.time = [1945*4+3; 1950*4+2; 1950*4+1; 1953*4+4];
%$ e.freq = 4;
%$
%$ % Call the tested routine.
%$ d = dates(B1,B2,B3,B4);
%$
%$ % Check the results.
%$ t(1) = isequal(d.time, e.time);
%$ t(2) = isequal(d.freq, e.freq);
%$ t(3) = isequal(d.ndat(), size(e.time, 1));
%$ T = all(t);
%@eof:1
%@test:2
%$ % Define some dates
%$ B1 = '1945M3';
%$ B2 = '1950M2';
%$ B3 = '1950M10';
%$ B4 = '1953M12';
%$
%$ % Define expected results.
%$ e.time = [1945*12+3; 1950*12+2; 1950*12+10; 1953*12+12];
%$ e.freq = 12;
%$
%$ % Call the tested routine.
%$ d = dates(B1,B2,B3,B4);
%$
%$ % Check the results.
%$ t(1) = isequal(d.time,e.time);
%$ t(2) = isequal(d.freq,e.freq);
%$ t(3) = isequal(d.ndat(), size(e.time, 1));
%$ T = all(t);
%@eof:2
%@test:3
%$ % Define some dates
%$ B1 = '1945H1';
%$ B2 = '1950S2';
%$ B3 = '1950h1';
%$ B4 = '1953s2';
%$
%$ % Define expected results.
%$ e.time = [1945*2+1; 1950*2+2; 1950*2+1; 1953*2+2];
%$ e.freq = 2;
%$
%$ % Call the tested routine.
%$ d = dates(B1,B2,B3,B4);
%$
%$ % Check the results.
%$ t(1) = isequal(d.time,e.time);
%$ t(2) = isequal(d.freq,e.freq);
%$ t(3) = isequal(d.ndat(), size(e.time, 1));
%$ T = all(t);
%@eof:3
%@test:4
%$ % Define some dates
%$ B1 = '1945y';
%$ B2 = '1950Y';
%$ B3 = '1950a';
%$ B4 = '1953A';
%$
%$ % Define expected results.
%$ e.time = [1945; 1950; 1950; 1953];
%$ e.freq = 1;
%$
%$ % Call the tested routine.
%$ d = dates(B1,B2,B3,B4);
%$
%$ % Check the results.
%$ t(1) = isequal(d.time, e.time);
%$ t(2) = isequal(d.freq, e.freq);
%$ t(3) = isequal(d.ndat(), size(e.time, 1));
%$ T = all(t);
%@eof:4
%@test:5
%$ % Define a dates object
%$ B = dates('1950H1'):dates('1960H2');
%$
%$
%$ % Call the tested routine.
%$ d = B(2);
%$ if isa(d,'dates')
%$ t(1) = true;
%$ else
%$ t(1) = false;
%$ end
%$
%$ if t(1)
%$ t(2) = isequal(d.freq,B.freq);
%$ t(3) = isequal(d.time,1950*2+2);
%$ end
%$ T = all(t);
%@eof:5
%@test:6
%$ % Define a dates object
%$ B = dates('1950Q1'):dates('1960Q3');
%$
%$
%$ % Call the tested routine.
%$ d = B(2);
%$ if isa(d,'dates')
%$ t(1) = true;
%$ else
%$ t(1) = false;
%$ end
%$
%$ if t(1)
%$ t(2) = isequal(d.freq,B.freq);
%$ t(3) = isequal(d.time,1950*4+2);
%$ end
%$ T = all(t);
%@eof:6
%@test:7
%$ % Define a dates object
%$ B = dates(4,1950,1):dates(4,1960,3);
%$
%$ % Call the tested routine.
%$ d = B(2);
%$ if isa(d,'dates')
%$ t(1) = true;
%$ else
%$ t(1) = false;
%$ end
%$
%$ if t(1)
%$ t(2) = isequal(d.freq,B.freq);
%$ t(3) = isequal(d.time,1950*4+2);
%$ end
%$ T = all(t);
%@eof:7
%@test:8
%$ % Define a dates object
%$ B = dates(4,[1950 1]):dates(4,[1960 3]);
%$
%$ % Call the tested routine.
%$ d = B(2);
%$ if isa(d,'dates')
%$ t(1) = true;
%$ else
%$ t(1) = false;
%$ end
%$
%$ if t(1)
%$ t(2) = isequal(d.freq,B.freq);
%$ t(3) = isequal(d.time,1950*4+2);
%$ end
%$ T = all(t);
%@eof:8
%@test:9
%$ try
%$ B = dates(4,[1950; 1950], [1; 2]);
%$ t = true;
%$ catch
%$ t = false;
%$ end
%$
%$ T = all(t);
%@eof:9
%@test:10
%$ try
%$ B = dates(365,[1956; 1956], [1; 1], [12; 13]);
%$ t = true;
%$ catch
%$ t = false;
%$ end
%$
%$ T = all(t);
%@eof:10
function disp(o)
% Overloads the disp function for dates object.
%
% INPUTS
% - o [dates]
%
% OUTPTS
% None
% Copyright © 2013-2017 Dynare Team
%
% This code is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare dates submodule is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <https://www.gnu.org/licenses/>.
fprintf(['\n' dates4display(o, inputname(1), Inf) '\n\n']);
\ No newline at end of file
function display(o)
% Overloads display method for dates object.
%
% INPUTS
% - o [dates]
%
% OUTPTS
% None
% Copyright © 2013-2017 Dynare Team
%
% This code is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare dates submodule is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <https://www.gnu.org/licenses/>.
fprintf(['\n' dates4display(o, inputname(1), 5) '\n\n']);
\ No newline at end of file
function [m, f] = double(o)
% Returns a vector of doubles with the fractional part corresponding
% to the subperiod. Used for plots and to store dates in a matrix.
%
% INPUTS
% - o [dates]
%
% OUTPUTS
% - m [double] o.ndat*1 vector of doubles.
% - f [integer] scalar, the frequency (1, 2, 4, or 12).
%
% REMARKS
% Obviously the frequency is lost during the conversion.
% Copyright © 2013-2022 Dynare Team
%
% This code is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare dates submodule is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <https://www.gnu.org/licenses/>.
if o.freq==365 || o.freq==52
error('This method is not implemented for daily frequency.')
% Would need to find a way to deal with leap years and long years.
end
if o.freq == 1
m = o.time;
else
years = floor((o.time-1)/o.freq);
subperiods = o.time-years*o.freq;
m = years+(subperiods-1)/o.freq;
end
if nargout>1
f = o.freq;
end
return % --*-- Unit tests --*--
%@test:1
% Define a dates object
B = dates('1950Q1'):dates('1951Q1');
% Call the tested routine.
try
C = double(B);
t(1) = 1;
catch
t(1) = 0;
end
% Define expected results.
E = [ones(4,1)*1950; 1951];
E = E + [(transpose(1:4)-1)/4; 0];
if t(1)
t(2) = isequal(C,E);
end
T = all(t);
%@eof:1
%@test:2
% Call the tested routine.
try
C = NaN(2,1);
C(1) = double(dates('1950Q1'));
C(2) = double(dates('1950Q2'));
t(1) = 1;
catch
t(1) = 0;
end
% Define expected results.
E = ones(2,1)*1950;
E = E + [0; .25];
if t(1)
t(2) = isequal(C,E);
end
T = all(t);
%@eof:2
%@test:3
% Regression test for dseries#47
B = dates('1950Y'):dates('1952Y');
% Call the tested routine.
try
C = double(B);
t(1) = 1;
catch
t(1) = 0;
end
% Define expected results.
E = [1950; 1951; 1952];
if t(1)
t(2) = isequal(C,E);
end
T = all(t);
%@eof:3
function lastIndex = end(o, k, n)
% Overloads end keyword.
%
% INPUTS
% o [dates]
% k [integer] index where end appears
% n [integer] number of indices
%
% OUTPUTS
% lastIndex [integer] last dates index
% Copyright © 2013-2022 Dynare Team
%
% This code is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare dates submodule is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <https://www.gnu.org/licenses/>.
assert(k==1 && n==1, 'dates:end:ArgCheck', 'dates only has one dimension');
lastIndex = o.ndat();
return % --*-- Unit tests --*--
%@test:1
% Define a dates object
o = dates('1938Q4'):dates('2015Q4');
q = dates('2015Q4');
% Call the tested routine.
try
p = o(end);
t(1) = true;
catch
t(1) = false;
end
if t(1)
t(2) = dassert(p, q);
end
T = all(t);
%@eof:1
\ No newline at end of file
function l = eq(varargin)
% Overloads == operator for dates objects.
%
% INPUTS
% - o [dates] dates object with n or 1 elements.
% - p [dates] dates object with n or 1 elements.
%
% OUTPUTS
% - l [logical] column vector of max(n,1) elements (zeros or ones).
% Copyright © 2013-2022 Dynare Team
%
% This code is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare dates submodule is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <https://www.gnu.org/licenses/>.
if varargin{1}.ndat>1 && varargin{2}.ndat>1 && ~isequal(varargin{1}.ndat, varargin{2}.ndat)
l = false;
return
end
[o, p] = comparison_arg_checks(varargin{:});
if isequal(o.ndat(), p.ndat())
l = eq(o.time(:),p.time(:));
else
l = bsxfun(@eq,o.time(:,1),p.time(:,1));
end
return % --*-- Unit tests --*--
%@test:1
% Define some dates objects
d1 = dates('1950Q1','1950Q2','1950Q3','1950Q4') ;
d2 = dates('1960Q1','1960Q2','1960Q3','1960Q4') ;
d3 = dates('1950Q1','1960Q2','1950Q3','1960Q4') ;
% Call the tested routine.
try
t1 = d1==d1;
t2 = d1==d2;
t3 = d1==d3;
t(1) = true;
catch
t(1) = false;
end
% Check the results.
if t(1)
t(2) = isequal(t1, true(4,1));
t(3) = isequal(t2, false(4,1));
t(4) = isequal(t3, [true; false; true; false]);
end
T = all(t);
%@eof:1
%@test:2
% Define some dates objects
d1 = dates('1950Q1') ;
d2 = dates('1960Q1') ;
d3 = dates('1960Q1') ;
% Call the tested routine.
try
t1 = d1==d1;
t2 = d1==d2;
t3 = d1==d3;
t(1) = true;
catch
t(1) = false;
end
% Check the results.
if t(1)
t(2) = t1;
t(3) = ~t2;
t(4) = ~t3;
end
T = all(t);
%@eof:2
%@test:3
% Define some dates objects
d1 = dates('1950Q1','1950Q2','1950Q3','1950Q4') ;
d2 = dates('1950Q2') ;
d3 = dates('1970Q1') ;
% Call the tested routine.
try
t1 = d1==d2;
t2 = d1==d3;
t(1) = true;
catch
t(1) = false;
end
% Check the results.
if t(1)
t(2) = isequal(t1, [false; true; false; false]);
t(3) = isequal(t2, false(4,1));
end
T = all(t);
%@eof:3
%@test:4
% Define some dates objects
d1 = dates('2000-01-01','2000-01-02','2000-01-03');
d2 = dates('2000-01-02');
% Call the tested routine.
try
t1 = d1==d2;
t(1) = true;
catch
t(1) = false;
end
% Check the results.
if t(1)
t(2) = ~t1(1) && t1(2) && ~t1(3);
end
T = all(t);
%@eof:4
function l = ge(varargin)
% Overloads the >= operator for dates objects.
%
% INPUTS
% - o [dates] object with n or 1 elements.
% - p [dates] object with n or 1 elements.
%
% OUTPUTS
% - l [logical] column vector of max(n,1) elements (zeros or ones).
% Copyright © 2013-2022 Dynare Team
%
% This code is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare dates submodule is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <https://www.gnu.org/licenses/>.
[o, p] = comparison_arg_checks(varargin{:});
l = o.time>=p.time;
return % --*-- Unit tests --*--
%@test:1
% Define some dates
date_2 = '1950Q2';
date_3 = '1950Q3';
date_4 = '1950Q1';
date_5 = '1949Q2';
% Call the tested routine.
d2 = dates(date_2);
d3 = dates(date_3);
d4 = dates(date_4);
d5 = dates(date_5);
i1 = (d2>=d3);
i2 = (d3>=d4);
i3 = (d4>=d2);
i4 = (d5>=d4);
i5 = (d5>=d5);
% Check the results.
t(1) = isequal(i1,false);
t(2) = isequal(i2,true);
t(3) = isequal(i3,false);
t(4) = isequal(i4,false);
t(5) = isequal(i5,true);
T = all(t);
%@eof:1
%@test:2
% Define some dates
B1 = '1945Q1';
B2 = '1945Q2';
B3 = '1945Q3';
B4 = '1945Q4';
B5 = '1950Q1';
% Create dates objects.
dd = dates(B1,B2,B3,B4);
% Check the results.
t(1) = isequal(dates(B1)>=dates(B2),false);
t(2) = isequal(dates(B2)>=dates(B1),true);
t(3) = isequal(dates(B2)>=dates(B2),true);
t(4) = isequal(dd>=dates(B5),false(4,1));
t(5) = isequal(dates(B5)>=dd,true(4,1));
t(6) = isequal(dates(B1)>=dd,[true; false(3,1)]);
T = all(t);
%@eof:2