Class: TwelvedataRuby::Endpoint

Inherits:
Object
  • Object
show all
Defined in:
lib/twelvedata_ruby/endpoint.rb

Constant Summary collapse

DEFAULT_FORMAT =
:json
VALID_FORMATS =
[DEFAULT_FORMAT, :csv].freeze
DEFINITIONS =

Complete endpoint definitions with parameters and response structure

{
  api_usage: {
    parameters: { keys: %i[format] },
    response: { keys: %i[timestamp current_usage plan_limit] },
  },
  stocks: {
    parameters: { keys: %i[symbol exchange country type format] },
    response: { data_keys: %i[symbol name currency exchange country type], collection: :data },
  },
  forex_pairs: {
    parameters: { keys: %i[symbol currency_base currency_quote format] },
    response: { data_keys: %i[symbol currency_group currency_base currency_quote], collection: :data },
  },
  cryptocurrencies: {
    parameters: { keys: %i[symbol exchange currency_base currency_quote format] },
    response: { data_keys: %i[symbol available_exchanges currency_base currency_quote], collection: :data },
  },
  etf: {
    parameters: { keys: %i[symbol format] },
    response: { data_keys: %i[symbol name currency exchange], collection: :data },
  },
  indices: {
    parameters: { keys: %i[symbol country format] },
    response: { data_keys: %i[symbol name country currency], collection: :data },
  },
  exchanges: {
    parameters: { keys: %i[type name code country format] },
    response: { data_keys: %i[name country code timezone], collection: :data },
  },
  cryptocurrency_exchanges: {
    parameters: { keys: %i[name format] },
    response: { data_keys: %i[name], collection: :data },
  },
  technical_indicators: {
    parameters: { keys: [] },
    response: { keys: %i[enable full_name description type overlay parameters output_values tinting] },
  },
  symbol_search: {
    parameters: { keys: %i[symbol outputsize], required: %i[symbol] },
    response: {
      data_keys: %i[symbol instrument_name exchange exchange_timezone instrument_type country],
      collection: :data,
    },
  },
  earliest_timestamp: {
    parameters: { keys: %i[symbol interval exchange] },
    response: { keys: %i[datetime unix_time] },
  },
  time_series: {
    parameters: {
      keys: %i[
        symbol interval exchange country type outputsize format dp order timezone
        start_date end_date previous_close
      ],
      required: %i[symbol interval],
    },
    response: {
      value_keys: %i[datetime open high low close volume],
      collection: :values,
      meta_keys: %i[symbol interval currency exchange_timezone exchange type],
    },
  },
  quote: {
    parameters: {
      keys: %i[symbol interval exchange country volume_time_period type format],
      required: %i[symbol],
    },
    response: {
      keys: %i[
        symbol name exchange currency datetime open high low close volume
        previous_close change percent_change average_volume fifty_two_week
      ],
    },
  },
  price: {
    parameters: { keys: %i[symbol exchange country type format], required: %i[symbol] },
    response: { keys: %i[price] },
  },
  eod: {
    parameters: { keys: %i[symbol exchange country type prepost dp], required: %i[symbol] },
    response: { keys: %i[symbol exchange currency datetime close] },
  },
  exchange_rate: {
    parameters: { keys: %i[symbol format precision timezone], required: %i[symbol] },
    response: { keys: %i[symbol rate timestamp] },
  },
  currency_conversion: {
    parameters: { keys: %i[symbol amount format precision timezone], required: %i[symbol amount] },
    response: { keys: %i[symbol rate amount timestamp] },
  },
  complex_data: {
    parameters: {
      keys: %i[symbols intervals start_date end_date dp order timezone methods name],
      required: %i[symbols intervals start_date end_date],
    },
    response: { keys: %i[data status] },
    http_verb: :post,
  },
  earnings: {
    parameters: { keys: %i[symbol exchange country type period outputsize format], required: %i[symbol] },
    response: { keys: %i[date time eps_estimate eps_actual difference surprise_prc] },
  },
  earnings_calendar: {
    parameters: { keys: %i[format] },
    response: {
      keys: %i[
        symbol name currency exchange country time eps_estimate eps_actual difference surprise_prc
      ],
    },
  },
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, **query_params) ⇒ Endpoint

Initialize endpoint with name and parameters

Parameters:

  • name (Symbol, String)

    Endpoint name

  • query_params (Hash)

    Query parameters



180
181
182
183
184
# File 'lib/twelvedata_ruby/endpoint.rb', line 180

def initialize(name, **query_params)
  @errors = {}
  self.name = name
  self.query_params = query_params
end

Instance Attribute Details

#nameObject

Returns the value of attribute name.



174
175
176
# File 'lib/twelvedata_ruby/endpoint.rb', line 174

def name
  @name
end

#query_paramsObject

Returns the value of attribute query_params.



174
175
176
# File 'lib/twelvedata_ruby/endpoint.rb', line 174

def query_params
  @query_params
end

Class Method Details

.build_definitionsObject (private)



163
164
165
166
167
168
169
170
171
# File 'lib/twelvedata_ruby/endpoint.rb', line 163

def build_definitions
  DEFINITIONS.transform_values do |definition|
    enhanced_params = definition[:parameters].dup
    enhanced_params[:keys] = enhanced_params[:keys] + [:apikey]
    enhanced_params[:required] = (enhanced_params[:required] || []) + [:apikey]

    definition.merge(parameters: enhanced_params)
  end.freeze
end

.default_apikey_paramsHash

Get default API key parameters

Returns:

  • (Hash)

    Default parameters including API key



140
141
142
# File 'lib/twelvedata_ruby/endpoint.rb', line 140

def default_apikey_params
  { apikey: Client.instance.apikey }
end

.definitionsHash

Get processed endpoint definitions with apikey parameter added

Returns:

  • (Hash)

    Complete endpoint definitions



126
127
128
# File 'lib/twelvedata_ruby/endpoint.rb', line 126

def definitions
  @definitions ||= build_definitions
end

.namesArray<Symbol>

Get all valid endpoint names

Returns:

  • (Array<Symbol>)

    Array of endpoint names



133
134
135
# File 'lib/twelvedata_ruby/endpoint.rb', line 133

def names
  @names ||= definitions.keys
end

.valid_name?(name) ⇒ Boolean

Validate endpoint name

Parameters:

  • name (Symbol, String)

    Endpoint name to validate

Returns:

  • (Boolean)

    True if valid endpoint name



148
149
150
# File 'lib/twelvedata_ruby/endpoint.rb', line 148

def valid_name?(name)
  names.include?(name&.to_sym)
end

.valid_params?(name, **params) ⇒ Boolean

Validate endpoint parameters

Parameters:

  • name (Symbol, String)

    Endpoint name

  • params (Hash)

    Parameters to validate

Returns:

  • (Boolean)

    True if parameters are valid



157
158
159
# File 'lib/twelvedata_ruby/endpoint.rb', line 157

def valid_params?(name, **params)
  new(name, **params).valid?
end

Instance Method Details

#create_error(attr_name, invalid_values, error_class) ⇒ Object (private)



331
332
333
# File 'lib/twelvedata_ruby/endpoint.rb', line 331

def create_error(attr_name, invalid_values, error_class)
  error_class.new(endpoint: self, invalid: invalid_values)
end

#csv_format_with_filename?Boolean (private)

Returns:

  • (Boolean)


279
280
281
# File 'lib/twelvedata_ruby/endpoint.rb', line 279

def csv_format_with_filename?
  parameters&.dig(:keys)&.include?(:format) && query_params&.dig(:format) == :csv
end

#definitionHash?

Get endpoint definition

Returns:

  • (Hash, nil)

    Endpoint definition hash



189
190
191
# File 'lib/twelvedata_ruby/endpoint.rb', line 189

def definition
  @definition ||= self.class.definitions[name]
end

#errorsHash

Get validation errors

Returns:

  • (Hash)

    Hash of validation errors



196
197
198
# File 'lib/twelvedata_ruby/endpoint.rb', line 196

def errors
  @errors.compact
end

#normalize_format(format) ⇒ Object (private)



299
300
301
# File 'lib/twelvedata_ruby/endpoint.rb', line 299

def normalize_format(format)
  VALID_FORMATS.include?(format) ? format : DEFAULT_FORMAT
end

#parametersHash?

Get parameter definition

Returns:

  • (Hash, nil)

    Parameter definition



212
213
214
# File 'lib/twelvedata_ruby/endpoint.rb', line 212

def parameters
  definition&.dig(:parameters)
end

#parameters_keysArray<Symbol>?

Get parameter keys including format-specific ones

Returns:

  • (Array<Symbol>, nil)

    Array of valid parameter keys



219
220
221
222
223
224
225
# File 'lib/twelvedata_ruby/endpoint.rb', line 219

def parameters_keys
  return nil unless parameters

  keys = parameters[:keys].dup
  keys << :filename if csv_format_with_filename?
  keys
end

#process_query_params(params) ⇒ Object (private)



283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
# File 'lib/twelvedata_ruby/endpoint.rb', line 283

def process_query_params(params)
  processed = params.dup

  # Normalize format parameter
  if parameters_keys&.include?(:format)
    processed[:format] = normalize_format(processed[:format])
  end

  # Remove filename if not CSV format
  if processed[:filename] && processed[:format] != :csv
    processed.delete(:filename)
  end

  processed
end

#query_params_keysArray<Symbol>

Get query parameter keys

Returns:

  • (Array<Symbol>)

    Array of current query parameter keys



230
231
232
# File 'lib/twelvedata_ruby/endpoint.rb', line 230

def query_params_keys
  query_params.keys
end

#required_parametersArray<Symbol>?

Get required parameter keys

Returns:

  • (Array<Symbol>, nil)

    Array of required parameter keys



247
248
249
# File 'lib/twelvedata_ruby/endpoint.rb', line 247

def required_parameters
  parameters&.dig(:required)
end

#reset_cached_dataObject (private)



275
276
277
# File 'lib/twelvedata_ruby/endpoint.rb', line 275

def reset_cached_data
  @definition = nil
end

#valid?Boolean

Check if endpoint and parameters are valid

Returns:

  • (Boolean)

    True if valid



254
255
256
# File 'lib/twelvedata_ruby/endpoint.rb', line 254

def valid?
  valid_name? && valid_query_params?
end

#valid_name?Boolean

Check if name is valid

Returns:

  • (Boolean)

    True if name is valid



261
262
263
# File 'lib/twelvedata_ruby/endpoint.rb', line 261

def valid_name?
  errors[:name].nil?
end

#valid_query_params?Boolean

Check if query parameters are valid

Returns:

  • (Boolean)

    True if query parameters are valid



268
269
270
271
# File 'lib/twelvedata_ruby/endpoint.rb', line 268

def valid_query_params?
  validate_query_params
  errors[:parameters_keys].nil? && errors[:required_parameters].nil?
end

#validate_nameObject (private)



303
304
305
306
307
308
# File 'lib/twelvedata_ruby/endpoint.rb', line 303

def validate_name
  (@errors.delete(:name) || true) and return if self.class.valid_name?(name)

  invalid_name = name.nil? || name.to_s.empty? ? "blank name" : name
  @errors[:name] = create_error(:name, invalid_name, EndpointNameError)
end

#validate_parameter_keysObject (private)



324
325
326
327
328
329
# File 'lib/twelvedata_ruby/endpoint.rb', line 324

def validate_parameter_keys
  invalid = query_params_keys - parameters_keys
  (@errors.delete(:parameters_keys) || true) and return if invalid.empty?

  @errors[:parameters_keys] = create_error(:parameters_keys, invalid, EndpointParametersKeysError)
end

#validate_query_paramsObject (private)



310
311
312
313
314
315
# File 'lib/twelvedata_ruby/endpoint.rb', line 310

def validate_query_params
  return unless valid_name? && parameters_keys

  validate_required_parameters
  validate_parameter_keys
end

#validate_required_parametersObject (private)



317
318
319
320
321
322
# File 'lib/twelvedata_ruby/endpoint.rb', line 317

def validate_required_parameters
  missing = required_parameters - query_params_keys
  (@errors.delete(:required_parameters) || true) and return if missing.empty?

  @errors[:required_parameters] = create_error(:required_parameters, missing, EndpointRequiredParametersError)
end