ib-technical-analysis 0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +56 -0
- data/Gemfile +6 -0
- data/Guardfile +24 -0
- data/LICENSE +21 -0
- data/README.md +140 -0
- data/bin/console +100 -0
- data/bin/console.yml +3 -0
- data/bin/gateway +113 -0
- data/bin/history.irb +186 -0
- data/ib-technical-analysis.gemspec +38 -0
- data/lib/calculation_helpers.rb +149 -0
- data/lib/ib/bar.rb +23 -0
- data/lib/ta_support.rb +157 -0
- data/lib/technical-analysis.rb +11 -0
- data/lib/technical_analysis/bar_calculation.rb +4 -0
- data/lib/technical_analysis/lane.rb +46 -0
- data/lib/technical_analysis/momentum/lane-stochastic.rb +105 -0
- data/lib/technical_analysis/momentum/rsi.rb +76 -0
- data/lib/technical_analysis/momentum/tsi.rb +79 -0
- data/lib/technical_analysis/moving-average/base.rb +59 -0
- data/lib/technical_analysis/moving-average/exp-ma.rb +53 -0
- data/lib/technical_analysis/moving-average/ka-ma.rb +90 -0
- data/lib/technical_analysis/moving-average/simple-ma.rb +42 -0
- data/lib/technical_analysis/moving-average/weighted-ma.rb +25 -0
- data/lib/technical_analysis/moving_average.rb +85 -0
- data/lib/technical_analysis/version.rb +4 -0
- metadata +183 -0
data/bin/history.irb
ADDED
@@ -0,0 +1,186 @@
|
|
1
|
+
exit
|
2
|
+
exit
|
3
|
+
exit
|
4
|
+
exit
|
5
|
+
exit
|
6
|
+
exit
|
7
|
+
exit
|
8
|
+
exit
|
9
|
+
exit
|
10
|
+
exit#
|
11
|
+
exit
|
12
|
+
exit
|
13
|
+
exit
|
14
|
+
exit
|
15
|
+
exit
|
16
|
+
exit
|
17
|
+
q
|
18
|
+
exit
|
19
|
+
exit
|
20
|
+
exit
|
21
|
+
exit
|
22
|
+
exit
|
23
|
+
exit
|
24
|
+
exit
|
25
|
+
exit
|
26
|
+
exit
|
27
|
+
exit
|
28
|
+
ATS.keys
|
29
|
+
ATS.first
|
30
|
+
p ATS.first
|
31
|
+
p ATS.first
|
32
|
+
puts ATS.first
|
33
|
+
puts ATS.first.result
|
34
|
+
puts ATS.first
|
35
|
+
irb ATS.first
|
36
|
+
@momentum
|
37
|
+
methods
|
38
|
+
@momentum
|
39
|
+
exit
|
40
|
+
puts ATS.first
|
41
|
+
puts ATS.first.result
|
42
|
+
p ATS.first
|
43
|
+
p ATS.first.result
|
44
|
+
p ATS.first..call :result
|
45
|
+
p= ATS.first
|
46
|
+
p
|
47
|
+
purs p.result
|
48
|
+
p= ATS[:"mini-dax"]
|
49
|
+
puts p.result
|
50
|
+
z= const_set
|
51
|
+
Base
|
52
|
+
Base.const_set 'G'
|
53
|
+
Base.const_set 'G', 6
|
54
|
+
G
|
55
|
+
z= Base.const_set 'G', 6
|
56
|
+
z
|
57
|
+
IB::Base::G
|
58
|
+
z= IB.const_set 'GU', 6
|
59
|
+
GU
|
60
|
+
z= 'jleor'
|
61
|
+
z.capitalize
|
62
|
+
exit
|
63
|
+
Dax
|
64
|
+
Russel
|
65
|
+
exit
|
66
|
+
ATS.keys
|
67
|
+
ATS[:dax]
|
68
|
+
puts Russel.result
|
69
|
+
puts Russell.result
|
70
|
+
puts Russell.result[:result]
|
71
|
+
puts Russell.result.map{|y| y[:result]}
|
72
|
+
puts dax.result.map{|y| y[:result]}
|
73
|
+
puts Dax.result.map{|y| y[:result]}
|
74
|
+
print Dax.result.map{|y| y[:result]}
|
75
|
+
print Dax.result.map{|y| y[:result].to_d}
|
76
|
+
print Dax.result.map{|y| y[:result].to_f}
|
77
|
+
print Russell.result.map{|y| y[:result].to_f}
|
78
|
+
exit
|
79
|
+
exit
|
80
|
+
Dax.result
|
81
|
+
puts Dax.result
|
82
|
+
exit
|
83
|
+
puts Dax.result
|
84
|
+
puts Dax.result.result
|
85
|
+
puts Dax.result
|
86
|
+
print Dax.result.result
|
87
|
+
print Dax.result.result.to_i
|
88
|
+
print Russell.result.result.to_i
|
89
|
+
exti
|
90
|
+
extit
|
91
|
+
exit
|
92
|
+
print Dax.raw_data.result.to_i
|
93
|
+
print Dax.contract
|
94
|
+
print exit
|
95
|
+
print Dax.raw_data.result.to_i
|
96
|
+
print Dax.contract
|
97
|
+
print Dax.current_price_signal
|
98
|
+
print Dax.current_price_signal
|
99
|
+
Dax.current_price_signal
|
100
|
+
exit
|
101
|
+
print Dax.current_price_signal
|
102
|
+
Dax.current_price_signal
|
103
|
+
print Dax.contract
|
104
|
+
Dax.contract
|
105
|
+
Dax.contract ; nil
|
106
|
+
irb Dax
|
107
|
+
@contract
|
108
|
+
exit
|
109
|
+
Dax.contract.to_human
|
110
|
+
Dax.contract.to_human
|
111
|
+
exit
|
112
|
+
exit
|
113
|
+
IB::BAR_SIZES
|
114
|
+
IB::BAR_SIZES.keys
|
115
|
+
exit
|
116
|
+
Dax.contract.to_human
|
117
|
+
Dax.raw_data.first
|
118
|
+
exit
|
119
|
+
i = IB::Bar.new
|
120
|
+
i.methods
|
121
|
+
require 'technical-analysis'
|
122
|
+
z.capitalize
|
123
|
+
z= 'jleor'
|
124
|
+
z = Symbols::Futures.mini_dax
|
125
|
+
zz= z.eod duration: '50 D'
|
126
|
+
zz= z.eod( duration: '50 D').each
|
127
|
+
zz= z.calculate( :ema, period: 15 , use: :close )
|
128
|
+
require 'ib-technical-analysis'
|
129
|
+
TechnicalAnalysis::Momentum::Lane
|
130
|
+
zz= z.eod duration: '50 D'
|
131
|
+
indicator = TechnicalAnalysis::MovingAverage::KaMA.new period: 30, fast: 5, slow: 15, data: zz
|
132
|
+
exit
|
133
|
+
z = Symbols::Futures.mini_dax
|
134
|
+
zz= z.eod duration: '50 D'
|
135
|
+
indicator = TechnicalAnalysis::MovingAverage::KaMA.new period: 30, fast: 5, slow: 15, data: zz
|
136
|
+
exit
|
137
|
+
z = Symbols::Futures.mini_dax
|
138
|
+
zz= z.eod duration: '50 D'
|
139
|
+
indicator = TechnicalAnalysis::MovingAverage::KaMA.new period: 30, fast: 5, slow: 15, data: zz
|
140
|
+
exit
|
141
|
+
exit
|
142
|
+
exit
|
143
|
+
z = Symbols::Futures.mini_dax
|
144
|
+
zz= z.eod duration: '50 D'
|
145
|
+
indicator = TechnicalAnalysis::MovingAverage::KaMA.new period: 30, fast: 5, slow: 15, data: zz
|
146
|
+
indicator = TechnicalAnalysis::MovingAverage::KaMA.new period: 30, fast: 5, slow: 15, data: zz.close
|
147
|
+
exit
|
148
|
+
z = Symbols::Futures.mini_dax
|
149
|
+
zz= z.eod duration: '50 D'
|
150
|
+
indicator = TechnicalAnalysis::MovingAverage::KaMA.new period: 30, fast: 5, slow: 15, data: zz.close
|
151
|
+
indicator = TechnicalAnalysis::MovingAverage::KaMA.new period: 30, fast: 5, slow: 15, data: zz
|
152
|
+
exit
|
153
|
+
z = Symbols::Futures.mini_dax
|
154
|
+
zz= z.eod duration: '50 D'
|
155
|
+
indicator = TechnicalAnalysis::MovingAverage::KaMA.new period: 30, fast: 5, slow: 15, data: zz
|
156
|
+
zz.first
|
157
|
+
zz.first.pivot
|
158
|
+
exit
|
159
|
+
exit
|
160
|
+
exit
|
161
|
+
Dax.result
|
162
|
+
Russell
|
163
|
+
exit
|
164
|
+
Dax
|
165
|
+
Dax
|
166
|
+
Dax.result
|
167
|
+
Dax.raw_data.result
|
168
|
+
Dax.raw_data.result.to_i
|
169
|
+
exit
|
170
|
+
z = Symbols::Futures.mini_dax
|
171
|
+
zz= z.eod duration: '50 D'
|
172
|
+
Symbols::Stocks.all
|
173
|
+
z= Symbols::Stocks.msft
|
174
|
+
zz= z.eod duration: '50 D'
|
175
|
+
z.close
|
176
|
+
zz.close
|
177
|
+
Symbols::Forex.all
|
178
|
+
IB::BAR_SIZES
|
179
|
+
IB::BAR_SIZES.key(hour)
|
180
|
+
IB::BAR_SIZES.key(:hour)
|
181
|
+
IB::BAR_SIZES.keys
|
182
|
+
IB::BAR_SIZES.values
|
183
|
+
exit
|
184
|
+
exit
|
185
|
+
TradingSystem::Base
|
186
|
+
exit
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require_relative 'lib/technical_analysis/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = "ib-technical-analysis"
|
5
|
+
spec.version = TechnicalAnalysis::VERSION
|
6
|
+
spec.authors = ["Hartmut Bischoff"]
|
7
|
+
spec.email = ["topofocus@gmail.com"]
|
8
|
+
|
9
|
+
spec.summary = %q{.Tools to perform technical analysis on financial data .}
|
10
|
+
spec.homepage = "https://ib-ruby.github.io/ib-doc/"
|
11
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 3.0.0")
|
12
|
+
|
13
|
+
# spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com"
|
14
|
+
|
15
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
16
|
+
spec.metadata["source_code_uri"] = "https://github.cm/ib-ruby/ib-technical-analysis"
|
17
|
+
spec.metadata["changelog_uri"] = "https://github.cm/ib-ruby/ib-technical-analysis/changelog.md"
|
18
|
+
|
19
|
+
# Specify which files should be added to the gem when it is released.
|
20
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
21
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
22
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
23
|
+
end
|
24
|
+
spec.bindir = "exe"
|
25
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
26
|
+
spec.require_paths = ["lib"]
|
27
|
+
|
28
|
+
|
29
|
+
spec.add_dependency "ib-api"
|
30
|
+
spec.add_dependency "ib-extensions"
|
31
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
32
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
33
|
+
spec.add_development_dependency 'rspec-collection_matchers'
|
34
|
+
spec.add_development_dependency 'rspec-its'
|
35
|
+
|
36
|
+
spec.add_development_dependency "guard"
|
37
|
+
spec.add_development_dependency "guard-rspec"
|
38
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
require 'dry/core/class_attributes'
|
2
|
+
|
3
|
+
module TechnicalAnalysis
|
4
|
+
module BarCalculation
|
5
|
+
|
6
|
+
def true_range previous_close
|
7
|
+
[
|
8
|
+
(high - low),
|
9
|
+
(high - previous_close).abs,
|
10
|
+
(low - previous_close).abs
|
11
|
+
].max
|
12
|
+
end
|
13
|
+
|
14
|
+
def typical_price
|
15
|
+
( high + low + close ) / 3.0
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
module MovingAverage
|
22
|
+
EMA = Struct.new :time, :value
|
23
|
+
WMA = Struct.new :time, :value
|
24
|
+
|
25
|
+
|
26
|
+
# Calculates the exponential moving average (EMA) for the data over the given period
|
27
|
+
# https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average
|
28
|
+
#
|
29
|
+
#
|
30
|
+
# z = Symbols::Futures.mini_dax.eod( duration: '30 d').each
|
31
|
+
# e= nil
|
32
|
+
# ema= z.map{|y| e= TechnicalAnalysis::MovingAverage.ema( y.close, z.map(&:close), 30, e ) }
|
33
|
+
#
|
34
|
+
# or
|
35
|
+
#
|
36
|
+
# EMA = Struct.new :time, :ema
|
37
|
+
# e = nil
|
38
|
+
# ema = z.map do |y|
|
39
|
+
# EMA.new y.time,
|
40
|
+
# e = TechnicalAnalysis::MovingAverage.ema y.close, z.map(&:close), 30, e
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
|
44
|
+
def self.ema current_value, data, period, prev_ema
|
45
|
+
if prev_ema.nil?
|
46
|
+
data.sum / data.size.to_f # Average
|
47
|
+
else
|
48
|
+
(current_value - prev_ema) * (2.0 / (period + 1.0)) + prev_ema
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Calculates the weighted moving average
|
53
|
+
#
|
54
|
+
# Parameter is the data-array.
|
55
|
+
#
|
56
|
+
# Takes an optional Block. Specify a method name that returns the data item
|
57
|
+
#
|
58
|
+
# z = Symbols::Futures.mini_dax.eod( duration: '30 d').each
|
59
|
+
# TechnicalAnalysis::ArrayCalculation.wma( z ){ :close }
|
60
|
+
#
|
61
|
+
def self.wma(data)
|
62
|
+
intermediate_values = []
|
63
|
+
data.each_with_index do |datum, i|
|
64
|
+
datum = datum.send yield if block_given?
|
65
|
+
intermediate_values << datum * (i + 1) / (data.size * (data.size + 1) / 2).to_f
|
66
|
+
end
|
67
|
+
intermediate_values.sum
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
## reopen IB::Bar and include BarCalculation ( as Mixin )
|
73
|
+
|
74
|
+
module IB
|
75
|
+
class Bar
|
76
|
+
include TechnicalAnalysis::BarCalculation
|
77
|
+
end
|
78
|
+
# z= Symbols::Futures.mini_dax.eod( duration: '30 d').each
|
79
|
+
#
|
80
|
+
# loop do
|
81
|
+
# bar= z.next
|
82
|
+
# puts bar.time, z.peek.true_range(bar.close)
|
83
|
+
# end.
|
84
|
+
|
85
|
+
# z.rewind
|
86
|
+
#
|
87
|
+
# z.map{ |y| x.typical_price }
|
88
|
+
#
|
89
|
+
end # module
|
90
|
+
|
91
|
+
module TASupport
|
92
|
+
refine Enumerator do
|
93
|
+
#
|
94
|
+
# first include
|
95
|
+
# using TASupport
|
96
|
+
# in your script.
|
97
|
+
#
|
98
|
+
# After fetching stock-data from a file, a database or the broker and
|
99
|
+
# converting it into an Enumerator (simply using array.each)
|
100
|
+
#
|
101
|
+
# calculate
|
102
|
+
#
|
103
|
+
# is just performed on the object
|
104
|
+
#
|
105
|
+
# The result is returned as array of structs.
|
106
|
+
#
|
107
|
+
# z = Symbols::Futures.mini_dax.eod( duration: '50 d').each
|
108
|
+
# z.calculate { :close }
|
109
|
+
#
|
110
|
+
# zz= z.calculate( :ema ){ :typical_price }
|
111
|
+
#
|
112
|
+
# zz= z.calculate( :ema, period: 3 ) { :close }
|
113
|
+
# zz.first
|
114
|
+
# => #<struct TechnicalAnalysis::MovingAverage::EMA time=Wed, 10 Mar 2021, value=0.149441e5
|
115
|
+
def calculate indicator= :ema, **params
|
116
|
+
struct = TechnicalAnalysis::MovingAverage.send :const_get, indicator.to_s.upcase
|
117
|
+
buffer, start = nil, []
|
118
|
+
choice = if block_given?
|
119
|
+
yield
|
120
|
+
elsif peek.respond_to?(:time)
|
121
|
+
:close
|
122
|
+
else
|
123
|
+
nil
|
124
|
+
end
|
125
|
+
data = choice.nil? ? self.to_a : map{|y| y.send choice }
|
126
|
+
period = params[:period] || 30
|
127
|
+
calc_ema = ->(item){ buffer= TechnicalAnalysis::MovingAverage.ema item, data, period, buffer }
|
128
|
+
|
129
|
+
if peek.respond_to? :time
|
130
|
+
map{ | d |
|
131
|
+
value = case indicator
|
132
|
+
when :ema
|
133
|
+
calc_ema[ d.send choice ]
|
134
|
+
when :wma
|
135
|
+
TechnicalAnalysis::MovingAverage.wma start << d.send( choice )
|
136
|
+
end
|
137
|
+
struct.new d.time , value
|
138
|
+
}#map
|
139
|
+
else
|
140
|
+
case indicator
|
141
|
+
when :ema
|
142
|
+
map{ | d | calc_ema[ choice.nil? ? d : d.send( choice ) ] }
|
143
|
+
when :wma
|
144
|
+
map{ |d| TechnicalAnalysis::MovingAverage.wma( start << choice.nil? ? d : d.send( choice ) ) }
|
145
|
+
end # case
|
146
|
+
end # branch
|
147
|
+
end # def
|
148
|
+
end # refine
|
149
|
+
end # module
|
data/lib/ib/bar.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
module IB
|
2
|
+
class Bar
|
3
|
+
def true_range previous_close
|
4
|
+
[
|
5
|
+
(high - low),
|
6
|
+
(high - previous_close).abs,
|
7
|
+
(low - previous_close).abs
|
8
|
+
].max
|
9
|
+
end
|
10
|
+
|
11
|
+
def typical_price
|
12
|
+
( high + low + close ) / 3.0
|
13
|
+
end
|
14
|
+
|
15
|
+
def pivot
|
16
|
+
{ pp: p=( high + close + low ).to_f / 3 ,
|
17
|
+
r1: ( 2 * p ).to_f - low.to_f,
|
18
|
+
r2: p + ( high - low ).to_f,
|
19
|
+
s1: ( 2 * p ).to_f - high.to_f,
|
20
|
+
s2: p - ( high - low ).to_f }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/ta_support.rb
ADDED
@@ -0,0 +1,157 @@
|
|
1
|
+
|
2
|
+
module TASupport
|
3
|
+
refine Enumerator do
|
4
|
+
#
|
5
|
+
# first include
|
6
|
+
# using TASupport
|
7
|
+
# in your script.
|
8
|
+
#
|
9
|
+
# After fetching stock-data from a file, a database or the broker and
|
10
|
+
# converting it into an Enumerator (simply using array.each)
|
11
|
+
#
|
12
|
+
# calculate
|
13
|
+
#
|
14
|
+
# is just performed on the object
|
15
|
+
#
|
16
|
+
# The result is returned as array of structs.
|
17
|
+
#
|
18
|
+
# z = Symbols::Futures.mini_dax.eod( duration: '150 d').each
|
19
|
+
# z.calculate use: :close
|
20
|
+
#
|
21
|
+
# zz= z.calculate :ema, use: :typical_price
|
22
|
+
#
|
23
|
+
# zz= z.calculate( :ema, period: 3, use: :close
|
24
|
+
# zz.first
|
25
|
+
# => #<struct TechnicalAnalysis::MovingAverage::EMA time=Wed, 10 Mar 2021, value=0.149441e5
|
26
|
+
#
|
27
|
+
# Input-data are converted to float and then applied to the indicator-calculations
|
28
|
+
#
|
29
|
+
# A block can be provided to execute commands after calculating each single indicator value
|
30
|
+
# This is provided to enable backtests on the data
|
31
|
+
#
|
32
|
+
# The block gets the input-data **and** the calculated indicator struct.
|
33
|
+
#
|
34
|
+
# i.e.
|
35
|
+
# buffer=[]
|
36
|
+
# zz= z.calculate( :ema, use: :typical_price ) do | raw, struct |
|
37
|
+
# buffer << struct.value
|
38
|
+
# buffer.shift if buffer.size >2
|
39
|
+
# momentum_indicator = (buffer.first - buffer.last) <=> 0
|
40
|
+
# crossing = case momentum_indicator
|
41
|
+
# when +1
|
42
|
+
# buffer.first > raw.close && buffer.last < raw.close
|
43
|
+
# when -1
|
44
|
+
# buffer.first < raw.close && buffer.last > raw.close
|
45
|
+
# end
|
46
|
+
# buy_or_sell = momentum_indicator == 1 ? "buy" : "sell"
|
47
|
+
# puts "#{buy_or_sell}-Signal: EMA-Indicator-Crossing @ #{struct.time}" if crossing
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
#
|
51
|
+
def calculate indicator= :ema, **params
|
52
|
+
struct = if indicator.to_s[-2,2]=='ma'
|
53
|
+
TechnicalAnalysis::MovingAverage.send :const_get, indicator.to_s.upcase
|
54
|
+
elsif indicator.to_s[-2,2]=='si' || indicator== :lane
|
55
|
+
TechnicalAnalysis::Momentum.send :const_get, indicator.to_s.upcase
|
56
|
+
end
|
57
|
+
buffer, start, default_value = nil, [], nil
|
58
|
+
|
59
|
+
## strict-mode
|
60
|
+
strict_mode = params[:strict] || false
|
61
|
+
|
62
|
+
choice = if params[:use].present?
|
63
|
+
params[:use]
|
64
|
+
elsif peek.respond_to?(:time)
|
65
|
+
:close
|
66
|
+
else
|
67
|
+
nil
|
68
|
+
end
|
69
|
+
## fill in defaults
|
70
|
+
case indicator
|
71
|
+
when :ema, :wma, :sma, :rsi
|
72
|
+
period = params[:period] || 15
|
73
|
+
when :kama
|
74
|
+
period = params[:period] || 15
|
75
|
+
fast = params[:fast] || 2
|
76
|
+
slow= params[:slow] || 30
|
77
|
+
when :tsi
|
78
|
+
high = params[:high] || 25
|
79
|
+
low = params[:low] || 13
|
80
|
+
when :lane
|
81
|
+
period = params[:period] || 10
|
82
|
+
fast = params[:fast] || 3
|
83
|
+
slow= params[:slow] || 3
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
# start (array of processed values) is updated in every iteration
|
88
|
+
# applies to indicators
|
89
|
+
# kama
|
90
|
+
# sma
|
91
|
+
# wma
|
92
|
+
#
|
93
|
+
a = peek
|
94
|
+
date_field = if a.respond_to? :time
|
95
|
+
:time
|
96
|
+
elsif a.respond_to? :date_time
|
97
|
+
:date_time
|
98
|
+
elsif a.respond_to? :date
|
99
|
+
:date
|
100
|
+
else
|
101
|
+
nil
|
102
|
+
end
|
103
|
+
indicator_method = case indicator
|
104
|
+
when :sma, :simple_ma
|
105
|
+
TechnicalAnalysis::MovingAverage::SimpleMA.new period: period, strict: strict_mode
|
106
|
+
when :ema, :exp_ma
|
107
|
+
TechnicalAnalysis::MovingAverage::ExpMA.new period: period, strict: strict_mode
|
108
|
+
when :wma
|
109
|
+
TechnicalAnalysis::MovingAverage::Wma.new period: period, strict: strict_mode
|
110
|
+
when :kama
|
111
|
+
TechnicalAnalysis::MovingAverage::KaMA.new period: period, strict: strict_mode,
|
112
|
+
fast: fast, slow: slow
|
113
|
+
when :rsi
|
114
|
+
TechnicalAnalysis::Momentum::Rsi.new period: period
|
115
|
+
when :tsi
|
116
|
+
TechnicalAnalysis::Momentum::Tsi.new low: low, high: high
|
117
|
+
when :lane
|
118
|
+
TechnicalAnalysis::Momentum::Lane.new slow: slow, fast: fast, period: period,
|
119
|
+
take: choice
|
120
|
+
end
|
121
|
+
## iterate across the enumerator and return the result of the calculations
|
122
|
+
map.with_index { | d, i |
|
123
|
+
# central point to convert to float
|
124
|
+
unless indicator == :lane
|
125
|
+
raw_data = if date_field.present? || choice.present?
|
126
|
+
d.send(choice).to_f
|
127
|
+
else
|
128
|
+
d.to_f
|
129
|
+
end
|
130
|
+
indicator_method.add_item(raw_data)
|
131
|
+
else
|
132
|
+
indicator_method.add_item(d)
|
133
|
+
end
|
134
|
+
|
135
|
+
next if indicator_method.current.nil? # creates a nil entry
|
136
|
+
value = indicator_method.current # return this value
|
137
|
+
## data-format of the returned array-elements
|
138
|
+
result = if date_field.present?
|
139
|
+
struct.new d.send(date_field), value
|
140
|
+
else
|
141
|
+
value
|
142
|
+
end
|
143
|
+
# expose the input-data and the calculated indicator to the block
|
144
|
+
yielder = yield( d, result) if block_given?
|
145
|
+
yielder.nil? ? result : yielder # return the expression from the block if present
|
146
|
+
}.compact # map
|
147
|
+
end # def
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
## notes on Enumerators
|
152
|
+
#- z:= An Enumerator
|
153
|
+
#- z.size == z.count
|
154
|
+
#- z.entries == z.to_a
|
155
|
+
#- z.take n returns an array of the first n elements
|
156
|
+
#- z.sum, if enumerator-objects define a "+" method
|
157
|
+
#
|