TimeArrays.jl

TimeArrays simplifies working with time series data. It offers features like basic math operations, sliding window techniques, data resampling, and handling of missing values
Popularity
29 Stars
Updated Last
2 Months Ago
Started In
June 2024

TimeArrays.jl

Stable Dev Build Status Coverage Registry

TimeArrays simplifies working with time series data. It offers features like basic math operations, sliding window techniques, data resampling, and handling of missing values.

Installation

To install TimeArrays, simply use the Julia package manager:

] add TimeArrays

Usage

In this example we perform math operations on several sets of time series.

using Dates
using TimeArrays

a = TimeArray{DateTime,Float64}([
    TimeTick(DateTime("2024-01-01"), 1.0),
    TimeTick(DateTime("2024-01-02"), 4.0),
    TimeTick(DateTime("2024-01-05"), 2.0),
    TimeTick(DateTime("2024-01-07"), 5.0),
])

b = TimeArray{DateTime,Float64}([
    (DateTime("2024-01-02"), 4.0),
    (DateTime("2024-01-06"), 2.0),
    (DateTime("2024-01-10"), 1.0),
])

c = TimeArray{DateTime,Float64}([
    DateTime("2024-01-01") => 2.0,
    DateTime("2024-01-09") => 5.0,
    DateTime("2024-01-11") => 4.0,
])

julia> 2(a * b) + b / c
8-element TimeArray{DateTime, Float64}:
 TimeTick(2024-01-01T00:00:00, NaN)
 TimeTick(2024-01-02T00:00:00, 34.0)
 
 TimeTick(2024-01-11T00:00:00, 10.25)

Note

Since our implementation of arithmetic operations between elements of two TimeArray's is somewhat different from the usual work with arrays, a diagram is provided below that shows how exactly the elements of the time series are related to each other. For more information see arithmetic section in documentation.

time:     - - - 1 - - - - 2 - - - - 3 - - - - 4 - - - - 5 - - - - 6 - - - - 7 - - - >

               2.0                 4.0﹉﹉﹉﹉﹉﹉﹉﹉﹉﹉⤵                   6.0
t_array1:       ● - - - - - - - - - ● - - - - - - - - - - - - - - - - - - - ● - - - >
                ┊                   ┊                   ┊                   ┊
   +       [2.0 + NaN]         [4.0 + 3.0]         [4.0 + 5.0]         [6.0 + 5.0]
                ┊                   ┊                   ┊                   ┊
t_array2:       X                   ● - - - - - - - - - ● - - - - - - - - - - - - - >
               NaN                 3.0                 5.0 ﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍⤴

result:         ● - - - - - - - - - ● - - - - - - - - - ● - - - - - - - - - ● - - - >
               NaN                 7.0                 9.0                11.0

TimeArrays can also deal with missing values.

using Dates
using TimeArrays

nan_values = TimeArray{DateTime,Float64}([
    TimeTick(DateTime("2024-01-02"), 2.0),
    TimeTick(DateTime("2024-01-04"), NaN),
    TimeTick(DateTime("2024-01-06"), NaN),
    TimeTick(DateTime("2024-01-08"), 8.0),
])

julia> ta_forward_fill(nan_values)
4-element TimeArray{DateTime, Float64}:
 TimeTick(2024-01-02T00:00:00, 2.0)
 TimeTick(2024-01-04T00:00:00, 8.0)
 TimeTick(2024-01-06T00:00:00, 8.0)
 TimeTick(2024-01-08T00:00:00, 8.0)

julia> ta_linear_fill(nan_values)
4-element TimeArray{DateTime, Float64}:
 TimeTick(2024-01-02T00:00:00, 2.0)
 TimeTick(2024-01-04T00:00:00, 4.0)
 TimeTick(2024-01-06T00:00:00, 6.0)
 TimeTick(2024-01-08T00:00:00, 8.0)

Here we calculate the average price between two time series of high and low prices.

using TimeArrays

julia> high_prices = ta_high_price_sample_data()
2416-element TimeArray{DateTime, Float64}:
 TimeTick(2023-01-01T00:00:08.998, 0.2457)
 TimeTick(2023-01-01T00:00:43.315, 0.2458)
 
 TimeTick(2023-01-01T23:59:43.246, 0.25)

julia> low_prices = ta_low_price_sample_data()
2396-element TimeArray{DateTime, Float64}:
 TimeTick(2023-01-01T00:00:08.995, 0.2456)
 TimeTick(2023-01-01T00:00:43.319, 0.2457)
 
 TimeTick(2023-01-01T23:59:43.252, 0.2499)

julia> (low_prices + high_prices) / 2
3930-element TimeArray{DateTime, Float64}:
 TimeTick(2023-01-01T00:00:08.995, NaN)
 TimeTick(2023-01-01T00:00:08.998, 0.24565)
 
 TimeTick(2023-01-01T23:59:43.252, 0.24995)

Visualized with LightweightCharts.jl.


You can smooth the price data by using different Moving Average algorithms.

using TimeArrays

julia> prices = ta_price_sample_data()
7777-element TimeArray{DateTime, Float64}:
 TimeTick(2024-04-01T00:00:00.661, 0.6501)
 TimeTick(2024-04-01T00:05:57.481, 0.6505)
 
 TimeTick(2024-04-30T23:42:11.920, 0.4417)

julia> sma_prices = ta_sma(prices, 20)
7777-element TimeArray{DateTime, Float64}:
 TimeTick(2024-04-01T00:00:00.661, NaN)
 TimeTick(2024-04-01T00:05:57.481, NaN)
 
 TimeTick(2024-04-30T23:42:11.920, 0.4403)

julia> wma_prices = ta_wma(prices, 20)
7777-element TimeArray{DateTime, Float64}:
 TimeTick(2024-04-01T00:00:00.661, NaN)
 TimeTick(2024-04-01T00:05:57.481, NaN)
 
 TimeTick(2024-04-30T23:42:11.920, 0.4409)

julia> ema_prices = ta_ema(prices, 20)
7777-element TimeArray{DateTime, Float64}:
 TimeTick(2024-04-01T00:00:00.661, 0.6501)
 TimeTick(2024-04-01T00:05:57.481, 0.6501)
 
 TimeTick(2024-04-30T23:42:11.920, 0.4399)

Visualized with LightweightCharts.jl.


You can also use custom types with TimeArrays. Below we convert prices into four-hour candlesticks using resampling.

using Dates
using TimeArrays

struct OHLC
    open::Float64
    high::Float64
    low::Float64
    close::Float64
end

function ohlc(x::AbstractVector{<:Number})
    return if isempty(x)
        ta_nan(OHLC)
    else
        OHLC(x[1], maximum(x), minimum(x), x[end])
    end
end

TimeArrays.ta_nan(::Type{OHLC}) = OHLC(NaN, NaN, NaN, NaN)
TimeArrays.return_type(::typeof(ohlc), ::Type{<:Number}) = OHLC

julia> prices = ta_price_sample_data()
7777-element TimeArray{DateTime, Float64}:
 TimeTick(2024-04-01T00:00:00.661, 0.6501)
 TimeTick(2024-04-01T00:05:57.481, 0.6505)
 
 TimeTick(2024-04-30T23:42:11.920, 0.4417)

julia> ta_resample(ohlc, prices, Hour(2); closed = CLOSED_RIGHT, label = LABEL_RIGHT)
360-element TimeArray{DateTime, OHLC}:
 TimeTick(2024-04-01T02:00:00, OHLC(0.6501, 0.6505, 0.6462, 0.6491))
 TimeTick(2024-04-01T04:00:00, OHLC(0.6478, 0.6480, 0.6443, 0.6452))
 
 TimeTick(2024-05-01T00:00:00, OHLC(0.4396, 0.4436, 0.4396, 0.4417))

Visualized with LightweightCharts.jl.

Contributing

Contributions to TimeArrays are welcome! If you encounter a bug, have a feature request, or would like to contribute code, please open an issue or a pull request on GitHub.