iex-ruby-client 1.3.0 → 1.6.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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +21 -0
  4. data/README.md +202 -16
  5. data/RELEASING.md +3 -3
  6. data/UPGRADING.md +8 -0
  7. data/iex-ruby-client.gemspec +1 -1
  8. data/lib/iex/api/client.rb +5 -0
  9. data/lib/iex/api.rb +5 -0
  10. data/lib/iex/endpoints/balance_sheet.rb +13 -0
  11. data/lib/iex/endpoints/cash_flow.rb +13 -0
  12. data/lib/iex/endpoints/fx.rb +13 -0
  13. data/lib/iex/endpoints/historial_prices.rb +30 -0
  14. data/lib/iex/endpoints/key_stat.rb +14 -0
  15. data/lib/iex/endpoints/ref_data.rb +5 -0
  16. data/lib/iex/errors/invalid_symbols_list.rb +14 -0
  17. data/lib/iex/errors/stat_not_found_error.rb +13 -0
  18. data/lib/iex/errors.rb +3 -1
  19. data/lib/iex/resources/advanced_stats.rb +43 -1
  20. data/lib/iex/resources/balance_sheet.rb +60 -0
  21. data/lib/iex/resources/cash_flow.rb +43 -0
  22. data/lib/iex/resources/currency_rate.rb +9 -0
  23. data/lib/iex/resources/historical_prices.rb +31 -0
  24. data/lib/iex/resources/income.rb +2 -0
  25. data/lib/iex/resources/news.rb +3 -0
  26. data/lib/iex/resources/resource.rb +17 -1
  27. data/lib/iex/resources.rb +4 -0
  28. data/lib/iex/version.rb +1 -1
  29. data/lib/iex-ruby-client.rb +1 -1
  30. data/script/console +9 -0
  31. data/spec/fixtures/iex/balance_sheet/invalid.yml +50 -0
  32. data/spec/fixtures/iex/balance_sheet/msft.yml +56 -0
  33. data/spec/fixtures/iex/cash_flow/invalid.yml +50 -0
  34. data/spec/fixtures/iex/cash_flow/msft.yml +56 -0
  35. data/spec/fixtures/iex/fx/invalid.yml +83 -0
  36. data/spec/fixtures/iex/fx/latest.yml +85 -0
  37. data/spec/fixtures/iex/fx/latest_one_symbol.yml +85 -0
  38. data/spec/fixtures/iex/historical_prices/abcd.yml +56 -0
  39. data/spec/fixtures/iex/historical_prices/invalid.yml +50 -0
  40. data/spec/fixtures/iex/historical_prices/invalid_date.yml +50 -0
  41. data/spec/fixtures/iex/historical_prices/invalid_range.yml +47 -0
  42. data/spec/fixtures/iex/historical_prices/msft.yml +79 -0
  43. data/spec/fixtures/iex/historical_prices/msft_5d.yml +61 -0
  44. data/spec/fixtures/iex/historical_prices/msft_date_and_chart_by_day.yml +57 -0
  45. data/spec/fixtures/iex/historical_prices/msft_specific_date_trimmed.yml +445 -0
  46. data/spec/fixtures/iex/income/msft.yml +54 -51
  47. data/spec/fixtures/iex/key_stat/individual.yml +60 -0
  48. data/spec/fixtures/iex/key_stat/invalid_stat.yml +60 -0
  49. data/spec/fixtures/iex/key_stat/invalid_symbol.yml +50 -0
  50. data/spec/fixtures/iex/ref-data/exchange_symbols.yml +1926 -0
  51. data/spec/iex/endpoints/advanced_stats_spec.rb +56 -0
  52. data/spec/iex/endpoints/balance_sheet_spec.rb +80 -0
  53. data/spec/iex/endpoints/cash_flow_spec.rb +59 -0
  54. data/spec/iex/endpoints/fx_spec.rb +48 -0
  55. data/spec/iex/endpoints/historical_prices_spec.rb +206 -0
  56. data/spec/iex/endpoints/income_spec.rb +31 -29
  57. data/spec/iex/endpoints/key_stat_spec.rb +43 -0
  58. data/spec/iex/endpoints/news_spec.rb +3 -0
  59. data/spec/iex/endpoints/ref_data_spec.rb +44 -9
  60. data/spec/iex/resources/resource_spec.rb +36 -0
  61. metadata +68 -8
@@ -39,6 +39,62 @@ describe IEX::Resources::AdvancedStats do
39
39
  expect(subject.week_52_high_date).to eq '2020-09-02'
40
40
  expect(subject.pe_low).to eq 23.046956521739133
41
41
  expect(subject.week_52_low_date).to eq '2020-03-23'
42
+ expect(subject.put_call_ratio).to eq 0.36251766583920975
43
+ end
44
+
45
+ it 'retrieves a keyStats' do
46
+ expect(subject.company_name).to eq 'Microsoft Corp.'
47
+ expect(subject.market_cap).to eq 1_621_141_983_000
48
+ expect(subject.market_cap_dollar).to eq '$1,621,141,983,000'
49
+ expect(subject.employees).to eq 163_000
50
+ end
51
+
52
+ it 'weekly stats' do
53
+ expect(subject.week_52_high).to eq 232.86
54
+ expect(subject.week_52_high_dollar).to eq '$232.86'
55
+ expect(subject.week_52_low).to eq 132.52
56
+ expect(subject.week_52_low_dollar).to eq '$132.52'
57
+ expect(subject.week_52_change).to eq 0.533539
58
+ expect(subject.week_52_change_dollar).to eq '$0.53'
59
+ end
60
+
61
+ it 'general stats' do
62
+ expect(subject.ttm_dividend_rate).to eq 2.04
63
+ expect(subject.dividend_yield).to eq 0.009522920362244423
64
+ expect(subject.ex_dividend_date).to eq '2020-08-19'
65
+ expect(subject.shares_outstanding).to eq 7_567_650_000
66
+ expect(subject.float).to eq 7_454_581_741
67
+ expect(subject.ttm_eps).to eq 5.8207
68
+ expect(subject.next_dividend_date).to eq '2020-11-18'
69
+ expect(subject.next_earnings_date).to eq '2020-10-27'
70
+ expect(subject.pe_ratio).to eq 36.88
71
+ expect(subject.beta).to eq 1.1472751624864646
72
+ expect(subject.day_200_moving_avg).to eq 187.72
73
+ expect(subject.day_50_moving_avg).to eq 212.09
74
+ end
75
+
76
+ it 'changes stats' do
77
+ expect(subject.avg_10_volume).to be 26_989_991
78
+ expect(subject.avg_30_volume).to be 31_404_571.1
79
+ expect(subject.max_change_percent).to eq 7.1248
80
+ expect(subject.year_5_change_percent).to be 3.3093
81
+ expect(subject.year_5_change_percent_s).to eq '+330.93%'
82
+ expect(subject.year_2_change_percent).to eq 1.0108
83
+ expect(subject.year_2_change_percent_s).to eq '+101.08%'
84
+ expect(subject.year_1_change_percent).to eq 0.572482
85
+ expect(subject.year_1_change_percent_s).to eq '+57.25%'
86
+ expect(subject.ytd_change_percent).to eq 0.367576
87
+ expect(subject.ytd_change_percent_s).to eq '+36.76%'
88
+ expect(subject.month_6_change_percent).to eq 0.229899
89
+ expect(subject.month_6_change_percent_s).to eq '+22.99%'
90
+ expect(subject.month_3_change_percent).to eq 0.082709
91
+ expect(subject.month_3_change_percent_s).to eq '+8.27%'
92
+ expect(subject.month_1_change_percent).to eq 0.082549
93
+ expect(subject.month_1_change_percent_s).to eq '+8.25%'
94
+ expect(subject.day_5_change_percent).to eq(-0.007859)
95
+ expect(subject.day_5_change_percent_s).to eq '-0.79%'
96
+ expect(subject.day_30_change_percent).to eq 0.025251
97
+ expect(subject.day_30_change_percent_s).to eq '+2.53%'
42
98
  end
43
99
  end
44
100
 
@@ -0,0 +1,80 @@
1
+ require 'spec_helper'
2
+
3
+ describe IEX::Resources::BalanceSheet do
4
+ include_context 'client'
5
+
6
+ context 'general information', vcr: { cassette_name: 'balance_sheet/msft' } do
7
+ subject do
8
+ client.balance_sheet('MSFT')
9
+ end
10
+ let(:balance_sheet) { subject.first }
11
+
12
+ it 'fetches balance sheet' do
13
+ expect(subject.size).to eq 1
14
+ expect(balance_sheet.report_date).to eq '2020-09-30'
15
+ expect(balance_sheet.fiscal_date).to eq '2020-09-30'
16
+ expect(balance_sheet.currency).to eq 'USD'
17
+ expect(balance_sheet.current_cash).to eq 17_205_000_000
18
+ expect(balance_sheet.current_cash_dollar).to eq '$17,205,000,000'
19
+ expect(balance_sheet.short_term_investments).to eq 120_772_000_000
20
+ expect(balance_sheet.short_term_investments_dollar).to eq '$120,772,000,000'
21
+ expect(balance_sheet.receivables).to eq 22_851_000_000
22
+ expect(balance_sheet.receivables_dollar).to eq '$22,851,000,000'
23
+ expect(balance_sheet.inventory).to eq 2_705_000_000
24
+ expect(balance_sheet.inventory_dollar).to eq '$2,705,000,000'
25
+ expect(balance_sheet.other_current_assets).to eq 13_544_000_000
26
+ expect(balance_sheet.other_current_assets_dollar).to eq '$13,544,000,000'
27
+ expect(balance_sheet.current_assets).to eq 177_077_000_000
28
+ expect(balance_sheet.current_assets_dollar).to eq '$177,077,000,000'
29
+ expect(balance_sheet.long_term_investments).to eq 3_196_000_000
30
+ expect(balance_sheet.long_term_investments_dollar).to eq '$3,196,000,000'
31
+ expect(balance_sheet.property_plant_equipment).to eq 56_974_000_000
32
+ expect(balance_sheet.property_plant_equipment_dollar).to eq '$56,974,000,000'
33
+ expect(balance_sheet.goodwill).to eq 43_890_000_000
34
+ expect(balance_sheet.goodwill_dollar).to eq '$43,890,000,000'
35
+ expect(balance_sheet.intangible_assets).to eq 6_923_000_000
36
+ expect(balance_sheet.intangible_assets_dollar).to eq '$6,923,000,000'
37
+ expect(balance_sheet.other_assets).to eq 12_941_000_000
38
+ expect(balance_sheet.other_assets_dollar).to eq '$12,941,000,000'
39
+ expect(balance_sheet.total_assets).to eq 301_001_000_000
40
+ expect(balance_sheet.total_assets_dollar).to eq '$301,001,000,000'
41
+ expect(balance_sheet.accounts_payable).to eq 12_509_000_000
42
+ expect(balance_sheet.accounts_payable_dollar).to eq '$12,509,000,000'
43
+ expect(balance_sheet.current_long_term_debt).to eq 7_093_000_000
44
+ expect(balance_sheet.current_long_term_debt_dollar).to eq '$7,093,000,000'
45
+ expect(balance_sheet.other_current_liabilities).to eq 46_326_000_000
46
+ expect(balance_sheet.other_current_liabilities_dollar).to eq '$46,326,000,000'
47
+ expect(balance_sheet.total_current_liabilities).to eq 70_056_000_000
48
+ expect(balance_sheet.total_current_liabilities_dollar).to eq '$70,056,000,000'
49
+ expect(balance_sheet.long_term_debt).to eq 74_379_000_000
50
+ expect(balance_sheet.long_term_debt_dollar).to eq '$74,379,000,000'
51
+ expect(balance_sheet.other_liabilities).to eq 32_987_000_000
52
+ expect(balance_sheet.other_liabilities_dollar).to eq '$32,987,000,000'
53
+ expect(balance_sheet.minority_interest).to eq 0
54
+ expect(balance_sheet.minority_interest_dollar).to eq '$0'
55
+ expect(balance_sheet.total_liabilities).to eq 177_609_000_000
56
+ expect(balance_sheet.total_liabilities_dollar).to eq '$177,609,000,000'
57
+ expect(balance_sheet.common_stock).to eq 7_564_000_000
58
+ expect(balance_sheet.retained_earnings).to eq 39_193_000_000
59
+ expect(balance_sheet.retained_earnings_dollar).to eq '$39,193,000,000'
60
+ expect(balance_sheet.treasury_stock).to eq nil
61
+ expect(balance_sheet.treasury_stock_dollar).to eq nil
62
+ expect(balance_sheet.capital_surplus).to eq nil
63
+ expect(balance_sheet.capital_surplus_dollar).to eq nil
64
+ expect(balance_sheet.shareholder_equity).to eq 123_392_000_000
65
+ expect(balance_sheet.shareholder_equity_dollar).to eq '$123,392,000,000'
66
+ expect(balance_sheet.net_tangible_assets).to eq 17_585_000_000
67
+ expect(balance_sheet.net_tangible_assets_dollar).to eq '$17,585,000,000'
68
+ end
69
+ end
70
+
71
+ context 'invalid symbol', vcr: { cassette_name: 'balance_sheet/invalid' } do
72
+ subject do
73
+ client.balance_sheet('INVALID')
74
+ end
75
+
76
+ it 'fails with SymbolNotFoundError' do
77
+ expect { subject }.to raise_error IEX::Errors::SymbolNotFoundError, 'Symbol INVALID Not Found'
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ describe IEX::Resources::CashFlow do
4
+ include_context 'client'
5
+
6
+ context 'general information', vcr: { cassette_name: 'cash_flow/msft' } do
7
+ subject do
8
+ client.cash_flow('MSFT')
9
+ end
10
+ let(:cash_flow) { subject.first }
11
+
12
+ it 'fetches cash flow statement' do
13
+ expect(subject.size).to eq 1
14
+ expect(cash_flow.report_date).to eq '2020-09-30'
15
+ expect(cash_flow.fiscal_date).to eq '2020-09-30'
16
+ expect(cash_flow.currency).to eq 'USD'
17
+ expect(cash_flow.net_income).to eq 13_893_000_000
18
+ expect(cash_flow.net_income_dollar).to eq '$13,893,000,000'
19
+ expect(cash_flow.depreciation).to eq 2_645_000_000
20
+ expect(cash_flow.depreciation_dollar).to eq '$2,645,000,000'
21
+ expect(cash_flow.changes_in_receivables).to eq 9_160_000_000
22
+ expect(cash_flow.changes_in_receivables_dollar).to eq '$9,160,000,000'
23
+ expect(cash_flow.changes_in_inventories).to eq(-808_000_000)
24
+ expect(cash_flow.changes_in_inventories_dollar).to eq '$-808,000,000'
25
+ expect(cash_flow.cash_change).to eq 3_629_000_000
26
+ expect(cash_flow.cash_change_dollar).to eq '$3,629,000,000'
27
+ expect(cash_flow.cash_flow).to eq 19_335_000_000
28
+ expect(cash_flow.cash_flow_dollar).to eq '$19,335,000,000'
29
+ expect(cash_flow.capital_expenditures).to eq(-4_907_000_000)
30
+ expect(cash_flow.capital_expenditures_dollar).to eq '$-4,907,000,000'
31
+ expect(cash_flow.investments).to eq 2_100_000_000
32
+ expect(cash_flow.investments_dollar).to eq '$2,100,000,000'
33
+ expect(cash_flow.investing_activity_other).to eq(-2_083_000_000)
34
+ expect(cash_flow.investing_activity_other_dollar).to eq '$-2,083,000,000'
35
+ expect(cash_flow.total_investing_cash_flows).to eq(-5_371_000_000)
36
+ expect(cash_flow.total_investing_cash_flows_dollar).to eq '$-5,371,000,000'
37
+ expect(cash_flow.dividends_paid).to eq(-3_856_000_000)
38
+ expect(cash_flow.dividends_paid_dollar).to eq '$-3,856,000,000'
39
+ expect(cash_flow.net_borrowings).to eq nil
40
+ expect(cash_flow.net_borrowings_dollar).to eq nil
41
+ expect(cash_flow.other_financing_cash_flows).to eq(-235_000_000)
42
+ expect(cash_flow.other_financing_cash_flows_dollar).to eq '$-235,000,000'
43
+ expect(cash_flow.cash_flow_financing).to eq(-10_289_000_000)
44
+ expect(cash_flow.cash_flow_financing_dollar).to eq '$-10,289,000,000'
45
+ expect(cash_flow.exchange_rate_effect).to eq(-46_000_000)
46
+ expect(cash_flow.exchange_rate_effect_dollar).to eq '$-46,000,000'
47
+ end
48
+ end
49
+
50
+ context 'invalid symbol', vcr: { cassette_name: 'cash_flow/invalid' } do
51
+ subject do
52
+ client.cash_flow('INVALID')
53
+ end
54
+
55
+ it 'fails with SymbolNotFoundError' do
56
+ expect { subject }.to raise_error IEX::Errors::SymbolNotFoundError, 'Symbol INVALID Not Found'
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ describe IEX::Endpoints::FX do
4
+ include_context 'client'
5
+
6
+ context 'known symbol', vcr: { cassette_name: 'fx/latest_one_symbol' } do
7
+ subject do
8
+ client.fx_latest('USDCAD')
9
+ end
10
+ it 'retrieves a list of CurrencyRates' do
11
+ expect(subject.length).to eq 1
12
+
13
+ expect(subject[0].symbol).to eq 'USDCAD'
14
+ expect(subject[0].rate).to eq 1.25674
15
+ expect(subject[0].timestamp).to eq Date.strptime('1627045829.863', '%s')
16
+ end
17
+ end
18
+
19
+ context 'known symbols', vcr: { cassette_name: 'fx/latest' } do
20
+ subject do
21
+ client.fx_latest(%w[USDCAD USDGBP USDJPY])
22
+ end
23
+ it 'retrieves a list of CurrencyRates' do
24
+ expect(subject.length).to eq 3
25
+
26
+ expect(subject[0].symbol).to eq 'USDCAD'
27
+ expect(subject[0].rate).to eq 1.25674
28
+ expect(subject[0].timestamp).to eq Date.strptime('1627045829.863', '%s')
29
+
30
+ expect(subject[1].symbol).to eq 'USDGBP'
31
+ expect(subject[1].rate).to eq 0.7262111386264443
32
+ expect(subject[1].timestamp).to eq Date.strptime('1627045780.863', '%s')
33
+
34
+ expect(subject[2].symbol).to eq 'USDJPY'
35
+ expect(subject[2].rate).to eq 110.426
36
+ expect(subject[2].timestamp).to eq Date.strptime('1627045825.365', '%s')
37
+ end
38
+ end
39
+
40
+ context 'invalid symbol', vcr: { cassette_name: 'fx/invalid' } do
41
+ subject do
42
+ client.fx_latest(%w[INVALID])
43
+ end
44
+ it 'fails with InvalidSymbolsList' do
45
+ expect { subject }.to raise_error IEX::Errors::InvalidSymbolsList, 'Invalid symbol list: INVALID'
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,206 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe IEX::Resources::HistorialPrices do
6
+ include_context 'client'
7
+
8
+ context 'known symbol' do
9
+ context 'with valid params' do
10
+ context 'with defaults', vcr: { cassette_name: 'historical_prices/msft' } do
11
+ subject do
12
+ client.historical_prices('MSFT')
13
+ end
14
+ let(:historical_price) { subject.first }
15
+
16
+ it 'retrieves historical prices' do
17
+ expect(subject.size).to eq 23
18
+ expect(historical_price.date).to eq '2020-10-07'
19
+ expect(historical_price.open).to eq 207.06
20
+ expect(historical_price.open_dollar).to eq '$207.06'
21
+ expect(historical_price.close).to eq 209.83
22
+ expect(historical_price.close_dollar).to eq '$209.83'
23
+ expect(historical_price.high).to eq 210.11
24
+ expect(historical_price.high_dollar).to eq '$210.11'
25
+ expect(historical_price.low).to eq 206.72
26
+ expect(historical_price.low_dollar).to eq '$206.72'
27
+ expect(historical_price.volume).to eq 25_681_054
28
+ expect(historical_price.u_open).to eq 207.06
29
+ expect(historical_price.u_open_dollar).to eq '$207.06'
30
+ expect(historical_price.u_close).to eq 209.83
31
+ expect(historical_price.u_close_dollar).to eq '$209.83'
32
+ expect(historical_price.u_low).to eq 206.72
33
+ expect(historical_price.u_low_dollar).to eq '$206.72'
34
+ expect(historical_price.u_high).to eq 210.11
35
+ expect(historical_price.u_high_dollar).to eq '$210.11'
36
+ expect(historical_price.u_volume).to eq 25_681_054
37
+ expect(historical_price.change).to eq 0
38
+ expect(historical_price.change_percent).to eq 0
39
+ expect(historical_price.change_percent_s).to eq '+0.00%'
40
+ expect(historical_price.label).to eq 'Oct 7'
41
+ expect(historical_price.change_over_time).to eq 0
42
+ expect(historical_price.change_over_time_s).to eq '+0.00%'
43
+ end
44
+ end
45
+
46
+ context 'with a valid range provided', vcr: { cassette_name: 'historical_prices/msft_5d' } do
47
+ subject { client.historical_prices('MSFT', range: '5d') }
48
+ let(:historical_price) { subject.last }
49
+
50
+ it 'retrieves historical prices' do
51
+ expect(subject.size).to eq 5
52
+ expect(historical_price.date).to eq '2020-11-10'
53
+ expect(historical_price.open).to eq 214.50
54
+ expect(historical_price.open_dollar).to eq '$214.50'
55
+ expect(historical_price.close).to eq 211.01
56
+ expect(historical_price.close_dollar).to eq '$211.01'
57
+ expect(historical_price.high).to eq 216.50
58
+ expect(historical_price.high_dollar).to eq '$216.50'
59
+ expect(historical_price.low).to eq 209.72
60
+ expect(historical_price.low_dollar).to eq '$209.72'
61
+ expect(historical_price.volume).to eq 44_045_120
62
+ expect(historical_price.u_open).to eq 214.50
63
+ expect(historical_price.u_open_dollar).to eq '$214.50'
64
+ expect(historical_price.u_close).to eq 211.01
65
+ expect(historical_price.u_close_dollar).to eq '$211.01'
66
+ expect(historical_price.u_low).to eq 209.72
67
+ expect(historical_price.u_low_dollar).to eq '$209.72'
68
+ expect(historical_price.u_high).to eq 216.50
69
+ expect(historical_price.u_high_dollar).to eq '$216.50'
70
+ expect(historical_price.u_volume).to eq 44_045_120
71
+ expect(historical_price.change).to eq(-7.38)
72
+ expect(historical_price.change_percent).to eq(-3.3793)
73
+ expect(historical_price.change_percent_s).to eq '-3.38%'
74
+ expect(historical_price.label).to eq 'Nov 10'
75
+ expect(historical_price.change_over_time).to eq(-0.024863)
76
+ expect(historical_price.change_over_time_s).to eq '-0.02%'
77
+ end
78
+ end
79
+
80
+ context 'with a range provided for a specific date (passed as a Date object) and chartByDay param',
81
+ vcr: { cassette_name: 'historical_prices/msft_date_and_chart_by_day' } do
82
+ options = { range: 'date', date: Date.parse('2020-11-10'), chartByDay: 'true' }
83
+ subject { client.historical_prices('MSFT', options) }
84
+ let(:historical_price) { subject.first }
85
+
86
+ it 'retrieves historical prices' do
87
+ expect(subject.size).to eq 1
88
+ expect(historical_price.date).to eq '2020-11-10'
89
+ expect(historical_price.open).to eq 214.50
90
+ expect(historical_price.open_dollar).to eq '$214.50'
91
+ expect(historical_price.close).to eq 211.01
92
+ expect(historical_price.close_dollar).to eq '$211.01'
93
+ expect(historical_price.high).to eq 216.50
94
+ expect(historical_price.high_dollar).to eq '$216.50'
95
+ expect(historical_price.low).to eq 209.72
96
+ expect(historical_price.low_dollar).to eq '$209.72'
97
+ expect(historical_price.volume).to eq 44_045_120
98
+ expect(historical_price.u_open).to eq 214.50
99
+ expect(historical_price.u_open_dollar).to eq '$214.50'
100
+ expect(historical_price.u_close).to eq 211.01
101
+ expect(historical_price.u_close_dollar).to eq '$211.01'
102
+ expect(historical_price.u_low).to eq 209.72
103
+ expect(historical_price.u_low_dollar).to eq '$209.72'
104
+ expect(historical_price.u_high).to eq 216.50
105
+ expect(historical_price.u_high_dollar).to eq '$216.50'
106
+ expect(historical_price.u_volume).to eq 44_045_120
107
+ expect(historical_price.change).to eq(-7.38)
108
+ expect(historical_price.change_percent).to eq(-3.3793)
109
+ expect(historical_price.change_percent_s).to eq '-3.38%'
110
+ expect(historical_price.label).to eq 'Nov 10'
111
+ expect(historical_price.change_over_time).to eq(-0.033793)
112
+ expect(historical_price.change_over_time_s).to eq '-0.03%'
113
+ end
114
+ end
115
+
116
+ context 'with a range provided for a specific date (passed as a string) and chartByDay param',
117
+ vcr: { cassette_name: 'historical_prices/msft_date_and_chart_by_day' } do
118
+ options = { range: 'date', date: '20201110', chartByDay: 'true' }
119
+ subject { client.historical_prices('MSFT', options) }
120
+ let(:historical_price) { subject.first }
121
+
122
+ it 'retrieves historical prices' do
123
+ expect(subject.size).to eq 1
124
+ expect(historical_price.date).to eq '2020-11-10'
125
+ expect(historical_price.open).to eq 214.50
126
+ expect(historical_price.open_dollar).to eq '$214.50'
127
+ expect(historical_price.close).to eq 211.01
128
+ expect(historical_price.close_dollar).to eq '$211.01'
129
+ expect(historical_price.high).to eq 216.50
130
+ expect(historical_price.high_dollar).to eq '$216.50'
131
+ expect(historical_price.low).to eq 209.72
132
+ expect(historical_price.low_dollar).to eq '$209.72'
133
+ expect(historical_price.volume).to eq 44_045_120
134
+ expect(historical_price.u_open).to eq 214.50
135
+ expect(historical_price.u_open_dollar).to eq '$214.50'
136
+ expect(historical_price.u_close).to eq 211.01
137
+ expect(historical_price.u_close_dollar).to eq '$211.01'
138
+ expect(historical_price.u_low).to eq 209.72
139
+ expect(historical_price.u_low_dollar).to eq '$209.72'
140
+ expect(historical_price.u_high).to eq 216.50
141
+ expect(historical_price.u_high_dollar).to eq '$216.50'
142
+ expect(historical_price.u_volume).to eq 44_045_120
143
+ expect(historical_price.change).to eq(-7.38)
144
+ expect(historical_price.change_percent).to eq(-3.3793)
145
+ expect(historical_price.change_percent_s).to eq '-3.38%'
146
+ expect(historical_price.label).to eq 'Nov 10'
147
+ expect(historical_price.change_over_time).to eq(-0.033793)
148
+ expect(historical_price.change_over_time_s).to eq '-0.03%'
149
+ end
150
+ end
151
+ end
152
+
153
+ context 'with invalid params' do
154
+ context 'with an invalid range', vcr: { cassette_name: 'historical_prices/invalid_range' } do
155
+ subject { client.historical_prices('MSFT', range: 'invalid') }
156
+
157
+ it 'fails with ArgumentError' do
158
+ expect { subject }.to raise_error IEX::Errors::PermissionDeniedError
159
+ end
160
+ end
161
+
162
+ context "with a range as 'date' but without a date param" do
163
+ subject { client.historical_prices('MSFT', range: 'date') }
164
+
165
+ it 'fails with ArgumentError' do
166
+ expect { subject }.to raise_error ArgumentError
167
+ end
168
+ end
169
+
170
+ context "with a range as 'date' but without chartByDay query param" do
171
+ subject { client.historical_prices('MSFT', range: 'date', date: Date.parse('2020-11-10')) }
172
+
173
+ it 'fails with ArgumentError' do
174
+ expect { subject }.to raise_error ArgumentError
175
+ end
176
+ end
177
+
178
+ context "with a range as 'date' but without date as a Date object that is incorrectly formatted",
179
+ vcr: { cassette_name: 'historical_prices/invalid_date' } do
180
+ subject { client.historical_prices('MSFT', range: 'date', date: '2020-11-10', chartByDay: 'true') }
181
+
182
+ it 'fails with ArgumentError' do
183
+ expect { subject }.to raise_error IEX::Errors::ClientError
184
+ end
185
+ end
186
+ end
187
+ end
188
+
189
+ context 'no result', vcr: { cassette_name: 'historical_prices/abcd' } do
190
+ subject do
191
+ client.historical_prices('abcd')
192
+ end
193
+ it 'returns empty array' do
194
+ expect(subject).to eq []
195
+ end
196
+ end
197
+
198
+ context 'invalid symbol', vcr: { cassette_name: 'historical_prices/invalid' } do
199
+ subject do
200
+ client.historical_prices('INVALID')
201
+ end
202
+ it 'fails with SymbolNotFoundError' do
203
+ expect { subject }.to raise_error IEX::Errors::SymbolNotFoundError, 'Symbol INVALID Not Found'
204
+ end
205
+ end
206
+ end
@@ -14,36 +14,38 @@ describe IEX::Resources::Income do
14
14
 
15
15
  it 'retrieves income statement' do
16
16
  expect(subject.size).to eq 1
17
- expect(income.report_date).to eq '2019-03-31'
18
- expect(income.total_revenue).to eq 30_505_000_000
19
- expect(income.total_revenue_dollar).to eq '$30,505,000,000'
20
- expect(income.cost_of_revenue).to eq 10_170_000_000
21
- expect(income.cost_of_revenue_dollar).to eq '$10,170,000,000'
22
- expect(income.gross_profit).to eq 20_335_000_000
23
- expect(income.gross_profit_dollar).to eq '$20,335,000,000'
24
- expect(income.research_and_development).to eq 4_316_000_000
25
- expect(income.research_and_development_dollar).to eq '$4,316,000,000'
26
- expect(income.selling_general_and_admin).to eq 5_744_000_000
27
- expect(income.selling_general_and_admin_dollar).to eq '$5,744,000,000'
28
- expect(income.operating_expense).to eq 20_230_000_000
29
- expect(income.operating_expense_dollar).to eq '$20,230,000,000'
30
- expect(income.operating_income).to eq 10_275_000_000
31
- expect(income.operating_income_dollar).to eq '$10,275,000,000'
32
- expect(income.other_income_expense_net).to eq 211_000_000
33
- expect(income.other_income_expense_net_dollar).to eq '$211,000,000'
34
- expect(income.ebit_dollar).to eq '$10,275,000,000'
35
- expect(income.ebit).to eq 10_275_000_000
36
- expect(income.interest_income).to eq 671_000_000
37
- expect(income.interest_income_dollar).to eq '$671,000,000'
38
- expect(income.pretax_income).to eq 10_486_000_000
39
- expect(income.pretax_income_dollar).to eq '$10,486,000,000'
40
- expect(income.income_tax).to eq 1_677_000_000
41
- expect(income.income_tax_dollar).to eq '$1,677,000,000'
17
+ expect(income.report_date).to eq '2020-09-30'
18
+ expect(income.fiscal_date).to eq '2020-09-30'
19
+ expect(income.currency).to eq 'USD'
20
+ expect(income.total_revenue).to eq 37_154_000_000
21
+ expect(income.total_revenue_dollar).to eq '$37,154,000,000'
22
+ expect(income.cost_of_revenue).to eq 11_002_000_000
23
+ expect(income.cost_of_revenue_dollar).to eq '$11,002,000,000'
24
+ expect(income.gross_profit).to eq 26_152_000_000
25
+ expect(income.gross_profit_dollar).to eq '$26,152,000,000'
26
+ expect(income.research_and_development).to eq 4_926_000_000
27
+ expect(income.research_and_development_dollar).to eq '$4,926,000,000'
28
+ expect(income.selling_general_and_admin).to eq 5_350_000_000
29
+ expect(income.selling_general_and_admin_dollar).to eq '$5,350,000,000'
30
+ expect(income.operating_expense).to eq 21_278_000_000
31
+ expect(income.operating_expense_dollar).to eq '$21,278,000,000'
32
+ expect(income.operating_income).to eq 15_876_000_000
33
+ expect(income.operating_income_dollar).to eq '$15,876,000,000'
34
+ expect(income.other_income_expense_net).to eq 248_000_000
35
+ expect(income.other_income_expense_net_dollar).to eq '$248,000,000'
36
+ expect(income.ebit).to eq 15_876_000_000
37
+ expect(income.ebit_dollar).to eq '$15,876,000,000'
38
+ expect(income.interest_income).to eq 589_000_000
39
+ expect(income.interest_income_dollar).to eq '$589,000,000'
40
+ expect(income.pretax_income).to eq 16_124_000_000
41
+ expect(income.pretax_income_dollar).to eq '$16,124,000,000'
42
+ expect(income.income_tax).to eq 2_231_000_000
43
+ expect(income.income_tax_dollar).to eq '$2,231,000,000'
42
44
  expect(income.minority_interest).to eq 0
43
- expect(income.net_income).to eq 8_809_000_000
44
- expect(income.net_income_dollar).to eq '$8,809,000,000'
45
- expect(income.net_income_basic).to eq 8_809_000_000
46
- expect(income.net_income_basic_dollar).to eq '$8,809,000,000'
45
+ expect(income.net_income).to eq 13_893_000_000
46
+ expect(income.net_income_dollar).to eq '$13,893,000,000'
47
+ expect(income.net_income_basic).to eq 13_893_000_000
48
+ expect(income.net_income_basic_dollar).to eq '$13,893,000,000'
47
49
  end
48
50
  end
49
51
  end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ describe IEX::Endpoints::KeyStat do
4
+ include_context 'client'
5
+
6
+ let(:stat) { 'ttmDividendRate' }
7
+ let(:symbol) { 'VTI' }
8
+
9
+ context 'when asking for a single stat', vcr: { cassette_name: 'key_stat/individual' } do
10
+ subject { client.key_stat(symbol, stat) }
11
+
12
+ it 'returns that stat in the type provided by the API' do
13
+ expect(subject).to be_within(0.0001).of(2.7887)
14
+ end
15
+ end
16
+
17
+ context 'invalid symbol', vcr: { cassette_name: 'key_stat/invalid_symbol' } do
18
+ subject { client.key_stat('INVALID', stat) }
19
+
20
+ it 'fails with SymbolNotFoundError' do
21
+ expect { subject }.to raise_error IEX::Errors::SymbolNotFoundError, 'Symbol INVALID Not Found'
22
+ end
23
+ end
24
+
25
+ context 'invalid stat', vcr: { cassette_name: 'key_stat/invalid_stat' } do
26
+ subject { client.key_stat(symbol, 'INVALID') }
27
+
28
+ it 'fails with StatNotFoundError' do
29
+ expect { subject }.to raise_error IEX::Errors::StatNotFoundError, 'Stat INVALID Not Found'
30
+ end
31
+
32
+ it 'keeps the API response so it can be used if caught' do
33
+ response = begin
34
+ subject
35
+ rescue IEX::Errors::StatNotFoundError => e
36
+ e.response
37
+ end
38
+
39
+ expect(response).to be_a(Hash)
40
+ expect(response).to have_key(stat)
41
+ end
42
+ end
43
+ end
@@ -14,6 +14,9 @@ describe IEX::Resources::News do
14
14
  expect(news.datetime.to_f).to eq 1_554_412_248.0
15
15
  expect(news.headline).to eq "Spotify joins Microsoft's Xbox Game Bar"
16
16
  expect(news.related).to eq(['MSFT'])
17
+ expect(news.image).to eq('https://cloud.iexapis.com/beta/news/image/b8a6ae18-ab19-42e8-b066-d9a9dc111f1f')
18
+ expect(news.paywalled).to eq(false)
19
+ expect(news.language).to eq('en')
17
20
  end
18
21
  end
19
22
  context 'with range', vcr: { cassette_name: 'news/msft_7' } do