@ducatjs/money 0.1.0 → 0.2.1
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.
- package/NOTICE +73 -0
- package/README.md +479 -62
- package/data/cash-rounding.json +123 -2
- package/data/cldr-cash.json +101 -0
- package/data/historic.json +78 -0
- package/data/iso4217-list-three.xml +1185 -0
- package/dist/adyen-fx.d.ts.map +1 -1
- package/dist/adyen-fx.js +22 -4
- package/dist/adyen-fx.js.map +1 -1
- package/dist/boc.d.ts +31 -0
- package/dist/boc.d.ts.map +1 -0
- package/dist/boc.js +114 -0
- package/dist/boc.js.map +1 -0
- package/dist/boe.d.ts +33 -0
- package/dist/boe.d.ts.map +1 -0
- package/dist/boe.js +114 -0
- package/dist/boe.js.map +1 -0
- package/dist/cash.d.ts +30 -1
- package/dist/cash.d.ts.map +1 -1
- package/dist/cash.js +50 -2
- package/dist/cash.js.map +1 -1
- package/dist/convert.d.ts +10 -9
- package/dist/convert.d.ts.map +1 -1
- package/dist/convert.js +13 -3
- package/dist/convert.js.map +1 -1
- package/dist/drizzle/mysql.d.ts +105 -0
- package/dist/drizzle/mysql.d.ts.map +1 -0
- package/dist/drizzle/mysql.js +60 -0
- package/dist/drizzle/mysql.js.map +1 -0
- package/dist/drizzle/pg.d.ts +103 -0
- package/dist/drizzle/pg.d.ts.map +1 -0
- package/dist/drizzle/pg.js +60 -0
- package/dist/drizzle/pg.js.map +1 -0
- package/dist/drizzle/sqlite.d.ts +102 -0
- package/dist/drizzle/sqlite.d.ts.map +1 -0
- package/dist/drizzle/sqlite.js +59 -0
- package/dist/drizzle/sqlite.js.map +1 -0
- package/dist/ecb.d.ts +37 -2
- package/dist/ecb.d.ts.map +1 -1
- package/dist/ecb.js +148 -10
- package/dist/ecb.js.map +1 -1
- package/dist/fed.d.ts +35 -0
- package/dist/fed.d.ts.map +1 -0
- package/dist/fed.js +134 -0
- package/dist/fed.js.map +1 -0
- package/dist/fetch.d.ts +45 -0
- package/dist/fetch.d.ts.map +1 -1
- package/dist/fetch.js +167 -24
- package/dist/fetch.js.map +1 -1
- package/dist/fn.d.ts +8 -1
- package/dist/fn.d.ts.map +1 -1
- package/dist/fn.js +8 -1
- package/dist/fn.js.map +1 -1
- package/dist/generated/cash.d.ts +2 -0
- package/dist/generated/cash.d.ts.map +1 -1
- package/dist/generated/cash.js +101 -0
- package/dist/generated/cash.js.map +1 -1
- package/dist/generated/historic.d.ts +337 -0
- package/dist/generated/historic.d.ts.map +1 -0
- package/dist/generated/historic.js +66 -0
- package/dist/generated/historic.js.map +1 -0
- package/dist/historic.d.ts +40 -0
- package/dist/historic.d.ts.map +1 -0
- package/dist/historic.js +43 -0
- package/dist/historic.js.map +1 -0
- package/dist/history.d.ts +96 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +213 -0
- package/dist/history.js.map +1 -0
- package/dist/hmrc.d.ts +28 -0
- package/dist/hmrc.d.ts.map +1 -0
- package/dist/hmrc.js +108 -0
- package/dist/hmrc.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/kysely.d.ts +120 -0
- package/dist/kysely.d.ts.map +1 -0
- package/dist/kysely.js +309 -0
- package/dist/kysely.js.map +1 -0
- package/dist/money.d.ts +93 -9
- package/dist/money.d.ts.map +1 -1
- package/dist/money.js +135 -9
- package/dist/money.js.map +1 -1
- package/dist/parse.d.ts +45 -1
- package/dist/parse.d.ts.map +1 -1
- package/dist/parse.js +290 -3
- package/dist/parse.js.map +1 -1
- package/dist/pg.d.ts +100 -0
- package/dist/pg.d.ts.map +1 -0
- package/dist/pg.js +343 -0
- package/dist/pg.js.map +1 -0
- package/dist/plugins/adyen.d.ts +1 -1
- package/dist/plugins/adyen.d.ts.map +1 -1
- package/dist/plugins/adyen.js.map +1 -1
- package/dist/plugins/all.d.ts +8 -1
- package/dist/plugins/all.d.ts.map +1 -1
- package/dist/plugins/all.js +8 -1
- package/dist/plugins/all.js.map +1 -1
- package/dist/plugins/allocate.d.ts +1 -1
- package/dist/plugins/allocate.d.ts.map +1 -1
- package/dist/plugins/allocate.js.map +1 -1
- package/dist/plugins/braintree.d.ts +1 -1
- package/dist/plugins/braintree.d.ts.map +1 -1
- package/dist/plugins/braintree.js.map +1 -1
- package/dist/plugins/cash.d.ts +1 -1
- package/dist/plugins/cash.d.ts.map +1 -1
- package/dist/plugins/cash.js.map +1 -1
- package/dist/plugins/checkout.d.ts +1 -1
- package/dist/plugins/checkout.d.ts.map +1 -1
- package/dist/plugins/checkout.js.map +1 -1
- package/dist/plugins/convert.d.ts +5 -5
- package/dist/plugins/convert.d.ts.map +1 -1
- package/dist/plugins/convert.js.map +1 -1
- package/dist/plugins/exact.d.ts +1 -1
- package/dist/plugins/exact.d.ts.map +1 -1
- package/dist/plugins/exact.js.map +1 -1
- package/dist/plugins/fixed.d.ts +1 -1
- package/dist/plugins/fixed.d.ts.map +1 -1
- package/dist/plugins/fixed.js.map +1 -1
- package/dist/plugins/format.d.ts +1 -1
- package/dist/plugins/format.d.ts.map +1 -1
- package/dist/plugins/format.js.map +1 -1
- package/dist/plugins/klarna.d.ts +1 -1
- package/dist/plugins/klarna.d.ts.map +1 -1
- package/dist/plugins/klarna.js.map +1 -1
- package/dist/plugins/paypal.d.ts +1 -1
- package/dist/plugins/paypal.d.ts.map +1 -1
- package/dist/plugins/paypal.js +0 -4
- package/dist/plugins/paypal.js.map +1 -1
- package/dist/plugins/prisma.d.ts +1 -1
- package/dist/plugins/prisma.d.ts.map +1 -1
- package/dist/plugins/prisma.js +0 -4
- package/dist/plugins/prisma.js.map +1 -1
- package/dist/plugins/stripe.d.ts +1 -1
- package/dist/plugins/stripe.d.ts.map +1 -1
- package/dist/plugins/stripe.js +0 -4
- package/dist/plugins/stripe.js.map +1 -1
- package/dist/plugins/tax.d.ts +6 -6
- package/dist/plugins/tax.d.ts.map +1 -1
- package/dist/plugins/tax.js.map +1 -1
- package/dist/policy.d.ts +34 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +90 -0
- package/dist/policy.js.map +1 -0
- package/dist/prisma.d.ts +25 -14
- package/dist/prisma.d.ts.map +1 -1
- package/dist/prisma.js +29 -19
- package/dist/prisma.js.map +1 -1
- package/dist/provider.d.ts +21 -7
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +51 -11
- package/dist/provider.js.map +1 -1
- package/dist/rate-text.d.ts +38 -0
- package/dist/rate-text.d.ts.map +1 -0
- package/dist/rate-text.js +143 -0
- package/dist/rate-text.js.map +1 -0
- package/dist/rate.d.ts +61 -5
- package/dist/rate.d.ts.map +1 -1
- package/dist/rate.js +133 -33
- package/dist/rate.js.map +1 -1
- package/dist/rounding.js +1 -1
- package/dist/rounding.js.map +1 -1
- package/dist/schema.d.ts +43 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +77 -0
- package/dist/schema.js.map +1 -0
- package/dist/sql.d.ts +54 -0
- package/dist/sql.d.ts.map +1 -0
- package/dist/sql.js +131 -0
- package/dist/sql.js.map +1 -0
- package/dist/tax.d.ts +13 -9
- package/dist/tax.d.ts.map +1 -1
- package/dist/tax.js +20 -4
- package/dist/tax.js.map +1 -1
- package/dist/testing/arbitraries.d.ts +43 -0
- package/dist/testing/arbitraries.d.ts.map +1 -0
- package/dist/testing/arbitraries.js +98 -0
- package/dist/testing/arbitraries.js.map +1 -0
- package/dist/testing/index.d.ts +67 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +159 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/jest.d.ts +2 -0
- package/dist/testing/jest.d.ts.map +1 -0
- package/dist/testing/jest.js +15 -0
- package/dist/testing/jest.js.map +1 -0
- package/dist/testing/vitest.d.ts +7 -0
- package/dist/testing/vitest.d.ts.map +1 -0
- package/dist/testing/vitest.js +12 -0
- package/dist/testing/vitest.js.map +1 -0
- package/dist/valibot.d.ts +33 -0
- package/dist/valibot.d.ts.map +1 -0
- package/dist/valibot.js +61 -0
- package/dist/valibot.js.map +1 -0
- package/dist/zod.d.ts +36 -0
- package/dist/zod.d.ts.map +1 -0
- package/dist/zod.js +58 -0
- package/dist/zod.js.map +1 -0
- package/package.json +116 -5
- package/src/adyen-fx.ts +25 -4
- package/src/boc.ts +136 -0
- package/src/boe.ts +131 -0
- package/src/cash.ts +70 -2
- package/src/convert.ts +33 -15
- package/src/drizzle/mysql.ts +78 -0
- package/src/drizzle/pg.ts +78 -0
- package/src/drizzle/sqlite.ts +70 -0
- package/src/ecb.ts +179 -13
- package/src/fed.ts +146 -0
- package/src/fetch.ts +207 -28
- package/src/fn.ts +14 -0
- package/src/generated/cash.ts +103 -0
- package/src/generated/historic.ts +67 -0
- package/src/historic.ts +77 -0
- package/src/history.ts +333 -0
- package/src/hmrc.ts +125 -0
- package/src/index.ts +4 -0
- package/src/kysely.ts +588 -0
- package/src/money.ts +210 -12
- package/src/parse.ts +371 -4
- package/src/pg.ts +410 -0
- package/src/plugins/adyen.ts +3 -2
- package/src/plugins/all.ts +10 -0
- package/src/plugins/allocate.ts +3 -2
- package/src/plugins/braintree.ts +3 -2
- package/src/plugins/cash.ts +3 -2
- package/src/plugins/checkout.ts +3 -2
- package/src/plugins/convert.ts +6 -6
- package/src/plugins/exact.ts +3 -2
- package/src/plugins/fixed.ts +3 -2
- package/src/plugins/format.ts +3 -2
- package/src/plugins/klarna.ts +3 -2
- package/src/plugins/paypal.ts +3 -2
- package/src/plugins/prisma.ts +3 -2
- package/src/plugins/stripe.ts +3 -2
- package/src/plugins/tax.ts +11 -11
- package/src/policy.ts +124 -0
- package/src/prisma.ts +91 -10
- package/src/provider.ts +81 -16
- package/src/rate-text.ts +151 -0
- package/src/rate.ts +205 -36
- package/src/rounding.ts +1 -1
- package/src/schema.ts +119 -0
- package/src/sql.ts +178 -0
- package/src/tax.ts +40 -9
- package/src/testing/arbitraries.ts +134 -0
- package/src/testing/index.ts +247 -0
- package/src/testing/jest.ts +18 -0
- package/src/testing/vitest.ts +18 -0
- package/src/valibot.ts +87 -0
- package/src/zod.ts +78 -0
package/dist/ecb.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Offline parsers for the ECB euro foreign exchange reference rates (eurofxref). No I/O: fetch or
|
|
2
2
|
// read the files yourself, or use ducat/convert/fetch. Rates are kept exactly as published.
|
|
3
3
|
import { rateTable } from './provider.js';
|
|
4
|
+
import { addDayRate, csvRows, newestFirst, readRateCell, withDecimals } from './rate-text.js';
|
|
4
5
|
const MONTHS = [
|
|
5
6
|
'january',
|
|
6
7
|
'february',
|
|
@@ -59,9 +60,6 @@ function ratesOfDay(body) {
|
|
|
59
60
|
}
|
|
60
61
|
return rates;
|
|
61
62
|
}
|
|
62
|
-
function newestFirst(tables) {
|
|
63
|
-
return tables.sort((table, other) => other.asOf.localeCompare(table.asOf));
|
|
64
|
-
}
|
|
65
63
|
/**
|
|
66
64
|
* Parses eurofxref-daily.xml, eurofxref-hist-90d.xml or eurofxref-hist.xml into one EUR-based table
|
|
67
65
|
* per day, newest first. Each rate is EUR → currency, with `source: 'ECB'`, `type: 'reference'` and
|
|
@@ -115,8 +113,8 @@ function isoDay(text) {
|
|
|
115
113
|
}
|
|
116
114
|
/**
|
|
117
115
|
* Parses eurofxref.csv or eurofxref-hist.csv (from the ECB's zips) the way parseEcbXml does.
|
|
118
|
-
* 'N/A' and blank cells (currencies not quoted that day) are
|
|
119
|
-
* all is left out, so a lookback goes on to the day before.
|
|
116
|
+
* 'N/A' and blank cells (currencies not quoted that day) are listed in the table's `missing`, and a
|
|
117
|
+
* day with no rates at all is left out, so a lookback goes on to the day before.
|
|
120
118
|
*/
|
|
121
119
|
export function parseEcbCsv(csv) {
|
|
122
120
|
const lines = withoutByteOrderMark(csv)
|
|
@@ -129,16 +127,156 @@ export function parseEcbCsv(csv) {
|
|
|
129
127
|
const tables = [];
|
|
130
128
|
for (const line of lines.slice(1)) {
|
|
131
129
|
const cells = line.split(',').map((cell) => cell.trim());
|
|
130
|
+
const day = isoDay(cells[0]);
|
|
132
131
|
const rates = {};
|
|
132
|
+
let quoted = 0;
|
|
133
133
|
for (let i = 1; i < columns.length; i++) {
|
|
134
134
|
const currency = columns[i];
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
135
|
+
if (!currency) {
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
const rate = readRateCell(cells[i] ?? '', `${currency} on ${day}`);
|
|
139
|
+
rates[currency] = rate;
|
|
140
|
+
if (rate !== null) {
|
|
141
|
+
quoted++;
|
|
138
142
|
}
|
|
139
143
|
}
|
|
140
|
-
|
|
141
|
-
|
|
144
|
+
if (quoted > 0) {
|
|
145
|
+
tables.push(ecbTable(day, rates));
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return newestFirst(tables);
|
|
149
|
+
}
|
|
150
|
+
// Series whose DECIMALS attribute says more than the ECB has ever published for them. Evidence:
|
|
151
|
+
// eurofxref-daily.xml publishes THB to 3 decimals (37.459 on 2026-11-06) while DECIMALS says 4,
|
|
152
|
+
// and eurofxref-hist.xml (1999 to 2026) never has more than 4 for LTL, whose DECIMALS says 5.
|
|
153
|
+
// Padding to the attribute would invent a digit. A cap only limits padding: a value published
|
|
154
|
+
// with more digits keeps them all (withDecimals never drops digits).
|
|
155
|
+
const PUBLISHED_DECIMALS = { THB: 3, LTL: 4 };
|
|
156
|
+
/** A DECIMALS cell as a number of decimals, or SyntaxError. */
|
|
157
|
+
function readDecimals(text, where) {
|
|
158
|
+
if (!/^\d{1,2}$/.test(text) || Number(text) > 30) {
|
|
159
|
+
throw new SyntaxError(`Malformed DECIMALS ${JSON.stringify(text)} (${where})`);
|
|
160
|
+
}
|
|
161
|
+
return Number(text);
|
|
162
|
+
}
|
|
163
|
+
/** A series' stated decimals, capped at what the ECB actually publishes for it. */
|
|
164
|
+
function statedDecimals(currency, text) {
|
|
165
|
+
const stated = readDecimals(text, currency);
|
|
166
|
+
const published = PUBLISHED_DECIMALS[currency];
|
|
167
|
+
if (published !== undefined && published < stated) {
|
|
168
|
+
return published;
|
|
169
|
+
}
|
|
170
|
+
return stated;
|
|
171
|
+
}
|
|
172
|
+
/** The records of an SDMX-CSV file after its header, each with as many cells as the header. */
|
|
173
|
+
function sdmxRecords(csv) {
|
|
174
|
+
const [header, ...rows] = csvRows(withoutByteOrderMark(csv));
|
|
175
|
+
if (header === undefined) {
|
|
176
|
+
throw new SyntaxError('Not an ECB SDMX-CSV file: it is empty');
|
|
177
|
+
}
|
|
178
|
+
for (const cells of rows) {
|
|
179
|
+
if (cells.length !== header.length) {
|
|
180
|
+
throw new SyntaxError(`Malformed ECB SDMX-CSV row: ${cells.length} cells, the header has ${header.length}`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return { header, rows };
|
|
184
|
+
}
|
|
185
|
+
/** The columns of an SDMX-CSV file, by name, or SyntaxError when a required one is missing. */
|
|
186
|
+
function sdmxColumns(header, required) {
|
|
187
|
+
const columns = new Map(header.map((name, i) => [name.trim(), i]));
|
|
188
|
+
for (const name of required) {
|
|
189
|
+
if (!columns.has(name)) {
|
|
190
|
+
throw new SyntaxError(`Not an ECB SDMX-CSV file: no ${name} column`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return columns;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* The DECIMALS of each series in an ECB SDMX-CSV file: the data file itself with full detail, or
|
|
197
|
+
* the series file the API returns with `detail=nodata`.
|
|
198
|
+
*/
|
|
199
|
+
export function parseEcbSdmxDecimals(csv) {
|
|
200
|
+
const { header, rows } = sdmxRecords(csv);
|
|
201
|
+
const columns = sdmxColumns(header, ['CURRENCY', 'DECIMALS']);
|
|
202
|
+
const decimals = {};
|
|
203
|
+
for (const cells of rows) {
|
|
204
|
+
const currency = cells[columns.get('CURRENCY')].trim();
|
|
205
|
+
decimals[currency] = statedDecimals(currency, cells[columns.get('DECIMALS')].trim());
|
|
206
|
+
}
|
|
207
|
+
return decimals;
|
|
208
|
+
}
|
|
209
|
+
/** The value of an optional column, or undefined when the file doesn't have it. */
|
|
210
|
+
function optionalCell(cells, columns, name) {
|
|
211
|
+
const index = columns.get(name);
|
|
212
|
+
if (index === undefined) {
|
|
213
|
+
return undefined;
|
|
214
|
+
}
|
|
215
|
+
return cells[index]?.trim();
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Parses the ECB Data Portal's SDMX-CSV (`format=csvdata`) for the daily euro reference rates
|
|
219
|
+
* (dataflow EXR, key `D.<currencies>.EUR.SP00.A`) into one EUR-based table per day, newest first,
|
|
220
|
+
* like parseEcbXml. Any date range back to 1999 comes in one file.
|
|
221
|
+
*
|
|
222
|
+
* The API strips trailing zeros ('136.8' for the published 136.80), so the published digits are
|
|
223
|
+
* rebuilt from each series' DECIMALS attribute: in the file with full detail, or from `decimals`
|
|
224
|
+
* (see parseEcbSdmxDecimals) for a `detail=dataonly` file. Two series overstate it (THB and LTL),
|
|
225
|
+
* and are padded only to the decimals the ECB actually published. Without DECIMALS, the digits
|
|
226
|
+
* stay as the file gives them; the values are exact either way. An empty or `NaN` value is a missing value.
|
|
227
|
+
* A row for another frequency, rate type or base currency, or with a UNIT_MULT other than 0,
|
|
228
|
+
* throws SyntaxError rather than being read as a daily rate. Discontinued series simply end, so
|
|
229
|
+
* the tables of their last days include them.
|
|
230
|
+
*
|
|
231
|
+
* No `availableAt` is set, as with parseEcbXml: the API gives no publication time, and the ECB
|
|
232
|
+
* publishes at about 16:00 CET. So a backtest that asks for 10:00 CET on a day still gets that
|
|
233
|
+
* day's rate; ask for the day before if that matters.
|
|
234
|
+
*
|
|
235
|
+
* const tables = parseEcbSdmxCsv(await (await fetch(url)).text());
|
|
236
|
+
* const history = rateHistory(tables); // from @ducatjs/money/convert/history
|
|
237
|
+
*/
|
|
238
|
+
export function parseEcbSdmxCsv(csv, options) {
|
|
239
|
+
const { header, rows } = sdmxRecords(csv);
|
|
240
|
+
const columns = sdmxColumns(header, ['CURRENCY', 'CURRENCY_DENOM', 'TIME_PERIOD', 'OBS_VALUE']);
|
|
241
|
+
const at = (cells, name) => cells[columns.get(name)]?.trim() ?? '';
|
|
242
|
+
const days = new Map();
|
|
243
|
+
for (const cells of rows) {
|
|
244
|
+
const currency = at(cells, 'CURRENCY');
|
|
245
|
+
const day = at(cells, 'TIME_PERIOD');
|
|
246
|
+
const where = `${currency} on ${day}`;
|
|
247
|
+
const unexpected = at(cells, 'CURRENCY_DENOM') !== 'EUR' ||
|
|
248
|
+
(optionalCell(cells, columns, 'FREQ') ?? 'D') !== 'D' ||
|
|
249
|
+
(optionalCell(cells, columns, 'EXR_TYPE') ?? 'SP00') !== 'SP00' ||
|
|
250
|
+
(optionalCell(cells, columns, 'EXR_SUFFIX') ?? 'A') !== 'A';
|
|
251
|
+
if (unexpected) {
|
|
252
|
+
throw new SyntaxError(`Not a daily EUR reference rate: ${cells.join(',')}`);
|
|
253
|
+
}
|
|
254
|
+
if (!/^[A-Z]{3}$/.test(currency) || !ISO_DAY.test(day)) {
|
|
255
|
+
throw new SyntaxError(`Malformed ECB SDMX-CSV row: ${cells.join(',')}`);
|
|
256
|
+
}
|
|
257
|
+
const multiplier = optionalCell(cells, columns, 'UNIT_MULT');
|
|
258
|
+
if (multiplier !== undefined && multiplier !== '' && multiplier !== '0') {
|
|
259
|
+
throw new SyntaxError(`Unsupported UNIT_MULT ${multiplier} (${where})`);
|
|
260
|
+
}
|
|
261
|
+
const value = at(cells, 'OBS_VALUE');
|
|
262
|
+
let rate = readRateCell(value, where);
|
|
263
|
+
if (rate !== null) {
|
|
264
|
+
// The file's own DECIMALS, capped like parseEcbSdmxDecimals; else the caller's, as given.
|
|
265
|
+
const stated = optionalCell(cells, columns, 'DECIMALS');
|
|
266
|
+
let decimals = options?.decimals?.[currency];
|
|
267
|
+
if (stated !== undefined && stated !== '') {
|
|
268
|
+
decimals = statedDecimals(currency, stated);
|
|
269
|
+
}
|
|
270
|
+
if (decimals !== undefined) {
|
|
271
|
+
rate = withDecimals(rate, decimals);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
const isoDay = calendarDay(Number(day.slice(0, 4)), Number(day.slice(5, 7)), Number(day.slice(8)));
|
|
275
|
+
addDayRate(days, isoDay, currency, rate);
|
|
276
|
+
}
|
|
277
|
+
const tables = [];
|
|
278
|
+
for (const [day, rates] of days) {
|
|
279
|
+
if (Object.values(rates).some((rate) => rate !== null)) {
|
|
142
280
|
tables.push(ecbTable(day, rates));
|
|
143
281
|
}
|
|
144
282
|
}
|
package/dist/ecb.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ecb.js","sourceRoot":"","sources":["../src/ecb.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAClG,4FAA4F;AAC5F,OAAO,EAAE,SAAS,EAAkB,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"ecb.js","sourceRoot":"","sources":["../src/ecb.ts"],"names":[],"mappings":"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"}
|
package/dist/fed.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { RateTable } from './provider.js';
|
|
2
|
+
/**
|
|
3
|
+
* Parses the Federal Reserve Board's H.10 daily foreign exchange rates, as CSV from its Data
|
|
4
|
+
* Download Program (DDP), into one USD-based table per day, newest first. These are the noon
|
|
5
|
+
* buying rates in New York, certified by the New York Fed for customs purposes, with `source:
|
|
6
|
+
* 'FRB'` and `type: 'noon buying'`, back to 1971.
|
|
7
|
+
*
|
|
8
|
+
* - **Direction.** H.10 quotes "currency units per U.S. dollar except as noted": AUD, EUR, NZD and
|
|
9
|
+
* GBP (series `RXI$US_N.B.*`) are USD per unit. Those four are stored as exact inverses, so
|
|
10
|
+
* every table is USD → currency, and the published quote stays on the rate:
|
|
11
|
+
* `rate('USD', 'EUR').inverse().toString()` is '1.1750' again.
|
|
12
|
+
* - **Holidays** are rows of `ND` ("no data"); such a day is left out, so a lookback goes on to
|
|
13
|
+
* the day before, and a file of holidays only gives []. A single `ND` cell is a missing value.
|
|
14
|
+
* A file with no observation rows at all throws, as it is more likely cut short than empty.
|
|
15
|
+
* - **Strict:** each column's Unit, Multiplier and Currency must be "Currency", 1 and the code
|
|
16
|
+
* its series ID stands for (EU is EUR), a currency can't have two columns, and two different
|
|
17
|
+
* values for one day throw.
|
|
18
|
+
* - **Digits.** H.10 publishes four decimals and keeps trailing zeros; they are kept.
|
|
19
|
+
* - **Codes.** The Fed's column codes are used as they are, so the bolivar is `VEB`, as the Fed
|
|
20
|
+
* labels it.
|
|
21
|
+
* - **Publication.** The release is weekly (Mondays, 4:15 p.m. ET) and covers the week before,
|
|
22
|
+
* so a Tuesday's rate is known only up to six days later. The CSV doesn't say when each row was
|
|
23
|
+
* released, so no `availableAt` is set; give each table one yourself if a backtest needs it.
|
|
24
|
+
*
|
|
25
|
+
* **Where the data comes from.** The DDP at federalreserve.gov/datadownload (release H10, CSV,
|
|
26
|
+
* "series in columns", with labels) serves these files today. The Board is retiring the DDP: the
|
|
27
|
+
* "Build Your Package" feature goes in November 2026 and the rest later, and it points users to
|
|
28
|
+
* FRED (fred.stlouisfed.org) instead. FRED needs an API key, and its terms forbid storing or
|
|
29
|
+
* caching its content and any commercial use without consent, which is why ducat has no H.10
|
|
30
|
+
* fetcher. Board data itself is public domain ("please cite to the Board as the source").
|
|
31
|
+
*
|
|
32
|
+
* const tables = parseFedH10Csv(await readFile('FRB_H10.csv', 'utf8'));
|
|
33
|
+
*/
|
|
34
|
+
export declare function parseFedH10Csv(csv: string): RateTable[];
|
|
35
|
+
//# sourceMappingURL=fed.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fed.d.ts","sourceRoot":"","sources":["../src/fed.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAqC/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,CAyEvD"}
|
package/dist/fed.js
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
// `@ducatjs/money/convert/fed`: an offline parser for the Federal Reserve Board's H.10 foreign
|
|
2
|
+
// exchange rates. Parser only, no fetcher: see parseFedH10Csv for where the files come from.
|
|
3
|
+
import { quotedTable } from './history.js';
|
|
4
|
+
import { addDayRate, csvRows, isCalendarDay, newestFirst, readRateCell } from './rate-text.js';
|
|
5
|
+
// RXI$US_N.B.EU is USD per euro; RXI_N.B.JA is yen per USD.
|
|
6
|
+
const SERIES = /^(?:H10\/H10\/)?RXI(\$US)?_N\.B\.([A-Z]{2,3})$/;
|
|
7
|
+
// The country codes in H.10 series IDs, and the currency each one's column must carry.
|
|
8
|
+
const FED_COUNTRIES = {
|
|
9
|
+
AL: 'AUD',
|
|
10
|
+
EU: 'EUR',
|
|
11
|
+
NZ: 'NZD',
|
|
12
|
+
UK: 'GBP',
|
|
13
|
+
BZ: 'BRL',
|
|
14
|
+
CA: 'CAD',
|
|
15
|
+
CH: 'CNY',
|
|
16
|
+
DN: 'DKK',
|
|
17
|
+
HK: 'HKD',
|
|
18
|
+
IN: 'INR',
|
|
19
|
+
JA: 'JPY',
|
|
20
|
+
MA: 'MYR',
|
|
21
|
+
MX: 'MXN',
|
|
22
|
+
NO: 'NOK',
|
|
23
|
+
SF: 'ZAR',
|
|
24
|
+
SI: 'SGD',
|
|
25
|
+
KO: 'KRW',
|
|
26
|
+
SL: 'LKR',
|
|
27
|
+
SD: 'SEK',
|
|
28
|
+
SZ: 'CHF',
|
|
29
|
+
TA: 'TWD',
|
|
30
|
+
TH: 'THB',
|
|
31
|
+
VES: 'VEB',
|
|
32
|
+
};
|
|
33
|
+
function notH10(why) {
|
|
34
|
+
throw new SyntaxError(`Not a Federal Reserve H.10 CSV file: ${why}`);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Parses the Federal Reserve Board's H.10 daily foreign exchange rates, as CSV from its Data
|
|
38
|
+
* Download Program (DDP), into one USD-based table per day, newest first. These are the noon
|
|
39
|
+
* buying rates in New York, certified by the New York Fed for customs purposes, with `source:
|
|
40
|
+
* 'FRB'` and `type: 'noon buying'`, back to 1971.
|
|
41
|
+
*
|
|
42
|
+
* - **Direction.** H.10 quotes "currency units per U.S. dollar except as noted": AUD, EUR, NZD and
|
|
43
|
+
* GBP (series `RXI$US_N.B.*`) are USD per unit. Those four are stored as exact inverses, so
|
|
44
|
+
* every table is USD → currency, and the published quote stays on the rate:
|
|
45
|
+
* `rate('USD', 'EUR').inverse().toString()` is '1.1750' again.
|
|
46
|
+
* - **Holidays** are rows of `ND` ("no data"); such a day is left out, so a lookback goes on to
|
|
47
|
+
* the day before, and a file of holidays only gives []. A single `ND` cell is a missing value.
|
|
48
|
+
* A file with no observation rows at all throws, as it is more likely cut short than empty.
|
|
49
|
+
* - **Strict:** each column's Unit, Multiplier and Currency must be "Currency", 1 and the code
|
|
50
|
+
* its series ID stands for (EU is EUR), a currency can't have two columns, and two different
|
|
51
|
+
* values for one day throw.
|
|
52
|
+
* - **Digits.** H.10 publishes four decimals and keeps trailing zeros; they are kept.
|
|
53
|
+
* - **Codes.** The Fed's column codes are used as they are, so the bolivar is `VEB`, as the Fed
|
|
54
|
+
* labels it.
|
|
55
|
+
* - **Publication.** The release is weekly (Mondays, 4:15 p.m. ET) and covers the week before,
|
|
56
|
+
* so a Tuesday's rate is known only up to six days later. The CSV doesn't say when each row was
|
|
57
|
+
* released, so no `availableAt` is set; give each table one yourself if a backtest needs it.
|
|
58
|
+
*
|
|
59
|
+
* **Where the data comes from.** The DDP at federalreserve.gov/datadownload (release H10, CSV,
|
|
60
|
+
* "series in columns", with labels) serves these files today. The Board is retiring the DDP: the
|
|
61
|
+
* "Build Your Package" feature goes in November 2026 and the rest later, and it points users to
|
|
62
|
+
* FRED (fred.stlouisfed.org) instead. FRED needs an API key, and its terms forbid storing or
|
|
63
|
+
* caching its content and any commercial use without consent, which is why ducat has no H.10
|
|
64
|
+
* fetcher. Board data itself is public domain ("please cite to the Board as the source").
|
|
65
|
+
*
|
|
66
|
+
* const tables = parseFedH10Csv(await readFile('FRB_H10.csv', 'utf8'));
|
|
67
|
+
*/
|
|
68
|
+
export function parseFedH10Csv(csv) {
|
|
69
|
+
const rows = csvRows(csv.charCodeAt(0) === 0xfeff ? csv.slice(1) : csv);
|
|
70
|
+
const series = rows.find((cells) => cells[0]?.trim() === 'Time Period') ?? notH10('no "Time Period" row');
|
|
71
|
+
const labelled = (label) => {
|
|
72
|
+
const row = rows.find((cells) => cells[0]?.trim() === label);
|
|
73
|
+
if (row === undefined || row.length !== series.length) {
|
|
74
|
+
notH10(`no "${label}" row matching the columns`);
|
|
75
|
+
}
|
|
76
|
+
return row;
|
|
77
|
+
};
|
|
78
|
+
const currencies = labelled('Currency:');
|
|
79
|
+
const multipliers = labelled('Multiplier:');
|
|
80
|
+
const units = labelled('Unit:');
|
|
81
|
+
// Each column: its currency, and whether it is quoted as USD per unit (to be inverted).
|
|
82
|
+
const columns = [];
|
|
83
|
+
for (let i = 1; i < series.length; i++) {
|
|
84
|
+
const id = SERIES.exec(series[i].trim());
|
|
85
|
+
const currency = currencies[i].trim();
|
|
86
|
+
if (id === null || !/^[A-Z]{3}$/.test(currency) || currency === 'USD') {
|
|
87
|
+
notH10(`column ${i + 1} is ${series[i]} for ${currency}`);
|
|
88
|
+
}
|
|
89
|
+
// The series ID names the country; it must agree with the currency code beside it.
|
|
90
|
+
const expected = FED_COUNTRIES[id[2]];
|
|
91
|
+
if (expected !== undefined && expected !== currency) {
|
|
92
|
+
notH10(`series ${series[i]} is ${expected}, not ${currency}`);
|
|
93
|
+
}
|
|
94
|
+
if (columns.some((column) => column.currency === currency)) {
|
|
95
|
+
notH10(`${currency} has two columns`);
|
|
96
|
+
}
|
|
97
|
+
// Other units or a multiplier other than 1 would make the published number mean something else.
|
|
98
|
+
if (units[i].trim() !== 'Currency' || multipliers[i].trim() !== '1') {
|
|
99
|
+
throw new SyntaxError(`Unsupported H.10 unit ${units[i]} × ${multipliers[i]} for ${currency}`);
|
|
100
|
+
}
|
|
101
|
+
columns.push({ currency, inverted: id[1] !== undefined });
|
|
102
|
+
}
|
|
103
|
+
const observations = rows.slice(rows.indexOf(series) + 1);
|
|
104
|
+
if (observations.length === 0) {
|
|
105
|
+
notH10('no observations');
|
|
106
|
+
}
|
|
107
|
+
const days = new Map();
|
|
108
|
+
for (const cells of observations) {
|
|
109
|
+
const day = cells[0].trim();
|
|
110
|
+
if (!isCalendarDay(day) || cells.length !== series.length) {
|
|
111
|
+
throw new SyntaxError(`Malformed H.10 row: ${cells.join(',')}`);
|
|
112
|
+
}
|
|
113
|
+
columns.forEach(({ currency }, i) => {
|
|
114
|
+
addDayRate(days, day, currency, readRateCell(cells[i + 1], `${currency} on ${day}`));
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
const tables = [];
|
|
118
|
+
for (const [day, published] of days) {
|
|
119
|
+
const rates = {};
|
|
120
|
+
let quoted = 0;
|
|
121
|
+
for (const { currency, inverted } of columns) {
|
|
122
|
+
const rate = published[currency] ?? null;
|
|
123
|
+
rates[currency] = rate === null ? null : { rate, inverted };
|
|
124
|
+
if (rate !== null) {
|
|
125
|
+
quoted++;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (quoted > 0) {
|
|
129
|
+
tables.push(quotedTable({ base: 'USD', source: 'FRB', type: 'noon buying', asOf: day, rates }));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return newestFirst(tables);
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=fed.js.map
|
package/dist/fed.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fed.js","sourceRoot":"","sources":["../src/fed.ts"],"names":[],"mappings":"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"}
|
package/dist/fetch.d.ts
CHANGED
|
@@ -55,4 +55,49 @@ export declare class FetchRatesError extends Error {
|
|
|
55
55
|
* const hist = snapshotsFrom(await fetchEcb({ history: '90d' }));
|
|
56
56
|
*/
|
|
57
57
|
export declare function fetchEcb(options?: FetchEcbOptions): Promise<RateTable[]>;
|
|
58
|
+
/** The ECB Data Portal's SDMX REST API (no key, and CORS-enabled, so it works in browsers). */
|
|
59
|
+
export declare const ECB_DATA_API = "https://data-api.ecb.europa.eu/service/data/EXR";
|
|
60
|
+
/** Options for fetching a date range of ECB reference rates. */
|
|
61
|
+
export interface FetchEcbRangeOptions extends Omit<FetchEcbOptions, 'history'> {
|
|
62
|
+
/** The first day ('1999-01-04' at the earliest). */
|
|
63
|
+
readonly start: string | Date;
|
|
64
|
+
/** The last day (default: the latest published). */
|
|
65
|
+
readonly end?: string | Date;
|
|
66
|
+
/** ISO codes to fetch (default: every currency, including discontinued series). */
|
|
67
|
+
readonly currencies?: readonly string[];
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Fetches a date range of ECB euro reference rates from the ECB Data Portal and parses them with
|
|
71
|
+
* parseEcbSdmxCsv: EUR-based tables, one per TARGET working day, newest first, with the published
|
|
72
|
+
* digits. It makes two requests: the series' DECIMALS (small) and the observations without
|
|
73
|
+
* attributes, which keeps the full history since 1999 to about 15 MB. Give a few days before the
|
|
74
|
+
* first day you need, so that a lookback from it has a table to fall back on. A range with no
|
|
75
|
+
* rates (a weekend, or after the latest day) gives []. Both requests share one timeout and are
|
|
76
|
+
* cancelled together: if one fails, the other is aborted. The ECB states that its rates are for
|
|
77
|
+
* information purposes only.
|
|
78
|
+
*
|
|
79
|
+
* const tables = await fetchEcbRange({ start: '2026-01-01', currencies: ['USD', 'JPY'] });
|
|
80
|
+
* const history = rateHistory(tables); // from @ducatjs/money/convert/history
|
|
81
|
+
*/
|
|
82
|
+
export declare function fetchEcbRange(options: FetchEcbRangeOptions): Promise<RateTable[]>;
|
|
83
|
+
/** The Bank of Canada's Valet API for its daily exchange rates (no key; CORS-enabled). */
|
|
84
|
+
export declare const BANK_OF_CANADA_URL = "https://www.bankofcanada.ca/valet/observations/group/FX_RATES_DAILY/json";
|
|
85
|
+
/** Options for fetching Bank of Canada rates. */
|
|
86
|
+
export interface FetchBankOfCanadaOptions extends Omit<FetchEcbOptions, 'history'> {
|
|
87
|
+
/** The first day (2017-01-03 at the earliest). Default: only the latest published day. */
|
|
88
|
+
readonly start?: string | Date;
|
|
89
|
+
/** The last day (default: the latest published). Needs a `start`. */
|
|
90
|
+
readonly end?: string | Date;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Fetches the Bank of Canada's daily exchange rates from its Valet API and parses them with
|
|
94
|
+
* parseBankOfCanadaJson: CAD-based tables, newest first. Without `start`, only the latest day;
|
|
95
|
+
* without `end`, up to the latest. A range with no business days in it gives [].
|
|
96
|
+
* The Bank asks users to keep within its request limits, which it doesn't publish, and its rates
|
|
97
|
+
* are "released for statistical and analytical purposes only", not for transactions.
|
|
98
|
+
*
|
|
99
|
+
* const [latest] = await fetchBankOfCanada();
|
|
100
|
+
* const year = await fetchBankOfCanada({ start: '2026-01-01' });
|
|
101
|
+
*/
|
|
102
|
+
export declare function fetchBankOfCanada(options?: FetchBankOfCanadaOptions): Promise<RateTable[]>;
|
|
58
103
|
//# sourceMappingURL=fetch.d.ts.map
|
package/dist/fetch.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../src/fetch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../src/fetch.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE/C;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,EAAE,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IAC1F,mBAAmB,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;CAChE;AAED,2FAA2F;AAC3F,MAAM,MAAM,KAAK,GAAG,CAClB,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,eAAe,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,KAClE,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,CAAA;CAAE,CAAC,CAAC;AAUvE,oGAAoG;AACpG,eAAO,MAAM,QAAQ;;;;CAIX,CAAC;AAEX,gDAAgD;AAChD,MAAM,WAAW,eAAe;IAC9B,kGAAkG;IAClG,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,OAAO,QAAQ,CAAC;IACzC,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,CAAC,EAAE,eAAe,CAAC;IAClC;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,gFAAgF;IAChF,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;CACxB;AAED,mEAAmE;AACnE,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;gBACT,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAMxC;AAED;;;;;;;GAOG;AACH,wBAAsB,QAAQ,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAI9E;AA0BD,+FAA+F;AAC/F,eAAO,MAAM,YAAY,oDAAoD,CAAC;AAE9E,gEAAgE;AAChE,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC;IAC5E,oDAAoD;IACpD,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,oDAAoD;IACpD,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,mFAAmF;IACnF,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACzC;AA2ED;;;;;;;;;;;;GAYG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAyDvF;AAED,0FAA0F;AAC1F,eAAO,MAAM,kBAAkB,6EAC6C,CAAC;AAE7E,iDAAiD;AACjD,MAAM,WAAW,wBAAyB,SAAQ,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC;IAChF,0FAA0F;IAC1F,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,qEAAqE;IACrE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED;;;;;;;;;GASG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,CAAC,EAAE,wBAAwB,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAqBhG"}
|