I want to generate a standard normal distributed time-series. In addition the ACF of my timeseries should match a desired ACF. I have given lags 1 to 30 with the corresponding ACF-values. For further processing, the CDF of the timeseries should be the standard normal CDF.
When i try filtering a standard normal distributed timeseries with my ACF, the result does not have the desired attributes. Neither is the ACF like the desired ACF, nor is the CDF unchanged.
I tried the approach from jblood94 from this and this thread. But this approach only works for very specific ACF-values.
When i insert my desired ACF, this approach does not work.
Here is my desired ACF:
The model for my ACF:
lags = 0:30
a = 0.9999
b = -0.07197
acf = a*exp(b.*lags)
I assume that the problem is the high correlation at the beginning.
The timeseries needs to be standard normal distributed, for the next steps in my program.
The following Matlab-Code includes the approach. But as you can see, it will only work, if we set a minimum of 45 lags. Why is this so? In addition, i have to adjust the initial STD of my samples. How can i calculate the initial STD, to be after the filtering 1?
%% init
clear;
close all;
clc;
set(groot, 'DefaultAxesLineWidth', 2);
set(groot, 'DefaultLineLineWidth', 2);
set(groot, 'DefaultAxesFontSize', 14);
%% define desired auto-correlation function
lagsDesired = 0:45; % if lag is <45 the approach fails
a = 0.999;
b = -0.07197;
acfDesired = a * exp(b .* lagsDesired);
%% generate normal distributed samples
numSamples = 1e6;
% sigma increases during filtering (How can i calculate the factor?)
sigmaFactor = 0.35;
x = sigmaFactor * randn(numSamples, 1);
%% predefine indices
m = length(acfDesired);
i1 = sequence((m-1):-1:1);
i2 = sequence((m-1):-1:1, 'from', 2:m);
i3 = cumsum((m-1):-1:1);
%% initial values for adjustment
w = acfDesired;
temp = cumsum(w(i1) .* w(i2));
a = [1, diff([0 temp(i3)])/sum(w.^2)];
%% iterative adjustment of the filter weights
while (max(abs(acfDesired - a)) >= 2e-3) %sqrt(eps))
max(abs(acfDesired - a))
temp = cumsum(w(i1) .* w(i2));
a = [1, diff([0 temp(i3)])/sum(w.^2)];
w = w .* (acfDesired./a);
end
%% filter normal samples with weights
y = filter(w, 1, x);
%% transform normal to uniform samples via standard normal cdf
uniRandCorr = normcdf(y);
%% plot
figure;
[Fy, xy] = ecdf(y);
[Fn, xn] = ecdf(randn(numSamples, 1));
plot(xy, Fy);
hold on;
plot(xn, Fn);
l = legend({'ECDF of samples' , 'Desired ECDF'}, 'Location', 'best');
title(l, 'Legend');
title('CDF');
xlabel('Value');
ylabel('CDF');
grid on;
figure;
[acf, lags] = autocorr(uniRandCorr, 'NumLags', 60);
plot(lags, acf);
hold on;
plot(lagsDesired, acfDesired);
l = legend({'ACF of samples' , 'Desired ACF'}, 'Location', 'best');
title(l, 'Legend');
title('ACF');
xlabel('Lag');
ylabel('ACF');
grid on;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [seq] = sequence(nvec, varargin)
% [seq] = sequence(nvec, varargin)
%
% DESCRIPTION:
% R-Functions translated to MATLAB
% Creates a vector of sequences
% R: A Language and Environment for Statistical Computing Reference Index
% Version 4.2.3 Page 505 ff
%
% EXAMPLE:
% -
%
% INPUT:
% nvec : Input vector
% from : Starting value(s)
% by : Increment of the sequence(s)
%
% OUTPUT:
% seq : Generated sequence
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Parse inputs
iParser = inputParser;
addRequired(iParser, 'nvec', ...
@(x) isnumeric(x) && all(x>=0));
addOptional(iParser, 'from', ones(length(nvec), 1), ...
@(x) isnumeric(x) && (isscalar(x) || length(x)==length(nvec)));
addOptional(iParser, 'by', ones(length(nvec), 1), ...
@(x) isnumeric(x) && (isscalar(x) || length(x)==length(nvec)));
parse(iParser, nvec, varargin{:});
if isscalar(iParser.Results.from)
from = ones(length(nvec))*iParser.Results.from;
else
from = iParser.Results.from;
end
if isscalar(iParser.Results.by)
by = ones(length(nvec))*iParser.Results.by;
else
by = iParser.Results.by;
end
seq = [];
for i=1:length(nvec)
seq = [seq, linspace(from(i), from(i) + (by(i)*(nvec(i)-1)), nvec(i))];
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
This gives the following output:
As you can see, the result is correct. BUT, it works only with min. 45 lags AND if i change the model of the acf I have to adapt this parameter. In addition i have no idea, how i can calculate the sigma of the gauss samples, so that the sigma AFTER the filtering is 1 (standard). I know, that the standarddeviation changes during filtering, but I have not found a formula for this yet.



a*exp(b.*lags)forlags <= 30and approximately 0 forlags > 30? – jblood94 Mar 23 '23 at 14:04