ib-technical-analysis 0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+