diff --git a/src/AxisArrays.jl b/src/AxisArrays.jl index 05a1b52..7b3e536 100644 --- a/src/AxisArrays.jl +++ b/src/AxisArrays.jl @@ -2,11 +2,13 @@ module AxisArrays using Requires -export AxisArray, Axis, Interval, axisnames, axisdim, axes +export AxisArray, Axis, Interval, axisnames, axisdim, axes, + moving, merge include("core.jl") include("intervals.jl") include("indexing.jl") include("utils.jl") +include("timeseries.jl") end diff --git a/src/timeseries.jl b/src/timeseries.jl new file mode 100644 index 0000000..098fb52 --- /dev/null +++ b/src/timeseries.jl @@ -0,0 +1,60 @@ +# these methods are not specific to time series necessarily, but quarantined here for the time being + +import TimeSeries.moving, Base.merge + +# only works for single column AxisArrays +# TODO generalize to work over any dimension (see commented prototype code below + +function moving(a::AxisArray, f::Function, n::Int) + m = length(a)-n+1 + res = zeros(m) + for i in 1:m + #res[i] = f(a[Interval(a.axes[1][i],a.axes[1][i+n-1])]) + res[i] = f(a[Axis{1}(i:i+n-1)]) + end + AxisArray(res, (a.axes[1][n:end],)) +end + +# generalized moving over any dimension +# to be called thus: moving(AAPL, mean, Axis{:time}(10)) +##### NOT WORKING ### function moving{Ax<:Axis}(a::AxisArray, f::Function, n::Ax) +##### NOT WORKING ### v = n.val +##### NOT WORKING ### m = size(a, n) - v +##### NOT WORKING ### res = similar(a, (Ax(m),), (axes(a, Ax)[cld(v,2):end-fld(v,2)],)) +##### NOT WORKING ### for i in 1:m +##### NOT WORKING ### #res[Ax(i)] = f(a[Ax[i:i+v-1]) +##### NOT WORKING ### res[Ax(i)] = f(a[Ax[i:i+v-1]]) +##### NOT WORKING ### end +##### NOT WORKING ### end + + + + +# this is @tshort implementation with correction to overlaps + +function overlaps(ordered1, ordered2) + i = j = 1 + idx1 = Int[] + idx2 = Int[] + while i < length(ordered1) + 1 && j < length(ordered2) + 1 + if ordered1[i] > ordered2[j] + j += 1 + elseif ordered1[i] < ordered2[j] + i += 1 + else + push!(idx1, i) + push!(idx2, j) + i += 1 + j += 1 + end + end + (idx1, idx2) +end + +function merge(a1::AxisArray, a2::AxisArray) + idx1, idx2 = overlaps(a1.axes[1], a2.axes[1]) + vals1 = a1[Axis{:row}(idx1)].data + vals2 = a2[Axis{:row}(idx2)].data + vals = reshape(hcat(vals1,vals2), size(vals1)..., 2) + AxisArray(vals,(a1.axes[1][idx1], a1.axes[2], ["stock1","stock2"])) +end diff --git a/src/utils.jl b/src/utils.jl index 0dbe084..9bd5d09 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -65,3 +65,36 @@ end Gadfly.plot(A::AxisArray, args...; kwargs...) = Gadfly.plot(DataFrames.DataFrame(A), args...; kwargs...) end + +@require TimeSeries begin + + """ + Convert a TimeArray into an AxisArray + + ```julia + AxisArray(a::TimeArray) + ``` + + ### Arguments + + * `a::TimeArray` + + ### Returns + + * `::AxisArray` : an AxisArray from a TimeArray. The first axis + is of type Base.Dates and the second axis is String. + + ### Examples + + ```julia + using MarketData + Apple = AxisArray(AAPL) + ``` + + """ + function Base.convert(::Type{AxisArrays.AxisArray}, A::TimeSeries.TimeArray) + length(A.colnames) > 1 ? + AxisArray(A.values, (A.timestamp,A.colnames)) : + AxisArray(A.values, (A.timestamp,)) + end +end diff --git a/test/timeseries.jl b/test/timeseries.jl new file mode 100644 index 0000000..30f6749 --- /dev/null +++ b/test/timeseries.jl @@ -0,0 +1,30 @@ +using FactCheck, MarketData + +facts("conversion from TimeArray to AxisArray") do + + context("axes values are correct") do + @fact AxisArray(AAPL).axes[1][1] => Date(1980,12,12) + @fact AxisArray(AAPL).axes[2][1] => "Open" + @fact_throws AxisArray(cl).axes[2] + end + + context("data values are correct") do + @fact AxisArray(AAPL).data[1] => 28.75 + @fact AxisArray(AAPL).data[8336] => 554.17 + end +end + +facts("moving") do + + context("moving only works on single column") do + @fact moving(AxisArray(cl), mean, 10)[1] => roughly(98.782) + @fact_throws moving(AxisArray(AAPL), mean, 10) + end +end + +facts("merge") do + + context("only inner join supported") do + @fact size(merge(AxisArray(AAPL), AxisArray(BA)),1) => 8335 + end +end