async-polygon 0.1.0

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: 72601ebefe1b4076f1e0023b517cac7f59003ec1e656a7eb7c236503b77f4e44
4
+ data.tar.gz: f9ad0cf70c8555c8a11a2daeb8ef04621478e4994664e1c137474458f9223e20
5
+ SHA512:
6
+ metadata.gz: b6964250f6fdc464898ec480030f5b68991a7805ebf18c68eae89569f8028ec6f0de50344332c6f3121f4cd4b80efbad8f3551939a3794248d18b9a8fb4bacf7
7
+ data.tar.gz: 31afcacc010c7b687c91c0bfad8e1574607a42986eb4d7287703bc01b49716eb0bcd7da927512050fb320cecaa46f8a3b639412746655f6cc227707ab3036539
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2024 William T. Nelson
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,68 @@
1
+ # Async::Polygon
2
+
3
+ A stub asynchronous HTTP/2 client for [polygon.io](https://polygon.io/docs/). Made with [async-http](https://github.com/socketry/async-http).
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ gem install async-polygon
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Create a client
14
+
15
+ An API key is required and can be set in the `POLYGON_API_KEY` environment variable or specified at client initialization:
16
+
17
+ ```ruby
18
+ client = Async::Polygon::Client.new api_key: '2qKgb9s3qUIwt6B2zGSqrVe6H5v44y6m'
19
+ ```
20
+
21
+ By default, requests are rate limited to 5 per minute. For subscription tiers above basic, initialize a client with `basic: false` to remove the restriction.
22
+
23
+ ### Make a request
24
+
25
+ ```ruby
26
+ uri = URI 'https://api.polygon.io/v3/reference/tickers'
27
+ uri.query = URI.encode_www_form ticker: 'SPY', date: '2024-10-04'
28
+ client = Async::Polygon::Client.new
29
+ res = client.get uri
30
+ fail if ! res.success?
31
+ data = JSON.parse res.read
32
+ ```
33
+
34
+ ### Make requests asynchronously
35
+
36
+ ```ruby
37
+ client = Async::Polygon::Client.new basic: false
38
+ ticker_symbols = %w[AAPL MSFT NVDA GOOGL AMZN BRK.A WMT JPM AFMJF FLMMF NGXXF]
39
+ date = Date.new 2024, 10, 4
40
+ count = 99
41
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
42
+
43
+ Sync do
44
+ count.times do
45
+ Async do
46
+ uri = URI 'https://api.polygon.io/v3/reference/tickers'
47
+ uri.query = URI.encode_www_form ticker: ticker_symbols.sample, date: date.to_s
48
+ res = client.get uri
49
+ fail if ! res.success?
50
+ end
51
+ end
52
+ end
53
+
54
+ finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
55
+ duration = finish - start
56
+
57
+ puts "#{duration.round 2} seconds elapsed (#{(count/duration).round 2} per sec)"
58
+ ```
59
+
60
+ Starting with the hundredth request, non-basic clients are rate limited [per usage recommendations](https://polygon.io/knowledge-base/article/what-is-the-request-limit-for-polygons-restful-apis).
61
+
62
+ ## TODO
63
+
64
+ * Add a WebSocket client using [async-websocket](https://github.com/socketry/async-websocket).
65
+
66
+ ## License
67
+
68
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'minitest/test_task'
5
+
6
+ Minitest::TestTask.create
7
+
8
+ task default: :test
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'async/http'
4
+
5
+ module Async
6
+ module Polygon
7
+ class Client
8
+ def initialize(api_key: ENV['POLYGON_API_KEY'], basic: true)
9
+ api_key.to_s.length == 32 \
10
+ or raise ArgumentError, 'API key required'
11
+ set_pace basic
12
+ @auth_headers = {'authorization' => "Bearer #{api_key}"}
13
+ @client = Async::HTTP::Internet.new
14
+ @request_semaphore = Async::Semaphore.new @reconnect_after
15
+ @completion_semaphore = Async::Semaphore.new @reconnect_after
16
+ @reset_mutex = Mutex.new
17
+ end
18
+
19
+ def get(uri)
20
+ ensure_client_readiness
21
+ @request_semaphore.acquire
22
+ @completion_semaphore.acquire do
23
+ Sync do
24
+ @client.get uri, @auth_headers
25
+ end
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def set_pace(basic)
32
+ if basic
33
+ @reconnect_after = 5 # free tier
34
+ @reset_delay = 60
35
+ else
36
+ @reconnect_after = 99 # go fast
37
+ @reset_delay = 1
38
+ end
39
+ end
40
+
41
+ def ensure_client_readiness
42
+ if @request_semaphore.blocking? # time to reset
43
+ Sync do
44
+ @reset_mutex.synchronize do
45
+ return if ! @request_semaphore.blocking?
46
+ @reconnect_after.times { @completion_semaphore.acquire } # wait for requests
47
+ @client.close
48
+ @client = Async::HTTP::Internet.new
49
+ sleep @reset_delay
50
+ @reconnect_after.times { @completion_semaphore.release }
51
+ @reconnect_after.times { @request_semaphore.release }
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Async
4
+ module Polygon
5
+ VERSION = '0.1.0'
6
+ end
7
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'polygon/version'
4
+ require_relative 'polygon/client'
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: async-polygon
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - William T. Nelson
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-10-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: async-http
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.80'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.80'
27
+ description:
28
+ email:
29
+ - 35801+wtn@users.noreply.github.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - LICENSE.txt
35
+ - README.md
36
+ - Rakefile
37
+ - lib/async/polygon.rb
38
+ - lib/async/polygon/client.rb
39
+ - lib/async/polygon/version.rb
40
+ homepage: https://github.com/wtn/async-polygon
41
+ licenses:
42
+ - MIT
43
+ metadata: {}
44
+ post_install_message:
45
+ rdoc_options: []
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 3.0.0
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ requirements: []
59
+ rubygems_version: 3.5.20
60
+ signing_key:
61
+ specification_version: 4
62
+ summary: async client for polygon.io
63
+ test_files: []