Class: BankOfThailand::Response
- Inherits:
-
Object
- Object
- BankOfThailand::Response
- Defined in:
- lib/bank_of_thailand/response.rb
Overview
Wrapper for API responses with convenience methods
Instance Attribute Summary collapse
-
#data ⇒ Array<Hash>
readonly
The extracted data array.
-
#raw ⇒ Hash
readonly
The raw API response.
Instance Method Summary collapse
-
#[](key) ⇒ Object
Allow hash-like access for backward compatibility.
-
#average(column) ⇒ Float
(also: #mean)
Average value for a column.
-
#change(column = "value") ⇒ Hash?
Calculate change metrics for a column.
-
#complete? ⇒ Boolean
Check if data is complete for the date range.
-
#count ⇒ Integer
Count of data points.
-
#daily_changes(column = "value") ⇒ Array<Hash>
Calculate daily changes for a column.
-
#date_range ⇒ Array<String>?
Date range covered by the data.
-
#dig(*keys) ⇒ Object
Allow hash-like dig for backward compatibility.
-
#first ⇒ Hash?
First data point.
-
#initialize(raw_response) ⇒ Response
constructor
Initialize a new Response.
-
#last ⇒ Hash?
Last data point.
-
#max(column) ⇒ Float?
Maximum value for a column.
-
#min(column) ⇒ Float?
Minimum value for a column.
-
#missing_dates ⇒ Array<Date>
Find missing dates in the range.
-
#period_days ⇒ Integer
Number of days in the period.
-
#sum(column) ⇒ Float
Sum of values for a column.
-
#to_csv(filename = nil) ⇒ String
Export data to CSV.
-
#trend(column = "value") ⇒ Symbol
Determine trend direction.
-
#values_for(column) ⇒ Array<Float>
Extract numeric values for a column.
-
#volatility(column = "value") ⇒ Float
Calculate volatility (standard deviation of daily percentage changes).
Constructor Details
#initialize(raw_response) ⇒ Response
Initialize a new Response
17 18 19 20 |
# File 'lib/bank_of_thailand/response.rb', line 17 def initialize(raw_response) @raw = raw_response @data = extract_data(raw_response) end |
Instance Attribute Details
#data ⇒ Array<Hash> (readonly)
Returns the extracted data array.
13 14 15 |
# File 'lib/bank_of_thailand/response.rb', line 13 def data @data end |
#raw ⇒ Hash (readonly)
Returns the raw API response.
10 11 12 |
# File 'lib/bank_of_thailand/response.rb', line 10 def raw @raw end |
Instance Method Details
#[](key) ⇒ Object
Allow hash-like access for backward compatibility
25 26 27 28 29 |
# File 'lib/bank_of_thailand/response.rb', line 25 def [](key) return nil unless raw.is_a?(Hash) raw[key.to_s] end |
#average(column) ⇒ Float Also known as: mean
Average value for a column
89 90 91 92 93 94 |
# File 'lib/bank_of_thailand/response.rb', line 89 def average(column) vals = values_for(column) return 0.0 if vals.empty? vals.sum / vals.size.to_f end |
#change(column = "value") ⇒ Hash?
Calculate change metrics for a column
144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/bank_of_thailand/response.rb', line 144 def change(column = "value") vals = values_for(column) return nil if vals.size < 2 first_val = vals.first last_val = vals.last { absolute: last_val - first_val, percentage: first_val.zero? ? 0.0 : ((last_val - first_val) / first_val * 100).round(4), first_value: first_val, last_value: last_val } end |
#complete? ⇒ Boolean
Check if data is complete for the date range
120 121 122 123 124 125 |
# File 'lib/bank_of_thailand/response.rb', line 120 def complete? expected_days = period_days return true if expected_days.zero? count >= expected_days end |
#count ⇒ Integer
Count of data points
42 43 44 |
# File 'lib/bank_of_thailand/response.rb', line 42 def count data.size end |
#daily_changes(column = "value") ⇒ Array<Hash>
Calculate daily changes for a column
162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/bank_of_thailand/response.rb', line 162 def daily_changes(column = "value") vals = values_for(column) return [] if vals.size < 2 vals.each_cons(2).map do |prev, curr| { absolute: curr - prev, percentage: prev.zero? ? 0.0 : ((curr - prev) / prev * 100).round(4) } end end |
#date_range ⇒ Array<String>?
Date range covered by the data
100 101 102 103 104 105 |
# File 'lib/bank_of_thailand/response.rb', line 100 def date_range dates = data.select { |row| row.is_a?(Hash) }.map { |row| row["period"] || row["date"] }.compact return nil if dates.empty? dates.minmax end |
#dig(*keys) ⇒ Object
Allow hash-like dig for backward compatibility
34 35 36 37 38 |
# File 'lib/bank_of_thailand/response.rb', line 34 def dig(*keys) return nil unless raw.is_a?(Hash) raw.dig(*keys.map(&:to_s)) end |
#first ⇒ Hash?
First data point
48 49 50 |
# File 'lib/bank_of_thailand/response.rb', line 48 def first data.first end |
#last ⇒ Hash?
Last data point
54 55 56 |
# File 'lib/bank_of_thailand/response.rb', line 54 def last data.last end |
#max(column) ⇒ Float?
Maximum value for a column
75 76 77 |
# File 'lib/bank_of_thailand/response.rb', line 75 def max(column) values_for(column).max end |
#min(column) ⇒ Float?
Minimum value for a column
68 69 70 |
# File 'lib/bank_of_thailand/response.rb', line 68 def min(column) values_for(column).min end |
#missing_dates ⇒ Array<Date>
Find missing dates in the range
129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/bank_of_thailand/response.rb', line 129 def missing_dates return [] unless date_range start_date = Date.parse(date_range[0]) end_date = Date.parse(date_range[1]) actual_dates = data.select { |row| row.is_a?(Hash) }.map { |row| Date.parse(row["period"] || row["date"]) } (start_date..end_date).reject { |date| actual_dates.include?(date) } rescue Date::Error [] end |
#period_days ⇒ Integer
Number of days in the period
109 110 111 112 113 114 115 116 |
# File 'lib/bank_of_thailand/response.rb', line 109 def period_days range = date_range return 0 unless range (Date.parse(range[1]) - Date.parse(range[0])).to_i + 1 rescue Date::Error 0 end |
#sum(column) ⇒ Float
Sum of values for a column
82 83 84 |
# File 'lib/bank_of_thailand/response.rb', line 82 def sum(column) values_for(column).sum end |
#to_csv(filename = nil) ⇒ String
Export data to CSV
207 208 209 210 211 212 213 214 215 216 217 218 219 |
# File 'lib/bank_of_thailand/response.rb', line 207 def to_csv(filename = nil) csv_data = CSV.generate do |csv| csv << extract_headers extract_rows.each { |row| csv << row } end if filename File.write(filename, csv_data) filename else csv_data end end |
#trend(column = "value") ⇒ Symbol
Determine trend direction
189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/bank_of_thailand/response.rb', line 189 def trend(column = "value") change_data = change(column) return :flat unless change_data pct = change_data[:percentage] if pct > 1 :up elsif pct < -1 :down else :flat end end |
#values_for(column) ⇒ Array<Float>
Extract numeric values for a column
61 62 63 |
# File 'lib/bank_of_thailand/response.rb', line 61 def values_for(column) data.select { |row| row.is_a?(Hash) }.map { |row| row[column]&.to_f }.compact end |
#volatility(column = "value") ⇒ Float
Calculate volatility (standard deviation of daily percentage changes)
177 178 179 180 181 182 183 184 |
# File 'lib/bank_of_thailand/response.rb', line 177 def volatility(column = "value") changes = daily_changes(column).map { |c| c[:percentage] } return 0.0 if changes.empty? mean = changes.sum / changes.size.to_f variance = changes.sum { |x| (x - mean)**2 } / changes.size.to_f Math.sqrt(variance).round(4) end |