Skip to content

Commit

Permalink
Merge pull request #76 from JuliaQuant/ib-ama
Browse files Browse the repository at this point in the history
kama: Kaufman's Adaptive Moving Average

close #64
  • Loading branch information
iblislin committed May 10, 2017
2 parents 1960973 + f00b82d commit e7a5dcb
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 31 deletions.
12 changes: 6 additions & 6 deletions src/MarketTechnicals.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ module MarketTechnicals

using TimeSeries, StatsBase

export sma, ema,
bollingerbands, truerange, atr, #keltnerbands,
obv, vwap,
doji,
rsi, macd, cci,
export sma, ema, kama,
bollingerbands, truerange, atr, #keltnerbands,
obv, vwap,
doji,
rsi, macd, cci,
floorpivots, woodiespivots,
typical

Expand All @@ -22,4 +22,4 @@ include("utilities.jl")
include("volatility.jl")
include("volume.jl")

end
end
51 changes: 51 additions & 0 deletions src/movingaverages.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,30 @@ function ema{T,N}(ta::TimeArray{T,N}, n::Int; wilder=false)
TimeArray(tstamps, vals[n:length(ta),:], cname, ta.meta)
end

function kama{T,N}(ta::TimeArray{T,N}, n::Int=10, fn::Int=2, sn::Int=30)
vola = moving(abs(ta .- lag(ta)), sum, n)
change = abs(ta .- lag(ta, n))
er = change ./ vola # Efficiency Ratio

# Smooth Constant
sc = (er .* (2 / (fn + 1) - 2 / (sn + 1)) .+ 2 / (sn + 1)).^2

cl = ta[n+1:end]
vals = similar(cl.values)
# using simple moving average as initial kama
pri_kama = mean(ta[1:n].values, 1)

@assert length(cl) == length(sc)

for idx 1:length(cl)
vals[idx, :] =
pri_kama =
pri_kama .+ sc[idx].values .* (cl[idx].values .- pri_kama)
end

TimeArray(cl.timestamp, vals, ["$c\_kama" for c in ta.colnames])
end

# Array dispatch for use by other algorithms

function sma{T,N}(a::Array{T,N}, n::Int)
Expand Down Expand Up @@ -113,3 +137,30 @@ else ``k = \frac{2}{n + 1}``.
```
"""
ema

doc"""
Kaufman's Adaptive Moving Average
**Arguments**:
- `n`: period
- `fn`: the fastest EMA constant
- `sn`: the slowest EMA constant
**Formula**:
```math
\begin{align*}
KAMA_t & = KAMA_{t-1} + SC \times (Price - KAMA_{t-1}) \\
SC & =
(ER \times (\frac{2}{fn + 1} - \frac{2}{sn + 1}) + \frac{2}{sn + 1})^2 \\
ER & = \frac{Change}{Volatility} \\
Change & = | Price - Price_{t-n} | \\
Volatility & = \sum_{i}^{n} | Price_i - Price_{i-1} |
\end{align*}
```
"""
kama
62 changes: 37 additions & 25 deletions test/movingaverages.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ using MarketData

facts("Moving averages on TimeArrays") do

context("sma") do
context("sma") do
@fact sma(cl, 10).values[1] --> roughly(98.782, atol=.01) # TTR value 98.782
@fact sma(cl, 10).values[2] --> roughly(97.982, atol=.01) # TTR value 97.982
@fact sma(cl, 10).values[3] --> roughly(98.388, atol=.01) # TTR value 98.388
Expand All @@ -15,9 +15,9 @@ facts("Moving averages on TimeArrays") do
@fact sma(ohlc, 10).values[490,:] --> roughly([21.081, 21.685, 20.797, 21.266], atol=.01) # TTR value 21.266
@fact sma(ohlc, 10).values[491,:] --> roughly([21.259, 21.868, 20.971, 21.417], atol=.01) # TTR value 21.417
@fact sma(ohlc, 10).timestamp[491] --> Date(2001,12,31)
end
context("ema") do
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
@fact ema(cl, 10).values[3] --> roughly(100.963, atol=.01) # TTR value 100.96349
Expand All @@ -31,8 +31,8 @@ facts("Moving averages on TimeArrays") do
@fact ema(ohlc, 10).values[491,:] --> roughly([21.576, 22.145, 21.253, 21.642], atol=.01) # TTR value 21.64293
@fact ema(ohlc, 10).timestamp[491] --> Date(2001,12,31)
end
context("ema wilder true") do

context("ema wilder true") do
@fact ema(cl, 10, wilder=true).values[1] --> roughly(98.782, atol=.01) # TTR value 98.7820
@fact ema(cl, 10, wilder=true).values[2] --> roughly(99.297, atol=.01) # TTR value 99.2978
@fact ema(cl, 10, wilder=true).values[3] --> roughly(100.024, atol=.01) # TTR value 100.0240
Expand All @@ -46,29 +46,41 @@ facts("Moving averages on TimeArrays") do
@fact ema(ohlc, 10, wilder=true).values[491,:] --> roughly([21.317, 21.865, 20.945, 21.401], atol=.01) # TTR value 21.40100
@fact ema(ohlc, 10, wilder=true).timestamp[491] --> Date(2001,12,31)
end

context("kama") do
ta = kama(cl)
@fact ta.values[1] --> roughly(98.9052, atol=.01)
@fact ta.values[2] --> roughly(99.0098, atol=.01)
@fact ta.values[3] --> roughly(99.4499, atol=.01)
@fact ta.timestamp[1] --> Date(2000, 1, 18)

ta = kama(ohlc)
@fact length(ta.colnames) --> 4
@fact ta.timestamp[1] --> Date(2000, 1, 18)
end
end

facts("Moving averages on arrays") do
context("Array dispatch on sma") do

context("Array dispatch on sma") do
@fact sma(cl.values, 10)[1] --> roughly(98.782, atol=.01) # same values as above TimeArray dispatch
@fact sma(cl.values, 10)[2] --> roughly(97.982, atol=.01)
@fact sma(cl.values, 10)[3] --> roughly(98.388, atol=.01)
@fact sma(cl.values, 10)[490] --> roughly(21.266, atol=.01)
@fact sma(cl.values, 10)[491] --> roughly(21.417, atol=.01)
@fact sma(cl.values, 10)[2] --> roughly(97.982, atol=.01)
@fact sma(cl.values, 10)[3] --> roughly(98.388, atol=.01)
@fact sma(cl.values, 10)[490] --> roughly(21.266, atol=.01)
@fact sma(cl.values, 10)[491] --> roughly(21.417, atol=.01)
@fact sma(ohlc.values, 10)[1,:] --> roughly([100.692, 103.981, 96.001, 98.782] , atol=.01) # TTR value 98.782
@fact sma(ohlc.values, 10)[2,:] --> roughly([100.304, 103.331, 95.876, 97.982], atol=.01) # TTR value 97.982
@fact sma(ohlc.values, 10)[3,:] --> roughly([100.041, 103.144, 96.095,98.388], atol=.01) # TTR value 98.388
@fact sma(ohlc.values, 10)[490,:] --> roughly([21.081, 21.685, 20.797, 21.266], atol=.01) # TTR value 21.266
@fact sma(ohlc.values, 10)[491,:] --> roughly([21.259, 21.868, 20.971, 21.417], atol=.01) # TTR value 21.417
end
context("Array dispatch on ema") do
@fact ema(cl.values, 10)[1] --> roughly(98.782, atol=.01)
@fact ema(cl.values, 10)[2] --> roughly(99.719, atol=.01)
@fact ema(cl.values, 10)[3] --> roughly(100.963, atol=.01)
@fact ema(cl.values, 10)[490] --> roughly(21.585, atol=.01)
@fact ema(cl.values, 10)[491] --> roughly(21.642, atol=.01)
end

context("Array dispatch on ema") do
@fact ema(cl.values, 10)[1] --> roughly(98.782, atol=.01)
@fact ema(cl.values, 10)[2] --> roughly(99.719, atol=.01)
@fact ema(cl.values, 10)[3] --> roughly(100.963, atol=.01)
@fact ema(cl.values, 10)[490] --> roughly(21.585, atol=.01)
@fact ema(cl.values, 10)[491] --> roughly(21.642, atol=.01)
@fact ema(ohlc, 10).values[1,:] --> roughly([100.692, 103.981, 96.001, 98.782], atol=.01) # TTR value 98.78200
@fact ema(ohlc, 10).values[2,:] --> roughly([100.748, 104.348, 96.808, 99.719], atol=.01) # TTR value 99.71982
@fact ema(ohlc, 10).values[3,:] --> roughly([101.634, 105.148, 98.003, 100.963], atol=.01) # TTR value 100.96349
Expand All @@ -77,12 +89,12 @@ facts("Moving averages on arrays") do
@fact ema(ohlc, 10).timestamp[491] --> Date(2001,12,31)
end

context("Array dispatch on ema wilder true") do
context("Array dispatch on ema wilder true") do
@fact ema(cl.values, 10, wilder=true)[1] --> roughly(98.782, atol=.01)
@fact ema(cl.values, 10, wilder=true)[2] --> roughly(99.297, atol=.01)
@fact ema(cl.values, 10, wilder=true)[3] --> roughly(100.024, atol=.01)
@fact ema(cl.values, 10, wilder=true)[490] --> roughly(21.345, atol=.01)
@fact ema(cl.values, 10, wilder=true)[491] --> roughly(21.401, atol=.01)
@fact ema(cl.values, 10, wilder=true)[2] --> roughly(99.297, atol=.01)
@fact ema(cl.values, 10, wilder=true)[3] --> roughly(100.024, atol=.01)
@fact ema(cl.values, 10, wilder=true)[490] --> roughly(21.345, atol=.01)
@fact ema(cl.values, 10, wilder=true)[491] --> roughly(21.401, atol=.01)
@fact ema(ohlc.values, 10, wilder=true)[1,:] --> roughly([100.692, 103.981, 96.001, 98.782], atol=.01) # TTR value 98.7820
@fact ema(ohlc.values, 10, wilder=true)[2,:] --> roughly([100.723, 104.183, 96.444, 99.297], atol=.01) # TTR value 99.2978
@fact ema(ohlc.values, 10, wilder=true)[3,:] --> roughly([101.213, 104.64, 97.138, 100.024], atol=.01) # TTR value 100.0240
Expand Down

0 comments on commit e7a5dcb

Please sign in to comment.