diff --git a/src/@dates/colon.m b/src/@dates/colon.m index 2c43bae02c6e64455a271b5a140734f9201bc8a0..fd989baf917770da21eeeb0017131cd46119fce3 100644 --- a/src/@dates/colon.m +++ b/src/@dates/colon.m @@ -14,7 +14,7 @@ function q = colon(varargin) % --*-- Unitary tests --*-- % 1. p must be greater than o if d>0. % 2. p and q are dates objects with one element. -% Copyright (C) 2013-2017 Dynare Team +% Copyright (C) 2013-2020 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 @@ -67,7 +67,7 @@ end q = dates(); % Compute the number of elements in the returned dates object. -n = (p-o)+1; % The number of elements in q dates object if d==1. +n = (p-o)+1; % The number of elements in q dates object if d==1. m = n; if d>1 % Correction of the number of elements (if d is not equal to one). m = length(1:d:n); @@ -81,8 +81,12 @@ if isequal(q.freq, 1) q.time = NaN(m,2); q.time(:,1) = o.time(1)+transpose(0:d:n-1); q.time(:,2) = 1; +elseif isequal(q.freq, 365) + q.time = NaN(n,3); + initperiods = datenum(o.time):datenum(p.time); + q.time = str2num(datestr(initperiods, 'yyyy mm dd')); else - % Weekly, Monthly, Quaterly + % Weekly, Monthly, Quaterly, Bi-Annual q.time = NaN(n,2); initperiods = min(q.freq-o.time(2)+1,n); q.time(1:initperiods,1) = o.time(1); @@ -190,3 +194,20 @@ end %$ t(2) = dassert(d.freq,e.freq); %$ T = all(t); %$ @eof:4 + +%$ @test:5 +%$ % Create an empty dates object for daily data +%$ dd = dates('D'); +%$ +%$ % Define expected results. +%$ e.freq = 365; +%$ e.time = [1950 1 28; 1950 1 29; 1950 1 30]; +%$ +%$ % Call the tested routine. +%$ d = dd(1950, 01, 28):dd(1950, 01, 30); +%$ +%$ % Check the results. +%$ t(1) = dassert(d.time,e.time); +%$ t(2) = dassert(d.freq,e.freq); +%$ T = all(t); +%$ @eof:5 diff --git a/src/@dates/dates.m b/src/@dates/dates.m index fe0e1741703eef28f343442661fac5fd937bd16c..a813b43ad90cf75b5879fba821c23f4be46dcc04 100644 --- a/src/@dates/dates.m +++ b/src/@dates/dates.m @@ -1,6 +1,6 @@ classdef dates<handle % --*-- Unitary tests --*-- -% Copyright (C) 2014-2017 Dynare Team +% Copyright (C) 2014-2020 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 @@ -41,7 +41,12 @@ methods else error('dates:ArgCheck', 'All dates passed as inputs must have the same frequency!') end - o.time = transpose(reshape([tmp.time], 2, length(tmp))); + + if any(cellfun(@(c)(size(c,2)==3), {tmp.time}, 'UniformOutput', true)) + o.time = transpose(reshape([tmp.time], 3, length(tmp))); + else + o.time = transpose(reshape([tmp.time], 2, length(tmp))); + end return end if isequal(nargin,1) && isfreq(varargin{1}) @@ -107,6 +112,32 @@ methods end return end + if isequal(nargin,4) && isfreq(varargin{1}) && isequal(varargin{1},365) + o.time = NaN(0,3); + 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) && all(varargin{4}>=1) && all(varargin{3}<=31) + o.time = [varargin{2}(:), varargin{3}(:), varargin{4}(:)]; + else + error('dates:ArgCheck','Third input must contain integers between 1 and %i.', o.freq) + 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 @@ -303,7 +334,7 @@ end % classdef %@test:10 %$ try -%$ B = dates(4,[1950, 1950], [1, 2]); +%$ B = dates(365,[1956, 1956], [1, 1], [12, 13]); %$ t = 1; %$ catch %$ t = 0; diff --git a/src/@dates/subsref.m b/src/@dates/subsref.m index cbeea253d3618a5928be50fc4b9ddb1e663b08cd..aff73554da462c3545a7c1d03838c2fc49b7eaca 100644 --- a/src/@dates/subsref.m +++ b/src/@dates/subsref.m @@ -13,7 +13,7 @@ function B = subsref(A,S) % --*-- Unitary tests --*-- % 1. The type of the returned argument depends on the content of S. % 2. See the matlab's documentation about the subsref method. -% Copyright (C) 2011-2017 Dynare Team +% Copyright (C) 2011-2020 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 @@ -57,10 +57,11 @@ switch S(1).type case '()' if isempty(A) if isempty(A.freq) - % Populate an empty dates object with time member (freq is not specified). Needs two or three inputs. First input is an integer + % Populate an empty dates object with time member (freq is not specified). Needs two, three or four inputs. First input is an integer % scalar specifying the frequency. Second input is either the time member (a n*2 array of integers) or a column vector with n % elements (the first column of the time member --> years). If the the second input is a row vector and if A.freq~=1 a third input - % is necessary. The third input is n*1 vector of integers between 1 and A.freq (second column of the time member --> subperiods). + % is necessary. The third input is n*1 vector of integers between 1 and A.freq (or 31 in case of daily data) (second column of the time member --> subperiods). + % The fourth input is only necessary in case of daily data, it is n*1 vector of integers between 1 and 12. B = dates(); % First input is the frequency. if isfreq(S(1).subs{1}) @@ -72,7 +73,7 @@ switch S(1).type else error('dates::subsref: First input must be a frequency!') end - if isequal(length(S(1).subs),2) + if isequal(length(S(1).subs),2) && ~isequal(B.freq,365) % If two inputs are provided, the second input must be a n*2 array except if frequency is annual. [n, m] = size(S(1).subs{2}); if m>2 @@ -94,7 +95,7 @@ switch S(1).type else error('dates::subsref: This is a bug!') end - elseif isequal(length(S(1).subs),3) + elseif isequal(length(S(1).subs),3) && ~isequal(B.freq,365) % If three inputs are provided, the second and third inputs are column verctors of integers (years and subperiods). if ~iscolumn(S(1).subs{2}) && ~all(isint(S(1).subs{2})) error('dates::subsref: Second input argument must be a column vector of integers!') @@ -108,14 +109,32 @@ switch S(1).type error('dates::subsref: Second and third input arguments must have the same number of elements!') end B.time = [S(1).subs{2}, S(1).subs{3}]; + elseif isequal(length(S(1).subs),4) && isequal(B.freq,365) + % If four inputs are provided, the second, third and fourth inputs are column verctors of integers (years and subperiods (months and days when freq is 365)). + if ~iscolumn(S(1).subs{2}) && ~all(isint(S(1).subs{2})) + error('dates::subsref: Second input argument must be a column vector of integers!') + end + n1 = size(S(1).subs{2},1); + if ~iscolumn(S(1).subs{3}) && ~all(S(1).subs{2}>=1) && ~all(S(1).subs{2}<=12) + error('dates::subsref: Third input argument must be a column vector of subperiods (integers between 1 and 12)!') + end + n2 = size(S(1).subs{3},1); + if ~iscolumn(S(1).subs{4}) && ~all(S(1).subs{2}>=1) && ~all(S(1).subs{2}<=31) + error('dates::subsref: Fourth input argument must be a column vector of subperiods (integers between 1 and 31)!') + end + n3 = size(S(1).subs{4},1); + if ~isequal(n1,n2,n3) + error('dates::subsref: Second, third and fourth input arguments must have the same number of elements!') + end + B.time = [S(1).subs{2}, S(1).subs{3}, S(1).subs{4}]; else error('dates::subsref: Wrong calling sequence!') end else % Populate an empty dates object with time member (freq is already specified). - % Needs one (time) or two (first and second columns of time for years and subperiods) inputs. + % Needs one (time), two or three (first, second and third columns of time for years and subperiods (months and days when freq is 365)) inputs. B = copy(A); - if isequal(length(S(1).subs),2) + if isequal(length(S(1).subs),2) && ~isequal(B.freq,365) if ~iscolumn(S(1).subs{1}) && ~all(isint(S(1).subs{1})) error('dates::subsref: First argument has to be a column vector of integers!') end @@ -128,7 +147,7 @@ switch S(1).type error('dates::subsref: First and second argument must have the same number of rows!') end B.time = [S(1).subs{1}, S(1).subs{2}]; - elseif isequal(length(S(1).subs),1) + elseif isequal(length(S(1).subs),1) && ~isequal(B.freq,365) [n, m] = size(S(1).subs{1}); if ~isequal(m,2) && ~isequal(B.freq,1) error('dates::subsref: First argument has to be a n*2 array!') @@ -146,6 +165,23 @@ switch S(1).type else error('dates::subsref: This is a bug!') end + elseif isequal(length(S(1).subs),3) && isequal(B.freq,365) + if ~iscolumn(S(1).subs{1}) && ~all(isint(S(1).subs{1})) + error('dates::subsref: First argument has to be a column vector of integers!') + end + n1 = size(S(1).subs{1},1); + if ~iscolumn(S(1).subs{2}) && ~all(S(1).subs{2}>=1) && ~all(S(1).subs{2}<=12) + error('dates::subsref: Second argument has to be a column vector of subperiods (integers between 1 and 12!') + end + n2 = size(S(1).subs{2},1); + if ~iscolumn(S(1).subs{3}) && ~all(S(1).subs{2}>=1) && ~all(S(1).subs{2}<=31) + error('dates::subsref: Third argument has to be a column vector of subperiods (integers between 1 and 31!') + end + n3 = size(S(1).subs{3},1); + if ~isequal(n3,n2,n1) + error('dates::subsref: All arguments must have the same number of rows!') + end + B.time = [S(1).subs{1}, S(1).subs{2}, S(1).subs{3}]; else error('dates::subsref: Wrong number of inputs!') end @@ -345,3 +381,43 @@ end %$ end %$ T = all(t); %@eof:7 + +%@test:8 +%$ % Define a dates object +%$ B = dates('1950-11-15','1950-11-16','1950-11-17','1950-11-18'); +%$ +%$ % Try to extract a sub-dates object. +%$ try +%$ d = B([]); +%$ t(1) = true; +%$ catch +%$ t(1) = false; +%$ end +%$ +%$ if t(1) +%$ t(2) = dassert(isa(d,'dates'), true); +%$ t(3) = dassert(isempty(d), true); +%$ end +%$ T = all(t); +%@eof:8 + +%@test:9 +%$ % Define a dates object +%$ B = dates('1950-11-15','1950-11-16','1950-11-17','1950-11-18'); +%$ +%$ % Try to extract a sub-dates object. +%$ d = B(2); +%$ +%$ if isa(d,'dates') +%$ t(1) = 1; +%$ else +%$ t(1) = 0; +%$ end +%$ +%$ if t(1) +%$ t(2) = dassert(d.freq,B.freq); +%$ t(3) = dassert(d.time,[1950 11 16]); +%$ t(4) = dassert(d.ndat(),1); +%$ end +%$ T = all(t); +%@eof:9 \ No newline at end of file diff --git a/src/@dseries/dgrowth.m b/src/@dseries/dgrowth.m new file mode 100644 index 0000000000000000000000000000000000000000..1078a94a7a5db61521a6cf90c3f18bd60d3e1f4d --- /dev/null +++ b/src/@dseries/dgrowth.m @@ -0,0 +1,49 @@ +function o = dgrowth(o) % --*-- Unitary tests --*-- + +% Computes daily growth rates. +% +% INPUTS +% - o [dseries] +% +% OUTPUTS +% - o [dseries] + +% Copyright (C) 2020 Dynare Team +% +% This file is part of Dynare. +% +% Dynare 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 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 <http://www.gnu.org/licenses/>. + +o = copy(o); +o.dgrowth_(); + +%@test:1 +%$ try +%$ data = (1+.01).^transpose(0:1:50); +%$ ts = dseries(data,'1950-01-01'); +%$ ds = ts.dgrowth(); +%$ t(1) = 1; +%$ catch +%$ t(1) = 0; +%$ end +%$ +%$ if t(1) +%$ DATA = NaN(1,ds.vobs); +%$ DATA = [DATA; .01*ones(ds.nobs-1,ds.vobs)]; +%$ t(2) = dassert(ds.data,DATA,1e-15); +%$ t(3) = dassert(ts.data,data,1e-15); +%$ end +%$ +%$ T = all(t); +%@eof:1 \ No newline at end of file diff --git a/src/@dseries/dgrowth_.m b/src/@dseries/dgrowth_.m new file mode 100644 index 0000000000000000000000000000000000000000..c2425a19ac7c8cc8c992f3786285f8cbd81ec1b2 --- /dev/null +++ b/src/@dseries/dgrowth_.m @@ -0,0 +1,84 @@ +function o = dgrowth_(o) % --*-- Unitary tests --*-- + +% Computes daily growth rates. +% +% INPUTS +% - o [dseries] +% +% OUTPUTS +% - o [dseries] + +% Copyright (C) 2020 Dynare Team +% +% This file is part of Dynare. +% +% Dynare 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 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 <http://www.gnu.org/licenses/>. + +switch frequency(o) + case 1 + error('dseries::dgrowth: I cannot compute daily growth rates from yearly data!') + case 2 + error('dseries::dgrowth: I cannot compute daily growth rates from bi-annual data!') + case 4 + error('dseries::dgrowth: I cannot compute daily growth rates from quaterly data!') + case 12 + error('dseries::dgrowth: I cannot compute daily growth rates from monthly data!') + case 52 + error('dseries::dgrowth: I cannot compute daily growth rates from weekly data!') + case 365 + o.data(2:end,:) = o.data(2:end,:)./o.data(1:end-1,:) - 1; + o.data(1,:) = NaN; + otherwise + error(['dseries::dgrowth: object ' inputname(1) ' has unknown frequency']); +end + +for i = 1:vobs(o) + if isempty(o.ops{i}) + o.ops(i) = {['dgrowth(' o.name{i} ')']}; + else + o.ops(i) = {['dgrowth(' o.ops{i} ')']}; + end +end + +%@test:1 +%$ try +%$ data = (1+.01).^transpose(0:1:50); +%$ ts = dseries(data,'1950Q1'); +%$ ts.dgrowth_; +%$ t(1) = 0; +%$ catch +%$ t(1) = 1; +%$ end +%$ +%$ T = all(t); +%@eof:1 + +%@test:2 +%$ try +%$ data = (1+.01).^transpose(0:1:80); +%$ ts = dseries(data, '1950-01-01'); +%$ ts.dgrowth_; +%$ t(1) = 1; +%$ catch +%$ t(1) = 0; +%$ end +%$ +%$ if t(1) +%$ DATA = NaN(1,ts.vobs); +%$ DATA = [DATA; (1.01-1)*ones(ts.nobs-1, ts.vobs)]; +%$ t(2) = dassert(ts.data, DATA, 1e-15); +%$ end +%$ +%$ T = all(t); +%@eof:2 diff --git a/src/@dseries/dseries.m b/src/@dseries/dseries.m index afce0d6148fd86d17cb35a16a64ee1673757c73f..6351ff86ceacabf7444be0277c2512425f6389d7 100644 --- a/src/@dseries/dseries.m +++ b/src/@dseries/dseries.m @@ -124,7 +124,7 @@ methods init = dates(1,1); elseif (isdates(b) && isequal(length(b),1)) init = b; - elseif ischar(b) && isdate(b)% Weekly, Monthly, Quaterly, Bi-annual or Annual data (string). + elseif ischar(b) && isdate(b)% Daily, Weekly, Monthly, Quaterly, Bi-annual or Annual data (string). init = dates(b); elseif (isnumeric(b) && isscalar(b) && isint(b)) % Yearly data. init = dates([num2str(b) 'Y']); diff --git a/src/@dseries/hdiff_.m b/src/@dseries/hdiff_.m index 46b20ceb29e43ba842f7e93097ceb1b0da638b1e..d0cb75e78237b1bd37857097073492c28cd94ad9 100644 --- a/src/@dseries/hdiff_.m +++ b/src/@dseries/hdiff_.m @@ -39,6 +39,8 @@ switch frequency(o) o.data(1:6,:) = NaN; case 52 error('dseries::hdiff: I do not know yet how to compute bi-annual differences from weekly data!') + case 365 + error('dseries::hdiff: I do not know yet how to compute bi-annual differences from daily data!') otherwise error(['dseries::hdiff: object ' inputname(1) ' has unknown frequency']); end diff --git a/src/@dseries/hgrowth_.m b/src/@dseries/hgrowth_.m index ac30fd80093912b92b59df22d659a9bdb4782cb3..78ed8a9dbff4e3a72ce675bdd82a374cbf0d65e0 100644 --- a/src/@dseries/hgrowth_.m +++ b/src/@dseries/hgrowth_.m @@ -39,6 +39,8 @@ switch frequency(o) o.data(1:6,:) = NaN; case 52 error('dseries::hgrowth: I do not know yet how to compute bi-annual growth rates from weekly data!') + case 365 + error('dseries::hgrowth: I do not know yet how to compute bi-annual growth rates from daily data!') otherwise error(['dseries::hgrowth: object ' inputname(1) ' has unknown frequency']); end diff --git a/src/@dseries/mdiff_.m b/src/@dseries/mdiff_.m index a4e6b316d23db54e0c60a8912c59090d46023d6a..8195c4dd18e5dbd4286529980aede485e80f6576 100644 --- a/src/@dseries/mdiff_.m +++ b/src/@dseries/mdiff_.m @@ -35,6 +35,10 @@ switch frequency(o) case 12 o.data(2:end,:) = o.data(2:end,:)-o.data(1:end-1,:); o.data(1,:) = NaN; + case 52 + error('dseries::mdiff: I do not know yet how to compute monthly differences from weekly data!') + case 365 + error('dseries::mdiff: I do not know yet how to compute monthly differences from daily data!') otherwise error(['dseries::mdiff: object ' inputname(1) ' has unknown frequency']); end diff --git a/src/@dseries/mgrowth_.m b/src/@dseries/mgrowth_.m index 53369cfe135bcc888e2f036f75422b6dd7f5b0ec..1fe0439a28be3b9bc5b8b8a879529096b8eb04e5 100644 --- a/src/@dseries/mgrowth_.m +++ b/src/@dseries/mgrowth_.m @@ -35,6 +35,10 @@ switch frequency(o) case 12 o.data(2:end,:) = o.data(2:end,:)./o.data(1:end-1,:) - 1; o.data(1,:) = NaN; + case 52 + error('dseries::mgrowth: I do not know yet how to compute monthly growth rates from weekly data!') + case 365 + error('dseries::mgrowth: I do not know yet how to compute monthly growth rates from daily data!') otherwise error(['dseries::mgrowth: object ' inputname(1) ' has unknown frequency']); end diff --git a/src/@dseries/qdiff_.m b/src/@dseries/qdiff_.m index 7e02f3a263cc1b1629d5ca8f6f6ca943b05ae723..5036934eaf7b774b096b3b60cddbe905076ee107 100644 --- a/src/@dseries/qdiff_.m +++ b/src/@dseries/qdiff_.m @@ -38,6 +38,8 @@ switch frequency(o) o.data(1:3,:) = NaN; case 52 error('dseries::qdiff: I do not know yet how to compute quaterly differences from weekly data!') + case 365 + error('dseries::qdiff: I do not know yet how to compute quaterly differences from daily data!') otherwise error(['dseries::qdiff: object ' inputname(1) ' has unknown frequency']); end diff --git a/src/@dseries/qgrowth_.m b/src/@dseries/qgrowth_.m index 658b5c48dea1c156a2d0c9e43de7dcbf3a59bc6a..468ed10965c7c87cdb168f8691c382bf91604039 100644 --- a/src/@dseries/qgrowth_.m +++ b/src/@dseries/qgrowth_.m @@ -38,6 +38,8 @@ switch frequency(o) o.data(1:3,:) = NaN; case 52 error('dseries::qgrowth: I do not know yet how to compute quaterly growth rates from weekly data!') + case 365 + error('dseries::qgrowth: I do not know yet how to compute quaterly growth rates from daily data!') otherwise error(['dseries::qgrowth: object ' inputname(1) ' has unknown frequency']); end diff --git a/src/@dseries/subsref.m b/src/@dseries/subsref.m index f39b4a8dc0b510e36e33bbc09c0a0783af0a9239..62ffde82b3a3e22f61434ddc49a3a617b0a26b60 100644 --- a/src/@dseries/subsref.m +++ b/src/@dseries/subsref.m @@ -53,7 +53,7 @@ switch S(1).type % Returns a dates object (last date). r = o.dates(end); case 'freq' - % Returns an integer characterizing the data frequency (1, 4, 12 or 52) + % Returns an integer characterizing the data frequency (1, 2, 4, 12, 52 or 365) r = o.dates.freq; case 'length' error(['dseries::subsref: we do not support the length operator on ' ... @@ -112,6 +112,7 @@ switch S(1).type 'hgrowth','hgrowth_', ... 'qgrowth','qgrowth_', ... 'mgrowth','mgrowth_', ... + 'dgrowth','dgrowth_', ... 'ydiff','ydiff_', ... 'hdiff','hdiff_', ... 'qdiff','qdiff_', ... @@ -743,4 +744,21 @@ return end T = all(t); -%@eof:20 \ No newline at end of file +%@eof:20 + +%@test:21 + try + tseries = dseries(dates('2000-01-01')); + ts = tseries(ones(6,1)); + t(1) = true; + catch + t(1) = false; + end + + if t(1) + t(2) = ts.dates(1)==dates('2000-01-01'); + t(3) = ts.dates(6)==dates('2000-01-06'); + end + + T = all(t); +%@eof:21 \ No newline at end of file diff --git a/src/@dseries/ydiff_.m b/src/@dseries/ydiff_.m index 16e2f6aeb502df8e6d0c7edbf229ba1f46d696f8..796130cdc1b1fbf7b4386105f2c41b9bb6e4cf15 100644 --- a/src/@dseries/ydiff_.m +++ b/src/@dseries/ydiff_.m @@ -41,6 +41,9 @@ switch frequency(o) case 52 o.data(53:end,:) = o.data(53:end,:)-o.data(1:end-52,:); o.data(1:52,:) = NaN; + case 365 + o.data(366:end,:) = o.data(366:end,:)-o.data(1:end-365,:); + o.data(1:365,:) = NaN; otherwise error(['dseries::ydiff: object ' inputname(1) ' has unknown frequency']); end @@ -155,3 +158,23 @@ end %$ %$ T = all(t); %@eof:5 + +%@test:6 +%$ try +%$ data = transpose(1:1095); +%$ ts = dseries(data,'1950-01-01',{'A1'},{'A_1'}); +%$ ts.ydiff_; +%$ t(1) = true; +%$ catch +%$ t(1) = false; +%$ end +%$ +%$ if t(1) +%$ DATA = NaN(365,ts.vobs); +%$ DATA = [DATA; 365*ones(ts.nobs-365,ts.vobs)]; +%$ t(2) = dassert(ts.data,DATA); +%$ t(3) = dassert(ts.ops{1},['ydiff(A1)']); +%$ end +%$ +%$ T = all(t); +%@eof:6 \ No newline at end of file diff --git a/src/@dseries/ygrowth_.m b/src/@dseries/ygrowth_.m index 3bc3d77e81e991797e0738956f4085c87eb271cd..ce9c089c7522d0b08d501cee80153179d369a22c 100644 --- a/src/@dseries/ygrowth_.m +++ b/src/@dseries/ygrowth_.m @@ -41,6 +41,9 @@ switch frequency(o) case 52 o.data(53:end,:) = o.data(53:end,:)./o.data(1:end-52,:) - 1; o.data(1:52,:) = NaN; + case 365 + o.data(366:end,:) = o.data(366:end,:)./o.data(1:end-365,:) - 1; + o.data(1:365,:) = NaN; otherwise error(['dseries::ygrowth: object ' inputname(1) ' has unknown frequency']); end @@ -131,3 +134,23 @@ end %$ %$ T = all(t); %@eof:4 + +%@test:5 +%$ try +%$ data = repmat(transpose(1:365),100,1); +%$ ts = dseries(data,'1950-01-01'); +%$ ts.ygrowth_(); +%$ t(1) = true; +%$ catch +%$ t(1) = false; +%$ end +%$ +%$ +%$ if t(1) +%$ DATA = NaN(365,ts.vobs); +%$ DATA = [DATA; zeros(ts.nobs-365,ts.vobs)]; +%$ t(2) = dassert(ts.data,DATA); +%$ end +%$ +%$ T = all(t); +%@eof:5 diff --git a/src/utilities/convert/date2string.m b/src/utilities/convert/date2string.m index 49d675fe869dd813e628975e6294e028c2cb6403..9a94a8030ff6fa251d3bfbe39ab1131bf4afef64 100644 --- a/src/utilities/convert/date2string.m +++ b/src/utilities/convert/date2string.m @@ -4,8 +4,8 @@ function s = date2string(varargin) % --*-- Unitary tests --*-- % % INPUTS % o varargin{1} + dates object with one element, if nargin==1. -% + 1*2 vector of integers (first element is the year, second element is the subperiod), if nargin==2. -% o varargin{2} integer scalar equal to 1, 2, 4, 12 or 52 (frequency). +% + 1*3 vector of integers (first element is the year, second and third elements are the subperiods), if nargin==3. +% o varargin{2} integer scalar equal to 1, 2, 4, 12, 52 or 365 (frequency). % % OUTPUTS % o s string. @@ -37,8 +37,8 @@ if isequal(nargin,1) end if isequal(nargin,2) - if ~(isvector(varargin{1}) && isequal(length(varargin{1}),2) && all(isint(varargin{1})) && isscalar(varargin{2} && ismember(varargin{2},[1 2 4 12 52]))) - error(['dates::format: First input must be a 1*2 vector of integers and second input must be a scalar integer (1, 2, 4, 12 or 52)!']) + if ~(isvector(varargin{1}) && (isequal(length(varargin{1}),2) || isequal(length(varargin{1}),3)) && all(isint(varargin{1})) && isscalar(varargin{2} && ismember(varargin{2},[1 2 4 12 52 365]))) + error(['dates::format: First input must be a 1*2 or 1*3 vector of integers and second input must be a scalar integer (1, 2, 4, 12, 52 or 365)!']) else if varargin{1}(2)>varargin{2} || varargin{1}(2)<1 error('dates::format: Second element of the first input be between 1 and %s!',num2str(varargin{2})) @@ -48,9 +48,13 @@ if isequal(nargin,2) end end -s = [num2str(time(1)) freq2string(freq)]; -if freq>1 - s = strcat(s, num2str(time(2))); +if freq == 365 + s = [num2str(time(1),'%02d') '-' num2str(time(2),'%02d') '-' num2str(time(3),'%02d')]; +else + s = [num2str(time(1)) freq2string(freq)]; + if freq>1 + s = strcat(s, num2str(time(2))); + end end %@test:1 @@ -135,3 +139,17 @@ end %$ T = all(t); %@eof:6 +%@test:7 +%$ try +%$ str = date2string([1938; 1; 12], 365); +%$ t(1) = true; +%$ catch +%$ t(1) = false; +%$ end +%$ +%$ if t(1) +%$ t(2) = dassert(str, '1938-01-12'); +%$ end +%$ +%$ T = all(t); +%@eof:7 diff --git a/src/utilities/convert/freq2string.m b/src/utilities/convert/freq2string.m index 09b750237a821e242e9e63fb1b895ab2f670c1bf..fe622e34650acd4be3e3e2bf4cda93daa4918b06 100644 --- a/src/utilities/convert/freq2string.m +++ b/src/utilities/convert/freq2string.m @@ -1,10 +1,10 @@ function s = freq2string(freq) % --*-- Unitary tests --*-- % INPUTS -% o freq scalar integer, equal to 1, 2, 4, 12 or 52 (resp. annual, bi-annual, quaterly, monthly or weekly) +% o freq scalar integer, equal to 1, 2, 4, 12, 52 or 365 (resp. annual, bi-annual, quaterly, monthly, weekly or daily) % % OUTPUTS -% o s character, equal to Y, H, Q, M or W (resp. annual, bi-annual, quaterly, monthly or weekly) +% o s character, equal to Y, H, Q, M, W or D (resp. annual, bi-annual, quaterly, monthly, weekly or daily) % Copyright (C) 2013-2020 Dynare Team % @@ -34,6 +34,8 @@ switch freq s = 'M'; case 52 s = 'W'; + case 365 + s = 'D'; otherwise error('dates::freq2string: Unknown frequency!') end @@ -45,6 +47,7 @@ end %$ strQ = freq2string(4); %$ strM = freq2string(12); %$ strW = freq2string(52); +%$ strD = freq2string(365); %$ t(1) = true; %$ catch %$ t(1) = false; @@ -56,6 +59,7 @@ end %$ t(4) = dassert(strQ, 'Q'); %$ t(5) = dassert(strM, 'M'); %$ t(6) = dassert(strW, 'W'); +%$ t(7) = dassert(strD, 'D'); %$ end %$ %$ T = all(t); diff --git a/src/utilities/convert/string2date.m b/src/utilities/convert/string2date.m index 1801c42fd60cbb148143810bfe43cf64446008e3..1a5d3c65779d57c0cb1f4cd8ec1aba4d00c5587e 100644 --- a/src/utilities/convert/string2date.m +++ b/src/utilities/convert/string2date.m @@ -58,6 +58,14 @@ if isweekly(a) return end +if isdaily(a) + year = 1:(regexp(a,'[-]')-1); + month = 6:7; + day = 9:10; + date.freq = 365; + date.time = write_time_field_d(a, year, month, day); + return +end function b = write_time_field(c, d) b(1) = str2double(c(d)); @@ -67,6 +75,11 @@ function b = write_time_field_y(c, d) b(1) = str2double(c(d)); b(2) = 1; +function b = write_time_field_d(c, y, m, d) +b(1) = str2double(c(y)); +b(2) = str2double(c(m)); +b(3) = str2double(c(d)); + %@test:1 %$ %$ % Define some dates @@ -78,6 +91,7 @@ b(2) = 1; %$ date_6 = '2009A'; %$ date_7 = '2009H1'; %$ date_8 = '2009h2'; +%$ date_9 = '2009-01-01'; %$ %$ % Define expected results. %$ e_date_1 = [1950 2]; @@ -96,6 +110,8 @@ b(2) = 1; %$ e_freq_7 = 2; %$ e_date_8 = [2009 2]; %$ e_freq_8 = 2; +%$ e_date_9 = [2009 365]; +%$ e_freq_9 = 365; %$ %$ % Call the tested routine. %$ d1 = string2date(date_1); @@ -106,6 +122,7 @@ b(2) = 1; %$ d6 = string2date(date_6); %$ d7 = string2date(date_7); %$ d8 = string2date(date_8); +%$ d9 = string2date(date_9); %$ %$ % Check the results. %$ t(1) = dassert(d1.time,e_date_1); @@ -124,5 +141,6 @@ b(2) = 1; %$ t(14)= dassert(d6.freq,e_freq_6); %$ t(15)= dassert(d7.freq,e_freq_7); %$ t(16)= dassert(d8.freq,e_freq_8); +%$ t(17)= dassert(d9.freq,e_freq_9); %$ T = all(t); %@eof:1 \ No newline at end of file diff --git a/src/utilities/convert/string2freq.m b/src/utilities/convert/string2freq.m index a15e97c6d9209d07091922f7d469cb7d723d6a58..ca5894ad800d544e4a79a62df6d0d1da21a9f08c 100644 --- a/src/utilities/convert/string2freq.m +++ b/src/utilities/convert/string2freq.m @@ -1,10 +1,10 @@ function freq = string2freq(s) % --*-- Unitary tests --*-- % INPUTS -% o s character, equal to Y, H, Q, M or W (resp. annual, bi-annual, quaterly, monthly or weekly) +% o s character, equal to Y, H, Q, M, W or D (resp. annual, bi-annual, quaterly, monthly, weekly or daily) % % OUTPUTS -% o freq scalar integer, equal to 1, 2, 4, 12 or 52 (resp. annual, bi-annual, quaterly, monthly or weekly) +% o freq scalar integer, equal to 1, 2, 4, 12, 52 or 365 (resp. annual, bi-annual, quaterly, monthly, weekly or daily) % Copyright (C) 2013-2020 Dynare Team % @@ -34,6 +34,8 @@ switch upper(s) freq = 12; case 'W' freq = 52; + case 'D' + freq = 365; otherwise error('dates::freq2string: Unknown frequency!') end @@ -45,6 +47,7 @@ end %$ nQ = string2freq('Q'); %$ nM = string2freq('M'); %$ nW = string2freq('W'); +%$ nD = string2freq('D'); %$ t(1) = true; %$ catch %$ t(1) = false; @@ -56,6 +59,7 @@ end %$ t(4) = dassert(nQ, 4); %$ t(5) = dassert(nM, 12); %$ t(6) = dassert(nW, 52); +%$ t(7) = dassert(nD, 365); %$ end %$ %$ T = all(t); diff --git a/src/utilities/is/isdaily.m b/src/utilities/is/isdaily.m new file mode 100644 index 0000000000000000000000000000000000000000..9f5b85216f85577517d33da3879c8289a6c54bd8 --- /dev/null +++ b/src/utilities/is/isdaily.m @@ -0,0 +1,58 @@ +function b = isdaily(str) % --*-- Unitary tests --*-- + +% Tests if the input can be interpreted as a daily date. +% +% INPUTS +% o str string. +% +% OUTPUTS +% o b integer scalar, equal to 1 if str can be interpreted as a daily date or 0 otherwise. + +% Copyright (C) 2020 Dynare Team +% +% This file is part of Dynare. +% +% Dynare 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 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 <http://www.gnu.org/licenses/>. + +if ischar(str) + if isempty(regexp(str,'^-?[0-9]+[-](0[1-9]|1[0-2])+[-]([0-2][0-9]|3[0-1])$','once')) + b = false; + else + b = true; + end +else + b = false; +end + +%@test:1 +%$ +%$ date_1 = '1950-03-29'; +%$ date_2 = '1950-12-31'; +%$ date_3 = '-1950-11-28'; +%$ date_4 = '1976-01-19'; +%$ date_5 = '1950 azd '; +%$ date_6 = '1950Y'; +%$ date_7 = '1950Q3'; +%$ date_8 = '1950-13-39'; +%$ +%$ t(1) = dassert(isdaily(date_1),true); +%$ t(2) = dassert(isdaily(date_2),true); +%$ t(3) = dassert(isdaily(date_3),true); +%$ t(4) = dassert(isdaily(date_4),true); +%$ t(5) = dassert(isdaily(date_5),false); +%$ t(6) = dassert(isdaily(date_6),false); +%$ t(7) = dassert(isdaily(date_7),false); +%$ t(8) = dassert(isdaily(date_8),false); +%$ T = all(t); +%@eof:1 \ No newline at end of file diff --git a/src/utilities/is/isfreq.m b/src/utilities/is/isfreq.m index b6562de7c4200447cecc2bcea6732d7c51e8ec57..3bef38a862443c4d29f3480c9bf837a25ef4e8bb 100644 --- a/src/utilities/is/isfreq.m +++ b/src/utilities/is/isfreq.m @@ -28,13 +28,13 @@ function B = isfreq(A) % --*-- Unitary tests --*-- B = false; if ischar(A) - if isequal(length(A),1) && ismember(upper(A),{'Y','A', 'H', 'Q','M','W'}) + if isequal(length(A),1) && ismember(upper(A),{'Y','A', 'H', 'Q', 'M', 'W', 'D'}) B = true; return end end -if isnumeric(A) && isequal(length(A),1) && ismember(A,[1 2 4 12 52]) +if isnumeric(A) && isequal(length(A),1) && ismember(A,[1 2 4 12 52 365]) B = true; end @@ -127,3 +127,19 @@ end %$ %$ T = all(t); %@eof:6 + +%@test:7 +%$ try +%$ boolean = isfreq('D'); +%$ t(1) = true; +%$ catch +%$ t(1) = false; +%$ end +%$ +%$ if t(1) +%$ t(2) = dassert(boolean, true); +%$ end +%$ +%$ T = all(t); +%@eof:7 + diff --git a/src/utilities/is/isstringdate.m b/src/utilities/is/isstringdate.m index 1e063d896014607dd25f2d0429f3b78b4d0009c9..f199b7ea662b91135273febf984e3ac6c2755db1 100644 --- a/src/utilities/is/isstringdate.m +++ b/src/utilities/is/isstringdate.m @@ -26,7 +26,7 @@ function b = isstringdate(str) % --*-- Unitary tests --*-- % along with Dynare. If not, see <http://www.gnu.org/licenses/>. if ischar(str) - b = isquarterly(str) || isyearly(str) || isbiannual(str) || ismonthly(str) || isweekly(str); + b = isquarterly(str) || isyearly(str) || isbiannual(str) || ismonthly(str) || isweekly(str) || isdaily(str); else b = false; end @@ -50,6 +50,8 @@ end %$ date_15 = 'W1'; %$ date_16 = '1948H1'; %$ date_17 = 'h2'; +%$ date_18 = '1948-02-12'; +%$ date_19 = '12-30'; %$ %$ t(1) = dassert(isstringdate(date_1),true); %$ t(2) = dassert(isstringdate(date_2),true); @@ -68,6 +70,8 @@ end %$ t(15) = dassert(isstringdate(date_15),false); %$ t(16) = dassert(isstringdate(date_16),true); %$ t(17) = dassert(isstringdate(date_17),false); +%$ t(16) = dassert(isstringdate(date_18),true); +%$ t(17) = dassert(isstringdate(date_19),false); %$ %$ T = all(t); %@eof:1 \ No newline at end of file diff --git a/src/utilities/is/issubperiod.m b/src/utilities/is/issubperiod.m index bf02fee0a4954c99bf9aa1aeaa4c86a8230c9d5a..66722a0efff36c28a7105e84a301619c69ed8f2c 100644 --- a/src/utilities/is/issubperiod.m +++ b/src/utilities/is/issubperiod.m @@ -18,7 +18,11 @@ function C = issubperiod(A,B) % --*-- Unitary tests --*-- % along with Dynare. If not, see <http://www.gnu.org/licenses/>. if isfreq(B) - C = all(isint(A)) && all(A>=1) && all(A<=B); + if B == 365 + error('issubperiod:: The function does not support daily frequency!') + else + C = all(isint(A)) && all(A>=1) && all(A<=B); + end else error('issubperiod:: Second input argument must be equal to 1, 2, 4, 12 or 52 (frequency)!') end