finnhubrb 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 305ff27db99c18e1a76d1034fd69b568e89b45fd8cfba42a030199b03e4ba4f2
4
+ data.tar.gz: a65a7dc065c422855d5a4a6685349c6a634be771b517586541ab90e43e1c9fde
5
+ SHA512:
6
+ metadata.gz: c8cc6932d02616b872f2ac87737acde0ce0d4b951d72f76875edf32f4fc8e1ac37d37dc67ba59570bdd1a0d5fe4ec9463939748e6dfd8e950a6f029e94c63478
7
+ data.tar.gz: b0323e588781a3eabd6f49347f0985e51dd5d0eb872a02e07790aaa20a8407aab5adc8d5ef7d1ff477ebd134a3e9ca5dbff750c8622388b78d5e4de284f6fd6f
@@ -0,0 +1,24 @@
1
+ # lib = File.expand_path("../lib", __FILE__)
2
+ # $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "rake"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "finnhubrb"
7
+ s.version = "1.0.0"
8
+ s.authors = ["Stefano Martin"]
9
+ s.email = ["stefano.martin87@gmail.com"]
10
+ s.homepage = "https://github.com/StefanoMartin/FinnhubRB"
11
+ s.license = "MIT"
12
+ s.summary = "A gem for Alpha Vantage"
13
+ s.description = "A ruby wrapper for Finnhub's HTTP API"
14
+ s.platform = Gem::Platform::RUBY
15
+ s.require_paths = ["lib"]
16
+ s.files = FileList["lib/*", "spec/**/*", "FinnhubRB.gemspec", "Gemfile", "LICENSE.md", "README.md"].to_a
17
+ s.add_runtime_dependency "httparty", "~>0.17.0", ">= 0.17.0"
18
+ s.add_runtime_dependency "oj", "~>3.9.0", ">= 3.9.0"
19
+ s.add_runtime_dependency "faye-websocket", "~>0.10.9", ">= 0.10.9"
20
+ s.add_development_dependency "pry-byebug", '~> 0'
21
+ s.add_development_dependency "rspec", "~>3.5", ">=3.5"
22
+ s.add_development_dependency "awesome_print", "~>1.7", ">= 1.7"
23
+ s.add_development_dependency "eventmachine", "~>1.2.7", ">= 1.2.7"
24
+ end
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "httparty", ">= 0.17.1"
4
+ gem "oj", ">= 3.9.2"
5
+ gem "faye-websocket", ">= 0.10.9"
6
+ gem "eventmachine", "1.2.7"
7
+
8
+ group :development, :test do
9
+ gem "pry-byebug"
10
+ gem "rspec", ">= 3.5"
11
+ gem "awesome_print", ">= 1.7"
12
+ end
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2019 Stefano Martin
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.
@@ -0,0 +1,237 @@
1
+ FinnhubRB
2
+ =========================================================
3
+
4
+ [Finnhub](https://finnhub.io/) is an API for retrieving Stock
5
+ market data in JSON or CSV format.
6
+ FinnhubRB is a wrapper Gem to use Finnhub with Ruby. FinnhubRB is based
7
+ on the [HTTP API of Finnhub](https://finnhub.io/docs/api).
8
+
9
+ To install FinnhubRB: `gem install finnhubrb`
10
+
11
+ To use it in your application: `require "finnhubrb"`
12
+
13
+ ## How to test
14
+
15
+ To test the Gem create a config.yml file inside the folder /spec with inside a line
16
+
17
+ ``` ruby
18
+ key: [YOUR KEY]
19
+ ```
20
+
21
+ Then run "rspec spec/test_all.rb".
22
+
23
+ ## Support
24
+
25
+ * Without a premium account, testing is hard and I could have missed something. Any bug, suggestions and improvements are more than welcome. Please do not be shy to create issues or pull requests.
26
+ * This is a personal project, any stars for giving your support will make a man happy.
27
+
28
+ ## Client
29
+
30
+ To contact Alpha Vantage you need to use a valid key that you can require from [here](https://finnhub.io/register).
31
+
32
+ To setup your clients use:
33
+
34
+ ``` ruby
35
+ client = Finnhub::Client.new(key: "YOURKEY")
36
+ ```
37
+
38
+ If you want to see the request that the client will do to Finnhub you can
39
+ setup verbose equal to true.
40
+
41
+ ``` ruby
42
+ client.verbose = true # You can setup this during the initialization too
43
+ ```
44
+
45
+ ## Stock
46
+
47
+ Finnhub::Stock is used to manage a stock class.
48
+ To create a new Stock class you can use a client.
49
+
50
+ ``` ruby
51
+ stock = client.stock symbol: "AAPL"
52
+ ```
53
+
54
+ Several methods are available under this class:
55
+
56
+ ``` ruby
57
+ stock.symbol # Return the symbol
58
+ stock.profile # Retrieve profile of the stock
59
+ stock.ceo_compensation # Retrieve compensation of the stock's CEO
60
+ stock.recommendation # Retrieve recommendation about this stock
61
+ stock.price_target # Retrieve price target about this stock
62
+ stock.option_chain # Retrieve option chain about this stock
63
+ stock.earnings # Retrieve earnings about this stock
64
+ stock.news # Retrieve news about this stock (only US)
65
+ stock.sentiment # Retrieve social sentiment about this stock (only US)
66
+ stock.peers(plain: true) # Retrieve peers company similar to the one chosen
67
+ stock.peers # Like the previous one, but the results are Finnhub::Stock instances
68
+ stock.pattern # Retrieve pattern
69
+ stock.support_resistance # Retrieve support resistance
70
+ stock.technical_indicators # Retrieve techinical indicators
71
+ ```
72
+
73
+ To create a timeseries you can use:
74
+
75
+ ``` ruby
76
+ stock.timeseries(count: 100) # Return the last 100 entries (default count is 100)
77
+ stock.timeseries(resolution: "D") # Resolution is daily "D", alternative are 1, 5, 15, 30, 60, D, W, M) where the numeric one are for minutes (default resolution is "D")
78
+ stock.timeseries(from: Time.now-24*30*3600, to: Time.now) # Fetch from a date to another date (default from: nil, to: nil)
79
+ stock.timeseries(format: "json") # Return the output in json or in csv (default format: "json")
80
+ ```
81
+
82
+ Remember count and from/to are exclusive. If you use one, you cannot use the other two.
83
+ The methods "open", "high", "low", "close", "volume" and "status" will not work if you use format csv.
84
+
85
+ ``` ruby
86
+ timeseries = stock.timeseries(from: Time.now-24*30*3600, to: Time.now, resolution: 60)
87
+ timeseries.output # Return output obtained from the request
88
+ timeseris.timestamps # Return timestamps obtained from the request
89
+ timeseries.open # Return open obtained from the request
90
+ timeseries.low # Return low obtained from the request
91
+ timeseries.close # Return close obtained from the request
92
+ timeseries.volume # Return volume obtained from the request
93
+ timeseries.status # Return status obtained from the request
94
+ ```
95
+
96
+ ## Crypto
97
+
98
+ To analyse a crypto currency you should start by choosing which crypto exchange you want to analyse.
99
+
100
+ ``` ruby
101
+ client.crypto_exchanges # Retrieve the available crypto exchanges on Finnhub (Finnhub::Crypto_Exchange instances)
102
+ client.crypto_exchanges(plain: true) # As above, but it returns simply the output of the request
103
+ crypto_exchange = client.crypto_exchange(name: "NAME_CRYPTO_EXCHANGE") # Create a single instance of Finnhub::Crypto_Exchange
104
+ ```
105
+
106
+ After that you can choose, in that crypto exchange which symbol you want to check.
107
+
108
+ ``` ruby
109
+ crypto_exchange.symbols # Retrieve the available crypto symbols on the chosen crypto exchange (Finnhub::Crypto_Symbol instances)
110
+ crypto_exchange.symbols(plain: true) # As above, but it returns simply the output of the request
111
+ crypto_symbol = crypto_exchange.symbol(symbol: "BTC") # Create a single instance of Finnhub::Crypto_Symbol
112
+ ```
113
+
114
+ From crypto_symbol instance you can retrieve some interesting information.
115
+
116
+ ``` ruby
117
+ crypto_symbol.exchange # Exchange of the crypto_symbol
118
+ crypto_symbol.hasWM # If it has week and month
119
+ crypto_symbol.displaySymbol # Displayed symbol
120
+ crypto_symbol.symbol # Symbol of the crypto currency
121
+ ```
122
+
123
+ Furthermore you can create a timeseries with the same logic used for Stock timeseries.
124
+
125
+ ``` ruby
126
+ timeseries = crypto_symbol.timeseries(from: Time.now-24*30*3600, to: Time.now, resolution: 60)
127
+ timeseries.output # Return output obtained from the request
128
+ timeseris.timestamps # Return timestamps obtained from the request
129
+ timeseries.open # Return open obtained from the request
130
+ timeseries.low # Return low obtained from the request
131
+ timeseries.close # Return close obtained from the request
132
+ timeseries.volume # Return volume obtained from the request
133
+ timeseries.status # Return status obtained from the request
134
+ ```
135
+
136
+ ## Forex
137
+
138
+ To analyse a forex exchange you should start by choosing which forex exchange you want to analyse.
139
+
140
+ ``` ruby
141
+ client.forex_exchanges # Retrieve the available forex exchanges on Finnhub (Finnhub::Forex_Exchange instances)
142
+ client.forex_exchanges(plain: true) # As above, but it returns simply the output of the request
143
+ forex_exchange = client.forex_exchange(name: "NAME_FOREX_EXCHANGE") # Create a single instance of Finnhub::Forex_Exchange
144
+ ```
145
+
146
+ After that you can choose, in that forex exchange which symbol you want to check.
147
+
148
+ ``` ruby
149
+ forex_exchange.symbols # Retrieve the available forex symbols on the chosen forex exchange (Finnhub::Forex_Symbol instances)
150
+ forex_exchange.symbols(plain: true) # As above, but it returns simply the output of the request
151
+ forex_symbol = forex_exchange.symbol(symbol: "USD") # Create a single instance of Finnhub::Forex_Symbol
152
+ ```
153
+
154
+ From forex_symbol instance you can retrieve some interesting information.
155
+
156
+ ``` ruby
157
+ forex_symbol.exchange # Exchange of the crypto_symbol
158
+ forex_symbol.hasWM # If it has week and month
159
+ forex_symbol.displaySymbol # Displayed symbol
160
+ forex_symbol.symbol # Symbol of the crypto currency
161
+ ```
162
+
163
+ Furthermore you can create a timeseries with the same logic used for Stock timeseries.
164
+
165
+ ``` ruby
166
+ timeseries = forex_symbol.timeseries(from: Time.now-24*30*3600, to: Time.now, resolution: 60)
167
+ timeseries.output # Return output obtained from the request
168
+ timeseris.timestamps # Return timestamps obtained from the request
169
+ timeseries.open # Return open obtained from the request
170
+ timeseries.low # Return low obtained from the request
171
+ timeseries.close # Return close obtained from the request
172
+ timeseries.volume # Return volume obtained from the request
173
+ timeseries.status # Return status obtained from the request
174
+ ```
175
+
176
+ ## Merge
177
+
178
+ You can retrieve information about company that are merging in relation of a given country.
179
+
180
+ ``` ruby
181
+ client.merge_countries # Retrieve the available merge countries on Finnhub (Finnhub::Merge_Country instances)
182
+ client.merge_countries(plain: true) # As above, but it returns simply the output of the request
183
+ country = client.merge_country(country: "France") # Create a single instance of Finnhub::Merge_Country
184
+ country.merger # Fetch information about the company that are going to merge
185
+ ```
186
+
187
+ ## Economic Code
188
+
189
+ You can retrieve information about economic_codes.
190
+
191
+ ``` ruby
192
+ client.economic_codes # Retrieve the available economic_codes on Finnhub (Finnhub::Economic_Code instances)
193
+ client.economic_codes(plain: true) # As above, but it returns simply the output of the request
194
+ economic = client.economic_code(code: "CODE") # Create a single instance of Finnhub::Economic_Code
195
+ economic.data # Data of economic_code
196
+ economic.data(plaint: true) # As above, but it returns simply the output of the request
197
+ ```
198
+
199
+ ## News and calendar
200
+
201
+ You can retrieve news and calendar in the following way.
202
+
203
+ ``` ruby
204
+ client.news(category: "forex") # Retrieve news by category (general, forex, crypto, merger) and by minId (default 0)
205
+ client.economic_calendar # Retrieve economic calendar
206
+ client.earnings_calendar # Retrieve earning calendar
207
+ client.ipo_calendar # Retrieve IPO calendar
208
+ client.ico_calendar # Retrieve ICO calendar
209
+ ```
210
+
211
+ ## Websocket
212
+
213
+ Here an example of how to create websocket.
214
+
215
+ ``` ruby
216
+ Thread.new do
217
+ EM.run do
218
+ websocket = client.websocket # Create websocket
219
+ websocket.on :message do |event|
220
+ result = event.data # Result is not parsed
221
+ end
222
+ websocket.on :close do |event|
223
+ result = [:close, event.code, event.reason]
224
+ websocket = nil
225
+ end
226
+ end
227
+ end
228
+
229
+ websocket.subscribe("AAPL") # Subscribe to a stock
230
+ websocket.unsubscribe("AAPL") # Unubscribe to a stock
231
+ ```
232
+
233
+ The symbol under subscribe/unsubscribe can be a string of a stock, a crypto_symbol or a forex_symbol. Or in alternative can be a Finnhub::Stock, Finnhub::Crypto_Symbol, or a Finnhub::Forex_Symbol instance.
234
+
235
+ ## Errors
236
+
237
+ Error from FinnhubRB are returned under Finnhub::Error exception. You can use e.code to retrieve the code returned to a not successful request.
@@ -0,0 +1,15 @@
1
+ module Finnhub
2
+ module Analysis
3
+ def pattern(resolution: "D")
4
+ @client.request("/scan/pattern?symbol=#{@symbol}&resolution=#{resolution}")
5
+ end
6
+
7
+ def support_resistance(resolution: "D")
8
+ @client.request("/scan/support-resistance?symbol=#{@symbol}&resolution=#{resolution}")
9
+ end
10
+
11
+ def technical_indicators(resolution: "D")
12
+ @client.request("/scan/technical-indicator?symbol=#{@symbol}&resolution=#{resolution}")
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ module Finnhub
2
+ module Calendar
3
+ def economic_calendar
4
+ request("/calendar/economic")
5
+ end
6
+
7
+ def earnings_calendar
8
+ request("/calendar/earnings")
9
+ end
10
+
11
+ def ipo_calendar
12
+ request("/calendar/ipo")
13
+ end
14
+
15
+ def ico_calendar
16
+ request("/calendar/ico")
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,106 @@
1
+ module Finnhub
2
+ class Client
3
+ include Calendar
4
+
5
+ BASE_URI = 'https://finnhub.io/api/v1'
6
+
7
+ def initialize(key:, verbose: false)
8
+ @apikey = key
9
+ @verbose = verbose
10
+ end
11
+
12
+ attr_accessor :verbose
13
+ attr_reader :apikey
14
+
15
+ def request(url)
16
+ send_url = "#{BASE_URI}#{url}"
17
+ send_url += send_url.include?("?") ? "&" : "?"
18
+ send_url += "token=#{@apikey}"
19
+
20
+ puts "\nGET #{send_url}\n" if @verbose
21
+ response = HTTParty.get(send_url)
22
+ if @verbose
23
+ puts "\nCODE: #{response.code}\n"
24
+ puts "OUTPUT: #{response.body}\n"
25
+ end
26
+
27
+ if response.code == 200
28
+ data = response.body
29
+ if data[0] == "[" || data[0] == "{"
30
+ data = Oj.load(data, symbol_keys: true)
31
+ return data
32
+ elsif data.include?("\n")
33
+ return data
34
+ else
35
+ raise Finnhub::Error.new message: data, code: response.code
36
+ end
37
+ else
38
+ raise Finnhub::Error.new message: data, code: response.code
39
+ end
40
+
41
+ rescue Finnhub::Error => e
42
+ raise e
43
+ rescue StandardError => e
44
+ raise Finnhub::Error.new message: "Failed request: #{e.message}"
45
+ end
46
+
47
+ def websocket
48
+ Finnhub::Websocket.new(@apikey)
49
+ end
50
+
51
+ def stock(symbol:)
52
+ Finnhub::Stock.new(client: self, symbol: symbol)
53
+ end
54
+
55
+ def forex_exchanges(plain: false)
56
+ output = request("/forex/exchange")
57
+ return output if plain
58
+
59
+ output.map{|o| Finnhub::Forex_Exchange.new(client: self, name: o)}
60
+ end
61
+
62
+ def forex_exchange(name:)
63
+ Finnhub::Forex_Exchange.new(client: self, name: name)
64
+ end
65
+
66
+ def crypto_exchanges(plain: false)
67
+ output = request("/crypto/exchange")
68
+ return output if plain
69
+
70
+ output.map{|o| Finnhub::Crypto_Exchange.new(client: self, name: o)}
71
+ end
72
+
73
+ def crypto_exchange(name:)
74
+ Finnhub::Crypto_Exchange.new(client: self, name: name)
75
+ end
76
+
77
+ def news(category: "general", minId: nil)
78
+ url = "/news?category=#{category}"
79
+ url += "&minId=#{minId}" unless minId.nil?
80
+ request(url)
81
+ end
82
+
83
+ def merge_countries(plain: false)
84
+ output = request("/merger/country")
85
+ return output if plain
86
+
87
+ output.map{|o| Finnhub::Merge_Country.new(client: self, country: o)}
88
+ end
89
+
90
+ def merge_country(country:)
91
+ Finnhub::Merge_Country.new(client: self, country: country)
92
+ end
93
+
94
+ def economic_codes(plain: false)
95
+ output = request("/economic/code")
96
+ return output if plain
97
+
98
+ output.map{|o| Finnhub::Economic_Code.new(client: self, code: o[0], description: o[1])}
99
+ end
100
+
101
+ def economic_code(code:, description: nil)
102
+ Finnhub::Economic_Code.new(client: self, code: code,
103
+ description: description)
104
+ end
105
+ end
106
+ end