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

WIP: Add Indicators.jl functionality with TSFrames #155

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 5 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
6 changes: 6 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ version = "0.2.0"
[deps]
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
Indicators = "70c4c096-89a6-5ec6-8236-da8aa3bd86fd"
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be in [weakdeps]

MarketData = "945b72a4-3b13-509d-9b46-1525bb5c06de"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
RollingFunctions = "b0e4dd01-7b14-53d8-9b45-175a3e362653"
Expand All @@ -14,8 +16,12 @@ Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"

[extensions]
IndicatorsExt = "Indicators"

[compat]
DataFrames = "1.3.2"
Indicators = "0.8.2"
RecipesBase = "1.2.1"
RollingFunctions = "0.6.2, 0.7"
ShiftedArrays = "1.0.0, 2"
Expand Down
26 changes: 26 additions & 0 deletions ext/IndicatorsExt.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module IndicatorsExt

using TSFrames, Indicators

# Methods for porting Indicators.jl functions to TSFrame objects from TSFrames.jl package
# See their respective documentation on Indicators.jl
Indicators.runmean(X::TSFrame, x::Symbol; kwargs...) = TSFrame(Indicators.runmean(X[:, x]; kwargs...), X[:, :Index])
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Preserving Index. Is there better way to integrate to TSFrame? More optimised way to avoid extra Construction operations?

Indicators.sma(X::TSFrame, x::Symbol; kwargs...) = TSFrame(Indicators.sma(X[:, x]; kwargs...), X[:, :Index])
Indicators.trima(X::TSFrame, x::Symbol; kwargs...) = TSFrame(Indicators.trima(X[:, x]; kwargs...), X[:, :Index])
Indicators.wma(X::TSFrame, x::Symbol; kwargs...) = TSFrame(Indicators.wma(X[:, x]; kwargs...), X[:, :Index])
Indicators.ema(X::TSFrame, x::Symbol; kwargs...) = TSFrame(Indicators.ema(X[:, x]; kwargs...), X[:, :Index])
Indicators.mma(X::TSFrame, x::Symbol; kwargs...) = TSFrame(Indicators.mma(X[:, x]; kwargs...), X[:, :Index])
Indicators.dema(X::TSFrame, x::Symbol; kwargs...) = TSFrame(Indicators.dema(X[:, x]; kwargs...), X[:, :Index])
Indicators.tema(X::TSFrame, x::Symbol; kwargs...) = TSFrame(Indicators.tema(X[:, x]; kwargs...), X[:, :Index])
Indicators.mama(X::TSFrame, x::Symbol; kwargs...) = TSFrame(Indicators.dema(X[:, x]; kwargs...), X[:, :Index])
Indicators.hma(X::TSFrame, x::Symbol; kwargs...) = TSFrame(Indicators.hma(X[:, x]; kwargs...), X[:, :Index])
Indicators.swma(X::TSFrame, x::Symbol; kwargs...) = TSFrame(Indicators.swma(X[:, x]; kwargs...), X[:, :Index])
Indicators.kama(X::TSFrame, x::Symbol; kwargs...) = TSFrame(Indicators.kama(X[:, x]; kwargs...), X[:, :Index])
Indicators.alma(X::TSFrame, x::Symbol; kwargs...) = TSFrame(Indicators.alma(X[:, x]; kwargs...), X[:, :Index])
Indicators.zlema(X::TSFrame, x::Symbol; kwargs...) = TSFrame(Indicators.zlema(X[:, x]; kwargs...), X[:, :Index])
# VWMA is defined on Matrix, not Array
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still thinking how to adapt methods that work on AbstractMatrix, not Array

# VWAP is defined on Matrix, not Array
Indicators.hama(X::TSFrame, x::Symbol; kwargs...) = TSFrame(Indicators.hama(X[:, x]; kwargs...), X[:, :Index])


end
5 changes: 4 additions & 1 deletion src/TSFrames.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module TSFrames

using DataFrames, Dates, ShiftedArrays, RecipesBase, RollingFunctions, Tables
using DataFrames, Dates, ShiftedArrays, RecipesBase, RollingFunctions, Tables # , Indicators
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To remove comment


import Base.convert
import Base.diff
Expand Down Expand Up @@ -76,6 +76,8 @@ export TSFrame,
vcat,
DataFrame,
Date
# sma,
# runmean

include("TSFrame.jl")
include("utils.jl")
Expand All @@ -97,5 +99,6 @@ include("to_period.jl")
include("vcat.jl")
include("broadcasting.jl")
include("tables.jl")
# include("indicators.jl")
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rm comments


end # END module TSFrames
23 changes: 23 additions & 0 deletions test/indicators.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using MarketData

@testset "indicators_integration" begin
sp500 = TSFrame(MarketData.yahoo("^GSPC"))
date_from = Date(2021, 03, 1)
date_to = Date(2023, 03, 1)
sp500_2y = TSFrames.subset(sp500, date_from, date_to)
@test sma(sp500_2y, :AdjClose) |> typeof == TSFrame
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make tests more diverse and meaningful, by using kwargs from upstream method

@test runmean(sp500_2y, :Close) |> typeof == TSFrame
@test trima(sp500_2y, :Close) |> typeof == TSFrame
@test wma(sp500_2y, :AdjClose) |> typeof == TSFrame
@test ema(sp500_2y, :AdjClose) |> typeof == TSFrame
@test mma(sp500_2y, :AdjClose) |> typeof == TSFrame
@test dema(sp500_2y, :AdjClose) |> typeof == TSFrame
@test tema(sp500_2y, :AdjClose) |> typeof == TSFrame
@test mama(sp500_2y, :AdjClose) |> typeof == TSFrame
@test hma(sp500_2y, :AdjClose) |> typeof == TSFrame
@test swma(sp500_2y, :AdjClose) |> typeof == TSFrame
@test kama(sp500_2y, :AdjClose) |> typeof == TSFrame
@test alma(sp500_2y, :AdjClose) |> typeof == TSFrame
@test zlema(sp500_2y, :AdjClose) |> typeof == TSFrame
@test hama(sp500_2y, :AdjClose) |> typeof == TSFrame
end