diff --git a/.travis.yml b/.travis.yml index 8431f17..5141406 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,8 +11,8 @@ matrix: notifications: email: false after_success: - - julia -e 'using Pkg; cd(joinpath(dirname(pathof(Indicators)), "..")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())' - - julia -e 'using Pkg; cd(joinpath(dirname(pathof(Indicators)), "..")); Pkg.add("Coverage"); using Coverage; Codecov.submit(Codecov.process_folder())' + - julia -e 'using Pkg, Indicators; cd(joinpath(dirname(pathof(Indicators)), "..")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())' + - julia -e 'using Pkg, Indicators; cd(joinpath(dirname(pathof(Indicators)), "..")); Pkg.add("Coverage"); using Coverage; Codecov.submit(Codecov.process_folder())' jobs: include: - stage: "Documentation" diff --git a/Manifest.toml b/Manifest.toml index 9114d14..e4df64e 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -5,9 +5,9 @@ uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" [[BinaryProvider]] deps = ["Libdl", "SHA"] -git-tree-sha1 = "29995a7b317bbd06be147e1974a3541ce2502dca" +git-tree-sha1 = "5b08ed6036d9d3f0ee6369410b830f8873d4024c" uuid = "b99e7846-7c00-51b0-8f62-c81ae34c0232" -version = "0.5.7" +version = "0.5.8" [[Dates]] deps = ["Printf"] @@ -19,9 +19,9 @@ uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b" [[HTTP]] deps = ["Base64", "Dates", "IniFile", "MbedTLS", "Sockets"] -git-tree-sha1 = "f1e1b417a34cf73a70cbed919915bf8f8bad1806" +git-tree-sha1 = "5c49dab19938b119fe204fd7d7e8e174f4e9c68b" uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3" -version = "0.8.6" +version = "0.8.8" [[IniFile]] deps = ["Test"] @@ -39,6 +39,9 @@ git-tree-sha1 = "b34d7cef7b337321e97d22242c3c2b91f476748e" uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" version = "0.21.0" +[[LibGit2]] +uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" + [[Libdl]] uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" @@ -64,14 +67,22 @@ uuid = "a63ad114-7e13-5084-954f-fe012c677804" [[Parsers]] deps = ["Dates", "Test"] -git-tree-sha1 = "ef0af6c8601db18c282d092ccbd2f01f3f0cd70b" +git-tree-sha1 = "0139ba59ce9bc680e2925aec5b7db79065d60556" uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" -version = "0.3.7" +version = "0.3.10" + +[[Pkg]] +deps = ["Dates", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "UUIDs"] +uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" [[Printf]] deps = ["Unicode"] uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" +[[REPL]] +deps = ["InteractiveUtils", "Markdown", "Sockets"] +uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" + [[Random]] deps = ["Serialization"] uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" @@ -99,14 +110,18 @@ deps = ["LinearAlgebra", "SparseArrays"] uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" [[Temporal]] -deps = ["Dates", "HTTP", "JSON", "Printf", "Random", "RecipesBase", "Statistics", "Test"] -git-tree-sha1 = "ab2b14f510cd2a068974c9dc654ad8e743582dc1" +deps = ["Dates", "HTTP", "JSON", "Pkg", "Printf", "Random", "RecipesBase", "Statistics", "Test"] +git-tree-sha1 = "31560aae24d7fa64dd75aaa4a74a81ac7cd28576" uuid = "a110ec8f-48c8-5d59-8f7e-f91bc4cc0c3d" -version = "0.6.1" +version = "0.7.0" [[Test]] deps = ["Distributed", "InteractiveUtils", "Logging", "Random"] uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +[[UUIDs]] +deps = ["Random", "SHA"] +uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" + [[Unicode]] uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" diff --git a/src/reg.jl b/src/reg.jl index 427214f..6f55f14 100644 --- a/src/reg.jl +++ b/src/reg.jl @@ -159,7 +159,7 @@ Moving linear regression R-squared or adjusted R-squared """ function mlr_rsq(y::Array{T}; n::Int64=10, adjusted::Bool=false)::Array{T} where {T<:Real} yhat = mlr(y, n=n) - rsq = runcor(y, yhat, n=n, cumulative=false) .^ 2 + rsq = runcor(y, yhat, n=n, cumulative=false) .^ 2.0 if adjusted return rsq .- (1.0.-rsq)*(1.0/(float(n).-2.0)) else diff --git a/src/run.jl b/src/run.jl index 1d6f9b8..372db3c 100644 --- a/src/run.jl +++ b/src/run.jl @@ -4,80 +4,19 @@ using Statistics """ ``` -diffn(x::Array{T}; n::Int64=1)::Array{T} -``` - -Lagged differencing -""" -function diffn(x::Array{T}; n::Int64=1)::Array{T} where {T<:Real} - @assert n0 "Argument n out of bounds." - dx = zeros(size(x)) - dx[1:n] .= NaN - @inbounds for i=n+1:size(x,1) - dx[i] = x[i] - x[i-n] - end - return dx -end - -""" -``` -diffn(X::Array{T,2}; n::Int64=1)::Array{T} -``` - -Lagged differencing -""" -function diffn(X::Array{T,2}; n::Int64=1)::Matrix{T} where {T<:Real} - @assert n0 "Argument n out of bounds." - dx = zeros(size(X)) - @inbounds for j = 1:size(X,2) - dx[:,j] = diffn(X[:,j], n=n) - end - return dx -end - -""" -(Adapted from StatsBase: https://raw.githubusercontent.com/JuliaStats/StatsBase.jl/master/src/scalarstats.jl) - -Compute the mode of an arbitrary array::Array{T} -""" -function mode(a::AbstractArray{T}) where {T<:Real} - isempty(a) && error("mode: input array cannot be empty.") - cnts = Dict{T,Int64}() - # first element - mc = 1 - mv = a[1] - cnts[mv] = 1 - # find the mode along with table construction - @inbounds for i = 2 : length(a) - x = a[i] - if haskey(cnts, x) - c = (cnts[x] += 1) - if c > mc - mc = c - mv = x - end - else - cnts[x] = 1 - # in this case: c = 1, and thus c > mc won't happen - end - end - return mv -end - -""" -``` -runmean(x::Array{T}; n::Int64=10, cumulative::Bool=true)::Array{T} +runmean(x::Array{T}; n::Int=10, cumulative::Bool=true)::Array{T} +runmean(X::Matrix; n::Int=10, cumulative::Bool=true)::Matrix ``` Compute a running or rolling arithmetic mean of an array. """ -function runmean(x::Array{T}; n::Int64=10, cumulative::Bool=true)::Array{T} where {T<:Real} +function runmean(x::Vector{T}; n::Int=10, cumulative::Bool=true)::Vector{T} where {T<:AbstractFloat} @assert n1 "Argument n is out of bounds." - out = zeros(size(x)) + out = zeros(size(x,1)) out[1:n-1] .= NaN if cumulative fi = 1.0:size(x,1) - @inbounds for i = n:size(x,1) + @inbounds for i in n:size(x,1) out[i] = sum(x[1:i])/fi[i] end else @@ -108,14 +47,17 @@ function runmean(x::Array{T}; n::Int64=10, cumulative::Bool=true)::Array{T} wher end return out end +runmean(X::Matrix; n::Int=10, cumulative::Bool=true)::Matrix = hcat((runmean(X[:,j], n=n, cumulative=cumulative) for j in 1:size(X,2))...) + """ ``` -runsum(x::Array{T}; n::Int64=10, cumulative::Bool=true)::Array{T} +runsum(x::Vector{T}; n::Int=10, cumulative::Bool=true)::Vector{T} +runsum(X::Matrix; n::Int=10, cumulative::Bool=true)::Matrix ``` Compute a running or rolling summation of an array. """ -function runsum(x::Array{T}; n::Int64=10, cumulative::Bool=true)::Array{T} where {T<:Real} +function runsum(x::Vector{T}; n::Int=10, cumulative::Bool=true)::Vector{T} where {T<:AbstractFloat} @assert n1 "Argument n is out of bounds." if cumulative out = cumsum(x, dims=1) @@ -150,32 +92,17 @@ function runsum(x::Array{T}; n::Int64=10, cumulative::Bool=true)::Array{T} where end return out end -""" -``` -wilder_sum(x::Array{T}; n::Int64=10)::Array{T} -``` - -Welles Wilder summation of an array -""" -function wilder_sum(x::Array{T}; n::Int64=10)::Array{T} where {T<:Real} - @assert n0 "Argument n is out of bounds." - nf = float(n) # type stability -- all arithmetic done on floats - out = zeros(size(x)) - out[1] = x[1] - @inbounds for i = 2:size(x,1) - out[i] = x[i] + out[i-1]*(nf-1.0)/nf - end - return out -end +runsum(X::Matrix; n::Int=10, cumulative::Bool=true)::Matrix = hcat((runsum(X[:,j], n=n, cumulative=cumulative) for j in 1:size(X,2))...) """ ``` -runmad(x::Array{T}; n::Int64=10, cumulative::Bool=true, fun::Function=median)::Array{T} +runmad(x::Vector{T}; n::Int=10, cumulative::Bool=true, fun::Function=median)::Vector{T} +runmad(X::Matrix; n::Int=10, cumulative::Bool=true)::Matrix ``` Compute the running or rolling mean absolute deviation of an array """ -function runmad(x::Array{T}; n::Int64=10, cumulative::Bool=true, fun::Function=median)::Array{T} where {T<:Real} +function runmad(x::Vector{T}; n::Int=10, cumulative::Bool=true, fun::Function=median)::Vector{T} where {T<:AbstractFloat} @assert n1 "Argument n is out of bounds." out = zeros(size(x)) out[1:n-1] .= NaN @@ -195,15 +122,17 @@ function runmad(x::Array{T}; n::Int64=10, cumulative::Bool=true, fun::Function=m end return out end +runmad(X::Matrix; n::Int=10, cumulative::Bool=true)::Matrix = hcat((runmad(X[:,j], n=n, cumulative=cumulative) for j in 1:size(X,2))...) """ ``` -runvar(x::Array{T}; n::Int64=10, cumulative=true)::Array{T} +runvar(x::Vector{T}; n::Int=10, cumulative=true)::Vector{T} +runvar(X::Matrix; n::Int=10, cumulative::Bool=true)::Matrix ``` Compute the running or rolling variance of an array """ -function runvar(x::Array{T}; n::Int64=10, cumulative=true)::Array{T} where {T<:Real} +function runvar(x::Vector{T}; n::Int=10, cumulative=true)::Vector{T} where {T<:AbstractFloat} @assert n1 "Argument n is out of bounds." out = zeros(size(x)) out[1:n-1] .= NaN @@ -218,26 +147,30 @@ function runvar(x::Array{T}; n::Int64=10, cumulative=true)::Array{T} where {T<:R end return out end +runvar(X::Matrix; n::Int=10, cumulative::Bool=true)::Matrix = hcat((runvar(X[:,j], n=n, cumulative=cumulative) for j in 1:size(X,2))...) """ ``` -runsd(x::Array{T}; n::Int64=10, cumulative::Bool=true)::Array{T} +runsd(x::Vector{T}; n::Int=10, cumulative::Bool=true)::Vector{T} +runsd(X::Matrix; n::Int=10, cumulative::Bool=true)::Matrix ``` Compute the running or rolling standard deviation of an array """ -function runsd(x::Array{T}; n::Int64=10, cumulative::Bool=true)::Array{T} where {T<:Real} +function runsd(x::Vector{T}; n::Int=10, cumulative::Bool=true)::Vector{T} where {T<:AbstractFloat} return sqrt.(runvar(x, n=n, cumulative=cumulative)) end +runsd(X::Matrix; n::Int=10, cumulative::Bool=true)::Matrix = sqrt.(hcat((runvar(X[:,j], n=n, cumulative=cumulative) for j in 1:size(X,2))...)) """ ``` -runcov(x::Array{T}, y::Array{T}; n::Int64=10, cumulative::Bool=true)::Array{T} +runcov(x::Vector{T}, y::Vector{T}; n::Int=10, cumulative::Bool=true)::Vector{T} +runcov(X::Matrix, Y::Matrix; n::Int=10, cumulative::Bool=true)::Matrix ``` Compute the running or rolling covariance of two arrays """ -function runcov(x::Array{T}, y::Array{T}; n::Int64=10, cumulative::Bool=true)::Array{T} where {T<:Real} +function runcov(x::Vector{T}, y::Vector{T}; n::Int=10, cumulative::Bool=true)::Vector{T} where {T<:AbstractFloat} @assert length(x) == length(y) "Dimension mismatch: length of `x` not equal to length of `y`." @assert n1 "Argument n is out of bounds." out = zeros(size(x)) @@ -253,15 +186,18 @@ function runcov(x::Array{T}, y::Array{T}; n::Int64=10, cumulative::Bool=true)::A end return out end +runcov(X::Matrix, Y::Matrix; n::Int=10, cumulative::Bool=true)::Matrix = hcat((runcov(X[:,j], Y[:,j], n=n, cumulative=cumulative) for j in 1:size(X,2))...) """ ``` -runcor(x::Array{T}, y::Array{T}; n::Int64=10, cumulative::Bool=true)::Array{T} +runcor(x::Vector{T}, y::Vector{T}; n::Int=10, cumulative::Bool=true)::Vector{T} +runcor(X::Matrix, y::Vector; n::Int=10, cumulative::Bool=true)::Matrix +runcor(X::Matrix, Y::Matrix; n::Int=10, cumulative::Bool=true)::Matrix ``` Compute the running or rolling correlation of two arrays """ -function runcor(x::Array{T}, y::Array{T}; n::Int64=10, cumulative::Bool=true)::Array{T} where {T<:Real} +function runcor(x::Vector{T}, y::Vector{T}; n::Int=10, cumulative::Bool=true)::Vector{T} where {T<:Float64} @assert length(x) == length(y) "Dimension mismatch: length of `x` not equal to length of `y`." @assert n1 "Argument n is out of bounds." out = zeros(size(x)) @@ -277,15 +213,18 @@ function runcor(x::Array{T}, y::Array{T}; n::Int64=10, cumulative::Bool=true)::A end return out end +runcor(X::Matrix, Y::Matrix; n::Int=10, cumulative::Bool=true)::Matrix = hcat((runcor(X[:,j], Y[:,j], n=n, cumulative=cumulative) for j in 1:size(X,2))...) +runcor(X::Matrix, y::Vector; n::Int=10, cumulative::Bool=true)::Matrix = hcat((runcor(X[:,j], y, n=n, cumulative=cumulative) for j in 1:size(X,2))...) """ ``` -runmax(x::Array{T}; n::Int64=10, cumulative::Bool=true, inclusive::Bool=true)::Array{T} +runmax(x::Vector{T}; n::Int=10, cumulative::Bool=true, inclusive::Bool=true)::Vector{T} +runmax(X::Matrix; n::Int=10, cumulative::Bool=true, inclusive::Bool=true)::Matrix ``` Compute the running or rolling maximum of an array """ -function runmax(x::Array{T}; n::Int64=10, cumulative::Bool=true, inclusive::Bool=true)::Array{T} where {T<:Real} +function runmax(x::Vector{T}; n::Int=10, cumulative::Bool=true, inclusive::Bool=true)::Vector{T} where {T<:AbstractFloat} @assert n1 "Argument n is out of bounds." out = zeros(size(x)) if inclusive @@ -316,15 +255,17 @@ function runmax(x::Array{T}; n::Int64=10, cumulative::Bool=true, inclusive::Bool return out end end +runmax(X::Matrix; n::Int=10, cumulative::Bool=true, inclusive::Bool=true)::Matrix = hcat((runmax(X[:,j], n=n, cumulative=cumulative, inclusive=inclusive) for j in 1:size(X,2))...) """ ``` -runmin(x::Array{T}; n::Int64=10, cumulative::Bool=true, inclusive::Bool=true)::Array{T} +runmin(x::Vector{T}; n::Int=10, cumulative::Bool=true, inclusive::Bool=true)::Vector{T} +runmin(X::Matrix; n::Int=10, cumulative::Bool=true, inclusive::Bool=true)::Matrix ``` Compute the running or rolling minimum of an array """ -function runmin(x::Array{T}; n::Int64=10, cumulative::Bool=true, inclusive::Bool=true)::Array{T} where {T<:Real} +function runmin(x::Vector{T}; n::Int=10, cumulative::Bool=true, inclusive::Bool=true)::Vector{T} where {T<:AbstractFloat} @assert n1 "Argument n is out of bounds." out = zeros(size(x)) if inclusive @@ -355,48 +296,51 @@ function runmin(x::Array{T}; n::Int64=10, cumulative::Bool=true, inclusive::Bool return out end end +runmin(X::Matrix; n::Int=10, cumulative::Bool=true, inclusive::Bool=true)::Matrix = hcat((runmin(X[:,j], n=n, cumulative=cumulative, inclusive=inclusive) for j in 1:size(X,2))...) """ ``` runquantile(x::Vector{T}; p::T=0.05, n::Int=10, cumulative::Bool=true)::Vector{T} +runquantile(X::Matrix; n::Int=10, cumulative::Bool=true, p::Real=0.05)::Matrix ``` Compute the running/rolling quantile of an array """ -function runquantile(x::Array{T}; p::T=0.05, n::Int=10, cumulative::Bool=true)::Array{T} where {T<:Real} +function runquantile(x::Vector{T}; p::T=0.05, n::Int=10, cumulative::Bool=true)::Vector{T} where {T<:AbstractFloat} @assert n1 "Argument n is out of bounds." - out = zeros(T, (size(x,1), size(x,2))) + out = zeros(T, size(x,1)) if cumulative - @inbounds for j in 1:size(x,2), i in 2:size(x,1) - out[i,j] = quantile(x[1:i,j], p) + @inbounds for i in 2:size(x,1) + out[i] = quantile(x[1:i], p) end - out[1,:] .= NaN + out[1] = NaN else - @inbounds for j in 1:size(x,2), i in n:size(x,1) - out[i,j] = quantile(x[i-n+1:i,j], p) + @inbounds for i in n:size(x,1) + out[i] = quantile(x[i-n+1:i], p) end - out[1:n-1,:] .= NaN + out[1:n-1] .= NaN end return out end - +runquantile(X::Matrix; n::Int=10, cumulative::Bool=true, p::Real=0.05)::Matrix = hcat((runquantile(X[:,j], n=n, cumulative=cumulative, p=p) for j in 1:size(X,2))...) """ ``` -function runacf(x::Array{T}; +function runacf(x::Vector{T}; n::Int = 10, maxlag::Int = n-3, - lags::AbstractArray{Int,1} = 0:maxlag, - cumulative::Bool = true)::Matrix{T} where {T<:Real} + lags::AbstractVector{Int,1} = 0:maxlag, + cumulative::Bool = true)::Matrix{T} where {T<:AbstractFloat} +runacf(X::Matrix; n::Int=10, cumulative::Bool=true, maxlag::Int=n-3, lags::AbstractVector{Int}=0:maxlag)::Matrix ``` Compute the running/rolling autocorrelation of a vector. """ -function runacf(x::Array{T}; +function runacf(x::Vector{T}; n::Int = 10, maxlag::Int = n-3, - lags::AbstractArray{Int,1} = 0:maxlag, - cumulative::Bool = true)::Matrix{T} where {T<:Real} + lags::AbstractVector{Int} = 0:maxlag, + cumulative::Bool = true)::Matrix{T} where {T<:AbstractFloat} @assert size(x, 2) == 1 "Autocorrelation input array must be one-dimensional" N = size(x, 1) @assert n < N && n > 0 @@ -415,15 +359,17 @@ function runacf(x::Array{T}; end return out end +runacf(X::Matrix; n::Int=10, cumulative::Bool=true, maxlag::Int=n-3, lags::AbstractVector{Int}=0:maxlag)::Matrix = hcat((runacf(X[:,j], n=n, cumulative=cumulative, maxlag=maxlag, lags=lags) for j in 1:size(X,2))...) """ ``` -runfun(x::Array{T}, f::Function; n::Int = 10, args...) +runfun(x::Vector{T}, f::Function; n::Int = 10, cumulative::Bool=false, args...)::Vector{T} where {T<:AbstractFloat} +runfun(X::Matrix{T}, f::Function; n::Int=10, cumulative::Bool=false, args...)::Matrix{T} where {T<:AbstractFloat} ``` Apply a general function `f` that returns a scalar over an array """ -function runfun(x::Array{T}, f::Function; n::Int = 10, cumulative::Bool=false, args...)::Array{T} where {T<:Real} +function runfun(x::Vector{T}, f::Function; n::Int = 10, cumulative::Bool=false, args...)::Vector{T} where {T<:AbstractFloat} N = size(x,1) out = zeros(T, N) .* NaN if cumulative @@ -439,3 +385,7 @@ function runfun(x::Array{T}, f::Function; n::Int = 10, cumulative::Bool=false, a end return out end + +function runfun(X::Matrix{T}, f::Function; n::Int=10, cumulative::Bool=false, args...)::Matrix{T} where {T<:AbstractFloat} + return hcat((runfun(X[:,j], f, n=n, cumulative=cumulative; args...) for j in 1:size(X,2))...) +end diff --git a/src/utils.jl b/src/utils.jl index 5e25b70..59a9e2b 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -31,3 +31,70 @@ function crossunder(x::Array{T}, y::Array{T}) where {T<:Real} end return out end + +""" +``` +wilder_sum(x::Vector{T}; n::Int=10)::Vector{T} +``` + +Welles Wilder summation of an array +""" +function wilder_sum(x::Vector{T}; n::Int=10)::Vector{T} where {T<:AbstractFloat} + @assert n0 "Argument n is out of bounds." + nf = float(n) # type stability -- all arithmetic done on floats + out = zeros(size(x)) + out[1] = x[1] + @inbounds for i = 2:size(x,1) + out[i] = x[i] + out[i-1]*(nf-1.0)/nf + end + return out +end +wilder_sum(X::Matrix; n::Int=10)::Matrix = hcat((wilder_sum(X[:,j], n=n) for j in 1:size(X,2))...) + +""" +(Adapted from StatsBase: https://raw.githubusercontent.com/JuliaStats/StatsBase.jl/master/src/scalarstats.jl) + +Compute the mode of an arbitrary array::Array{T} +""" +function mode(a::AbstractArray{T}) where {T<:AbstractFloat} + isempty(a) && error("mode: input array cannot be empty.") + cnts = Dict{T,Int}() + # first element + mc = 1 + mv = a[1] + cnts[mv] = 1 + # find the mode along with table construction + @inbounds for i = 2 : length(a) + x = a[i] + if haskey(cnts, x) + c = (cnts[x] += 1) + if c > mc + mc = c + mv = x + end + else + cnts[x] = 1 + # in this case: c = 1, and thus c > mc won't happen + end + end + return mv +end + +""" +``` +diffn(x::Vector{T}; n::Int=1)::Vector{T} where {T<:AbstractFloat} +diffn(X::Matrix; n::Int=1)::Matrix = hcat([diffn(X[:,j], n=n) for j in 1:size(X,2)]...) +``` + +Lagged differencing +""" +function diffn(x::Vector{T}; n::Int=1)::Vector{T} where {T<:AbstractFloat} + @assert n0 "Argument n out of bounds." + dx = zeros(size(x)) + dx[1:n] .= NaN + @inbounds for i=n+1:size(x,1) + dx[i] = x[i] - x[i-n] + end + return dx +end +diffn(X::Matrix; n::Int=1)::Matrix = hcat([diffn(X[:,j], n=n) for j in 1:size(X,2)]...) diff --git a/test/chaos.jl b/test/chaos.jl new file mode 100644 index 0000000..8cc8902 --- /dev/null +++ b/test/chaos.jl @@ -0,0 +1,29 @@ +# analytical +@testset "Chaos" begin + Random.seed!(SEED) + @testset "Array" begin + x = randn(252) + # helpers + a, b = Indicators.divide(x) + @test [a; b] == x + x = randn(101) + a, b = Indicators.divide(x) + @test [a; b] == x + # workhorses + h = hurst(x, n=100) + @test size(h) == size(x) + rs = rsrange(x) + @test size(rs) == size(x) + x = randn(100) + end + @testset "Temporal" begin + # chaos indicators + x = TS(randn(N)) + tmp = hurst(x) + @test size(tmp,1) == size(x,1) + @test size(tmp,2) == 1 + tmp = rsrange(x) + @test size(tmp,1) == size(x,1) + @test size(tmp,2) == 1 + end +end diff --git a/test/ma.jl b/test/ma.jl new file mode 100644 index 0000000..479f759 --- /dev/null +++ b/test/ma.jl @@ -0,0 +1,102 @@ +# moving average functions +@testset "Moving Averages" begin + Random.seed!(SEED) + @testset "Array" begin + x = cumsum(randn(N)) + tmp = sma(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = mama(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 2 + @test sum(isnan.(tmp)) != N + tmp = ema(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = wma(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = hma(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = trima(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = mma(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = tema(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = dema(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = swma(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = kama(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = alma(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = zlema(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + end + @testset "Temporal" begin + x = TS(cumsum(randn(N))) + # moving average functions + tmp = sma(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = mama(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 2 + tmp = ema(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = wma(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = hma(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = trima(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = mma(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = tema(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = dema(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = swma(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = kama(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = alma(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = zlema(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + end +end diff --git a/test/mom.jl b/test/mom.jl new file mode 100644 index 0000000..b3ed020 --- /dev/null +++ b/test/mom.jl @@ -0,0 +1,119 @@ +@testset "Momentum" begin + Random.seed!(SEED) + @testset "Array" begin + x = cumsum(randn(N)) # close + Y = cumsum(randn(N, 2), dims=1) # high-low + Z = cumsum(randn(N, 3), dims=1) # high-low-close + tmp = aroon(Y) + @test size(tmp, 1) == N + @test size(tmp, 2) == 3 + @test sum(isnan.(tmp)) != N + tmp = donch(Y) + @test size(tmp, 1) == N + @test size(tmp, 2) == 3 + @test sum(isnan.(tmp)) != N + tmp = momentum(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = roc(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = macd(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 3 + @test sum(isnan.(tmp)) != N + tmp = rsi(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = adx(Z) + @test size(tmp, 1) == N + @test size(tmp, 2) == 3 + @test sum(isnan.(tmp)) != N + tmp = adx(Z, wilder=true) + @test size(tmp, 1) == N + @test size(tmp, 2) == 3 + @test sum(isnan.(tmp)) != N + tmp = psar(Y) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = kst(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = wpr(Z) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = cci(Z) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = stoch(Z, kind=:fast) + @test size(tmp, 1) == N + @test size(tmp, 2) == 2 + @test sum(isnan.(tmp)) != N + tmp = stoch(Z, kind=:slow) + @test size(tmp, 1) == N + @test size(tmp, 2) == 2 + @test sum(isnan.(tmp)) != N + tmp = smi(Z) + @test size(tmp, 1) == N + @test size(tmp, 2) == 2 + @test sum(isnan.(tmp)) != N + end + @testset "Temporal" begin + x = TS(cumsum(randn(N))) + Y = TS(cumsum(randn(N, 2), dims=1)) + Z = TS(cumsum(randn(N, 3), dims=1)) + # momentum function + tmp = aroon(Y) + @test size(tmp, 1) == N + @test size(tmp, 2) == 3 + tmp = donch(Y) + @test size(tmp, 1) == N + @test size(tmp, 2) == 3 + tmp = momentum(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = roc(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = macd(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 3 + tmp = rsi(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = adx(Z) + @test size(tmp, 1) == N + @test size(tmp, 2) == 3 + tmp = adx(Z, wilder=true) + @test size(tmp, 1) == N + @test size(tmp, 2) == 3 + tmp = psar(Y) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = kst(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = wpr(Z) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = cci(Z) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = stoch(Z, kind=:fast) + @test size(tmp, 1) == N + @test size(tmp, 2) == 2 + tmp = stoch(Z, kind=:slow) + @test size(tmp, 1) == N + @test size(tmp, 2) == 2 + tmp = smi(Z) + @test size(tmp, 1) == N + @test size(tmp, 2) == 2 + end +end diff --git a/test/patterns.jl b/test/patterns.jl new file mode 100644 index 0000000..08af8a0 --- /dev/null +++ b/test/patterns.jl @@ -0,0 +1,15 @@ +# chart patterns functions +@testset "Chart Patterns" begin + Random.seed!(SEED) + @testset "Array" begin + X = cumsum(randn(N, 3), dims=1) + tmp = renko(X, use_atr=true) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = renko(X, use_atr=false) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + end +end diff --git a/test/reg.jl b/test/reg.jl new file mode 100644 index 0000000..66e2f14 --- /dev/null +++ b/test/reg.jl @@ -0,0 +1,81 @@ +# moving regressions +@testset "Regressions" begin + Random.seed!(SEED) + @testset "Array" begin + x = cumsum(randn(N)) + tmp = mlr_beta(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 2 + @test sum(isnan.(tmp)) != N + tmp = mlr_slope(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = mlr_intercept(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = mlr(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = mlr_se(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = mlr_ub(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = mlr_lb(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = mlr_bands(tmp) + @test size(tmp, 1) == N + @test size(tmp, 2) == 3 + @test sum(isnan.(tmp)) != N + tmp = mlr_rsq(x, adjusted=true) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = mlr_rsq(x, adjusted=false) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + end + @testset "Temporal" begin + x = TS(cumsum(randn(N))) + # moving regressions + tmp = mlr_beta(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 2 + tmp = mlr_slope(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = mlr_intercept(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = mlr(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = mlr_se(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = mlr_ub(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = mlr_lb(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = mlr_bands(tmp) + @test size(tmp, 1) == N + @test size(tmp, 2) == 3 + tmp = mlr_rsq(x, adjusted=true) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = mlr_rsq(x, adjusted=false) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + end +end diff --git a/test/run.jl b/test/run.jl new file mode 100644 index 0000000..b564e6a --- /dev/null +++ b/test/run.jl @@ -0,0 +1,191 @@ +@testset "Running Calculations" begin + Random.seed!(SEED) + @testset "Array" begin + x = cumsum(randn(N)) + X = cumsum(randn(N, 4), dims=1) + tmp = diffn(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = diffn(X) + @test size(tmp, 1) == N + @test size(tmp, 2) == size(X,2) + @test sum(isnan.(tmp)) != N + tmp = runmean(x, cumulative=true) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = runmean(x, cumulative=false) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = runsum(x, cumulative=true) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = wilder_sum(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = runmad(x, cumulative=true) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = runmad(x, cumulative=false) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = runvar(x, cumulative=true) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = runvar(x, cumulative=false) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = runsd(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = runcov(x, x.*rand(N), cumulative=true) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = runcov(x, x.*rand(N), cumulative=false) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = runcor(x, x.*rand(N), cumulative=true) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = runcor(x, x.*rand(N), cumulative=false) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = runmin(x, cumulative=true, inclusive=true) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = runmin(x, cumulative=true, inclusive=false) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = runmin(x, cumulative=false, inclusive=true) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = runmin(x, cumulative=false, inclusive=false) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = runmax(x, cumulative=true, inclusive=true) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = runmax(x, cumulative=true, inclusive=false) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = runmax(x, cumulative=false, inclusive=true) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = runmax(x, cumulative=false, inclusive=false) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = mode(map(xi->round(xi), x)) + @test size(tmp, 1) == 1 + @test size(tmp, 2) == 1 + @test !isnan(tmp) + tmp = runquantile(x, cumulative=true) + @test !isnan(tmp[2]) && isnan(tmp[1]) + @test tmp[10] == quantile(x[1:10], 0.05) + tmp = runquantile(x, cumulative=false) + @test tmp[10] == quantile(x[1:10], 0.05) + n = 20 + tmp = runacf(x, n=n, maxlag=15, cumulative=true) + @test all(tmp[n:end,1] .== 1.0) + tmp = runacf(x, n=n, maxlag=15, cumulative=false) + @test all(tmp[n:end,1] .== 1.0) + end + @testset "Temporal" begin + # running calculations + x = TS(cumsum(randn(N))) + X = TS(cumsum(randn(N, 4), dims=1)) + tmp = runmean(x, cumulative=true) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = runmean(x, cumulative=false) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = runsum(x, cumulative=true) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = wilder_sum(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = runmad(x, cumulative=true) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = runmad(x, cumulative=false) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = runvar(x, cumulative=true) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = runvar(x, cumulative=false) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = runsd(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = runcov(X[:,1], X[:,4], cumulative=true) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = runcov(X[:,1], X[:,4], cumulative=false) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = runcor(X[:,1], X[:,4], cumulative=true) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = runcor(X[:,1], X[:,4], cumulative=false) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = runmin(x, cumulative=true, inclusive=true) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = runmin(x, cumulative=true, inclusive=false) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = runmin(x, cumulative=false, inclusive=true) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = runmin(x, cumulative=false, inclusive=false) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = runmax(x, cumulative=true, inclusive=true) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = runmax(x, cumulative=true, inclusive=false) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = runmax(x, cumulative=false, inclusive=true) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = runmax(x, cumulative=false, inclusive=false) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = runquantile(x, cumulative=true) + @test !isnan(tmp.values[2,1]) && isnan(tmp.values[1,1]) + @test tmp.values[10,1] == quantile(x.values[1:10,1], 0.05) + tmp = runquantile(x, cumulative=false) + @test tmp.values[10,1] == quantile(x.values[1:10,1], 0.05) + n = 20 + tmp = runacf(x, n=n, maxlag=15, cumulative=true) + @test all(tmp.values[n:end,1] .== 1.0) + tmp = runacf(x, n=n, maxlag=15, cumulative=false) + @test all(tmp.values[n:end,1] .== 1.0) + end +end diff --git a/test/runtests.jl b/test/runtests.jl index cb27363..af80167 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -4,628 +4,22 @@ using Test using Random using Statistics -const global N = 1_000 +const global N = 252 const global X0 = 50.0 const global SEED = 1 -@testset "Utilities" begin - Random.seed!(SEED) - @testset "Array" begin - x = cumsum(randn(N)) .+ X0 - y = x + randn(N) - cxo = crossover(x, y) - cxu = crossunder(x, y) - @test any(cxo) - @test any(cxu) - @test !any(cxo .* cxu) # ensure crossovers and crossunders never coincide - end -end - -# trendy -@testset "Trendlines" begin - Random.seed!(SEED) - @testset "Array" begin - x = cumsum(randn(N)) - tmp = resistance(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = support(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = minima(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = maxima(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - end -end - -# analytical -@testset "Chaos" begin - Random.seed!(SEED) - @testset "Array" begin - x = randn(252) - # helpers - a, b = Indicators.divide(x) - @test [a; b] == x - x = randn(101) - a, b = Indicators.divide(x) - @test [a; b] == x - # workhorses - h = hurst(x, n=100) - @test size(h) == size(x) - rs = rsrange(x) - @test size(rs) == size(x) - x = randn(100) - end - @testset "Temporal" begin - # chaos indicators - x = TS(randn(N)) - tmp = hurst(x) - @test size(tmp,1) == size(x,1) - @test size(tmp,2) == 1 - tmp = rsrange(x) - @test size(tmp,1) == size(x,1) - @test size(tmp,2) == 1 - end -end - -# moving regressions -@testset "Regressions" begin - Random.seed!(SEED) - @testset "Array" begin - x = cumsum(randn(N)) - tmp = mlr_beta(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 2 - @test sum(isnan.(tmp)) != N - tmp = mlr_slope(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = mlr_intercept(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = mlr(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = mlr_se(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = mlr_ub(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = mlr_lb(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = mlr_bands(tmp) - @test size(tmp, 1) == N - @test size(tmp, 2) == 3 - @test sum(isnan.(tmp)) != N - tmp = mlr_rsq(x, adjusted=true) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = mlr_rsq(x, adjusted=false) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - end - @testset "Temporal" begin - x = TS(cumsum(randn(N))) - # moving regressions - tmp = mlr_beta(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 2 - tmp = mlr_slope(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = mlr_intercept(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = mlr(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = mlr_se(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = mlr_ub(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = mlr_lb(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = mlr_bands(tmp) - @test size(tmp, 1) == N - @test size(tmp, 2) == 3 - tmp = mlr_rsq(x, adjusted=true) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = mlr_rsq(x, adjusted=false) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - end -end - -@testset "Running Calculations" begin - Random.seed!(SEED) - @testset "Array" begin - x = cumsum(randn(N)) - X = cumsum(randn(N, 4), dims=1) - tmp = diffn(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = diffn(X) - @test size(tmp, 1) == N - @test size(tmp, 2) == size(X,2) - @test sum(isnan.(tmp)) != N - tmp = runmean(x, cumulative=true) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = runmean(x, cumulative=false) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = runsum(x, cumulative=true) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = wilder_sum(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = runmad(x, cumulative=true) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = runmad(x, cumulative=false) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = runvar(x, cumulative=true) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = runvar(x, cumulative=false) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = runsd(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = runcov(x, x.*rand(N), cumulative=true) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = runcov(x, x.*rand(N), cumulative=false) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = runcor(x, x.*rand(N), cumulative=true) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = runcor(x, x.*rand(N), cumulative=false) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = runmin(x, cumulative=true, inclusive=true) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = runmin(x, cumulative=true, inclusive=false) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = runmin(x, cumulative=false, inclusive=true) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = runmin(x, cumulative=false, inclusive=false) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = runmax(x, cumulative=true, inclusive=true) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = runmax(x, cumulative=true, inclusive=false) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = runmax(x, cumulative=false, inclusive=true) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = runmax(x, cumulative=false, inclusive=false) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = mode(map(xi->round(xi), x)) - @test size(tmp, 1) == 1 - @test size(tmp, 2) == 1 - @test !isnan(tmp) - tmp = runquantile(x, cumulative=true) - @test !isnan(tmp[2]) && isnan(tmp[1]) - @test tmp[10] == quantile(x[1:10], 0.05) - tmp = runquantile(x, cumulative=false) - @test tmp[10] == quantile(x[1:10], 0.05) - n = 20 - tmp = runacf(x, n=n, maxlag=15, cumulative=true) - @test all(tmp[n:end,1] .== 1.0) - tmp = runacf(x, n=n, maxlag=15, cumulative=false) - @test all(tmp[n:end,1] .== 1.0) - end - @testset "Temporal" begin - # running calculations - x = TS(cumsum(randn(N))) - X = TS(cumsum(randn(N, 4), dims=1)) - tmp = runmean(x, cumulative=true) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = runmean(x, cumulative=false) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = runsum(x, cumulative=true) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = wilder_sum(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = runmad(x, cumulative=true) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = runmad(x, cumulative=false) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = runvar(x, cumulative=true) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = runvar(x, cumulative=false) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = runsd(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = runcov(X[:,1], X[:,4], cumulative=true) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = runcov(X[:,1], X[:,4], cumulative=false) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = runcor(X[:,1], X[:,4], cumulative=true) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = runcor(X[:,1], X[:,4], cumulative=false) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = runmin(x, cumulative=true, inclusive=true) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = runmin(x, cumulative=true, inclusive=false) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = runmin(x, cumulative=false, inclusive=true) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = runmin(x, cumulative=false, inclusive=false) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = runmax(x, cumulative=true, inclusive=true) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = runmax(x, cumulative=true, inclusive=false) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = runmax(x, cumulative=false, inclusive=true) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = runmax(x, cumulative=false, inclusive=false) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = runquantile(x, cumulative=true) - @test !isnan(tmp.values[2,1]) && isnan(tmp.values[1,1]) - @test tmp.values[10,1] == quantile(x.values[1:10,1], 0.05) - tmp = runquantile(x, cumulative=false) - @test tmp.values[10,1] == quantile(x.values[1:10,1], 0.05) - n = 20 - tmp = runacf(x, n=n, maxlag=15, cumulative=true) - @test all(tmp.values[n:end,1] .== 1.0) - tmp = runacf(x, n=n, maxlag=15, cumulative=false) - @test all(tmp.values[n:end,1] .== 1.0) - end -end - -# moving average functions -@testset "Moving Averages" begin - Random.seed!(SEED) - @testset "Array" begin - x = cumsum(randn(N)) - tmp = sma(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = mama(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 2 - @test sum(isnan.(tmp)) != N - tmp = ema(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = wma(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = hma(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = trima(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = mma(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = tema(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = dema(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = swma(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = kama(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = alma(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = zlema(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - end - @testset "Temporal" begin - x = TS(cumsum(randn(N))) - # moving average functions - tmp = sma(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = mama(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 2 - tmp = ema(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = wma(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = hma(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = trima(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = mma(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = tema(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = dema(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = swma(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = kama(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = alma(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = zlema(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - end -end - -# momentum function -@testset "Momentum" begin - Random.seed!(SEED) - @testset "Array" begin - x = cumsum(randn(N)) # close - Y = cumsum(randn(N, 2), dims=1) # high-low - Z = cumsum(randn(N, 3), dims=1) # high-low-close - tmp = aroon(Y) - @test size(tmp, 1) == N - @test size(tmp, 2) == 3 - @test sum(isnan.(tmp)) != N - tmp = donch(Y) - @test size(tmp, 1) == N - @test size(tmp, 2) == 3 - @test sum(isnan.(tmp)) != N - tmp = momentum(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = roc(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = macd(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 3 - @test sum(isnan.(tmp)) != N - tmp = rsi(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = adx(Z) - @test size(tmp, 1) == N - @test size(tmp, 2) == 3 - @test sum(isnan.(tmp)) != N - tmp = adx(Z, wilder=true) - @test size(tmp, 1) == N - @test size(tmp, 2) == 3 - @test sum(isnan.(tmp)) != N - tmp = psar(Y) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = kst(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = wpr(Z) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = cci(Z) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = stoch(Z, kind=:fast) - @test size(tmp, 1) == N - @test size(tmp, 2) == 2 - @test sum(isnan.(tmp)) != N - tmp = stoch(Z, kind=:slow) - @test size(tmp, 1) == N - @test size(tmp, 2) == 2 - @test sum(isnan.(tmp)) != N - tmp = smi(Z) - @test size(tmp, 1) == N - @test size(tmp, 2) == 2 - @test sum(isnan.(tmp)) != N - end - @testset "Temporal" begin - x = TS(cumsum(randn(N))) - Y = TS(cumsum(randn(N, 2), dims=1)) - Z = TS(cumsum(randn(N, 3), dims=1)) - # momentum function - tmp = aroon(Y) - @test size(tmp, 1) == N - @test size(tmp, 2) == 3 - tmp = donch(Y) - @test size(tmp, 1) == N - @test size(tmp, 2) == 3 - tmp = momentum(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = roc(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = macd(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 3 - tmp = rsi(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = adx(Z) - @test size(tmp, 1) == N - @test size(tmp, 2) == 3 - tmp = adx(Z, wilder=true) - @test size(tmp, 1) == N - @test size(tmp, 2) == 3 - tmp = psar(Y) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = kst(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = wpr(Z) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = cci(Z) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = stoch(Z, kind=:fast) - @test size(tmp, 1) == N - @test size(tmp, 2) == 2 - tmp = stoch(Z, kind=:slow) - @test size(tmp, 1) == N - @test size(tmp, 2) == 2 - tmp = smi(Z) - @test size(tmp, 1) == N - @test size(tmp, 2) == 2 - end -end - -# volatility functions -@testset "Volatility" begin - Random.seed!(SEED) - @testset "Array" begin - x = cumsum(randn(N)) - X = cumsum(randn(N, 3), dims=1) - tmp = bbands(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 3 - @test sum(isnan.(tmp)) != N - tmp = tr(X) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = atr(X) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = keltner(X) - @test size(tmp, 1) == N - @test size(tmp, 2) == 3 - @test sum(isnan.(tmp)) != N - end - @testset "Temporal" begin - x = TS(cumsum(randn(N))) - X = TS(cumsum(randn(N, 3), dims=1)) - tmp = bbands(x) - @test size(tmp, 1) == N - @test size(tmp, 2) == 3 - tmp = tr(X) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = atr(X) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - tmp = keltner(X) - @test size(tmp, 1) == N - @test size(tmp, 2) == 3 - end -end - -# chart patterns functions -@testset "Charting" begin - Random.seed!(SEED) - @testset "Array" begin - X = cumsum(randn(N, 3), dims=1) - tmp = renko(X, use_atr=true) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - tmp = renko(X, use_atr=false) - @test size(tmp, 1) == N - @test size(tmp, 2) == 1 - @test sum(isnan.(tmp)) != N - end +TEST_FILES = [ + "util.jl", + "run.jl", + "ma.jl", + "mom.jl", + "vol.jl", + "reg.jl", + "patterns.jl", + "chaos.jl", + "trendy.jl", +] + +@inbounds for testfile in TEST_FILES + include(testfile) end diff --git a/test/trendy.jl b/test/trendy.jl new file mode 100644 index 0000000..4f6aa10 --- /dev/null +++ b/test/trendy.jl @@ -0,0 +1,23 @@ +# trendy +@testset "Trendlines" begin + Random.seed!(SEED) + @testset "Array" begin + x = cumsum(randn(N)) + tmp = resistance(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = support(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = minima(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = maxima(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + end +end diff --git a/test/util.jl b/test/util.jl new file mode 100644 index 0000000..52b144b --- /dev/null +++ b/test/util.jl @@ -0,0 +1,13 @@ +@testset "Utilities" begin + @testset "Crossover/Crossunder" begin + Random.seed!(SEED) + x = cumsum(randn(N)) .+ X0 + y = x + randn(N) + cxo = crossover(x, y) + cxu = crossunder(x, y) + @test any(cxo) + @test any(cxu) + @test !any(cxo .* cxu) # ensure crossovers and crossunders never coincide + end +end + diff --git a/test/vol.jl b/test/vol.jl new file mode 100644 index 0000000..f999323 --- /dev/null +++ b/test/vol.jl @@ -0,0 +1,40 @@ +# volatility functions +@testset "Volatility" begin + Random.seed!(SEED) + @testset "Array" begin + x = cumsum(randn(N)) + X = cumsum(randn(N, 3), dims=1) + tmp = bbands(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 3 + @test sum(isnan.(tmp)) != N + tmp = tr(X) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = atr(X) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + @test sum(isnan.(tmp)) != N + tmp = keltner(X) + @test size(tmp, 1) == N + @test size(tmp, 2) == 3 + @test sum(isnan.(tmp)) != N + end + @testset "Temporal" begin + x = TS(cumsum(randn(N))) + X = TS(cumsum(randn(N, 3), dims=1)) + tmp = bbands(x) + @test size(tmp, 1) == N + @test size(tmp, 2) == 3 + tmp = tr(X) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = atr(X) + @test size(tmp, 1) == N + @test size(tmp, 2) == 1 + tmp = keltner(X) + @test size(tmp, 1) == N + @test size(tmp, 2) == 3 + end +end