Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

timearray: more Base functions support #338

Merged
merged 1 commit into from
Dec 3, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,23 @@
```

can perform faster than ```merge(ta1, ta2)``` in this case. (issue #TBD)
* Support more reduction functions of Base. (issue #TBD)
* `sum`
* `mean`
* `std`
* `var`

e.g.
```julia
sum(ta) # same as sum(ta, 1), and it's equivalent to moving(sum, ta, length(ta))
sum(ta, 2)
```

* Support cumulative prod `cumprod`. (issue #TBD)

### 0.10.0

* add support for time series plotting via RecipesBase dependency (thank you @mkborregaard)
* add support for time series plotting via RecipesBase dependency (thank you @mkborregaard)
* add StepRange indexing support (issue #311)

### 0.9.2
Expand Down Expand Up @@ -109,7 +122,7 @@

### 0.7.1

* readtimearray method now allows arbitrary delimiters (thanks @dourouc05)
* readtimearray method now allows arbitrary delimiters (thanks @dourouc05)

### 0.7.0

Expand Down Expand Up @@ -146,7 +159,7 @@
### 0.6.3

* precompile support added
* test/combine.jl and test/split.jl now imports Base.Dates explicity
* test/combine.jl and test/split.jl now imports Base.Dates explicity

### 0.6.2

Expand Down Expand Up @@ -184,7 +197,7 @@

### 0.5.9

* added kwarg argument `format` to the `readtimearray` method to allow parsing datetime formats that are not
* added kwarg argument `format` to the `readtimearray` method to allow parsing datetime formats that are not
currently supported.
* changed two references to `Range1` to `UnitRange`
* added import of Base.values. I had defined it first and I guess they like it so much they co-opted it. :)
Expand Down
61 changes: 59 additions & 2 deletions src/basemisc.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,61 @@
# Misc. Base functions

Base.cumsum(ta::TimeArray, dim::Int=1) =
TimeArray(ta.timestamp, cumsum(ta.values, dim), ta.colnames, ta.meta)
function _autoimport(s::Symbol)
if isdefined(Base, s)
:(import Base: $s)
else
:()
end
end

const _tsmap = Dict{Symbol, Dict{Number, Expr}}() # timestamp map
const _colmap = Dict{Symbol, Dict{Number, Expr}}() # colanmes map

macro _mapbase(sig::Expr, imp::Expr)
fname = sig.args[1]
import_expr = _autoimport(fname)

# these default values are useful for reduction function
ts = get(_tsmap, fname, Dict())
dim1ts = get(ts, 1, :(ta.timestamp[end]))
dim2ts = get(ts, 2, :(ta.timestamp))

# these default values are useful for reduction function
col = get(_colmap, fname, Dict())
dim1col = get(col, 1, :(ta.colnames))
dim2col = get(col, 2, :([string($fname)]))

fbody = quote
if dim == 1
TimeArray($dim1ts, $imp, $dim1col, ta.meta)
elseif dim == 2
TimeArray($dim2ts, $imp, $dim2col, ta.meta)
else
throw(DimensionMismatch("dim should be 1 or 2"))
end
end

doc = " $sig"
fdef = Expr(:function, sig, fbody)

esc(quote
$import_expr
@doc $doc ->
$fdef
end)
end

# Cumulative functions
_tsmap[:cumsum] = Dict(1 => :(ta.timestamp))
_colmap[:cumsum] = Dict(2 => :(ta.colnames))
@_mapbase cumsum(ta::TimeArray, dim = 1) cumsum(ta.values, dim)

_tsmap[:cumprod] = Dict(1 => :(ta.timestamp))
_colmap[:cumprod] = Dict(2 => :(ta.colnames))
@_mapbase cumprod(ta::TimeArray, dim = 1) cumprod(ta.values, dim)

# Reduction functions
@_mapbase sum(ta::TimeArray, dim = 1) sum(ta.values, dim)
@_mapbase mean(ta::TimeArray, dim = 1) mean(ta.values, dim)
@_mapbase std(ta::TimeArray, dim = 1; kw...) std(ta.values, dim; kw...)
@_mapbase var(ta::TimeArray, dim = 1; kw...) var(ta.values, dim; kw...)
72 changes: 71 additions & 1 deletion test/basemisc.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ using TimeSeries
@testset "basemisc" begin


@testset "cumsum" begin
@testset "cumulative functions" begin
let ta = cumsum(cl)
@test ta.values == cumsum(cl.values)
@test ta.meta == cl.meta
Expand All @@ -28,6 +28,76 @@ using TimeSeries
@test ta.values == cumsum(ohlc.values, 2)
@test ta.meta == ohlc.meta
end

@test_throws DimensionMismatch cumsum(cl, 3)
@test_throws DimensionMismatch cumsum(ohlc, 3)

let ta = cumprod(cl[1:5])
@test ta.values == cumprod(cl[1:5].values)
@test ta.meta == cl[1:5].meta
end

let ta = cumprod(ohlc[1:5])
@test ta.values == cumprod(ohlc[1:5].values)
@test ta.meta == ohlc[1:5].meta
end

let ta = cumprod(cl[1:5], 2)
@test ta.values == cumprod(cl[1:5].values, 2)
@test ta.meta == cl[1:5].meta
end

let ta = cumprod(ohlc[1:5], 2)
@test ta.values == cumprod(ohlc[1:5].values, 2)
@test ta.meta == ohlc[1:5].meta
end

@test_throws DimensionMismatch cumprod(cl, 3)
@test_throws DimensionMismatch cumprod(ohlc, 3)
end

@testset "reduction functions" begin
for (fname, f) ∈ ([(:sum, sum), (:mean, mean)])
for (name, src) ∈ [(:cl, cl), (:ohlc, ohlc)]
@testset "$fname::$name" begin
let ta = f(src)
@test ta.meta == src.meta
@test length(ta) == 1
@test ta.values == f(src.values, 1)
end

let ta = f(src, 2)
@test ta.meta == src.meta
@test length(ta) == length(src.timestamp)
@test ta.values == f(src.values, 2)
@test ta.colnames == [string(fname)]
end

@test_throws DimensionMismatch f(src, 3)
end # @testset
end
end # for func

for (fname, f) ∈ ([(:std, std), (:var, var)])
for (name, src) ∈ [(:cl, cl), (:ohlc, ohlc)]
@testset "$fname::$name" begin
let ta = f(src)
@test ta.meta == src.meta
@test length(ta) == 1
@test ta.values == f(src.values, 1)
end

let ta = f(src, 2, corrected=false)
@test ta.meta == src.meta
@test length(ta) == length(src.timestamp)
@test ta.values == f(src.values, 2, corrected=false)
@test ta.colnames == [string(fname)]
end

@test_throws DimensionMismatch f(src, 3)
end # @testset
end
end # for func
end


Expand Down