ib-technical-analysis 0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 89931b30ea1e6eb4f7c054d5b4a53cdb0ad310ef82d5d2c437ea2e51d2cfb748
4
+ data.tar.gz: c46db9983553e90e85d0e3b0f934337210375b4b83a1a63cb326f107f4a4d7a1
5
+ SHA512:
6
+ metadata.gz: 4865a345bcd2b421f54b1482c1801980fc98876450f008e721df532776a3b1c5ab2c0e2d328df37f8e6906c803041fb3eb439f01958e94493a6ccb3f53e76a7f
7
+ data.tar.gz: 158a1d66691ebdb8fd2f8a7b248375b436e94bf48394174f2961e048069cfa7abe624eb3be215c96be99a96f9bf5415efb1bea849bdd11baf816199154c3f9ae
data/.gitignore ADDED
@@ -0,0 +1,56 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ # Used by dotenv library to load environment variables.
14
+ # .env
15
+
16
+ # Ignore Byebug command history file.
17
+ .byebug_history
18
+
19
+ ## Specific to RubyMotion:
20
+ .dat*
21
+ .repl_history
22
+ build/
23
+ *.bridgesupport
24
+ build-iPhoneOS/
25
+ build-iPhoneSimulator/
26
+
27
+ ## Specific to RubyMotion (use of CocoaPods):
28
+ #
29
+ # We recommend against adding the Pods directory to your .gitignore. However
30
+ # you should judge for yourself, the pros and cons are mentioned at:
31
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
32
+ #
33
+ # vendor/Pods/
34
+
35
+ ## Documentation cache and generated files:
36
+ /.yardoc/
37
+ /_yardoc/
38
+ /doc/
39
+ /rdoc/
40
+
41
+ ## Environment normalization:
42
+ /.bundle/
43
+ /vendor/bundle
44
+ /lib/bundler/man/
45
+
46
+ # for a library or gem, you might want to ignore these files since the code is
47
+ # intended to run in multiple environments; otherwise, check them in:
48
+ # Gemfile.lock
49
+ # .ruby-version
50
+ # .ruby-gemset
51
+
52
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
53
+ .rvmrc
54
+
55
+ # Used by RuboCop. Remote config files pulled in from inherit_from directive.
56
+ # .rubocop-https?--*
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in ib-technical-analysis.gemspec
4
+ gemspec
5
+ gem "ib-symbols" #, path: "../ib-symbols/"
6
+ gem "rake", "~> 13.0"
data/Guardfile ADDED
@@ -0,0 +1,24 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :rspec, cmd: "bundle exec rspec --format documentation" do
5
+ require "ostruct"
6
+
7
+ # Generic Ruby apps
8
+ rspec = OpenStruct.new
9
+ rspec.spec = ->(m) { "spec/#{m}_spec.rb" }
10
+ rspec.spec_dir = "spec"
11
+ rspec.spec_helper = "spec/spec_helper.rb"
12
+
13
+
14
+ # watch(%r{^lib/models/ib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
15
+ # watch(%r{^lib/ib/messages/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
16
+ # watch(%r{^lib/ib/symbols/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
17
+
18
+ watch(%r{^ib-technical-analysis/(.+)\.rb$}) { |m| "spec/ib-technical-analysis/#{m[1]}_spec.rb" }
19
+ # watch(%r{^models/(.+)\.rb$}) { |m| "spec/models/#{m[1]}_spec.rb" }
20
+ watch(%r{^spec/lib/.+_spec\.rb$})
21
+ watch('spec/spec_helper.rb') { "spec" }
22
+ # watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
23
+ end
24
+
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 ib-ruby
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,140 @@
1
+ # IB-Technical-Analysis
2
+ A library for performing technical analysis
3
+
4
+ This Gem is inspired by the [intrinio package](https://github.com/intrinio/technical-analysis). However, `IB-Technical-Analysis` focusses on
5
+ calculation of indicators from a stream of data.
6
+
7
+ It fits perfectly into the **_IB-Ruby_** suite, but can be used isolated, too.
8
+
9
+ ### Indicator classes
10
+
11
+ Indicators live in the `TechnicalAnalysis` namespace:
12
+ ```ruby
13
+ TechnicalAnalysis::MovingAverage::SimpleMA
14
+ TechnicalAnalysis::MovingAverage::EspMA
15
+ TechnicalAnalysis::MovingAverage::Wma
16
+ TechnicalAnalysis::MovingAverage::KaMA
17
+ TechnicalAnalysis::Momentum::Rsi
18
+ TechnicalAnalysis::Momentum::Tsi
19
+ TechnicalAnalysis::Momentum::Lane
20
+ ```
21
+
22
+ Additional calculations on single Bars are defined as extension of `IB::Bar`:
23
+
24
+ * typical_price
25
+ * pivot
26
+ * true_range
27
+
28
+ ##### Common Interface
29
+ The indicators are initialized by
30
+ ```ruby
31
+ indicator = TechnicalAnalysis::MovingAverage::KaMA.new period: 30, fast: 5, slow: 15, data: {an Array}
32
+ ```
33
+
34
+ If an Array is passed, the indicator is calculated immediately.
35
+
36
+ Subsequent data elements are passed by `indicator.add_item {value}`.
37
+ The calculated indicator is returned for further processing.
38
+
39
+
40
+
41
+
42
+
43
+
44
+ ### Perform calculation on time-series
45
+
46
+
47
+ `IB-Technical-Analysis` calculations are embedded in the `Enumerator`-class.
48
+
49
+ The List is simply iterated.
50
+
51
+ Thus
52
+ ```ruby
53
+ require 'bundler/setup'
54
+ require 'ib-gateway'
55
+ require 'ib/eod'
56
+ require 'ib/symbols'
57
+ require 'technical-analysis'
58
+
59
+ using TASupport
60
+
61
+ z = Symbols::Futures.mini_dax.eod( duration: '50 d').each
62
+ zz= z.calculate( :ema, period: 15 , use: :close
63
+ zz.first
64
+ => #<struct TechnicalAnalysis::MovingAverage::EMA time=Wed, 10 Mar 2021, value=0.149524e5>
65
+
66
+ ```
67
+ calculates the _Exponential Moving Average_ on the _close_ property of each item in the
68
+ Enumerator returned by the [contract.eod](https://ib-ruby.github.io/ib-doc/Historical_data.html) method.
69
+
70
+ The same using a conventional array:
71
+ ```ruby
72
+ u = z.map( &:close ).each
73
+ uu= u.calculate( :ema, period: 15 )
74
+ uu.first
75
+ => 0.149524e5
76
+ ```
77
+
78
+ ### Signals and Backtesting
79
+
80
+ The `calculate`-method of Enumerator passes raw-data and calculated indicator-values to an optional block.
81
+ This enables the formulation of signal generators.
82
+
83
+ ```ruby
84
+ buffer=[]
85
+ zz= z.calculate( :ema, period: 5, use: :typical_price ) do | raw, struct |
86
+ buffer << struct.value
87
+ buffer.shift if buffer.size >2
88
+ momentum_indicator = (buffer.first - buffer.last) <=> 0
89
+ crossing = case momentum_indicator
90
+ when +1
91
+ buffer.first > raw.close && buffer.last < raw.close
92
+ when -1
93
+ buffer.first < raw.close && buffer.last > raw.close
94
+ end
95
+ buy_or_sell = momentum_indicator == 1 ? "buy" : "sell"
96
+ puts "#{buy_or_sell}-Signal: EMA-Indicator-Crossing @ #{struct.time}" if crossing
97
+ end
98
+
99
+ ```
100
+
101
+
102
+ ### Implemented Indicators
103
+
104
+ * Simple Moving Average
105
+ ```ruby
106
+ zz = z.calculate :sma, period: 15, use: :close
107
+ ```
108
+ * Exponential Moving Average
109
+ ```ruby
110
+ zz = z.calculate :ema, period: 15
111
+ ```
112
+ * Weighted Moving Average
113
+ ```ruby
114
+ zz = z.calculate :wma, period: 15
115
+ ```
116
+ * Kaufman Moving Average
117
+ ```ruby
118
+ zz = z.calculate :kama, period: 15, fast: 10, slow: 3
119
+ ```
120
+ * Relative Strength Index
121
+ ```ruby
122
+ zz = z.calculate :rsi, period: 15
123
+ ```
124
+ * True Strength Index
125
+ ```ruby
126
+ zz = z.calculate :tsi, high: 15, low: 7
127
+ ```
128
+ * Lane Stochastic
129
+ ```ruby
130
+ zz = z.calculate :lane, period: 10, fast: 3, slow: 3 , use: :wap
131
+ ```
132
+
133
+
134
+
135
+
136
+
137
+ (work in progress)
138
+
139
+
140
+
data/bin/console ADDED
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env ruby
2
+ ### loads the active-orient environment
3
+ ### and starts an interactive shell
4
+ ###
5
+ ### Parameter: t)ws | g)ateway (or number of port ) Default: Gateway ,
6
+ ### client_id , Default 2000
7
+ ###
8
+ ### Define Parameter in file console.yml
9
+ ###
10
+ require 'bundler/setup'
11
+ require 'yaml'
12
+
13
+ require 'logger'
14
+ require "ib-api"
15
+ require 'ib/extensions'
16
+ require 'ib/symbols'
17
+ require 'technical-analysis'
18
+
19
+ class Array
20
+ # enables calling members of an array. which are hashes by it name
21
+ # i.e
22
+ #
23
+ # 2.5.0 :006 > C.received[:OpenOrder].local_id
24
+ # => [16, 17, 21, 20, 19, 8, 7]
25
+ # 2.5.0 :007 > C.received[:OpenOrder].contract.to_human
26
+ # => ["<Bag: IECombo SMART USD legs: >", "<Stock: GE USD>", "<Stock: GE USD>", "<Stock: GE USD>", "<Stock: GE USD>", "<Stock: WFC USD>", "<Stock: WFC USD>"]
27
+ #
28
+ # its included only in the console, for inspection purposes
29
+
30
+ def method_missing(method, *key)
31
+ unless method == :to_hash || method == :to_str #|| method == :to_int
32
+ return self.map{|x| x.public_send(method, *key)}
33
+ end
34
+
35
+ end
36
+ end # Array
37
+
38
+
39
+ # read items from console.yml
40
+ read_yml = -> (key) do
41
+ YAML::load_file( File.expand_path('../console.yml',__FILE__))[key]
42
+ end
43
+
44
+
45
+ puts
46
+ puts ">> IB-Ruby Interactive Console <<"
47
+ puts '-'* 45
48
+ puts
49
+ puts "Namespace is IB ! "
50
+ puts
51
+ puts '-'* 45
52
+ include LogDev
53
+ include IB
54
+ require 'irb'
55
+ client_id = ARGV[1] || read_yml[:client_id]
56
+ specified_port = ARGV[0] || 'Gateway'
57
+ port = case specified_port
58
+ when Integer
59
+ specified_port # just use the number
60
+ when /^[gG]/
61
+ read_yml[:gateway]
62
+ when /^[Tt]/
63
+ read_yml[:tws]
64
+ end
65
+
66
+ ARGV.clear
67
+ logger = default_logger # Logger.new STDOUT
68
+
69
+ ## The Block takes instructions which are executed after initializing all instance-variables
70
+ ## and prior to the connection-process
71
+ ## Here we just subscribe to some events
72
+ C = Connection.new client_id: client_id, port: port do |c| # future use__ , optional_capacities: "+PACEAPI" do |c|
73
+
74
+ c.subscribe( :ContractData, :BondContractData) { |msg| logger.info { msg.contract.to_human } }
75
+ c.subscribe( :Alert, :ContractDataEnd, :ManagedAccounts, :OrderStatus ) {| m| logger.info { m.to_human } }
76
+ c.subscribe( :PortfolioValue, :AccountValue, :OrderStatus, :OpenOrderEnd, :ExecutionData ) {| m| logger.info { m.to_human }}
77
+ # c.subscribe :ManagedAccounts do |msg|
78
+ # puts "------------------------------- Managed Accounts ----------------------------------"
79
+ # puts "Detected Accounts: #{msg.accounts.account.join(' -- ')} "
80
+ # puts
81
+ # end
82
+
83
+ c.subscribe( :OpenOrder){ |msg| "Open Order detected and stored: C.received[:OpenOrders] " }
84
+ c.logger.level = Logger::INFO
85
+ end
86
+ unless C.received[:OpenOrder].blank?
87
+ puts "------------------------------- OpenOrders ----------------------------------"
88
+ puts C.received[:OpenOrder].to_human.join "\n"
89
+ end
90
+ puts "Connection established on Port #{port}, client_id #{client_id} used"
91
+ puts
92
+ puts "----> C points to the connection-instance"
93
+ puts
94
+ puts "some basic Messages are subscribed and accordingly displayed"
95
+ puts
96
+ puts "Technical Analysis Indicators are included"
97
+ puts '-'* 45
98
+
99
+ using TASupport
100
+ IRB.start(__FILE__)
data/bin/console.yml ADDED
@@ -0,0 +1,3 @@
1
+ :gateway: 4002
2
+ :tws: 7496
3
+ :client_id: 2000
data/bin/gateway ADDED
@@ -0,0 +1,113 @@
1
+ #!/usr/bin/env ruby
2
+ ### loads the active-orient environment
3
+ ### and starts an interactive shell
4
+ ###
5
+ ### Parameter: t)ws | g)ateway (or number of port ) Default: Gateway ,
6
+ ### client_id , Default 2000
7
+ require 'bundler/setup'
8
+ require 'yaml'
9
+
10
+ require 'logger'
11
+ LogLevel = Logger::DEBUG ##INFO # DEBUG # ERROR
12
+ #require File.expand_path(File.dirname(__FILE__) + "/../config/boot")
13
+
14
+ require 'ib-gateway'
15
+ require 'ib/market-price'
16
+ require 'ib/option-chain'
17
+ require 'ib/eod'
18
+ require 'ib/symbols'
19
+ require 'technical-analysis'
20
+ class Array
21
+ # enables calling members of an array. which are hashes by it name
22
+ # i.e
23
+ #
24
+ # 2.5.0 :006 > C.received[:OpenOrder].local_id
25
+ # => [16, 17, 21, 20, 19, 8, 7]
26
+ # 2.5.0 :007 > C.received[:OpenOrder].contract.to_human
27
+ # => ["<Bag: IECombo SMART USD legs: >", "<Stock: GE USD>", "<Stock: GE USD>", "<Stock: GE USD>", "<Stock: GE USD>", "<Stock: WFC USD>", "<Stock: WFC USD>"]
28
+ #
29
+ # its included only in the console, for inspection purposes
30
+
31
+ def method_missing(method, *key)
32
+ unless method == :to_hash || method == :to_str #|| method == :to_int
33
+ return self.map{|x| x.public_send(method, *key)}
34
+ end
35
+
36
+ end
37
+ end # Array
38
+
39
+ # read items from console.yml
40
+ read_yml = -> (key) do
41
+ YAML::load_file( File.expand_path('../console.yml',__FILE__))[key]
42
+ end
43
+
44
+ # History-file für IRB-Sitzung setzen
45
+ pwd = `pwd`[0..-2]
46
+ `sed -i '/HISTORY_FILE]/ c\
47
+ IRB.conf[:HISTORY_FILE] = "#{pwd}/history.irb"\
48
+ ' ~/.irbrc`
49
+
50
+
51
+ puts
52
+ puts ">> I B – G A T E W A Y Interactive Console <<"
53
+ puts '-'* 45
54
+ puts
55
+ puts "Namespace is IB ! "
56
+ puts
57
+ puts '-'* 45
58
+
59
+ include IB
60
+ require 'irb'
61
+ client_id = ARGV[1] || read_yml[:client_id]
62
+ specified_port = ARGV[0] || 'Gateway'
63
+ port = case specified_port
64
+ when Integer
65
+ specified_port # just use the number
66
+ when /^[gG]/
67
+ read_yml[:gateway]
68
+ when /^[Tt]/
69
+ read_yml[:tws]
70
+ end
71
+
72
+ ARGV.clear
73
+ logger = Logger.new STDOUT
74
+ logger.formatter = proc do |level, time, prog, msg|
75
+ "#{time.strftime('%H:%M:%S')} #{msg}\n"
76
+ end
77
+ logger.level = Logger::INFO
78
+
79
+ ## The Block takes instructions which are executed after initializing all instance-variables
80
+ ## and prior to the connection-process
81
+ ## Here we just subscribe to some events
82
+ begin
83
+ G = Gateway.new get_account_data: true, serial_array: true,
84
+ client_id: client_id, port: port, logger: logger,
85
+ watchlists: [:Spreads, :BuyAndHold]
86
+ rescue IB::TransmissionError => e
87
+ puts "E: #{e.inspect}"
88
+ end
89
+
90
+ C = G.tws
91
+ unless C.received[:OpenOrder].blank?
92
+ puts "------------------------------- OpenOrders ----------------------------------"
93
+ puts C.received[:OpenOrder].to_human.join "\n"
94
+ puts " ---------------- Open Orders are present in G.clients.orders --------------"
95
+ puts ""
96
+ end
97
+ puts "Connection established on Port #{port}, client_id #{client_id} used"
98
+ puts
99
+ puts "----> G points to the Gateway-Instance"
100
+ puts "----> C points to the Connection-Instance"
101
+ puts
102
+ puts "some basic Messages are subscribed and accordingly displayed"
103
+ puts ""
104
+ puts "Technical Analysis Indicators are included"
105
+ puts '-'* 45
106
+
107
+ using TASupport
108
+ begin
109
+ IRB.start(__FILE__)
110
+ rescue IB::OrderAttributeError => e
111
+ puts "OrderAtttributeerror"
112
+ end
113
+