TwelvedataRuby

TwelvedataRuby is a Ruby library that exposes some convenient ways to access Twelve Data API to get information on stock, forex, crypto, and other financial market data. In order to do so, a free API key is required which can be easily requested here. Visit their API’s full documentation

Installation

Add this line to your application’s Gemfile:

ruby gem 'twelvedata_ruby'

And then execute:

$ bundle install

Or install it yourself as:

$ gem install twelvedata_ruby

Usage

The preferred way to include the Twelve Data API key in the request payload is to assign it to an ENVIRONMENT variable which your Ruby application can fetch if none was explicitly assigned. The default ENVIRONMENTt variable name is TWELVEDATA_API_KEY but you can configure this to any other value using the #apikey_env_var_name= setter method.

To get hold of the singleton TwelvedataRuby::Client.instance, you can directly used that inherited instance method from the mixed in Singleton module or thru the gem’s module helper class method:

ruby require "twelvedata_ruby" client = TwelvedataRuby.client

By not passing anything to the options method parameters, the client instance attributes will have default values. Though you can still set different values to the attributes through their helper setter methods:

ruby client.apikey = "twelvedata-apikey" client.apikey_env_var_name = "the_environment_variable_name" # the helper getter method will upcase the value client.connect_timeout = 300 # can also accept "300"

or simply set them all at once:

ruby require "twelvedata_ruby" client = TwelvedataRuby.client(apikey: "twelvedata-apikey", connect_timeout: 300) # or client = TwelvedataRuby.client(apikey_env_var_name: "the_environment_variable_name", connect_timeout: 300)

The default values though are sufficient already.

Getting any type of financial data then from the API, simply invoke any valid endpoint name to the client instance. For example, to fetch some data for GOOG stock symbol using quote, timeseries, price, and etd API endpoints:

ruby # 1. response content-type will be :csv client.quote(symbol: "GOOG", format: :csv) # 2. assigns custom attachment name client.timeseries(symbol: "GOOG", interval: "1hour", format: :csv, filename: "google_timeseries_1hour.csv") # 3. the content-type format will be :json client.price(symbol: "GOOG") # 4. the passed apikey is the used in the request payload client.etd(symbol: "GOOG", apikey: "overrides-whatever-is-the-current-apikey") # 5. an example of invocation which the API will respond with 401 error code client.etd(symbol: "GOOG", apikey: "invalid-api-key") # 6. still exactly the same object with client TwelvedataRuby.client.api_usage # 7. an invalid request wherein the required query parameter :interval is missing TwelvedataRuby.client.timeseries(symbol: "GOOG") # 8. an invalid request because it contains an invalid parameter client.price(symbol: "GOOG", invalid_parameter: "value") # 9. invoking a non-existing API endpoint will cause a NoMethodError exception client.price(symbol: "GOOG", invalid_parameter: "value")

All of the invocations possible return instance value is one of the following: - TwelvedataRuby::Response instance object which #error instance getter method can return a nil or kind of TwelvedataRuby::ResponseError instance if the API, or the API web server responded with some errors. #5 is an example which the API response will have status error with 401 code. TwelvedataRuby::Response resolves this into TwelvedataRuby::UnauthorizedResponseError instance. - TwelvedataRuby::ResponseError instance object itself when some error occurred that’s not coming from the API - a Hash instance which has an :errors key that contains instances of kind TwelvedataRuby::EndpointError. This is an invalid request scenario which the #7, #8, and #9 examples. No actual API request was sent in this scenario.

On first invocation of a valid endpoint name, a TwelvedataRuby::Client instance method of the same name is dynamically defined. So in effect, ideally, there can be a one-to-one mapping of all the API endpoints with their respective parameters constraints. Please visit their excellent API documentation to know more of the endpoint details here https://twelvedata.com/doc. Or if you’re in a hurry, you can list the endpoints definitions:

ruby TwelvedataRuby::Endpoint.definitions

Another way of fetching data from API endpoints is by building a valid TwelvedataRuby::Request instance, then invoke #fetch on this instance. The possible return values are the same with the above examples.

ruby quote_req = TwelvedataRuby::Request.new(:quote, symbol: "IBM") quote_resp = quote_req.fetch timeseries_req = TwelvedataRuby::Request.new(:quote, symbol: "IBM", interval: "1hour", format: :csv) timeseries_resp = timeseries_req.fetch etd_req = TwelvedataRuby::Request.new(:etd, symbol: "GOOG") etd_resp = etd_req.fetch # or just simply chain price_resp = TwelvedataRuby::Request.new(:price, symbol: "GOOG").fetch

An advantage of building a valid request instance first then invoke the #fetch on it is you actually have an option to not send the request one by one BUT rather send them to the API server all at once simultaneously (might be in parallel). Like so taking the above examples’ request instance objects, send them all simultaneously

ruby # returns a 3 element array of Response objects resp_objects_array = TwelvedataRuby::Client.request(quote_req, timeseries_req, etd_req)

Be caution that the above example, depending on the number request objects sent and how large the responses, hitting the daily limit is likely possible. But then again if you have several api keys you might be able to supply each request object with its own apikey. :)

The data from a successful API request can be access from Response#parsed_body. If request format is :json then it will be a Hash instance

ruby TwelvedataRuby.client.quote(symbol: "GOOG").parsed_body => {:symbol=>"GOOG", :name=>"Alphabet Inc", :exchange=>"NASDAQ", :currency=>"USD", :datetime=>"2021-07-15", :open=>"2650.00000", :high=>"2651.89990", :low=>"2611.95996", :close=>"2625.33008", :volume=>"828300", :previous_close=>"2641.64990", :change=>"-16.31982", :percent_change=>"-0.61779", :average_volume=>"850344", :fifty_two_week=>{:low=>"1406.55005", :high=>"2659.91992", :low_change=>"1218.78003", :high_change=>"-34.58984", :low_change_percent=>"86.65031", :high_change_percent=>"-1.30041", :range=>"1406.550049 - 2659.919922"}}

Likewise, if the API request format is :csv then Response#parsed_body will be CSV#Table instance

ruby TwelvedataRuby.client.quote(symbol: "GOOG", format: :csv).parsed_body => #<CSV::Table mode:col_or_row row_count:2>

Documentation

You can browse the source code documentation ## Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/twelvedata_ruby. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.

License

The gem is available as open source under the terms of the MIT License.

Code of Conduct

Everyone interacting in the TwelvedataRuby project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.

Notice

This is not an offical Twelve Data ruby library and the author of this gem is not affiliated with Twelve Data in any way, shape or form. Twelve Data APIs and data are Copyright © 2020 Twelve Data Pte. Ltd