timeprice 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +99 -0
  3. data/README.md +73 -2
  4. data/data/cpi/au.json +419 -0
  5. data/data/cpi/br.json +529 -0
  6. data/data/cpi/ca.json +1501 -0
  7. data/data/cpi/ch.json +549 -0
  8. data/data/cpi/cn.json +487 -0
  9. data/data/cpi/cz.json +500 -0
  10. data/data/cpi/eu.json +1 -1
  11. data/data/cpi/hk.json +351 -0
  12. data/data/cpi/hu.json +537 -0
  13. data/data/cpi/id.json +550 -0
  14. data/data/cpi/il.json +549 -0
  15. data/data/cpi/in.json +549 -0
  16. data/data/cpi/jp.json +2 -2
  17. data/data/cpi/kr.json +550 -0
  18. data/data/cpi/mx.json +550 -0
  19. data/data/cpi/my.json +429 -0
  20. data/data/cpi/no.json +549 -0
  21. data/data/cpi/nz.json +94 -0
  22. data/data/cpi/ph.json +309 -0
  23. data/data/cpi/pl.json +539 -0
  24. data/data/cpi/ru.json +487 -0
  25. data/data/cpi/se.json +549 -0
  26. data/data/cpi/sg.json +369 -0
  27. data/data/cpi/th.json +309 -0
  28. data/data/cpi/tr.json +549 -0
  29. data/data/cpi/uk.json +1 -1
  30. data/data/cpi/us.json +1007 -5
  31. data/data/cpi/vn.json +32 -32
  32. data/data/cpi/za.json +549 -0
  33. data/data/fx/usd/1999.json +5982 -262
  34. data/data/fx/usd/2000.json +6999 -258
  35. data/data/fx/usd/2001.json +7142 -257
  36. data/data/fx/usd/2002.json +7170 -258
  37. data/data/fx/usd/2003.json +7170 -258
  38. data/data/fx/usd/2004.json +7282 -262
  39. data/data/fx/usd/2005.json +7226 -260
  40. data/data/fx/usd/2006.json +7170 -258
  41. data/data/fx/usd/2007.json +7169 -258
  42. data/data/fx/usd/2008.json +7184 -259
  43. data/data/fx/usd/2009.json +6941 -259
  44. data/data/fx/usd/2010.json +6995 -261
  45. data/data/fx/usd/2011.json +6968 -260
  46. data/data/fx/usd/2012.json +6941 -259
  47. data/data/fx/usd/2013.json +6914 -258
  48. data/data/fx/usd/2014.json +6914 -258
  49. data/data/fx/usd/2015.json +6941 -259
  50. data/data/fx/usd/2016.json +6968 -260
  51. data/data/fx/usd/2017.json +6914 -258
  52. data/data/fx/usd/2018.json +7148 -258
  53. data/data/fx/usd/2019.json +7170 -258
  54. data/data/fx/usd/2020.json +7226 -260
  55. data/data/fx/usd/2021.json +7254 -261
  56. data/data/fx/usd/2022.json +7226 -260
  57. data/data/fx/usd/2023.json +7170 -258
  58. data/data/fx/usd/2024.json +7198 -259
  59. data/data/fx/usd/2025.json +7170 -258
  60. data/data/fx/usd/2026.json +2561 -92
  61. data/data/fx/usd/_annual.json +46 -1
  62. data/data/manifest.json +565 -2
  63. data/lib/timeprice/cli/presenters/compare.rb +44 -8
  64. data/lib/timeprice/cli.rb +24 -7
  65. data/lib/timeprice/compare/series.rb +120 -0
  66. data/lib/timeprice/compare.rb +108 -15
  67. data/lib/timeprice/cpi_lookup.rb +14 -8
  68. data/lib/timeprice/data_loader.rb +8 -17
  69. data/lib/timeprice/date.rb +62 -0
  70. data/lib/timeprice/exchange.rb +49 -23
  71. data/lib/timeprice/forecast/cagr.rb +96 -0
  72. data/lib/timeprice/forecast/cpi_forecaster.rb +90 -0
  73. data/lib/timeprice/forecast/fx_forecaster.rb +173 -0
  74. data/lib/timeprice/forecast.rb +21 -0
  75. data/lib/timeprice/inflation.rb +12 -4
  76. data/lib/timeprice/metadata.rb +121 -0
  77. data/lib/timeprice/metadata_snapshot.rb +23 -0
  78. data/lib/timeprice/point.rb +11 -3
  79. data/lib/timeprice/schema.rb +78 -0
  80. data/lib/timeprice/sources.rb +1 -1
  81. data/lib/timeprice/supported.rb +16 -0
  82. data/lib/timeprice/version.rb +1 -1
  83. data/lib/timeprice.rb +48 -3
  84. metadata +49 -2
@@ -39,7 +39,7 @@ module Timeprice
39
39
  id: "jp_cpi",
40
40
  kind: "cpi",
41
41
  country: "JP",
42
- name: "World Bank — FP.CPI.TOTL (annual, JP fallback)",
42
+ name: "World Bank — FP.CPI.TOTL (annual)",
43
43
  license: "CC BY 4.0",
44
44
  license_url: "https://datacatalog.worldbank.org/public-licenses#cc-by",
45
45
  attribution: "Source: World Bank, FP.CPI.TOTL",
@@ -26,6 +26,22 @@ module Timeprice
26
26
  ([base] + DataLoader.load_manifest.dig("fx", "currencies")).uniq.freeze
27
27
  end
28
28
 
29
+ # @return [Array<String>] currencies with daily FX observations.
30
+ def daily_currencies
31
+ manifest = DataLoader.load_manifest
32
+ list = manifest.dig("fx", "daily_currencies")
33
+ return currencies if list.nil?
34
+
35
+ base = manifest.dig("fx", "base")
36
+ ([base] + list).uniq.freeze
37
+ end
38
+
39
+ # @return [Array<String>] currencies served only annually (e.g. VND, RUB).
40
+ def annual_only_currencies
41
+ manifest = DataLoader.load_manifest
42
+ (manifest.dig("fx", "annual_only_currencies") || []).freeze
43
+ end
44
+
29
45
  # @return [Hash{String=>String}] country code → currency code.
30
46
  def country_to_currency
31
47
  manifest_countries.to_h { |c| [c["code"], c["currency"]] }.freeze
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Timeprice
4
- VERSION = "0.6.0"
4
+ VERSION = "0.8.0"
5
5
  end
data/lib/timeprice.rb CHANGED
@@ -1,14 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "timeprice/version"
4
+ require_relative "timeprice/errors"
5
+ require_relative "timeprice/schema"
6
+ require_relative "timeprice/date"
4
7
  require_relative "timeprice/data_loader"
5
8
  require_relative "timeprice/supported"
6
- require_relative "timeprice/errors"
7
9
  require_relative "timeprice/point"
8
10
  require_relative "timeprice/inflation"
9
11
  require_relative "timeprice/exchange"
10
12
  require_relative "timeprice/compare"
13
+ require_relative "timeprice/forecast"
14
+ require_relative "timeprice/forecast/cagr"
15
+ require_relative "timeprice/forecast/cpi_forecaster"
16
+ require_relative "timeprice/forecast/fx_forecaster"
11
17
  require_relative "timeprice/sources"
18
+ require_relative "timeprice/metadata"
12
19
 
13
20
  # Offline historical inflation & FX for Ruby.
14
21
  #
@@ -51,6 +58,34 @@ module Timeprice
51
58
  Exchange.convert(amount: amount, from: from, to: to, date: date)
52
59
  end
53
60
 
61
+ # Project a CPI index or FX rate forward past the last bundled data point.
62
+ #
63
+ # @param kind [Symbol] :cpi or :fx
64
+ # @param target [String] target date as "YYYY" or "YYYY-MM"
65
+ # @param country [String] (only when kind: :cpi)
66
+ # @param from [String] (only when kind: :fx) source currency
67
+ # @param to [String] (only when kind: :fx) destination currency
68
+ # @param window_years [Integer, nil] override default trailing window
69
+ # @return [Forecast::Result]
70
+ def forecast(kind:, target:, country: nil, from: nil, to: nil, window_years: nil)
71
+ case kind
72
+ when :cpi
73
+ fail ArgumentError, "country: required for kind: :cpi" unless country
74
+
75
+ opts = { country: country, target: target }
76
+ opts[:window_years] = window_years if window_years
77
+ Forecast::CpiForecaster.project(**opts)
78
+ when :fx
79
+ fail ArgumentError, "from:/to: required for kind: :fx" unless from && to
80
+
81
+ opts = { from: from, to: to, target: target }
82
+ opts[:window_years] = window_years if window_years
83
+ Forecast::FxForecaster.project(**opts)
84
+ else
85
+ fail ArgumentError, "unknown forecast kind: #{kind.inspect} (expected :cpi or :fx)"
86
+ end
87
+ end
88
+
54
89
  # Compare an amount across two (currency, date) points: convert at the
55
90
  # source date, then inflate in the destination currency. See README.md
56
91
  # "Compare semantics" for why this order is correct.
@@ -59,7 +94,17 @@ module Timeprice
59
94
  # @param from [Point, Array(String, String)] source point
60
95
  # @param to [Point, Array(String, String)] destination point
61
96
  # @return [CompareResult]
62
- def compare(amount:, from:, to:)
63
- Compare.run(amount: amount, from: from, to: to)
97
+ def compare(amount:, from:, to:, forecast: false)
98
+ Compare.run(amount: amount, from: from, to: to, forecast: forecast)
99
+ end
100
+
101
+ # Snapshot describing the bundled dataset: version, refresh date, country
102
+ # list with CPI ranges, currency list with display names, and FX coverage.
103
+ # Intended as the single source of truth for downstream UIs (the website
104
+ # in particular) so dropdowns and date pickers never drift from the data.
105
+ #
106
+ # @return [Hash] frozen, JSON-serialisable
107
+ def metadata
108
+ Metadata.build
64
109
  end
65
110
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timeprice
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Patrick
@@ -16,13 +16,27 @@ dependencies:
16
16
  - - "~>"
17
17
  - !ruby/object:Gem::Version
18
18
  version: '1.3'
19
- type: :runtime
19
+ type: :development
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - "~>"
24
24
  - !ruby/object:Gem::Version
25
25
  version: '1.3'
26
+ - !ruby/object:Gem::Dependency
27
+ name: lefthook
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '2.1'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '2.1'
26
40
  - !ruby/object:Gem::Dependency
27
41
  name: rake
28
42
  requirement: !ruby/object:Gem::Requirement
@@ -107,11 +121,35 @@ files:
107
121
  - LICENSE.txt
108
122
  - NOTICE
109
123
  - README.md
124
+ - data/cpi/au.json
125
+ - data/cpi/br.json
126
+ - data/cpi/ca.json
127
+ - data/cpi/ch.json
128
+ - data/cpi/cn.json
129
+ - data/cpi/cz.json
110
130
  - data/cpi/eu.json
131
+ - data/cpi/hk.json
132
+ - data/cpi/hu.json
133
+ - data/cpi/id.json
134
+ - data/cpi/il.json
135
+ - data/cpi/in.json
111
136
  - data/cpi/jp.json
137
+ - data/cpi/kr.json
138
+ - data/cpi/mx.json
139
+ - data/cpi/my.json
140
+ - data/cpi/no.json
141
+ - data/cpi/nz.json
142
+ - data/cpi/ph.json
143
+ - data/cpi/pl.json
144
+ - data/cpi/ru.json
145
+ - data/cpi/se.json
146
+ - data/cpi/sg.json
147
+ - data/cpi/th.json
148
+ - data/cpi/tr.json
112
149
  - data/cpi/uk.json
113
150
  - data/cpi/us.json
114
151
  - data/cpi/vn.json
152
+ - data/cpi/za.json
115
153
  - data/fx/usd/1999.json
116
154
  - data/fx/usd/2000.json
117
155
  - data/fx/usd/2001.json
@@ -151,13 +189,22 @@ files:
151
189
  - lib/timeprice/cli/presenters/inflation.rb
152
190
  - lib/timeprice/cli/presenters/sources.rb
153
191
  - lib/timeprice/compare.rb
192
+ - lib/timeprice/compare/series.rb
154
193
  - lib/timeprice/cpi_lookup.rb
155
194
  - lib/timeprice/data_loader.rb
195
+ - lib/timeprice/date.rb
156
196
  - lib/timeprice/errors.rb
157
197
  - lib/timeprice/exchange.rb
198
+ - lib/timeprice/forecast.rb
199
+ - lib/timeprice/forecast/cagr.rb
200
+ - lib/timeprice/forecast/cpi_forecaster.rb
201
+ - lib/timeprice/forecast/fx_forecaster.rb
158
202
  - lib/timeprice/granularity.rb
159
203
  - lib/timeprice/inflation.rb
204
+ - lib/timeprice/metadata.rb
205
+ - lib/timeprice/metadata_snapshot.rb
160
206
  - lib/timeprice/point.rb
207
+ - lib/timeprice/schema.rb
161
208
  - lib/timeprice/sources.rb
162
209
  - lib/timeprice/sources/coverage.rb
163
210
  - lib/timeprice/supported.rb