finnhubrb 1.0.0
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 +7 -0
- data/FinnhubRB.gemspec +24 -0
- data/Gemfile +12 -0
- data/LICENSE.md +21 -0
- data/README.md +237 -0
- data/lib/Analysis.rb +15 -0
- data/lib/Calendar.rb +19 -0
- data/lib/Client.rb +106 -0
- data/lib/Country.rb +17 -0
- data/lib/Crypto.rb +59 -0
- data/lib/Economic.rb +18 -0
- data/lib/Error.rb +9 -0
- data/lib/Forex.rb +59 -0
- data/lib/Stock.rb +55 -0
- data/lib/Timeseries.rb +55 -0
- data/lib/Websocket.rb +29 -0
- data/lib/finnhubrb.rb +16 -0
- data/spec/1.0.0/crypto.rb +84 -0
- data/spec/1.0.0/forex.rb +84 -0
- data/spec/1.0.0/other.rb +62 -0
- data/spec/1.0.0/stock.rb +112 -0
- data/spec/1.0.0/websocket.rb +48 -0
- data/spec/all.rb +5 -0
- data/spec/config.yml +1 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/test_all.rb +5 -0
- metadata +202 -0
data/lib/Country.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module Finnhub
|
2
|
+
class Merge_Country
|
3
|
+
def initialize(client:, country:)
|
4
|
+
@client = client
|
5
|
+
@country = country
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_reader :country
|
9
|
+
|
10
|
+
def merger(from: nil, to: nil)
|
11
|
+
url = "/merger?country=#{@country}"
|
12
|
+
url += "&from=#{from}" unless from.nil?
|
13
|
+
url += "&to=#{to}" unless to.nil?
|
14
|
+
@client.request(url)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/Crypto.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
module Finnhub
|
2
|
+
class Crypto_Exchange
|
3
|
+
def initialize(client:, name:)
|
4
|
+
@client = client
|
5
|
+
@name = name
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_reader :name
|
9
|
+
|
10
|
+
def symbols(plain: false)
|
11
|
+
output = @client.request("/crypto/symbol?exchange=#{@name}")
|
12
|
+
return output if plain
|
13
|
+
|
14
|
+
output.map do |o|
|
15
|
+
Finnhub::Crypto_Symbol.new(client: @client, exchange: @name, **o)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def symbol(**args)
|
20
|
+
Finnhub::Crypto_Symbol.new(client: @client, exchange: @name, **args)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Crypto_Symbol
|
25
|
+
include Finnhub::Analysis
|
26
|
+
|
27
|
+
def initialize(client:, exchange:, description: nil, hasWM: nil,
|
28
|
+
displaySymbol: nil, symbol: nil)
|
29
|
+
@client = client
|
30
|
+
@exchange = exchange
|
31
|
+
@hashWM = hasWM
|
32
|
+
@displaySymbol = displaySymbol
|
33
|
+
@symbol = symbol
|
34
|
+
end
|
35
|
+
|
36
|
+
attr_reader :client, :exchange, :hashWM, :displaySymbol, :symbol
|
37
|
+
|
38
|
+
def timeseries(**args)
|
39
|
+
Finnhub::Crypto_Timeseries.new(client: @client, symbol: @symbol, **args)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class Crypto_Timeseries < Finnhub::Timeseries
|
44
|
+
def initialize(client:, symbol:, resolution: "D", count: nil,
|
45
|
+
from: nil, to: nil, format: nil)
|
46
|
+
url = "/crypto/candle?symbol=#{symbol}&resolution=#{resolution}"
|
47
|
+
url += "&count=#{count}" unless count.nil?
|
48
|
+
url += "&from=#{from}" unless from.nil?
|
49
|
+
url += "&to=#{to}" unless to.nil?
|
50
|
+
url += "&format=#{format}" unless format.nil?
|
51
|
+
@output = client.request(url)
|
52
|
+
if @output.is_a?(Hash) && @output[:s] == "ok"
|
53
|
+
@timestamps = @output[:t]&.map{|t| DateTime.strptime(t.to_s,'%s')}
|
54
|
+
else
|
55
|
+
@timestamps = []
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/Economic.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
module Finnhub
|
2
|
+
class Economic_Code
|
3
|
+
def initialize(client:, code:, description:)
|
4
|
+
@client = client
|
5
|
+
@code = code
|
6
|
+
@description = description
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :code, :description
|
10
|
+
|
11
|
+
def data(plain: false)
|
12
|
+
output = @client.request("/economic?code=#{@code}")
|
13
|
+
return output if plain
|
14
|
+
|
15
|
+
output.map{|o| [Time.parse(o[0]), o[1]]}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/Error.rb
ADDED
data/lib/Forex.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
module Finnhub
|
2
|
+
class Forex_Exchange
|
3
|
+
def initialize(client:, name:)
|
4
|
+
@client = client
|
5
|
+
@name = name
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_reader :name
|
9
|
+
|
10
|
+
def symbols(plain: false)
|
11
|
+
output = @client.request("/forex/symbol?exchange=#{@name}")
|
12
|
+
return output if plain
|
13
|
+
|
14
|
+
output.map do |o|
|
15
|
+
Finnhub::Forex_Symbol.new(client: @client, exchange: @name, **o)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def symbol(**args)
|
20
|
+
Finnhub::Forex_Symbol.new(client: @client, exchange: @name, **args)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Forex_Symbol
|
25
|
+
include Finnhub::Analysis
|
26
|
+
|
27
|
+
def initialize(client:, exchange: nil, description: nil, hasWM: nil,
|
28
|
+
displaySymbol: nil, symbol:)
|
29
|
+
@client = client
|
30
|
+
@exchange = exchange
|
31
|
+
@hashWM = hasWM
|
32
|
+
@displaySymbol = displaySymbol
|
33
|
+
@symbol = symbol
|
34
|
+
end
|
35
|
+
|
36
|
+
attr_reader :client, :exchange, :hashWM, :displaySymbol, :symbol
|
37
|
+
|
38
|
+
def timeseries(**args)
|
39
|
+
Finnhub::Forex_Timeseries.new(client: @client, symbol: @symbol, **args)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class Forex_Timeseries < Finnhub::Timeseries
|
44
|
+
def initialize(client:, symbol:, resolution: "D", count: nil,
|
45
|
+
from: nil, to: nil, format: nil)
|
46
|
+
url = "/forex/candle?symbol=#{symbol}&resolution=#{resolution}"
|
47
|
+
url += "&count=#{count}" unless count.nil?
|
48
|
+
url += "&from=#{from}" unless from.nil?
|
49
|
+
url += "&to=#{to}" unless to.nil?
|
50
|
+
url += "&format=#{format}" unless format.nil?
|
51
|
+
@output = client.request(url)
|
52
|
+
if @output.is_a?(Hash) && @output[:s] == "ok"
|
53
|
+
@timestamps = @output[:t]&.map{|t| DateTime.strptime(t.to_s,'%s')}
|
54
|
+
else
|
55
|
+
@timestamps = []
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/Stock.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
module Finnhub
|
2
|
+
class Stock
|
3
|
+
include Finnhub::Analysis
|
4
|
+
|
5
|
+
def initialize(client:, symbol:)
|
6
|
+
@client = client
|
7
|
+
@symbol = symbol
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_reader :symbol
|
11
|
+
|
12
|
+
def profile
|
13
|
+
@client.request("/stock/profile?symbol=#{@symbol}")
|
14
|
+
end
|
15
|
+
|
16
|
+
def ceo_compensation
|
17
|
+
@client.request("/stock/ceo-compensation?symbol=#{@symbol}")
|
18
|
+
end
|
19
|
+
|
20
|
+
def recommendation
|
21
|
+
@client.request("/stock/recommendation?symbol=#{@symbol}")
|
22
|
+
end
|
23
|
+
|
24
|
+
def price_target
|
25
|
+
@client.request("/stock/price-target?symbol=#{@symbol}")
|
26
|
+
end
|
27
|
+
|
28
|
+
def option_chain
|
29
|
+
@client.request("/stock/option-chain?symbol=#{@symbol}")
|
30
|
+
end
|
31
|
+
|
32
|
+
def peers(plain: false)
|
33
|
+
output = @client.request("/stock/peers?symbol=#{@symbol}")
|
34
|
+
return output if plain
|
35
|
+
|
36
|
+
output.map{|o| Finnhub::Stock.new(client: @client, symbol: o)}
|
37
|
+
end
|
38
|
+
|
39
|
+
def earnings
|
40
|
+
@client.request("/stock/earnings?symbol=#{@symbol}")
|
41
|
+
end
|
42
|
+
|
43
|
+
def news
|
44
|
+
@client.request("/news/#{@symbol}")
|
45
|
+
end
|
46
|
+
|
47
|
+
def sentiment
|
48
|
+
@client.request("/news-sentiment?symbol=#{@symbol}")
|
49
|
+
end
|
50
|
+
|
51
|
+
def timeseries(**args)
|
52
|
+
Finnhub::Timeseries.new(client: @client, stock: self, **args)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/Timeseries.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
module Finnhub
|
2
|
+
class Timeseries
|
3
|
+
def initialize(client:, stock:, resolution: "D", count: 100,
|
4
|
+
from: nil, to: nil, format: nil)
|
5
|
+
url = "/stock/candle?symbol=#{stock.symbol}&resolution=#{resolution}"
|
6
|
+
url += "&count=#{count}" unless count.nil?
|
7
|
+
from = from.to_i if from.is_a?(Time)
|
8
|
+
url += "&from=#{from}" unless from.nil?
|
9
|
+
to = to.to_i if to.is_a?(Time)
|
10
|
+
url += "&to=#{to}" unless to.nil?
|
11
|
+
url += "&format=#{format}" unless format.nil?
|
12
|
+
@output = client.request(url)
|
13
|
+
if @output.is_a?(Hash) && @output[:s] == "ok"
|
14
|
+
@timestamps = @output[:t]&.map{|t| DateTime.strptime(t.to_s,'%s')}
|
15
|
+
else
|
16
|
+
@timestamps = []
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_reader :output, :timestamps
|
21
|
+
|
22
|
+
def open
|
23
|
+
operation(:o)
|
24
|
+
end
|
25
|
+
|
26
|
+
def high
|
27
|
+
operation(:h)
|
28
|
+
end
|
29
|
+
|
30
|
+
def low
|
31
|
+
operation(:l)
|
32
|
+
end
|
33
|
+
|
34
|
+
def close
|
35
|
+
operation(:c)
|
36
|
+
end
|
37
|
+
|
38
|
+
def volume
|
39
|
+
operation(:v)
|
40
|
+
end
|
41
|
+
|
42
|
+
def status
|
43
|
+
raise Finnhub::Error message: "Output is not a hash" unless @output.is_a?(Hash)
|
44
|
+
@output[:s]
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def operation(type)
|
50
|
+
raise Finnhub::Error message: "Output is not a hash" unless @output.is_a?(Hash)
|
51
|
+
return [] if @output[type].nil?
|
52
|
+
@timestamps.zip(@output[type])
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/Websocket.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
module Finnhub
|
2
|
+
class Websocket < Faye::WebSocket::Client
|
3
|
+
def initialize(apikey)
|
4
|
+
super("wss://ws.finnhub.io?token=#{apikey}")
|
5
|
+
end
|
6
|
+
|
7
|
+
def subscribe(symbol)
|
8
|
+
case symbol
|
9
|
+
when Finnhub::Stock, Finnhub::Crypto_Symbol, Finnhub::Forex_Symbol
|
10
|
+
symbol = symbol.symbol
|
11
|
+
end
|
12
|
+
|
13
|
+
send(Oj.dump(
|
14
|
+
{"type": "subscribe", "symbol": symbol},
|
15
|
+
mode: :json))
|
16
|
+
end
|
17
|
+
|
18
|
+
def unsubscribe(symbol)
|
19
|
+
case symbol
|
20
|
+
when Finnhub::Stock, Finnhub::Crypto_Symbol, Finnhub::Forex_Symbol
|
21
|
+
symbol = symbol.symbol
|
22
|
+
end
|
23
|
+
|
24
|
+
send(Oj.dump(
|
25
|
+
{"type": "unsubscribe", "symbol": symbol},
|
26
|
+
mode: :json))
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/finnhubrb.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require "oj"
|
2
|
+
require "httparty"
|
3
|
+
require "time"
|
4
|
+
require 'em/pure_ruby'
|
5
|
+
require "faye/websocket"
|
6
|
+
require_relative "Analysis"
|
7
|
+
require_relative "Calendar"
|
8
|
+
require_relative "Timeseries"
|
9
|
+
require_relative "Client"
|
10
|
+
require_relative "Country"
|
11
|
+
require_relative "Crypto"
|
12
|
+
require_relative "Economic"
|
13
|
+
require_relative "Error"
|
14
|
+
require_relative "Forex"
|
15
|
+
require_relative "Stock"
|
16
|
+
require_relative "Websocket"
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
describe "1.0.0" do
|
4
|
+
context "Crypto" do
|
5
|
+
it "create a new client" do
|
6
|
+
@store[:client] = Finnhub::Client.new(key: @key, verbose: true)
|
7
|
+
expect(@store[:client].class).to be Finnhub::Client
|
8
|
+
end
|
9
|
+
|
10
|
+
it "can retrieve multiple crypto_exchanges" do
|
11
|
+
crypto_exchanges = @store[:client].crypto_exchanges(plain: true)
|
12
|
+
expect(crypto_exchanges.class).to be Array
|
13
|
+
|
14
|
+
@store[:crypto_exchange_name] = crypto_exchanges[0]
|
15
|
+
|
16
|
+
crypto_exchanges = @store[:client].crypto_exchanges
|
17
|
+
expect(crypto_exchanges.class).to be Array
|
18
|
+
expect(crypto_exchanges[0].class).to be Finnhub::Crypto_Exchange
|
19
|
+
end
|
20
|
+
|
21
|
+
it "can create a crypto_exchange instance" do
|
22
|
+
@store[:crypto_exchange] = @store[:client].crypto_exchange(name: @store[:crypto_exchange_name])
|
23
|
+
expect(@store[:crypto_exchange].class).to be Finnhub::Crypto_Exchange
|
24
|
+
end
|
25
|
+
|
26
|
+
it "can retrieve multiple symbols" do
|
27
|
+
crypto_symbols = @store[:crypto_exchange].symbols(plain: true)
|
28
|
+
expect(crypto_symbols.class).to be Array
|
29
|
+
|
30
|
+
@store[:crypto_exchange_symbol] = crypto_symbols[0][:symbol]
|
31
|
+
|
32
|
+
crypto_symbols = @store[:crypto_exchange].symbols
|
33
|
+
expect(crypto_symbols.class).to be Array
|
34
|
+
expect(crypto_symbols[0].class).to be Finnhub::Crypto_Symbol
|
35
|
+
end
|
36
|
+
|
37
|
+
it "create a new crypto_symbol" do
|
38
|
+
@store[:crypto_symbol] = @store[:crypto_exchange].symbol(symbol: @store[:crypto_exchange_symbol])
|
39
|
+
expect(@store[:crypto_symbol].class).to be Finnhub::Crypto_Symbol
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
it "can retrieve timeseries" do
|
44
|
+
timeseries = @store[:crypto_symbol].timeseries(count: 100)
|
45
|
+
expect(timeseries.open.class).to be Array
|
46
|
+
expect(timeseries.high.class).to be Array
|
47
|
+
expect(timeseries.low.class).to be Array
|
48
|
+
expect(timeseries.close.class).to be Array
|
49
|
+
expect(timeseries.volume.class).to be Array
|
50
|
+
expect(timeseries.status).to eq "ok"
|
51
|
+
expect(timeseries.output.class).to be Hash
|
52
|
+
|
53
|
+
timeseries = @store[:crypto_symbol].timeseries(resolution: 60, from: Time.now-24*30*3600, to: Time.now)
|
54
|
+
expect(timeseries.open.class).to be Array
|
55
|
+
expect(timeseries.status).to eq "ok"
|
56
|
+
|
57
|
+
timeseries = @store[:crypto_symbol].timeseries(resolution: 60, from: Time.now-24*30*3600, to: Time.now, format: "csv")
|
58
|
+
expect(timeseries.output.class).to be String
|
59
|
+
|
60
|
+
error = nil
|
61
|
+
begin
|
62
|
+
@store[:crypto_symbol].timeseries(resolution: 60, from: Time.now-24*30*3600, to: Time.now, format: "wrong")
|
63
|
+
rescue Finnhub::Error => e
|
64
|
+
error = e
|
65
|
+
end
|
66
|
+
expect(error.class).to be Finnhub::Error
|
67
|
+
end
|
68
|
+
|
69
|
+
it "can retrieve pattern" do
|
70
|
+
output = @store[:crypto_symbol].pattern
|
71
|
+
expect(output[:points][0].key?(:symbol)).to eq true
|
72
|
+
end
|
73
|
+
|
74
|
+
it "can retrieve support_resistance" do
|
75
|
+
output = @store[:crypto_symbol].support_resistance
|
76
|
+
expect(output.key?(:levels)).to be true
|
77
|
+
end
|
78
|
+
|
79
|
+
it "can retrieve technical_indicators" do
|
80
|
+
output = @store[:crypto_symbol].technical_indicators
|
81
|
+
expect(output.key?(:technicalAnalysis)).to be true
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/spec/1.0.0/forex.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
describe "1.0.0" do
|
4
|
+
context "Forex" do
|
5
|
+
it "create a new client" do
|
6
|
+
@store[:client] = Finnhub::Client.new(key: @key, verbose: true)
|
7
|
+
expect(@store[:client].class).to be Finnhub::Client
|
8
|
+
end
|
9
|
+
|
10
|
+
it "can retrieve multiple forex_exchanges" do
|
11
|
+
forex_exchanges = @store[:client].forex_exchanges(plain: true)
|
12
|
+
expect(forex_exchanges.class).to be Array
|
13
|
+
|
14
|
+
@store[:forex_exchange_name] = forex_exchanges[0]
|
15
|
+
|
16
|
+
forex_exchanges = @store[:client].forex_exchanges
|
17
|
+
expect(forex_exchanges.class).to be Array
|
18
|
+
expect(forex_exchanges[0].class).to be Finnhub::Forex_Exchange
|
19
|
+
end
|
20
|
+
|
21
|
+
it "can create a forex_exchange instance" do
|
22
|
+
@store[:forex_exchange] = @store[:client].forex_exchange(name: @store[:forex_exchange_name])
|
23
|
+
expect(@store[:forex_exchange].class).to be Finnhub::Forex_Exchange
|
24
|
+
end
|
25
|
+
|
26
|
+
it "can retrieve multiple symbols" do
|
27
|
+
forex_symbols = @store[:forex_exchange].symbols(plain: true)
|
28
|
+
expect(forex_symbols.class).to be Array
|
29
|
+
|
30
|
+
@store[:forex_exchange_symbol] = forex_symbols[0][:symbol]
|
31
|
+
|
32
|
+
forex_exchanges = @store[:forex_exchange].symbols
|
33
|
+
expect(forex_exchanges.class).to be Array
|
34
|
+
expect(forex_exchanges[0].class).to be Finnhub::Forex_Symbol
|
35
|
+
end
|
36
|
+
|
37
|
+
it "create a new forex_symbol" do
|
38
|
+
@store[:forex_symbol] = @store[:forex_exchange].symbol(symbol: @store[:forex_exchange_symbol])
|
39
|
+
expect(@store[:forex_symbol].class).to be Finnhub::Forex_Symbol
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
it "can retrieve timeseries" do
|
44
|
+
timeseries = @store[:forex_symbol].timeseries(count: 100)
|
45
|
+
expect(timeseries.open.class).to be Array
|
46
|
+
expect(timeseries.high.class).to be Array
|
47
|
+
expect(timeseries.low.class).to be Array
|
48
|
+
expect(timeseries.close.class).to be Array
|
49
|
+
expect(timeseries.volume.class).to be Array
|
50
|
+
expect(timeseries.status).to eq "ok"
|
51
|
+
expect(timeseries.output.class).to be Hash
|
52
|
+
|
53
|
+
timeseries = @store[:forex_symbol].timeseries(resolution: 60, from: Time.now-24*30*3600, to: Time.now)
|
54
|
+
expect(timeseries.open.class).to be Array
|
55
|
+
expect(["ok", "no_data"]).to include timeseries.status
|
56
|
+
|
57
|
+
timeseries = @store[:forex_symbol].timeseries(resolution: 60, from: Time.now-24*30*3600, to: Time.now, format: "csv")
|
58
|
+
expect(timeseries.output.class).to be String
|
59
|
+
|
60
|
+
error = nil
|
61
|
+
begin
|
62
|
+
@store[:forex_symbol].timeseries(resolution: 60, from: Time.now-24*30*3600, to: Time.now, format: "wrong")
|
63
|
+
rescue Finnhub::Error => e
|
64
|
+
error = e
|
65
|
+
end
|
66
|
+
expect(error.class).to be Finnhub::Error
|
67
|
+
end
|
68
|
+
|
69
|
+
it "can retrieve pattern" do
|
70
|
+
output = @store[:forex_symbol].pattern
|
71
|
+
expect(output[:points][0].key?(:symbol)).to eq true
|
72
|
+
end
|
73
|
+
|
74
|
+
it "can retrieve support_resistance" do
|
75
|
+
output = @store[:forex_symbol].support_resistance
|
76
|
+
expect(output.key?(:levels)).to be true
|
77
|
+
end
|
78
|
+
|
79
|
+
it "can retrieve technical_indicators" do
|
80
|
+
output = @store[:forex_symbol].technical_indicators
|
81
|
+
expect(output.key?(:technicalAnalysis)).to be true
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|