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

Start working on #52: sma #90

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
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
3 changes: 2 additions & 1 deletion src/MarketTechnicals.jl
Original file line number Diff line number Diff line change
@@ -14,11 +14,12 @@ export sma, ema, kama,
floorpivots, woodiespivots,
typical

include("utilities.jl") # we need macro in compiling stage

include("candlesticks.jl")
include("levels.jl")
include("movingaverages.jl")
include("momentum.jl")
include("utilities.jl")
include("volatility.jl")
include("volume.jl")

20 changes: 2 additions & 18 deletions src/movingaverages.jl
Original file line number Diff line number Diff line change
@@ -1,21 +1,5 @@
function sma{T,N}(ta::TimeArray{T,N}, n::Int)

tstamps = ta.timestamp[n:end]

vals = zeros(size(ta.values,1) - (n-1), size(ta.values,2))
for i in 1:size(ta.values,1) - (n-1)
for j in 1:size(ta.values,2)
vals[i,j] = mean(ta.values[i:i+(n-1),j])
end
end

cname = String[]
cols = colnames(ta)
for c in 1:length(cols)
push!(cname, string(cols[c], "_sma_", n))
end

TimeArray(tstamps, vals, cname, ta.meta)
@padding function sma{T,N}(ta::TimeArray{T,N}, n::Int)
rename(moving(ta, mean, n), gen_colnames(ta.colnames, "sma_$n"))
end

function ema{T,N}(ta::TimeArray{T,N}, n::Int; wilder=false)
64 changes: 64 additions & 0 deletions src/utilities.jl
Original file line number Diff line number Diff line change
@@ -42,3 +42,67 @@ julia> gen_colnames(["Open", "Close"], ["macd", "dif", "sig"])
function gen_colnames(orig::Vector{String}, suffix::Vector{String})
vec(["$o\_$s" for o ∈ orig, s ∈ suffix])
end

gen_colnames(orig::Vector{String}, suffix::String) = gen_colnames(orig, [suffix])

function add_padding_call(expr::Expr)
if expr.head != :call
return [add_padding_call(arg) for arg ∈ expr.args if isa(arg, Expr)]
end

func = expr.args[1]
if func ∈ (:diff, :lag, :lead, :moving, :percentchange)
push!(expr.args, Expr(:kw, :padding, :padding))
end

return [add_padding_call(arg)
for arg ∈ expr.args[2:end-1] if isa(arg, Expr)]
end

"""
This macro will append a keyword argument `padding=true` to
function parameters, and append `padding` to all related call
in function body. For the listed related call, please check out
`add_padding_call`.

e.g.

```
@padding function f(ta, n)
...
moving(...)
...
lag(...)
...
end
```

will make `f` compiled as following

```
function sma(ta, n; padding=false)
...
moving(..., padding=padding)
....
lag(..., padding=padding)
...
end
```

"""
macro padding(f)
@assert f.head == :function

# add :padding keyword argument in function signature
params_ast = f.args[1]
kw_node = Expr(:kw, :padding, false)

if (length(params_ast.args) < 2) || (params_ast.args[2].head != :parameters)
insert!(params_ast.args, 2, Expr(:parameters, kw_node))
else
push!(params_ast.args[2], kw_node)
end

add_padding_call(f.args[2])
return f
end
9 changes: 9 additions & 0 deletions test/movingaverages.jl
Original file line number Diff line number Diff line change
@@ -17,6 +17,15 @@ facts("Moving averages on TimeArrays") do
@fact sma(ohlc, 10).timestamp[491] --> Date(2001,12,31)
end

context("sma padding=true") do
ta = sma(cl, 5, padding=true)
@fact ta.meta --> cl.meta
@fact ta.timestamp[1] --> Date(2000, 1, 3)
@fact isnan(ta.values[1]) --> true
@fact isnan(ta.values[4]) --> true
@fact isnan(ta.values[5]) --> false
end

context("ema") do
@fact ema(cl, 10).values[1] --> roughly(98.782, atol=.01) # TTR value 98.78200
@fact ema(cl, 10).values[2] --> roughly(99.719, atol=.01) # TTR value 99.71982