MF-DFA from Matalb to Julia implementation - matlab

I'm working with the MF-DFA method in Matlab but I need to implement it in Julia. The goal is tho obtain the Hurst exponent of the S&P 500. The matlab code is as follows:
sp500 = readtable('sp500_Nasdaq.csv','PreserveVariableNames', true) ;
spClose = table2array(sp500(:,2)) ;
SP1=cumsum(spClose - mean(spClose)) ;
SP1_ordinary=sqrt(mean(SP1.^2));
X=cumsum(spClose-mean(spClose));
X=transpose(X);
scale=[16,32,64,128,256,512,1024];
q=[-5,-3,-1,0,1,3,5];
m=1;
for ns=1:length(scale),
segments(ns)=floor(length(X)/scale(ns));
for v=1:segments(ns)
Index=( ( ( (v-1)*scale(ns) )+1):(v*scale(ns)));
C = polyfit(Index,X(Index),m) ;
fit=polyval(C,Index);
RMS{ns}(v)=sqrt(mean((X(Index)-fit).^2));
end
for nq=1:length(q),
qRMS{nq,ns}=RMS{ns}.^q(nq);
Fq(nq,ns)=mean(qRMS{nq,ns}).^(1/q(nq));
end
Fq(q==0,ns)=exp(0.5*mean(log(RMS{ns}.^2)));
end
The Julia the code looks like this:
using DelimitedFiles, TimeSeries, Plots, DelimitedFiles, Plots, StatsBase
using Polynomials, LinearAlgebra, CSV, DataFrames
sp500 = CSV.read("sp500_Nasdaq.csv", DataFrame)
sp500_V = values(sp500[:,2])
SP1 = cumsum(sp500_V .- mean(sp500_V) ) ;
SP1_Ord = sqrt(mean(SP1.^2)) ;
X = SP1 ;
X = X';
function polyfit(xVals,yVals)
n = length(xVals)
xBar, yBar = #fastmath mean(xVals), mean(yVals)
sXX, sXY = #fastmath ones(n)'*(xVals.-xBar).^2 , dot(xVals.-xBar,yVals.-yBar)
b1A = #fastmath sXY/sXX
b0A = #fastmath yBar - b1A*xBar
return b0A, b1A
end
scales = [16,32,64,128,256,512,1024];
q = [-5,-3,-1,0,1,3,5] ;
segments = zeros(Int64, (1,length(scales)))
global qRMS = zeros( length(q) ,length(scales) ) ;
global Fq = zeros( length(q) , length(scales) ) ;
#inbounds for ns = 1:length(scales)
global segments[ns] = Int(floor( length(X)/scales[ns] ) ) ;
global Index = Array{UnitRange{Int128}}(undef, (segments[ns], length(scales)) ) ;
global ft = zeros(Float64, (segments[ns], length(scales) ) ) ;
global RMS = zeros(Float64, (length(scales) ,segments[ns] ) ) ;
#inbounds for v=1:segments[ns]
global RMSk = Array{Float64}[] ;
Index = ( ( (v-1)*scales[ns] ) + 1 ):( v*scales[ns] ) ;
global C = polyfit( Index, X[Index]) ;
global p = Polynomial(C)
ft =p.(Index);
RMS[ns,v] = sqrt(mean((X[Index] .- ft).^2));
push!(RMSk,RMS )
end
#inbounds for nq = 1:length(q)
qRMS[nq,ns] = RMS[ns].^q[nq];
Fq[nq,ns] = mean( qRMS[nq,ns] ).^(1/q[nq] );
end
Fq[findall(x->x==0, q)[1], ns] = exp( 0.5*mean(log.(RMS[ns].^2) ) ) ;
end
The thing is that the array RMS in Matlab's code is an array of arrays like this:
RMS =
1×7 cell array
{1×159 double} {1×79 double} {1×39 double} {1×19 double} {1×9 double} {1×4 double} {1×2 double}
But Julia returns only the last array
RMS
7×2 Matrix{Float64}:
0.0 0.0
0.0 0.0
0.0 0.0
0.0 0.0
0.0 0.0
0.0 0.0
62178.0 18238.2
How can I obtain the same output as in Matlab?
How can you store arrays into arrays in Julia?

The solutions for this is to use RMScell = Array{Float64}[] is equivalent to a Matlab cell array
using DelimitedFiles, TimeSeries, Plots, DelimitedFiles, Plots
using Polynomials, LinearAlgebra, CSV, DataFrames, StatsBase
sp500 = CSV.read("sp500_Nasdaq.csv", DataFrame) ;
sp500_V = values(sp500[:,2]) ;
SP1 = cumsum( sp500_V .- mean(sp500_V) ) ;
SP1_Ord = sqrt( mean(SP1.^2) ) ;
X = SP1 ;
X = X' ;
function polyfit(xVals,yVals)
n = length(xVals)
xBar, yBar = #fastmath mean(xVals), mean(yVals)
sXX, sXY = #fastmath ones(n)'*(xVals.-xBar).^2 , dot(xVals.- xBar,yVals.-yBar)
b1A = #fastmath sXY/sXX
b0A = #fastmath yBar - b1A*xBar
return b0A, b1A
end
""" Multifractal detrended fluctuation analysis of time series """
scales = [16,32,64,128,256,512,1024];
q = [-5,-3,-1,0,1,3,5] ;
segments = zeros(Int64, (1,length(scales))) ;
global qRMS = zeros( length(q) ,length(scales) ) ;
global Fq = zeros( length(q) , length(scales) ) ;
global RMScell = Array{Float64}[] ;
global qRMScell =[] ;
global segmentsFq = [] ;
#inbounds for ns = 1:length(scales)
global segments[ns] = Int(floor( length(X)/scales[ns] ) ) ;
global ft = zeros(Float64, (segments[ns], length(scales) ) ) ;
global RMS = zeros(Float64, segments[ns]);
#inbounds for v=1:segments[ns]
global Index = ( (v-1)*scales[ns] ) + 1: v*scales[ns] ;
global C = polyfit( Index, X[Index]) ;
global p = Polynomial(C) ;
ft =p.(Index) ;
RMS[v] = sqrt(mean((X[Index] .- ft).^2)) ;
end
l = deepcopy(RMS)
push!(RMScell,l)
global IndexFq = ((ns-1)*length(q) ) + 1 : ns*length(q) ;
push!(segmentsFq, IndexFq) ;
#inbounds for nq = 1:length(q)
l = RMScell[ns].^q[nq]
r = deepcopy(l) ;
push!(qRMScell, r) ;
end
#inbounds for nq = 1: length(scales)
Fq[nq,ns] = mean( qRMScell[segmentsFq[ns]][nq] ).^(1/q[nq] ) ;
end
Fq[findall(x->x==0, q)[1], ns] = exp( 0.5*mean(log.(RMScell[ns].^2) ) ) ;
end
Hq = zeros( Float64,length(q) ) ;
global qRegLine = Array{Float64}[] ;
for nq = 1:length(q)
global C = polyfit( log2.(scales),log2.(Fq[nq,:]) ) ;
Hq[nq] = C[2] ;
global p = Polynomial(C) ;
push!( qRegLine, p.( log2.(scales) ) )
end
tq = Hq.*q .- 1 ;
hq = diff(tq)./(q[2]-q[1]) ;
Dq = ( q[1:end-1].*hq ) - tq[1:end-1] ;

Related

Improve speed of appending array elements if not already in array

I have an array S, which has some number of unique elements. I want to append elements from array N which are not already in S.
A syntactically simple way to do this would be:
S = union( S, N, 'stable' );
I found manually appending could be quicker, using ismember or implicit expansion:
% ismember approach
S = [S; N(~ismember(N,S))];
% imp. expansion approach
S = [S; N(~any(S(:)==N(:).',1))];
However, this still feels pretty dirty to do inside a loop, and the implicit expansion can be expensive for large inputs.
Is there a more performant alternative?
If it helps, we can assume S and N contain only integers. However, we can't assume that S is sorted, new elements appended from N could be any positive integer.
Minimal example:
Ntest = [1 2 3 4
2 5 3 6
1 5 7 9];
S = [];
for ii = 1:3
N = Ntest(ii,:).';
S = union(S,N,'stable');
end
% S = [ 1; 2; 3; 4; 5; 6; 7; 9 ]
In the real case, I don't know the potential values of N up front like I did with Ntest above.
Here is some benchmarking code for 4 methods, with the following results. In my case, it's likely that I'll have a large loop for different values of N, and a small number of elements in each N. This corresponds to the right-most columns in this summary table, where you can see the implicit expansion method is much quicker.
range(Ntest): 1 to 1e4 1 to 1e4 1 to 1e4 1 to 1e4
size(Ntest): [1e3,1e3] [1e4,1e3] [1e2,1e3] [1e2,1e4]
union: 0.972 sec 1.217 sec 0.779 sec 9.341 sec
ismember: 0.763 sec 0.559 sec 0.492 sec 5.439 sec
implicit: 6.966 sec too long! 0.295 sec 3.886 sec
setdiff: 0.599 sec 0.534 sec 0.477 sec 5.364 sec
rng(0);
Ntest = randi([1,1e4],1e3,1e3);
f = #()f_union( Ntest );
fprintf( 'union: \t%.3f sec\n', timeit( f ) );
f = #()f_ismember( Ntest );
fprintf( 'ismember: \t%.3f sec\n', timeit( f ) );
f = #()f_implicit( Ntest );
fprintf( 'implicit: \t%.3f sec\n', timeit( f ) );
f = #()f_setdiff( Ntest );
fprintf( 'setdiff: \t%.3f sec\n', timeit( f ) );
function f_union( Ntest )
S = [];
for ii = 1:size(Ntest,2)
N = Ntest(:,ii);
S = union(S,N,'stable');
end
end
function f_ismember( Ntest )
S = [];
for ii = 1:size(Ntest,2)
N = Ntest(:,ii);
S = [S; N(~ismember(N,S))];
end
end
function f_implicit( Ntest )
S = [];
for ii = 1:size(Ntest,2)
N = Ntest(:,ii);
S = [S; N(~any(S(:)==N(:).',1))];
end
end
function f_setdiff( Ntest )
S = [];
for ii = 1:size(Ntest,2)
N = Ntest(:,ii);
S = [S;setdiff(N,S)];
end
end
Since it is assumed that the data type is positive integer you can use logical matrix to store position of integers:
function f_logical( Ntest )
S = false;
for ii = 1:size(Ntest,2)
N = Ntest(:,ii);
S(N) = true;
end
end
If the range of elements is large and the data has sparsity it may be beneficial to use sparse matrix:
function f_sparse( Ntest )
S = sparse(false);
for ii = 1:size(Ntest,2)
N = Ntest(:,ii);
S(N) = true;
end
end
Comparing with the ismember solution in Octave:
Elapsed time for <ismember> is 1.54181 seconds.
Elapsed time for <sparse> is 0.266474 seconds.
Elapsed time for <logical> is 0.0189412 seconds.
I guess you can use the following code to speed up
X = setdiff(N,S);
S(end + (1:length(X))) = X;
Remarks
X = N(~ismember(N,S)) and X = setdiff(N,S) are both fine to find the elements that in N but not in S, but the key step for speeding up the appending process is the following way
S(end + (1:length(X))) = X;
Performance Comparison
rng(0);
Ntest = randi([1,1e4],1e4,1e4);
f = #()f_union( Ntest );
fprintf( 'union: \t%.3f sec\n', timeit( f ) );
f = #()f_ismember_v1( Ntest );
fprintf( 'ismember_v1: \t%.3f sec\n', timeit( f ) );
f = #()f_ismember_v2( Ntest );
fprintf( 'ismember_v2: \t%.3f sec\n', timeit( f ) );
f = #()f_setdiff_v1( Ntest );
fprintf( 'setdiff_v1: \t%.3f sec\n', timeit( f ) );
f = #()f_setdiff_v2( Ntest );
fprintf( 'setdiff_v2: \t%.3f sec\n', timeit( f ) );
function f_union( Ntest )
S = [];
for ii = 1:size(Ntest,2)
N = Ntest(:,ii);
S = union(S,N,'stable');
end
end
function f_ismember_v1( Ntest )
S = [];
for ii = 1:size(Ntest,2)
N = Ntest(:,ii);
S = [S; N(~ismember(N,S))];
end
end
function f_ismember_v2( Ntest )
S = [];
for ii = 1:size(Ntest,2)
N = Ntest(:,ii);
X = N(~ismember(N,S));
S(end + (1:length(X))) = X;
end
end
function f_setdiff_v1( Ntest )
S = [];
for ii = 1:size(Ntest,2)
N = Ntest(:,ii);
S = [S;setdiff(N,S)];
end
end
function f_setdiff_v2( Ntest )
S = [];
for ii = 1:size(Ntest,2)
N = Ntest(:,ii);
X = setdiff(N,S);
S(end + (1:length(X))) = X;
end
end
giving
union: 13.314 sec
ismember_v1: 5.836 sec
ismember_v2: 5.658 sec
setdiff_v1: 4.371 sec
setdiff_v2: 4.248 sec

How to display a function with double values instead of symbolic?

I want the function P to look like this:
-1 + 0.6366*(x+pi/2) + (-0.000)*(x + pi/2)*(x)
and right now it looks like this
(5734161139222659*x)/9007199254740992 + (5734161139222659*pi)/18014398509481984 - (8131029572207409*x*(x + pi/2))/324518553658426726783156020576256 - 1.
How to convert S array so that the values are not symbolic?
syms P x
f = sin(x);
f = matlabFunction(f);
X = [-pi/2, 0, pi/2];
Y = f(sym(X));
P = MetN(X,Y,x)
P = matlabFunction(P);
function [P] = MetN(X,Y,x)
n = length(X);
for i = 1:n
A(i,1) = 1;
end
for i = 2:n
for j = 2: n
if i >= j
produs = 1;
for k =1:j-1
produs = produs * (X(i) - X(k));
end
A(i,j) = produs;
end
end
end
S = SubsAsc(A, Y);
S = double(S);
disp(S);
sym produs
P = double(sym(S(1)));
for i = 2:n
produs = 1;
for j = 1:i-1
produs = produs * (x - sym(X(j)));
end
disp(produs);
P = P + double(S(i))*produs;
end
end
function [x] = SubsAsc(A,b)
n = length(b);
x(1) = (1/A(1,1))*b(1);
for k = 2:n
s = 0;
for j = 1:k-1
s = s + A(k,j)*x(j);
end
x(k) = (1/A(k,k))*(b(k)-s);
end
end
The output you currently have is because symbolic uses exact arithmetic, so it outputs it as a rational number (hence the ugly fraction).
To have it output P using decimals, use vpa(). For instance output P using decimals to 5 significant digits
>> vpa(P, 5)
ans =
0.63662*x - 2.5056e-17*x*(x + 1.5708)
This will, however, also round pi, so you can't really have the best of both worlds here.

Image Transformation Without Loop

I am writing image transformation function in matlab instead of using predefined functions like 'imwarp or imtransform'. I am done with writing the code roughly but it is taking too long due to the use of loop.
Please suggest me a solution which can achieve the same result without loops
function I2 = f_transform(A, I1)
%A is an affine transformation matrix
%I1 is original image to be transformed
s=size(A);
if(s(1)~=3 || s(2)~=3)
disp("Invalid Transforming Matrix");
I2=0;
return;
end
if(det(A)==0)
disp("The given Transforming Matrix is Singular");
I2=0;
return;
end
[r, c]=size(I1);
extremeValues = [1 1 r r ; 1 c 1 c; 1 1 1 1];
newExtremeValues = A * extremeValues;
minRow = floor( min( newExtremeValues(1,:) ) );
maxRow = ceil( max( newExtremeValues(1,:) ) );
minCol = floor( min( newExtremeValues(2,:) ) );
maxCol = ceil( max( newExtremeValues(2,:) ) );
I2 = zeros(maxRow - minRow + 1, maxCol - minCol + 1);
for i = minRow:maxRow
for j=minCol:maxCol
b = A \ [i j 1]';
p = b(1) / b(3);
q = b(2) / b(3);
if(p >= 1 && p <= r && q >= 1 && q <= c)
I2(i - minRow + 1, j - minCol + 1) = I1(round(p),round(q));
end
end
end
I2 = uint8(I2);
return;
end

about Clamped cubic spline code in Matlab

I did the program, but for some reason it marks a mistake (c = tridiagonal ( hi(1:n-1), dd, hi(1:n-1), ri ); ) and I don't know why, I'm sure it's correct so please somebody help.
Here is the code:
function csc = cubic_clamped ( xi, fi, fpa, fpb )n = length ( xi );
m = length ( fi );
if ( n ~= m )
disp ( 'number of ordinates and number of function values must be equal' )
return
end
for i = 1 : n-1
hi(i) = xi(i+1) - xi(i);
end
dd(1) = 2.0*hi(1); dd(n) = 2.0*hi(n-1);
ri(1) = (3.0/hi(1))*(fi(2)-fi(1)) - 3.0 * fpa;
ri(n) = 3.0 * fpb - (3.0/hi(n-1))*(fi(n)-fi(n-1));
for i = 1 : n-2
dd(i+1) = 2.0 * ( hi(i) + hi(i+1) );
ri(i+1) = (3.0/hi(i+1))*(fi(i+2)-fi(i+1))-(3.0/hi(i))*(fi(i+1)-fi(i));
end
disp ( [dd' ri'] )
c = tridiagonal ( hi(1:n-1), dd, hi(1:n-1), ri );
d = zeros ( n,1 );
b = d;
for i = 1 : n-1
d(i) = (c(i+1)-c(i))/(3.0*hi(i));
b(i) = (fi(i+1)-fi(i))/hi(i) - hi(i)*(c(i+1)+2.0*c(i))/3.0;
end
if ( nargout == 0 )
disp ( [ xi' fi' b c' d ] )
else
csc = [ xi' fi' b c' d ];
end
tridiagonal code (error is: w = a(i) - b(i)*v(i-1); )
function y = tridiagonal( a, b, c, f )
n = length(f);
v = zeros(n,1);
y = v;
w = a(1);
y(1) = f(1)/w;
for i=2:n
v(i-1) = c(i-1)/w;
w = a(i) - b(i)*v(i-1);
y(i) = ( f(i) - b(i)*y(i-1) )/w;
end
for j=n-1:-1:1
y(j) = y(j) - v(j)*y(j+1);
end

How to replace a "for loop" to make it run faster

I have a for loop as a part of my code. Its run takes too long, specially for large lenghts of I. Is there any way to make it faster?
[temp,I,J] = unique(cc_new,'rows');
I=sort(I);
cc_new = cc_new(I,:);
C = C(I,:);
n = 0;
clear K;
for i = 1 : length(I)-1,
for j = i+1 : length(I),
if sum(intersect(cc_new(i,:),cc_new(j,:)))-sum(cc_new(j,:))==0,
n = n+1;
K(n) = j;
end
end
end
if n > 0,
K=unique(K);
removed = cc_new(K',:);
[temp,I]=setdiff(cc_new,removed,'rows');
I=sort(I);
cc_new = cc_new(I,:);
C = C(I,:);
end
cc = cc_new;
index0=find (A (:,2 )==0);
A0=A(index0,:);
A1=A;
A1(index0,:) =[]; % A ( : , 2 ) ~= 0
[ia1,ja1]=size(A1);
A20 = A1;
A30 = A20 ( : , 1 );
A40 = A0 ( : , 1 );
A50 = [ A30 ; A40 ];
[~,ix2,~] = unique(A50,'rows');
A60 = A0;
ix3 = ix2-ia1;
A60(ix3,:) = [];
A21 = A1;
A31 = A21 ( : , 2 );
A41 = A0 ( : , 1 );
A51 = [ A31 ; A41 ];
[~,ix21,~] = unique(A51,'rows');
A61 = A0;
ix31 = ix21-ia1;
A61(ix31,:) = [];
AN = [ A1 ; A60 ; A61 ];