iex-ruby-client 1.3.0 → 1.4.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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/README.md +147 -2
  4. data/RELEASING.md +2 -2
  5. data/lib/iex/api.rb +3 -0
  6. data/lib/iex/api/client.rb +3 -0
  7. data/lib/iex/endpoints/balance_sheet.rb +13 -0
  8. data/lib/iex/endpoints/cash_flow.rb +13 -0
  9. data/lib/iex/endpoints/historial_prices.rb +30 -0
  10. data/lib/iex/resources.rb +3 -0
  11. data/lib/iex/resources/advanced_stats.rb +43 -1
  12. data/lib/iex/resources/balance_sheet.rb +60 -0
  13. data/lib/iex/resources/cash_flow.rb +43 -0
  14. data/lib/iex/resources/historical_prices.rb +31 -0
  15. data/lib/iex/resources/income.rb +2 -0
  16. data/lib/iex/resources/resource.rb +12 -0
  17. data/lib/iex/version.rb +1 -1
  18. data/spec/fixtures/iex/balance_sheet/invalid.yml +50 -0
  19. data/spec/fixtures/iex/balance_sheet/msft.yml +56 -0
  20. data/spec/fixtures/iex/cash_flow/invalid.yml +50 -0
  21. data/spec/fixtures/iex/cash_flow/msft.yml +56 -0
  22. data/spec/fixtures/iex/historical_prices/abcd.yml +56 -0
  23. data/spec/fixtures/iex/historical_prices/invalid.yml +50 -0
  24. data/spec/fixtures/iex/historical_prices/invalid_date.yml +50 -0
  25. data/spec/fixtures/iex/historical_prices/invalid_range.yml +47 -0
  26. data/spec/fixtures/iex/historical_prices/msft.yml +79 -0
  27. data/spec/fixtures/iex/historical_prices/msft_5d.yml +61 -0
  28. data/spec/fixtures/iex/historical_prices/msft_date_and_chart_by_day.yml +57 -0
  29. data/spec/fixtures/iex/historical_prices/msft_specific_date_trimmed.yml +445 -0
  30. data/spec/fixtures/iex/income/msft.yml +54 -51
  31. data/spec/iex/endpoints/advanced_stats_spec.rb +56 -0
  32. data/spec/iex/endpoints/balance_sheet_spec.rb +80 -0
  33. data/spec/iex/endpoints/cash_flow_spec.rb +59 -0
  34. data/spec/iex/endpoints/historical_prices_spec.rb +206 -0
  35. data/spec/iex/endpoints/income_spec.rb +31 -29
  36. data/spec/iex/resources/resource_spec.rb +36 -0
  37. metadata +39 -3
@@ -1,53 +1,56 @@
1
1
  ---
2
2
  http_interactions:
3
- - request:
4
- method: get
5
- uri: https://cloud.iexapis.com/v1/stock/MSFT/income?token=test-iex-api-publishable-token
6
- body:
7
- encoding: US-ASCII
8
- string: ""
9
- headers:
10
- Accept:
11
- - application/json; charset=utf-8
12
- User-Agent:
13
- - IEX Ruby Client/1.0.1
14
- Accept-Encoding:
15
- - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
16
- response:
17
- status:
18
- code: 200
19
- message: OK
20
- headers:
21
- Server:
22
- - nginx
23
- Date:
24
- - Mon, 08 Jul 2019 04:53:26 GMT
25
- Content-Type:
26
- - application/json; charset=utf-8
27
- Transfer-Encoding:
28
- - chunked
29
- Connection:
30
- - keep-alive
31
- Set-Cookie:
32
- - ctoken=153fb65c56854cf995c8112a5cd5f554; Max-Age=43200; Path=/; Expires=Mon,
33
- 08 Jul 2019 16:53:26 GMT
34
- Iexcloud-Messages-Used:
35
- - "1000"
36
- X-Content-Type-Options:
37
- - nosniff
38
- Strict-Transport-Security:
39
- - max-age=15768000
40
- Access-Control-Allow-Origin:
41
- - "*"
42
- Access-Control-Allow-Credentials:
43
- - "true"
44
- Access-Control-Allow-Methods:
45
- - GET, OPTIONS
46
- Access-Control-Allow-Headers:
47
- - Origin, X-Requested-With, Content-Type, Accept
48
- body:
49
- encoding: ASCII-8BIT
50
- string: '{"symbol":"MSFT","income":[{"reportDate":"2019-03-31","totalRevenue":30505000000,"costOfRevenue":10170000000,"grossProfit":20335000000,"researchAndDevelopment":4316000000,"sellingGeneralAndAdmin":5744000000,"operatingExpense":20230000000,"operatingIncome":10275000000,"otherIncomeExpenseNet":211000000,"ebit":10275000000,"interestIncome":671000000,"pretaxIncome":10486000000,"incomeTax":1677000000,"minorityInterest":0,"netIncome":8809000000,"netIncomeBasic":8809000000}]}'
51
- http_version:
52
- recorded_at: Mon, 08 Jul 2019 04:53:26 GMT
53
- recorded_with: VCR 4.0.0
3
+ - request:
4
+ method: get
5
+ uri: https://cloud.iexapis.com/v1/stock/MSFT/income?token=test-iex-api-publishable-token
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - application/json; charset=utf-8
12
+ Content-Type:
13
+ - application/json; charset=utf-8
14
+ User-Agent:
15
+ - IEX Ruby Client/1.3.1
16
+ Accept-Encoding:
17
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
18
+ response:
19
+ status:
20
+ code: 200
21
+ message: OK
22
+ headers:
23
+ Server:
24
+ - nginx
25
+ Date:
26
+ - Sat, 07 Nov 2020 21:59:07 GMT
27
+ Content-Type:
28
+ - application/json; charset=utf-8
29
+ Transfer-Encoding:
30
+ - chunked
31
+ Connection:
32
+ - keep-alive
33
+ Set-Cookie:
34
+ - ctoken=88f9e21273b94c5683bb6f7214f0ad64; Max-Age=43200; Path=/; Expires=Sun,
35
+ 08 Nov 2020 09:59:07 GMT
36
+ Iexcloud-Messages-Used:
37
+ - '1000'
38
+ Iexcloud-Premium-Messages-Used:
39
+ - '0'
40
+ X-Content-Type-Options:
41
+ - nosniff
42
+ Strict-Transport-Security:
43
+ - max-age=15768000
44
+ Access-Control-Allow-Origin:
45
+ - "*"
46
+ Access-Control-Allow-Credentials:
47
+ - 'true'
48
+ Access-Control-Allow-Methods:
49
+ - GET, OPTIONS
50
+ Access-Control-Allow-Headers:
51
+ - Origin, X-Requested-With, Content-Type, Accept, Request-Source
52
+ body:
53
+ encoding: ASCII-8BIT
54
+ string: '{"symbol":"MSFT","income":[{"reportDate":"2020-09-30","fiscalDate":"2020-09-30","currency":"USD","totalRevenue":37154000000,"costOfRevenue":11002000000,"grossProfit":26152000000,"researchAndDevelopment":4926000000,"sellingGeneralAndAdmin":5350000000,"operatingExpense":21278000000,"operatingIncome":15876000000,"otherIncomeExpenseNet":248000000,"ebit":15876000000,"interestIncome":589000000,"pretaxIncome":16124000000,"incomeTax":2231000000,"minorityInterest":0,"netIncome":13893000000,"netIncomeBasic":13893000000}]}'
55
+ recorded_at: Sat, 07 Nov 2020 21:59:07 GMT
56
+ recorded_with: VCR 6.0.0
@@ -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,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