polygonio-ruby 0.2.8

Sign up to get free protection for your applications and to get access to all the features.
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