/
indicators.jl
141 lines (119 loc) · 4.12 KB
/
indicators.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
"""
MovingStdDev{horizon, T}
The moving standard deviation of a value over a sliding window of `horizon`.
"""
@component struct MovingStdDev{horizon,T}
σ::T
end
value(m::MovingStdDev) = value(m.σ)
Base.eltype(::Type{MovingStdDev{x,T}}) where {x,T} = T
prefixes(::Type{<:MovingStdDev{horizon}}) where {horizon} = ("MovingStdDev_$(horizon)",)
"""
SMA{horizon, T}
The simple moving average of a value over a sliding window of `horizon`.
"""
@component struct SMA{horizon,T}
sma::T
end
value(sma::SMA) = value(sma.sma)
Base.eltype(::Type{SMA{x,T}}) where {x,T} = T
prefixes(::Type{<:SMA{horizon}}) where {horizon} = ("SMA_$(horizon)",)
"""
EMA{horizon, T}
The exponential moving average of a value over a sliding window of `horizon`.
"""
@component struct EMA{horizon,T}
ema::T
end
value(ema::EMA) = value(ema.ema)
Base.eltype(::Type{EMA{x,T}}) where {x,T} = T
prefixes(::Type{<:EMA{horizon}}) where {horizon} = ("EMA_$(horizon)",)
"""
Bollinger{horizon, T}
The up and down Bollinger bands for a value, over a sliding window of `horizon`.
"""
@component struct Bollinger{horizon,T}
up::T
down::T
end
value(b::Bollinger) = (value(b.up), value(b.down))
Base.eltype(::Type{Bollinger{x,T}}) where {x,T} = T
prefixes(::Type{<:Bollinger{horizon}}) where {horizon} = ("Bollinger_$(horizon)_up","Bollinger_$(horizon)_down")
for diff_T in (:Difference, :RelativeDifference)
@eval begin
@component struct $diff_T{T} <: SingleValIndicator{T}
v::T
end
value(d::$diff_T) = value(d.v)
Base.zero(d::$diff_T) = $diff_T(zero(value(d)))
end
end
prefixes(::Type{<:Difference}) = ("Difference",)
prefixes(::Type{<:RelativeDifference}) = ("RelativeDifference",)
"""
Difference
The lag 1 difference.
"""
Difference
"""
RelativeDifference
The lag 1 relative difference.
"""
RelativeDifference
@component struct UpDown{T}
up::T
down::T
end
Base.zero(d::UpDown) = UpDown(zero(d.up), zero(d.down))
Base.eltype(::Type{UpDown{T}}) where {T} = T
prefixes(::Type{UpDown}) = ("UpDown_up", "UpDown_down")
for op in (:+, :-, :*)
@eval @inline function Base.$op(b1::UpDown, b2::UpDown)
return UpDown($op(b1.up, b2.up), $op(b1.down, b2.down))
end
end
@inline Base.:(/)(b::UpDown, i::Int) = UpDown(b.up / i, b.down / i)
@inline Base.:(^)(b::UpDown, i::Int) = UpDown(b.up^i, b.down^i)
@inline Base.:(*)(b::UpDown, i::AbstractFloat) = UpDown(b.up * i, b.down * i)
@inline Base.:(*)(i::Integer, b::UpDown) = b * i
@inline Base.sqrt(b::UpDown) = UpDown(sqrt(b.up), sqrt(b.down))
@inline Base.:(<)(i::Number, b::UpDown) = i < b.up && i < b.down
@inline Base.:(<)(b::UpDown, i::Number) = b.up < i && b.down < i
@inline Base.:(>)(i::Number, b::UpDown) = i > b.up && i > b.down
@inline Base.:(>)(b::UpDown, i::Number) = b.up > i && b.down > i
@inline Base.:(>=)(i::Number, b::UpDown) = i >= b.up && i >= b.down
@inline Base.:(>=)(b::UpDown, i::Number) = b.up >= i && b.down >= i
@inline Base.:(<=)(i::Number, b::UpDown) = i <= b.up && i <= b.down
@inline Base.:(<=)(b::UpDown, i::Number) = b.up <= i && b.down <= i
Base.zero(::Type{UpDown{T}}) where {T} = UpDown(zero(T), zero(T))
@assign UpDown with Is{Indicator}
value(ud::UpDown) = (value(ud.up), value(ud.down))
"""
RSI{horizon, T}
The relative strength index of a value over timeframe of `horizon`.
"""
@component struct RSI{horizon,T}
rsi::T
end
value(rsi::RSI) = value(rsi.rsi)
Base.eltype(::Type{RSI{horizon,T}}) where {horizon,T} = T
prefixes(::Type{<:RSI{horizon}}) where {horizon} = ("RSI_$(horizon)",)
"""
Sharpe{horizon, T}
The sharpe ratio of a value over a timeframe `horizon`.
"""
@component struct Sharpe{horizon,T}
sharpe::T
end
Base.eltype(::Type{Sharpe{horizon,T}}) where {horizon,T} = T
prefixes(::Type{<:Sharpe{horizon}}) where {horizon} = ("Sharpe_$(horizon)",)
function TimeSeries.colnames(::Type{T}) where {T<:Union{Difference, RelativeDifference, LogVal, MovingStdDev, SMA, EMA, RSI, Sharpe, Bollinger, UpDown}}
cnames = colnames(eltype(T))
out = String[]
for c in cnames
for prefix in prefixes(T)
push!(out, replace("$(prefix)_$c", "Trading." => ""))
end
end
return out
end