polygonio-ruby 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 0025e44c36af5a1d8091cca11ac55ebf929a3dae3ecde2f047bf6d4effb46d52
4
+ data.tar.gz: 0306c02483d4f80046c64adb45b3062b49c4bb5c979708d1c096c95b397e1087
5
+ SHA512:
6
+ metadata.gz: e4026dea18165f8554ac3f66c28460a85f15a8caba691eaf3c9dfde7f91d9a2f10ac419f87ece14eed5af0548bb3b29d54ab8a537a8c92720f5f51fa63f6026d
7
+ data.tar.gz: '01865cb6d541ed0e6d49c9c0897528bb98c9f89581d906f023a4578e9b9689c5f920834c80a3f23e3b35458086f831f7261a4ed6d1c39af3d85908d4e3f51dd1'
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ .env
2
+ pkg
data/.rubocop.yml ADDED
@@ -0,0 +1,49 @@
1
+ require:
2
+ - rubocop-performance
3
+
4
+ AllCops:
5
+ TargetRubyVersion: 2.6.0
6
+ DisabledByDefault: false
7
+ Exclude:
8
+ - '**/vendor/**/*'
9
+ - 'bin/**/*'
10
+
11
+ Layout/LineLength:
12
+ Max: 120
13
+
14
+ Metrics/AbcSize:
15
+ Max: 24
16
+
17
+ Metrics/CyclomaticComplexity:
18
+ Max: 10
19
+
20
+ Metrics/PerceivedComplexity:
21
+ Max: 10
22
+
23
+ Style/StringLiterals:
24
+ EnforcedStyle: double_quotes
25
+
26
+ Style/Documentation:
27
+ Enabled: false
28
+
29
+ Style/SymbolArray:
30
+ EnforcedStyle: brackets
31
+
32
+ Style/AccessModifierDeclarations:
33
+ EnforcedStyle: group
34
+
35
+ Style/HashEachMethods:
36
+ Enabled: true
37
+
38
+ Style/HashTransformKeys:
39
+ Enabled: true
40
+
41
+ Style/HashTransformValues:
42
+ Enabled: true
43
+
44
+ Layout/MultilineMethodCallIndentation:
45
+ EnforcedStyle: indented_relative_to_receiver
46
+
47
+ Performance:
48
+ Exclude:
49
+ - '**/test/**/*'
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in gatekeeper_client.gemspec
6
+ gemspec
data/README.md ADDED
@@ -0,0 +1,50 @@
1
+ # Polygonio (Ruby)
2
+
3
+ ## Table of Contents
4
+
5
+ - [Background](#background)
6
+ - [Installation](#installation)
7
+ - [Usage](#usage)
8
+
9
+ ## Background
10
+
11
+ This is a client library for Polygon.io. Please see [Polygon.io](https://polygon.io)
12
+
13
+ ## Installation
14
+
15
+ Add this line to your application's Gemfile:
16
+
17
+ ```ruby
18
+ gem 'polygonio'
19
+ ```
20
+
21
+ And then execute:
22
+
23
+ $ bundle install
24
+
25
+
26
+ ## Usage
27
+
28
+ **Create an instance of the client:**
29
+
30
+ All methods follow the documentation found [here]:https://polygon.io/docs pretty closely:
31
+
32
+
33
+
34
+ ```ruby
35
+ client = Polygonio::Rest::Client.new(api_key)
36
+
37
+ # See tests for a full reference of all of methods
38
+ client.reference.tickers.list
39
+
40
+ client.stocks.list_exchanges
41
+
42
+ client.forex.historic_ticks
43
+
44
+ client.crypto.list # list exchanges
45
+
46
+ Polygonio::Websocket::Client.new("crypto", api_key).subscribe("XQ.BTC-USD") do |event|
47
+ pp "Incoming message"
48
+ pp event
49
+ end
50
+ ```
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rake/testtask"
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << "test"
8
+ t.libs << "lib"
9
+ t.test_files = FileList["test/**/*_test.rb"]
10
+ end
11
+
12
+ task default: :test
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "polygonio"
5
+ require "dotenv/load"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require "irb"
15
+ IRB.start(__FILE__)
@@ -0,0 +1,198 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Polygonio
4
+ module Rest
5
+ class Crypto < PolygonRestHandler
6
+ class CryptoExchange < PolygonResponse
7
+ attribute :id, Types::Integer
8
+ attribute :type, Types::String
9
+ attribute :market, Types::String
10
+ attribute :name, Types::String
11
+ attribute :url, Types::String
12
+ end
13
+
14
+ def list
15
+ res = client.request.get("/v1/meta/crypto-exchanges")
16
+ Types::Array.of(CryptoExchange)[res.body]
17
+ end
18
+
19
+ class LastTradeResponse < PolygonResponse
20
+ attribute :status, Types::String
21
+ attribute :symbol, Types::String
22
+ attribute :last do
23
+ attribute :price, Types::JSON::Decimal
24
+ attribute :size, Types::JSON::Decimal
25
+ attribute :exchange, Types::Integer
26
+ attribute :conditions, Types::Array.of(Types::Integer)
27
+ attribute :timestamp, Types::Integer
28
+ end
29
+ attribute :last_average do
30
+ attribute :avg, Types::JSON::Decimal
31
+ attribute :trades_averaged, Types::Integer
32
+ end
33
+ end
34
+
35
+ def last_trade(from, to)
36
+ from = Types::String[from]
37
+ to = Types::String[to]
38
+
39
+ res = client.request.get("/v1/last/crypto/#{from}/#{to}")
40
+ LastTradeResponse[res.body]
41
+ end
42
+
43
+ class DailyOpenCloseResponse < PolygonResponse
44
+ attribute :symbol, Types::String
45
+ attribute :is_utc, Types::Bool
46
+ attribute :day, Types::JSON::Date
47
+ attribute :open, Types::JSON::Decimal
48
+ attribute :close, Types::JSON::Decimal
49
+ attribute :open_trades, Types::Array do
50
+ attribute? :p, Types::JSON::Decimal
51
+ attribute? :s, Types::JSON::Decimal
52
+ attribute? :x, Types::Integer
53
+ attribute? :c, Types::Array.of(Types::Integer)
54
+ attribute? :t, Types::Integer
55
+ end
56
+ attribute :closing_trades, Types::Array do
57
+ attribute? :p, Types::JSON::Decimal
58
+ attribute? :s, Types::JSON::Decimal
59
+ attribute? :x, Types::Integer
60
+ attribute? :c, Types::Array.of(Types::Integer)
61
+ attribute? :t, Types::Integer
62
+ end
63
+ end
64
+
65
+ def daily_open_close(from, to, date)
66
+ from = Types::String[from]
67
+ to = Types::String[to]
68
+ date = Types::JSON::Date[date]
69
+
70
+ res = client.request.get("/v1/open-close/crypto/#{from}/#{to}/#{date}")
71
+ DailyOpenCloseResponse[res.body]
72
+ end
73
+
74
+ class HistoricTradesResponse < PolygonResponse
75
+ attribute? :day, Types::JSON::Date
76
+ attribute? :map, Types::Hash
77
+ attribute? :ms_latency, Types::Integer
78
+ attribute? :status, Types::String
79
+ attribute? :symbol, Types::String
80
+ attribute? :type, Types::String
81
+ attribute :ticks, Types::Array do
82
+ attribute? :p, Types::JSON::Decimal
83
+ attribute? :s, Types::JSON::Decimal
84
+ attribute? :x, Types::Integer
85
+ attribute? :c, Types::Array.of(Types::Integer)
86
+ attribute? :t, Types::Integer
87
+ end
88
+ end
89
+
90
+ def historic_trades(from, to, date, opts = {})
91
+ from = Types::String[from]
92
+ to = Types::String[to]
93
+ date = Types::JSON::Date[date]
94
+ opts = PagingParameters[opts]
95
+
96
+ res = client.request.get("/v1/historic/crypto/#{from}/#{to}/#{date}", opts.to_h)
97
+ HistoricTradesResponse[res.body]
98
+ end
99
+
100
+ class SnapshotTicker < PolygonResponse
101
+ attribute :ticker, Types::String
102
+ attribute :day do
103
+ attribute :c, Types::JSON::Decimal
104
+ attribute :h, Types::JSON::Decimal
105
+ attribute :l, Types::JSON::Decimal
106
+ attribute :o, Types::JSON::Decimal
107
+ attribute :v, Types::JSON::Decimal
108
+ end
109
+ attribute :last_trade do
110
+ attribute :p, Types::JSON::Decimal
111
+ attribute :s, Types::JSON::Decimal
112
+ attribute :x, Types::Integer
113
+ attribute :c, Types::Array.of(Types::Integer)
114
+ attribute :t, Types::Integer
115
+ end
116
+ attribute :min do
117
+ attribute :c, Types::JSON::Decimal
118
+ attribute :h, Types::JSON::Decimal
119
+ attribute :l, Types::JSON::Decimal
120
+ attribute :o, Types::JSON::Decimal
121
+ attribute :v, Types::JSON::Decimal
122
+ end
123
+ attribute :prev_day do
124
+ attribute :c, Types::JSON::Decimal
125
+ attribute :h, Types::JSON::Decimal
126
+ attribute :l, Types::JSON::Decimal
127
+ attribute :o, Types::JSON::Decimal
128
+ attribute :v, Types::JSON::Decimal
129
+ end
130
+ attribute :todays_change, Types::JSON::Decimal
131
+ attribute :todays_change_perc, Types::JSON::Decimal
132
+ attribute :updated, Types::Integer
133
+ end
134
+
135
+ class FullSnapshotResponse < PolygonResponse
136
+ attribute :status, Types::String
137
+ attribute :tickers, Types::Array.of(SnapshotTicker)
138
+ end
139
+
140
+ def full_snapshot
141
+ res = client.request.get("/v2/snapshot/locale/global/markets/crypto/tickers")
142
+ FullSnapshotResponse[res.body]
143
+ end
144
+
145
+ class SnapshotResponse < PolygonResponse
146
+ attribute :status, Types::String
147
+ attribute :ticker, SnapshotTicker
148
+ end
149
+
150
+ def snapshot(ticker)
151
+ ticker = Types::String[ticker]
152
+ res = client.request.get("/v2/snapshot/locale/global/markets/crypto/tickers/#{ticker}")
153
+ SnapshotResponse[res.body]
154
+ end
155
+
156
+ class SnapshotBookResponse < PolygonResponse
157
+ attribute :status, Types::String
158
+ attribute :data do
159
+ attribute :ticker, Types::String
160
+ attribute :bids, Types::Array do
161
+ attribute :p, Types::JSON::Decimal
162
+ attribute :x do
163
+ PolygonResponse::NUMBERS_TO_WORDS.each do |_n, w|
164
+ attribute? w.to_sym, Types::JSON::Decimal
165
+ end
166
+ end
167
+ end
168
+ attribute :asks, Types::Array do
169
+ attribute :p, Types::JSON::Decimal
170
+ attribute :x do
171
+ PolygonResponse::NUMBERS_TO_WORDS.each do |_n, w|
172
+ attribute? w.to_sym, Types::JSON::Decimal
173
+ end
174
+ end
175
+ end
176
+ attribute :bid_count, Types::JSON::Decimal
177
+ attribute :ask_count, Types::JSON::Decimal
178
+ attribute :spread, Types::JSON::Decimal
179
+ attribute :updated, Types::Integer
180
+ end
181
+ end
182
+
183
+ def snapshot_book(ticker)
184
+ ticker = Types::String[ticker]
185
+ res = client.request.get("/v2/snapshot/locale/global/markets/crypto/tickers/#{ticker}/book")
186
+ SnapshotBookResponse[res.body]
187
+ end
188
+
189
+ class SnapshotGainersLosersResponse < FullSnapshotResponse; end
190
+
191
+ def snapshot_gainers_losers(direction)
192
+ direction = Types::Coercible::String.enum("gainers", "losers")[direction]
193
+ res = client.request.get("/v2/snapshot/locale/global/markets/crypto/#{direction}")
194
+ SnapshotGainersLosersResponse[res.body]
195
+ end
196
+ end
197
+ end
198
+ end
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Polygonio
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 Polygonio
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 Polygonio
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 Polygonio
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