eodhd.rb 0.17.0 → 0.18.1

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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +101 -0
  3. data/README.md +86 -14
  4. data/Rakefile +28 -0
  5. data/eodhd.rb.gemspec +30 -15
  6. data/lib/Eodhd/Client.rb +7 -0
  7. data/lib/Eodhd/EodBulkLastDay.rb +2 -0
  8. data/lib/Eodhd/EodData.rb +2 -0
  9. data/lib/Eodhd/Exchange.rb +2 -0
  10. data/lib/Eodhd/ExchangeSymbol.rb +2 -0
  11. data/lib/Eodhd/Fundamentals/AnalystRatings.rb +29 -0
  12. data/lib/Eodhd/Fundamentals/ESGScores.rb +37 -0
  13. data/lib/Eodhd/Fundamentals/Earnings.rb +21 -0
  14. data/lib/Eodhd/Fundamentals/Financials/Statement.rb +21 -0
  15. data/lib/Eodhd/Fundamentals/Financials.rb +23 -0
  16. data/lib/Eodhd/Fundamentals/General.rb +85 -0
  17. data/lib/Eodhd/Fundamentals/Highlights.rb +63 -0
  18. data/lib/Eodhd/Fundamentals/Holders.rb +19 -0
  19. data/lib/Eodhd/Fundamentals/SharesStats.rb +33 -0
  20. data/lib/Eodhd/Fundamentals/SplitsDividends.rb +31 -0
  21. data/lib/Eodhd/Fundamentals/Technicals.rb +33 -0
  22. data/lib/Eodhd/Fundamentals/Valuation.rb +29 -0
  23. data/lib/Eodhd/Fundamentals.rb +85 -0
  24. data/lib/Eodhd/VERSION.rb +1 -1
  25. data/lib/Thoran/Hash/XWwwFormUrlencode/x_www_form_urlencode.rb +14 -13
  26. data/lib/Thoran/String/Urlencode/urlencode.rb +29 -0
  27. data/lib/{Eodhd.rb → eodhd.rb} +27 -17
  28. data/test/{client_test.rb → Eodhd/Client_test.rb} +38 -14
  29. data/test/Eodhd/Fundamentals_test.rb +78 -0
  30. data/test/{validations_test.rb → Eodhd/Validations_test.rb} +4 -2
  31. data/test/{web_socket_client_test.rb → Eodhd/WebSocketClient_test.rb} +9 -7
  32. data/test/{eodhd_test.rb → Eodhd_test.rb} +12 -1
  33. data/test/helper.rb +3 -0
  34. metadata +41 -12
  35. data/lib/Thoran/String/UrlEncode/url_encode.rb +0 -26
  36. data/test/test_all.rb +0 -5
@@ -0,0 +1,19 @@
1
+ # Eodhd/Fundamentals/Holders.rb
2
+ # Eodhd::Fundamentals::Holders
3
+
4
+ class Eodhd
5
+ class Fundamentals
6
+ class Holders
7
+ attr_reader\
8
+ :institutions,
9
+ :funds
10
+
11
+ private
12
+
13
+ def initialize(data)
14
+ @institutions = data['Institutions']
15
+ @funds = data['Funds']
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,33 @@
1
+ # Eodhd/Fundamentals/SharesStats.rb
2
+ # Eodhd::Fundamentals::SharesStats
3
+
4
+ class Eodhd
5
+ class Fundamentals
6
+ class SharesStats
7
+ attr_reader\
8
+ :shares_outstanding,
9
+ :shares_float,
10
+ :percent_insiders,
11
+ :percent_institutions,
12
+ :shares_short,
13
+ :shares_short_prior_month,
14
+ :short_ratio,
15
+ :short_percent_outstanding,
16
+ :short_percent_float
17
+
18
+ private
19
+
20
+ def initialize(data)
21
+ @shares_outstanding = data['SharesOutstanding']
22
+ @shares_float = data['SharesFloat']
23
+ @percent_insiders = data['PercentInsiders']
24
+ @percent_institutions = data['PercentInstitutions']
25
+ @shares_short = data['SharesShort']
26
+ @shares_short_prior_month = data['SharesShortPriorMonth']
27
+ @short_ratio = data['ShortRatio']
28
+ @short_percent_outstanding = data['ShortPercentOutstanding']
29
+ @short_percent_float = data['ShortPercentFloat']
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,31 @@
1
+ # Eodhd/Fundamentals/SplitsDividends.rb
2
+ # Eodhd::Fundamentals::SplitsDividends
3
+
4
+ class Eodhd
5
+ class Fundamentals
6
+ class SplitsDividends
7
+ attr_reader\
8
+ :forward_annual_dividend_rate,
9
+ :forward_annual_dividend_yield,
10
+ :payout_ratio,
11
+ :dividend_date,
12
+ :ex_dividend_date,
13
+ :last_split_factor,
14
+ :last_split_date,
15
+ :number_dividends_by_year
16
+
17
+ private
18
+
19
+ def initialize(data)
20
+ @forward_annual_dividend_rate = data['ForwardAnnualDividendRate']
21
+ @forward_annual_dividend_yield = data['ForwardAnnualDividendYield']
22
+ @payout_ratio = data['PayoutRatio']
23
+ @dividend_date = data['DividendDate']
24
+ @ex_dividend_date = data['ExDividendDate']
25
+ @last_split_factor = data['LastSplitFactor']
26
+ @last_split_date = data['LastSplitDate']
27
+ @number_dividends_by_year = data['NumberDividendsByYear']
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,33 @@
1
+ # Eodhd/Fundamentals/Technicals.rb
2
+ # Eodhd::Fundamentals::Technicals
3
+
4
+ class Eodhd
5
+ class Fundamentals
6
+ class Technicals
7
+ attr_reader\
8
+ :beta,
9
+ :fifty_two_week_high,
10
+ :fifty_two_week_low,
11
+ :fifty_day_ma,
12
+ :two_hundred_day_ma,
13
+ :shares_short,
14
+ :shares_short_prior_month,
15
+ :short_ratio,
16
+ :short_percent
17
+
18
+ private
19
+
20
+ def initialize(data)
21
+ @beta = data['Beta']
22
+ @fifty_two_week_high = data['52WeekHigh']
23
+ @fifty_two_week_low = data['52WeekLow']
24
+ @fifty_day_ma = data['50DayMA']
25
+ @two_hundred_day_ma = data['200DayMA']
26
+ @shares_short = data['SharesShort']
27
+ @shares_short_prior_month = data['SharesShortPriorMonth']
28
+ @short_ratio = data['ShortRatio']
29
+ @short_percent = data['ShortPercent']
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,29 @@
1
+ # Eodhd/Fundamentals/Valuation.rb
2
+ # Eodhd::Fundamentals::Valuation
3
+
4
+ class Eodhd
5
+ class Fundamentals
6
+ class Valuation
7
+ attr_reader\
8
+ :trailing_pe,
9
+ :forward_pe,
10
+ :price_sales_ttm,
11
+ :price_book_mrq,
12
+ :enterprise_value,
13
+ :enterprise_value_revenue,
14
+ :enterprise_value_ebitda
15
+
16
+ private
17
+
18
+ def initialize(data)
19
+ @trailing_pe = data['TrailingPE']
20
+ @forward_pe = data['ForwardPE']
21
+ @price_sales_ttm = data['PriceSalesTTM']
22
+ @price_book_mrq = data['PriceBookMRQ']
23
+ @enterprise_value = data['EnterpriseValue']
24
+ @enterprise_value_revenue = data['EnterpriseValueRevenue']
25
+ @enterprise_value_ebitda = data['EnterpriseValueEbitda']
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,85 @@
1
+ # Eodhd/Fundamentals.rb
2
+ # Eodhd::Fundamentals
3
+
4
+ require_relative './Fundamentals/AnalystRatings'
5
+ require_relative './Fundamentals/Earnings'
6
+ require_relative './Fundamentals/ESGScores'
7
+ require_relative './Fundamentals/Financials'
8
+ require_relative './Fundamentals/General'
9
+ require_relative './Fundamentals/Highlights'
10
+ require_relative './Fundamentals/Holders'
11
+ require_relative './Fundamentals/SharesStats'
12
+ require_relative './Fundamentals/SplitsDividends'
13
+ require_relative './Fundamentals/Technicals'
14
+ require_relative './Fundamentals/Valuation'
15
+
16
+ class Eodhd
17
+ class Fundamentals
18
+ class << self
19
+ def all(client: nil, api_token: nil, exchange_code:, symbol:, filter: nil)
20
+ load(client: client, api_token: api_token, exchange_code: exchange_code, symbol: symbol, filter: filter)
21
+ end
22
+
23
+ private
24
+
25
+ def load(client: nil, api_token: nil, exchange_code:, symbol:, filter:)
26
+ client ||= Client.new(api_token: api_token)
27
+ response = client.fundamentals(exchange_code: exchange_code, symbol: symbol, filter: filter)
28
+ self.new(
29
+ exchange_code: exchange_code,
30
+ symbol: symbol,
31
+ general: response['General'],
32
+ highlights: response['Highlights'],
33
+ valuation: response['Valuation'],
34
+ shares_stats: response['SharesStats'],
35
+ technicals: response['Technicals'],
36
+ splits_dividends: response['SplitsDividends'],
37
+ analyst_ratings: response['AnalystRatings'],
38
+ holders: response['Holders'],
39
+ insider_transactions: response['InsiderTransactions'],
40
+ esg_scores: response['ESGScores'],
41
+ outstanding_shares: response['outstandingShares'],
42
+ earnings: response['Earnings'],
43
+ financials: response['Financials']
44
+ )
45
+ end
46
+ end # class << self
47
+
48
+ attr_reader\
49
+ :exchange_code,
50
+ :symbol,
51
+ :general,
52
+ :highlights,
53
+ :valuation,
54
+ :shares_stats,
55
+ :technicals,
56
+ :splits_dividends,
57
+ :analyst_ratings,
58
+ :holders,
59
+ :insider_transactions,
60
+ :esg_scores,
61
+ :outstanding_shares,
62
+ :earnings,
63
+ :financials
64
+
65
+ private
66
+
67
+ def initialize(exchange_code:, symbol:, general:, highlights:, valuation:, shares_stats:, technicals:, splits_dividends:, analyst_ratings:, holders:, insider_transactions:, esg_scores:, outstanding_shares:, earnings:, financials:)
68
+ @exchange_code = exchange_code
69
+ @symbol = symbol
70
+ @general = General.new(general) if general
71
+ @highlights = Highlights.new(highlights) if highlights
72
+ @valuation = Valuation.new(valuation) if valuation
73
+ @shares_stats = SharesStats.new(shares_stats) if shares_stats
74
+ @technicals = Technicals.new(technicals) if technicals
75
+ @splits_dividends = SplitsDividends.new(splits_dividends) if splits_dividends
76
+ @analyst_ratings = AnalystRatings.new(analyst_ratings) if analyst_ratings
77
+ @holders = Holders.new(holders) if holders
78
+ @insider_transactions = insider_transactions
79
+ @esg_scores = ESGScores.new(esg_scores) if esg_scores
80
+ @outstanding_shares = outstanding_shares
81
+ @earnings = Earnings.new(earnings) if earnings
82
+ @financials = Financials.new(financials) if financials
83
+ end
84
+ end
85
+ end
data/lib/Eodhd/VERSION.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class Eodhd
2
- VERSION = '0.17.0'
2
+ VERSION = '0.18.1'
3
3
  end
@@ -1,26 +1,27 @@
1
- # Thoran/Hash/XWwwFormUrlEncode/x_www_form_urlencode.rb
2
- # Thoran::Hash::XWwwFormUrlEncode#x_www_form_urlencode
1
+ # Thoran/Hash/XWwwFormUrlencode/x_www_form_urlencode.rb
2
+ # Thoran::Hash::XWwwFormUrlencode#x_www_form_urlencode
3
3
 
4
- # 20241009
5
- # 0.2.0
4
+ # 20260713
5
+ # 0.3.0
6
6
 
7
- # Changes since 0.1:
8
- # -/0: (The class name and the snake case name are consistent now.)
9
- # 1. /XWWWFormUrlEncode/XWwwFormUrlEncode/
7
+ # Changes since 0.2:
8
+ # -/0: (The class name and the snake case name really are consistent now.)
9
+ # 1. /XWwwFormUrlEncode/XWwwFormUrlencode/
10
+ # 2. /url_encode/urlencode/
10
11
 
11
- require 'Thoran/String/UrlEncode/url_encode'
12
+ require 'Thoran/String/Urlencode/urlencode'
12
13
 
13
14
  module Thoran
14
15
  module Hash
15
- module XWwwFormUrlEncode
16
+ module XWwwFormUrlencode
16
17
 
17
- def x_www_form_url_encode(joiner = '&')
18
- inject([]){|a,e| a << "#{e.first.to_s.url_encode}=#{e.last.to_s.url_encode}" unless e.last.nil?; a}.join(joiner)
18
+ def x_www_form_urlencode(joiner = '&')
19
+ inject([]){|a,e| a << "#{e.first.to_s.urlencode}=#{e.last.to_s.urlencode}" unless e.last.nil?; a}.join(joiner)
19
20
  end
20
- alias_method :x_www_form_urlencode, :x_www_form_url_encode
21
+ alias_method :x_www_form_url_encode, :x_www_form_urlencode
21
22
 
22
23
  end
23
24
  end
24
25
  end
25
26
 
26
- Hash.send(:include, Thoran::Hash::XWwwFormUrlEncode)
27
+ Hash.send(:include, Thoran::Hash::XWwwFormUrlencode)
@@ -0,0 +1,29 @@
1
+ # Thoran/String/Urlencode/urlencode.rb
2
+ # Thoran::String::Urlencode#urlencode
3
+
4
+ # 20260713
5
+ # 0.4.0
6
+
7
+ # Acknowledgements: I've simply ripped off and refashioned the code from the CGI module!...
8
+
9
+ # Changes since 0.3:
10
+ # -/0: More consistent naming.
11
+ # 1. /UrlEncode/Urlencode/
12
+ # 2. /url_encode/urlencode/
13
+
14
+ module Thoran
15
+ module String
16
+ module Urlencode
17
+
18
+ def urlencode
19
+ self.gsub(/([^ a-zA-Z0-9_.-]+)/n) do
20
+ '%' + $1.unpack('H2' * $1.size).join('%').upcase
21
+ end.tr(' ', '+')
22
+ end
23
+ alias_method :url_encode, :urlencode
24
+
25
+ end
26
+ end
27
+ end
28
+
29
+ String.send(:include, Thoran::String::Urlencode)
@@ -7,45 +7,40 @@ require_relative './Eodhd/EodData'
7
7
  require_relative './Eodhd/Exchange'
8
8
  require_relative './Eodhd/ExchangeSymbol'
9
9
  require_relative './Eodhd/Intraday'
10
+ require_relative './Eodhd/Fundamentals'
10
11
  require_relative './Eodhd/WebSocketClient'
11
12
 
12
13
  class Eodhd
13
- def initialize(api_token:, consumer: nil)
14
- @api_token = api_token
15
- @consumer = consumer
16
- end
17
-
18
14
  def exchanges
19
15
  Eodhd::Exchange.all(api_token: @api_token)
20
16
  end
21
17
 
22
18
  def exchange_symbols(exchange: nil, exchange_code: nil)
23
- exchange_code ||= exchange.code
19
+ exchange_code ||= exchange&.code
24
20
  Eodhd::ExchangeSymbol.all(api_token: @api_token, exchange_code: exchange_code)
25
21
  end
26
22
 
27
23
  def eod_data(exchange: nil, exchange_code: nil, exchange_symbol: nil, symbol: nil, period: nil, from: nil, to: nil)
28
- exchange_code ||= exchange.code
29
- symbol ||= exchange_symbol.code
24
+ exchange_code ||= exchange&.code
25
+ symbol ||= exchange_symbol&.code
30
26
  Eodhd::EodData.all(api_token: @api_token, exchange_code: exchange_code, symbol: symbol, period: period, from: from, to: to)
31
27
  end
32
28
 
33
29
  def eod_bulk_last_day(exchange: nil, exchange_code: nil, date:)
34
- exchange_code ||= exchange.code
30
+ exchange_code ||= exchange&.code
35
31
  Eodhd::EodBulkLastDay.all(api_token: @api_token, exchange_code: exchange_code, date: date)
36
32
  end
37
33
 
38
- def intraday(exchange: nil, exchange_code: nil, symbol:, interval:, from: nil, to: nil)
39
- exchange_code ||= exchange&.code || 'US'
34
+ def intraday(exchange: nil, exchange_code: nil, exchange_symbol: nil, symbol: nil, interval:, from: nil, to: nil)
35
+ exchange_code ||= exchange&.code
36
+ symbol ||= exchange_symbol&.code
40
37
  Eodhd::Intraday.all(api_token: @api_token, exchange_code: exchange_code, symbol: symbol, interval: interval, from: from, to: to)
41
38
  end
42
39
 
43
- def web_socket(asset_class:, symbols:)
44
- Eodhd::WebSocketClient.new(api_token: @api_token, asset_class: asset_class, symbols: symbols, consumer: @consumer)
45
- end
46
-
47
- def stream(asset_class:, symbols:)
48
- web_socket(asset_class: asset_class, symbols: symbols).run
40
+ def fundamentals(exchange: nil, exchange_code: nil, exchange_symbol: nil, symbol: nil, filter: nil)
41
+ exchange_code ||= exchange&.code
42
+ symbol ||= exchange_symbol&.code
43
+ Eodhd::Fundamentals.all(api_token: @api_token, exchange_code: exchange_code, symbol: symbol, filter: filter)
49
44
  end
50
45
 
51
46
  def us_trade_stream(symbols)
@@ -64,4 +59,19 @@ class Eodhd
64
59
  def crypto_stream(symbols)
65
60
  stream(asset_class: 'crypto', symbols: symbols)
66
61
  end
62
+
63
+ private
64
+
65
+ def initialize(api_token:, consumer: nil)
66
+ @api_token = api_token
67
+ @consumer = consumer
68
+ end
69
+
70
+ def web_socket(asset_class:, symbols:)
71
+ Eodhd::WebSocketClient.new(api_token: @api_token, asset_class: asset_class, symbols: symbols, consumer: @consumer)
72
+ end
73
+
74
+ def stream(asset_class:, symbols:)
75
+ web_socket(asset_class: asset_class, symbols: symbols).run
76
+ end
67
77
  end
@@ -1,12 +1,13 @@
1
- require_relative "helper"
1
+ # Eodhd/Client_test.rb
2
+
3
+ require_relative '../helper'
2
4
 
3
5
  describe Eodhd::Client do
4
6
  let(:api_token){ENV.fetch('EODHD_API_TOKEN', '<API_TOKEN>')}
5
-
6
7
  let(:client){Eodhd::Client.new(api_token: api_token)}
7
8
 
8
9
  describe "#exchanges_list" do
9
- it "exchanges_list returns parsed JSON array" do
10
+ it "returns parsed JSON array" do
10
11
  VCR.use_cassette("client_exchanges_list") do
11
12
  result = client.exchanges_list
12
13
  _(result).must_be_kind_of(Array)
@@ -22,7 +23,7 @@ describe Eodhd::Client do
22
23
  end
23
24
 
24
25
  describe "#exchange_symbol_list" do
25
- it "exchange_symbol_list returns parsed JSON array" do
26
+ it "returns parsed JSON array" do
26
27
  VCR.use_cassette("client_exchange_symbol_list") do
27
28
  result = client.exchange_symbol_list(exchange_code: 'AU')
28
29
  _(result).must_be_kind_of(Array)
@@ -38,7 +39,7 @@ describe Eodhd::Client do
38
39
  end
39
40
 
40
41
  describe "#eod_data" do
41
- it "eod_data returns parsed JSON array" do
42
+ it "returns parsed JSON array" do
42
43
  VCR.use_cassette('client_eod_data') do
43
44
  result = client.eod_data(exchange_id: 'AU', symbol: 'BHP', period: 'd')
44
45
  _(result).must_be_kind_of(Array)
@@ -53,8 +54,24 @@ describe Eodhd::Client do
53
54
  end
54
55
  end
55
56
 
57
+ describe "#eod_bulk_last_day" do
58
+ it "returns parsed JSON array" do
59
+ VCR.use_cassette("client_eod_bulk_last_day") do
60
+ result = client.eod_bulk_last_day(exchange_id: 'AU', date: "2024-09-30")
61
+ _(result).must_be_kind_of(Array)
62
+ _(result.first.keys).must_equal(%w{code exchange_short_name date open high low close adjusted_close volume})
63
+ end
64
+ end
65
+
66
+ it "raises Eodhd::Error on failure" do
67
+ VCR.use_cassette('client_eod_bulk_last_day_401_error') do
68
+ _{client.eod_bulk_last_day(exchange_id: 'AU', date: "2024-09-30")}.must_raise(Eodhd::Error)
69
+ end
70
+ end
71
+ end
72
+
56
73
  describe "#intraday" do
57
- it "intraday returns parsed JSON array" do
74
+ it "returns parsed JSON array" do
58
75
  VCR.use_cassette('client_intraday') do
59
76
  result = client.intraday(exchange_code: 'US', symbol: 'AAPL', interval: '5m')
60
77
  _(result).must_be_kind_of(Array)
@@ -69,18 +86,25 @@ describe Eodhd::Client do
69
86
  end
70
87
  end
71
88
 
72
- describe "#eod_bulk_last_day" do
73
- it "eod_bulk_last_day returns parsed JSON array" do
74
- VCR.use_cassette("client_eod_bulk_last_day") do
75
- result = client.eod_bulk_last_day(exchange_id: 'AU', date: "2024-09-30")
76
- _(result).must_be_kind_of(Array)
77
- _(result.first.keys).must_equal(%w{code exchange_short_name date open high low close adjusted_close volume})
89
+ describe "#fundamentals" do
90
+ it "returns parsed JSON hash" do
91
+ VCR.use_cassette('client_fundamentals') do
92
+ result = client.fundamentals(exchange_code: 'US', symbol: 'AAPL')
93
+ _(result).must_be_kind_of(Hash)
94
+ _(result['General']).wont_be_nil
95
+ end
96
+ end
97
+
98
+ it "supports filter parameter" do
99
+ VCR.use_cassette('client_fundamentals_filtered') do
100
+ result = client.fundamentals(exchange_code: 'US', symbol: 'AAPL', filter: 'General')
101
+ _(result).must_be_kind_of(Hash)
78
102
  end
79
103
  end
80
104
 
81
105
  it "raises Eodhd::Error on failure" do
82
- VCR.use_cassette('client_eod_bulk_last_day_401_error') do
83
- _{client.eod_bulk_last_day(exchange_id: 'AU', date: "2024-09-30")}.must_raise(Eodhd::Error)
106
+ VCR.use_cassette('client_fundamentals_401_error') do
107
+ _{client.fundamentals(exchange_code: 'US', symbol: 'AAPL')}.must_raise(Eodhd::Error)
84
108
  end
85
109
  end
86
110
  end
@@ -0,0 +1,78 @@
1
+ # Eodhd/Fundamentals_test.rb
2
+
3
+ require_relative '../helper'
4
+
5
+ describe Eodhd::Fundamentals do
6
+ let(:api_token){ENV.fetch('EODHD_API_TOKEN', '<API_TOKEN>')}
7
+ let(:fd){Eodhd::Fundamentals.all(api_token: api_token, exchange_code: 'US', symbol: 'AAPL')}
8
+
9
+ describe ".all" do
10
+ it "returns an Eodhd::Fundamentals object" do
11
+ VCR.use_cassette('fundamentals_aapl') do
12
+ _(fd).must_be_kind_of(Eodhd::Fundamentals)
13
+ end
14
+ end
15
+
16
+ it "stores exchange_code and symbol" do
17
+ VCR.use_cassette('fundamentals_aapl') do
18
+ _(fd.exchange_code).must_equal('US')
19
+ _(fd.symbol).must_equal('AAPL')
20
+ end
21
+ end
22
+
23
+ it "returns General as an Eodhd::Fundamentals::General" do
24
+ VCR.use_cassette('fundamentals_aapl') do
25
+ _(fd.general).must_be_kind_of(Eodhd::Fundamentals::General)
26
+ _(fd.general.code).must_equal('AAPL')
27
+ _(fd.general.name).wont_be_nil
28
+ end
29
+ end
30
+
31
+ it "returns Highlights as an Eodhd::Fundamentals::Highlights" do
32
+ VCR.use_cassette('fundamentals_aapl') do
33
+ _(fd.highlights).must_be_kind_of(Eodhd::Fundamentals::Highlights)
34
+ _(fd.highlights.market_capitalization).wont_be_nil
35
+ end
36
+ end
37
+
38
+ it "returns Valuation as an Eodhd::Fundamentals::Valuation" do
39
+ VCR.use_cassette('fundamentals_aapl') do
40
+ _(fd.valuation).must_be_kind_of(Eodhd::Fundamentals::Valuation)
41
+ end
42
+ end
43
+
44
+ it "returns Financials as an Eodhd::Fundamentals::Financials" do
45
+ VCR.use_cassette('fundamentals_aapl') do
46
+ _(fd.financials).must_be_kind_of(Eodhd::Fundamentals::Financials)
47
+ end
48
+ end
49
+
50
+ it "returns Financials with income_statement, balance_sheet, and cash_flow" do
51
+ VCR.use_cassette('fundamentals_aapl') do
52
+ _(fd.financials.income_statement).must_be_kind_of(Eodhd::Fundamentals::Financials::Statement)
53
+ _(fd.financials.balance_sheet).must_be_kind_of(Eodhd::Fundamentals::Financials::Statement)
54
+ _(fd.financials.cash_flow).must_be_kind_of(Eodhd::Fundamentals::Financials::Statement)
55
+ end
56
+ end
57
+
58
+ it "returns quarterly and yearly data as hashes on financial statements" do
59
+ VCR.use_cassette('fundamentals_aapl') do
60
+ _(fd.financials.income_statement.quarterly).must_be_kind_of(Hash)
61
+ _(fd.financials.income_statement.yearly).must_be_kind_of(Hash)
62
+ end
63
+ end
64
+
65
+ it "returns Earnings as an Eodhd::Fundamentals::Earnings" do
66
+ VCR.use_cassette('fundamentals_aapl') do
67
+ _(fd.earnings).must_be_kind_of(Eodhd::Fundamentals::Earnings)
68
+ end
69
+ end
70
+
71
+ it "returns SharesStats as an Eodhd::Fundamentals::SharesStats" do
72
+ VCR.use_cassette('fundamentals_aapl') do
73
+ _(fd.shares_stats).must_be_kind_of(Eodhd::Fundamentals::SharesStats)
74
+ _(fd.shares_stats.shares_outstanding).wont_be_nil
75
+ end
76
+ end
77
+ end
78
+ end
@@ -1,10 +1,12 @@
1
- require_relative 'helper'
1
+ # Eodhd/Validations_test.rb
2
+
3
+ require_relative '../helper'
2
4
 
3
5
  class DummyIncludingValidations
4
6
  include Eodhd::Validations
5
7
  end
6
8
 
7
- describe "Eodhd::Validations" do
9
+ describe Eodhd::Validations do
8
10
  let(:v){DummyIncludingValidations.new}
9
11
 
10
12
  describe "#validate_arguments" do
@@ -1,4 +1,6 @@
1
- require_relative 'helper'
1
+ # Eodhd/WebSocketClient_test.rb
2
+
3
+ require_relative '../helper'
2
4
 
3
5
  describe Eodhd::WebSocketClient do
4
6
  let(:api_token){ENV.fetch('EODHD_API_TOKEN', '<API_TOKEN>')}
@@ -53,10 +55,10 @@ describe Eodhd::WebSocketClient do
53
55
  describe "#run" do
54
56
  it "configures Iodine and starts connection" do
55
57
  client = Eodhd::WebSocketClient.new(api_token: api_token, asset_class: 'us', symbols: 'AAPL', consumer: consumer)
56
-
58
+
57
59
  iodine_connect_called = false
58
60
  iodine_start_called = false
59
-
61
+
60
62
  Iodine.stub(:threads=, nil) do
61
63
  Iodine.stub(:connect, ->(opts){iodine_connect_called = true}) do
62
64
  Iodine.stub(:start, ->{iodine_start_called = true}) do
@@ -64,7 +66,7 @@ describe Eodhd::WebSocketClient do
64
66
  end
65
67
  end
66
68
  end
67
-
69
+
68
70
  _(iodine_connect_called).must_equal(true)
69
71
  _(iodine_start_called).must_equal(true)
70
72
  end
@@ -76,10 +78,10 @@ describe Eodhd::WebSocketClient do
76
78
  received_data = nil
77
79
  test_consumer = ->(data){received_data = data}
78
80
  handler = Eodhd::WebSocketClient::Handler.new(symbols: 'AAPL', consumer: test_consumer, logger: nil)
79
-
81
+
80
82
  message = '{"symbol":"AAPL","price":150.0}'
81
83
  handler.on_message(nil, message)
82
-
84
+
83
85
  _(received_data).must_be_kind_of(Hash)
84
86
  _(received_data['symbol']).must_equal('AAPL')
85
87
  _(received_data['price']).must_equal(150.0)
@@ -88,7 +90,7 @@ describe Eodhd::WebSocketClient do
88
90
  it "raises Eodhd::Error on invalid JSON" do
89
91
  test_consumer = ->(data){}
90
92
  handler = Eodhd::WebSocketClient::Handler.new(symbols: 'AAPL', consumer: test_consumer, logger: nil)
91
-
93
+
92
94
  invalid_message = '{invalid json'
93
95
  _{handler.on_message(nil, invalid_message)}.must_raise(Eodhd::Error)
94
96
  end
@@ -1,8 +1,9 @@
1
+ # Eodhd_test.rb
2
+
1
3
  require_relative "helper"
2
4
 
3
5
  describe Eodhd do
4
6
  let(:api_token){ENV.fetch('EODHD_API_TOKEN', '<API_TOKEN>')}
5
-
6
7
  let(:eodhd){Eodhd.new(api_token: api_token)}
7
8
 
8
9
  describe "#exchanges" do
@@ -59,4 +60,14 @@ describe Eodhd do
59
60
  end
60
61
  end
61
62
  end
63
+
64
+ describe "#fundamentals" do
65
+ it "delegates to Eodhd::Fundamentals.all" do
66
+ VCR.use_cassette('eodhd_fundamentals') do
67
+ fundamental_data = eodhd.fundamentals(exchange_code: 'US', symbol: 'AAPL')
68
+ _(fundamental_data).must_be_kind_of(Eodhd::Fundamentals)
69
+ _(fundamental_data.general).must_be_kind_of(Eodhd::Fundamentals::General)
70
+ end
71
+ end
72
+ end
62
73
  end
data/test/helper.rb CHANGED
@@ -1,4 +1,7 @@
1
+ # helper.rb
2
+
1
3
  require 'minitest/autorun'
4
+ require 'minitest/mock'
2
5
  require 'minitest/spec'
3
6
  require 'minitest-spec-context'
4
7
  require 'vcr'