massiveclient 0.3.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.
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MassiveClient
4
+ module Rest
5
+ class Forex < PolygonRestHandler
6
+ class HistoricTicksResponse < PolygonResponse
7
+ attribute? :day, Types::JSON::Date
8
+ attribute? :map, Types::Hash
9
+ attribute? :ms_latency, Types::Integer
10
+ attribute? :status, Types::String
11
+ attribute? :pair, Types::String
12
+ attribute? :type, Types::String
13
+ attribute :ticks, Types::Array do
14
+ attribute? :a, Types::JSON::Decimal # Asking price
15
+ attribute? :b, Types::JSON::Decimal # Bidding price
16
+ attribute? :x, Types::Integer # Exchange ID
17
+ attribute? :t, Types::Integer
18
+ end
19
+ end
20
+
21
+ def historic_ticks(from, to, date, opts = {})
22
+ from = Types::String[from]
23
+ to = Types::String[to]
24
+ date = Types::JSON::Date[date]
25
+ opts = PagingParameters[opts]
26
+
27
+ res = client.request.get("/v1/historic/forex/#{from}/#{to}/#{date}", opts.to_h)
28
+ HistoricTicksResponse[res.body]
29
+ end
30
+
31
+ class CurrencyConversionResponse < PolygonResponse
32
+ attribute :status, Types::String
33
+ attribute :from, Types::String
34
+ attribute :to, Types::String
35
+ attribute :initial_amount, Types::Integer
36
+ attribute :converted, Types::JSON::Decimal
37
+ attribute :last do
38
+ attribute :bid, Types::JSON::Decimal
39
+ attribute :ask, Types::JSON::Decimal
40
+ attribute :exchange, Types::Integer
41
+ attribute :timestamp, Types::Integer
42
+ end
43
+ end
44
+
45
+ def convert_currency(from, to, amount, precision = 2)
46
+ from = Types::String[from]
47
+ to = Types::String[to]
48
+ amount = Types::Coercible::Decimal[amount]
49
+ precision = Types::Integer[precision]
50
+ opts = { amount: amount, precision: precision }
51
+
52
+ res = client.request.get("/v1/conversion/#{from}/#{to}", opts)
53
+ CurrencyConversionResponse[res.body]
54
+ end
55
+
56
+ class LastQuoteResponse < PolygonResponse
57
+ attribute :status, Types::String
58
+ attribute :symbol, Types::String
59
+ attribute :last do
60
+ attribute :bid, Types::JSON::Decimal
61
+ attribute :ask, Types::JSON::Decimal
62
+ attribute :exchange, Types::Integer
63
+ attribute :timestamp, Types::Integer
64
+ end
65
+ end
66
+
67
+ def last_quote(from, to)
68
+ from = Types::String[from]
69
+ to = Types::String[to]
70
+
71
+ res = client.request.get("/v1/last_quote/currencies/#{from}/#{to}")
72
+ LastQuoteResponse[res.body]
73
+ end
74
+
75
+ class SnapshotTicker < PolygonResponse
76
+ attribute :ticker, Types::String
77
+ attribute :day do
78
+ attribute :c, Types::JSON::Decimal
79
+ attribute :h, Types::JSON::Decimal
80
+ attribute :l, Types::JSON::Decimal
81
+ attribute :o, Types::JSON::Decimal
82
+ attribute :v, Types::JSON::Decimal
83
+ end
84
+ attribute :last_quote do
85
+ attribute :a, Types::JSON::Decimal
86
+ attribute :b, Types::JSON::Decimal
87
+ attribute :i, Types::JSON::Decimal
88
+ attribute :x, Types::Integer
89
+ attribute :t, Types::Integer
90
+ end
91
+ attribute :min do
92
+ attribute :c, Types::JSON::Decimal
93
+ attribute :h, Types::JSON::Decimal
94
+ attribute :l, Types::JSON::Decimal
95
+ attribute :o, Types::JSON::Decimal
96
+ attribute :v, Types::JSON::Decimal
97
+ end
98
+ attribute :prev_day do
99
+ attribute :c, Types::JSON::Decimal
100
+ attribute :h, Types::JSON::Decimal
101
+ attribute :l, Types::JSON::Decimal
102
+ attribute :o, Types::JSON::Decimal
103
+ attribute :v, Types::JSON::Decimal
104
+ end
105
+ attribute :todays_change, Types::JSON::Decimal
106
+ attribute :todays_change_perc, Types::JSON::Decimal
107
+ attribute :updated, Types::Integer
108
+ end
109
+
110
+ class FullSnapshotResponse < PolygonResponse
111
+ attribute :status, Types::String
112
+ attribute :tickers, Types::Array.of(SnapshotTicker)
113
+ end
114
+
115
+ def full_snapshot
116
+ res = client.request.get("/v2/snapshot/locale/global/markets/forex/tickers")
117
+ FullSnapshotResponse[res.body]
118
+ end
119
+
120
+ class SnapshotGainersLosersResponse < FullSnapshotResponse; end
121
+
122
+ def snapshot_gainers_losers(direction)
123
+ direction = Types::Coercible::String.enum("gainers", "losers")[direction]
124
+ res = client.request.get("/v2/snapshot/locale/global/markets/forex/#{direction}")
125
+ SnapshotGainersLosersResponse[res.body]
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MassiveClient
4
+ module Rest
5
+ module Reference
6
+ class Locales < PolygonRestHandler
7
+ class LocalesResponse < PolygonResponse
8
+ attribute :status, Types::String
9
+ attribute :results, Types::Array do
10
+ attribute :locale, Types::String
11
+ attribute :name, Types::String
12
+ end
13
+ end
14
+
15
+ def list
16
+ res = client.request.get("/v2/reference/locales")
17
+ LocalesResponse[res.body]
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MassiveClient
4
+ module Rest
5
+ module Reference
6
+ class Markets < PolygonRestHandler
7
+ class MarketsResponse < PolygonResponse
8
+ attribute :status, Types::String
9
+ attribute :results, Types::Array do
10
+ attribute :market, Types::String
11
+ attribute :desc, Types::String
12
+ end
13
+ end
14
+
15
+ def list
16
+ res = client.request.get("/v2/reference/markets")
17
+ MarketsResponse[res.body]
18
+ end
19
+
20
+ class MarketStatusResponse < PolygonResponse
21
+ attribute :market, Types::String
22
+ attribute :server_time, Types::String
23
+ attribute :exchanges do
24
+ attribute :nyse, Types::String
25
+ attribute :nasdaq, Types::String
26
+ attribute :otc, Types::String
27
+ end
28
+ attribute :currencies do
29
+ attribute :fx, Types::String
30
+ attribute :crypto, Types::String
31
+ end
32
+ end
33
+
34
+ def status
35
+ res = client.request.get("/v1/marketstatus/now")
36
+ MarketStatusResponse[res.body]
37
+ end
38
+
39
+ class MarketHolidaysResponse < PolygonResponse
40
+ attribute :exchange, Types::String
41
+ attribute :name, Types::String
42
+ attribute :status, Types::String
43
+ attribute :date, Types::JSON::DateTime
44
+ attribute? :open, Types::JSON::DateTime
45
+ attribute? :close, Types::JSON::DateTime
46
+ end
47
+
48
+ def holidays
49
+ res = client.request.get("/v1/marketstatus/upcoming")
50
+ Types::Array.of(MarketHolidaysResponse)[res.body]
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MassiveClient
4
+ module Rest
5
+ module Reference
6
+ class Stocks < PolygonRestHandler
7
+ class StockSplitsResponse < PolygonResponse
8
+ attribute :status, Types::String
9
+ attribute :count, Types::Integer
10
+ attribute :results, Types::Array do
11
+ attribute :ticker, Types::String
12
+ attribute :ex_date, Types::JSON::Date
13
+ attribute :payment_date, Types::JSON::Date
14
+ attribute? :record_date, Types::JSON::Date
15
+ attribute? :declared_date, Types::JSON::Date
16
+ attribute :ratio, Types::JSON::Decimal
17
+ attribute? :to_factor, Types::Integer
18
+ attribute? :for_factor, Types::Integer
19
+ end
20
+ end
21
+
22
+ def splits(symbol)
23
+ res = client.request.get("/v2/reference/splits/#{symbol}")
24
+ StockSplitsResponse[res.body]
25
+ end
26
+
27
+ class StockDividendsResponse < PolygonResponse
28
+ attribute :status, Types::String
29
+ attribute :count, Types::Integer
30
+ attribute :results, Types::Array do
31
+ attribute :ticker, Types::String
32
+ attribute? :type, Types::String
33
+ attribute :ex_date, Types::String
34
+ attribute :payment_date, Types::JSON::Date
35
+ attribute :record_date, Types::JSON::Date
36
+ attribute? :declared_date, Types::JSON::Date
37
+ attribute :amount, Types::JSON::Decimal
38
+ attribute? :qualified, Types::String
39
+ attribute? :flag, Types::String
40
+ end
41
+ end
42
+
43
+ def dividends(symbol)
44
+ res = client.request.get("/v2/reference/dividends/#{symbol}")
45
+ StockDividendsResponse[res.body]
46
+ end
47
+
48
+ class StockFinancialsResponse < PolygonResponse
49
+ attribute :status, Types::String
50
+ attribute? :count, Types::Integer
51
+ # I'm lazy and didn't want to copy every field here. Please submit PR if you want to crack at it!
52
+ attribute :results, Types::Array.of(Types::Hash)
53
+ end
54
+
55
+ class StockFinancialsParameters < Dry::Struct
56
+ attribute? :limit, Types::Integer
57
+ attribute? :type, Types::String.enum("Y", "YA", "Q", "QA", "T", "TA")
58
+ attribute? :sort, Types::String.enum("reportPeriod", "-reportPeriod", "calendarDate", "-calendarDate")
59
+ end
60
+
61
+ def financials(symbol, params = {})
62
+ params = StockFinancialsParameters[params]
63
+
64
+ res = client.request.get("/v2/reference/financials/#{symbol}", params.to_h)
65
+ StockFinancialsResponse[res.body]
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,136 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MassiveClient
4
+ module Rest
5
+ module Reference
6
+ class Tickers < PolygonRestHandler
7
+ class Ticker < PolygonResponse
8
+ attribute :ticker, Types::String
9
+ attribute :name, Types::String
10
+ attribute :market, Types::String
11
+ attribute :locale, Types::String
12
+ attribute? :primary_exchange, Types::String
13
+ attribute? :type, Types::String
14
+ attribute :active, Types::Bool
15
+ attribute? :currency_name, Types::String
16
+ attribute? :cik, Types::String
17
+ attribute? :composite_figi, Types::String
18
+ attribute? :share_class_figi, Types::String
19
+ attribute? :last_updated_utc, Types::String
20
+ end
21
+
22
+ class TickerResponse < PolygonResponse
23
+ attribute :status, Types::String
24
+ attribute :results, Types::Array.of(Ticker)
25
+ attribute? :next_url, Types::String
26
+ attribute? :count, Types::Integer
27
+ end
28
+
29
+ class TickersParameters < Dry::Struct
30
+ attribute? :sort, Types::String
31
+ attribute? :type, Types::String
32
+ attribute? :market, Types::String
33
+ attribute? :locale, Types::String
34
+ attribute? :search, Types::String
35
+ attribute? :perpage, Types::String
36
+ attribute? :page, Types::Integer
37
+ attribute? :active, Types::Bool
38
+ end
39
+
40
+ def list(params = {})
41
+ params = TickersParameters[params]
42
+ res = client.request.get("/v3/reference/tickers", params.to_h)
43
+ TickerResponse[res.body]
44
+ end
45
+
46
+ class TickerTypesResponse < PolygonResponse
47
+ attribute :status, Types::String
48
+ attribute :results do
49
+ attribute :types, Types::Hash
50
+ attribute :index_types, Types::Hash
51
+ end
52
+ end
53
+
54
+ def types
55
+ res = client.request.get("/v2/reference/types")
56
+ TickerTypesResponse[res.body]
57
+ end
58
+
59
+ class TickerDetailsResponse < PolygonResponse
60
+ attribute? :logo, Types::String
61
+ attribute :exchange, Types::String
62
+ attribute :exchange_symbol, Types::String
63
+ attribute :name, Types::String
64
+ attribute :symbol, Types::String
65
+ attribute? :listdate, Types::JSON::Date
66
+ attribute? :cik, Types::String
67
+ attribute? :bloomberg, Types::String
68
+ attribute? :figi, Types::String.optional
69
+ attribute? :lie, Types::String
70
+ attribute? :sic, Types::Integer
71
+ attribute? :country, Types::String
72
+ attribute? :industry, Types::String
73
+ attribute? :sector, Types::String
74
+ attribute? :marketcap, Types::Integer
75
+ attribute? :employees, Types::Integer
76
+ attribute? :phone, Types::String
77
+ attribute? :ceo, Types::String
78
+ attribute? :url, Types::String
79
+ attribute? :description, Types::String
80
+ attribute? :similar, Types::Array
81
+ attribute? :tags, Types::Array
82
+ attribute? :hq_address, Types::String
83
+ attribute? :hq_state, Types::String
84
+ attribute? :hq_country, Types::String
85
+ attribute? :active, Types::Bool
86
+ attribute? :updated, Types::String
87
+ end
88
+
89
+ def details(symbol)
90
+ symbol = Types::String[symbol]
91
+ res = client.request.get("/v1/meta/symbols/#{symbol}/company")
92
+ TickerDetailsResponse[res.body]
93
+ end
94
+
95
+ class NewsResponse < PolygonResponse
96
+ attribute :status, Types::String
97
+ attribute :results, Types::Array do
98
+ attribute? :id, Types::String
99
+ attribute? :publisher do
100
+ attribute? :name, Types::String
101
+ attribute? :homepage_url, Types::String
102
+ attribute? :logo_url, Types::String
103
+ attribute? :favicon_url, Types::String
104
+ end
105
+ attribute :title, Types::String
106
+ attribute? :author, Types::String
107
+ attribute :published_utc, Types::String
108
+ attribute :article_url, Types::String
109
+ attribute :tickers, Types::Array.of(Types::String)
110
+ attribute? :amp_url, Types::String
111
+ attribute? :image_url, Types::String
112
+ attribute? :description, Types::String
113
+ attribute? :keywords, Types::Array.of(Types::String)
114
+ attribute? :insights, Types::Array do
115
+ attribute :ticker, Types::String
116
+ attribute :sentiment, Types::String
117
+ attribute :sentiment_reasoning, Types::String
118
+ end
119
+ end
120
+ attribute? :count, Types::Integer
121
+ attribute? :next_url, Types::String
122
+ attribute? :request_id, Types::String
123
+ end
124
+
125
+ def news(ticker, limit = 10)
126
+ ticker = Types::String[ticker]
127
+ limit = Types::Integer[limit]
128
+ opts = { ticker: ticker, limit: limit }
129
+
130
+ res = client.request.get("/v2/reference/news", opts)
131
+ NewsResponse[res.body]
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end