'use strict'; // currency-cross-rate.cjs -- METHOD DECK (X063), computes a cross rate from two rates quoted // against a common base currency, then converts an amount. Standard cross-rate arithmetic: // if rate_from and rate_to are both "units of currency per 1 unit of base", the cross rate // (units of to_currency per 1 unit of from_currency) is rate_to / rate_from. // Per the Founder rule via W001/PQ021, rate_from and rate_to are values that change over time, // so they carry a companion rate_date and rate_source input: the visitor supplies (or replaces) // the date and citation the two rates came from; this method never looks up or fetches a rate. function fmt(x, decimals) { return x.toLocaleString('en-US', { minimumFractionDigits: decimals, maximumFractionDigits: decimals }); } module.exports = { slug: 'currency-cross-rate', title: 'Currency cross rate', deck_category: 'currency', description: 'Computes the cross exchange rate between two currencies from their two given rates against a common base currency, and converts an amount.', inputs: [ { name: 'amount', type: 'number', required: true, description: 'The amount, in from_currency, to convert', min: 0 }, { name: 'base_currency', type: 'string', required: true, description: 'Label of the common base currency both rates are quoted against (e.g. "USD")' }, { name: 'from_currency', type: 'string', required: true, description: 'Label of the currency the amount is in (e.g. "JPY")' }, { name: 'to_currency', type: 'string', required: true, description: 'Label of the currency to convert into (e.g. "GBP")' }, { name: 'rate_from', type: 'number', required: true, description: 'Units of from_currency per 1 unit of base_currency', min: 0 }, { name: 'rate_to', type: 'number', required: true, description: 'Units of to_currency per 1 unit of base_currency', min: 0 }, { name: 'rate_date', type: 'string', unit: 'ISO date', required: true, description: 'The date rate_from and rate_to apply to; change it together with the rates to use a different day.' }, { name: 'rate_source', type: 'string', required: true, description: 'Citation for where rate_from and rate_to came from; change it together with the rates and rate_date when using a different table.' }, ], outputs: [ { name: 'result', description: 'amount converted into to_currency' } ], steps: [ 'Both input rates are quoted the same way: units of that currency per 1 unit of the common base_currency.', 'The visitor supplies rate_from, rate_to, rate_date, and rate_source together; this method never looks up or fetches a rate itself, so any newer official table may be substituted for all four together.', 'Compute the cross rate (units of to_currency per 1 unit of from_currency): cross_rate = rate_to / rate_from.', 'Convert the amount: result = amount * cross_rate.', 'Round result to 2 decimal places.', ], constants: [], sources: [ { kind: 'url', value: 'https://www.investopedia.com/terms/c/crossrate.asp', title: 'Cross Rate', publisher: 'Investopedia', retrieved_utc: '2026-09-30T19:29:48Z', note: 'Standard cross-rate arithmetic: derive the rate between two currencies from their two rates against a shared third (base) currency by dividing. rate_date and rate_source are supplied per use and cite where the two rate values themselves came from.' }, ], disclaimer: null, questionText(inputs) { return `Given ${inputs.rate_from} ${inputs.from_currency} per 1 ${inputs.base_currency} and ${inputs.rate_to} ${inputs.to_currency} per 1 ${inputs.base_currency} (dated ${inputs.rate_date}, sourced from ${inputs.rate_source}), how much is ${inputs.amount} ${inputs.from_currency} in ${inputs.to_currency}?`; }, run(inputs) { const { amount, base_currency, from_currency, to_currency, rate_from, rate_to, rate_date, rate_source } = inputs || {}; if (typeof amount !== 'number' || !isFinite(amount)) throw new Error('amount must be a finite number'); if (typeof rate_from !== 'number' || !isFinite(rate_from) || rate_from <= 0) throw new Error('rate_from must be a positive finite number'); if (typeof rate_to !== 'number' || !isFinite(rate_to) || rate_to <= 0) throw new Error('rate_to must be a positive finite number'); if (typeof rate_date !== 'string' || !/^\d{4}-\d{2}-\d{2}$/.test(rate_date)) throw new Error('rate_date must be a string in YYYY-MM-DD format'); if (typeof rate_source !== 'string' || !rate_source.trim()) throw new Error('rate_source must be a non-empty string'); for (const [k, v] of [['base_currency', base_currency], ['from_currency', from_currency], ['to_currency', to_currency]]) { if (typeof v !== 'string' || !v.trim()) throw new Error(k + ' must be a non-empty string'); } const crossRate = rate_to / rate_from; const raw = amount * crossRate; const result = Math.round(raw * 100) / 100; return { answer: `${fmt(result, 2)} ${to_currency}`, values: { result, cross_rate: crossRate } }; }, examples: [ { name: 'worked example', inputs: { amount: 10000, base_currency: 'USD', from_currency: 'JPY', to_currency: 'GBP', rate_from: 149.50, rate_to: 0.7830, rate_date: '2026-09-30', rate_source: 'Illustrative example rates for cross-rate arithmetic; replace rate_from, rate_to, rate_date, and rate_source with your own dated, cited quotes (for example the ECB euro reference rates page).' }, expected: { answer: '52.37 GBP' }, check: 'By hand: cross_rate = 0.7830/149.50 = 0.0052366555...; 10000 JPY * 0.0052366555... = 52.366555..., rounded to 2 decimals is 52.37.' }, { name: 'test vector: USD/EUR to GBP cross', inputs: { amount: 100, base_currency: 'EUR', from_currency: 'USD', to_currency: 'GBP', rate_from: 1.10, rate_to: 0.86, rate_date: '2026-09-30', rate_source: 'Illustrative example rates for cross-rate arithmetic; replace rate_from, rate_to, rate_date, and rate_source with your own dated, cited quotes (for example the ECB euro reference rates page).' }, expected: { answer: '78.18 GBP' }, check: 'By hand: cross_rate = 0.86/1.10 = 0.781818...; 100 * 0.781818... = 78.1818..., rounded to 2 decimals is 78.18.' }, { name: 'test vector: identical rates give a 1:1 cross rate', inputs: { amount: 250, base_currency: 'USD', from_currency: 'CAD', to_currency: 'AUD', rate_from: 1.35, rate_to: 1.35, rate_date: '2026-09-30', rate_source: 'Illustrative example rates for cross-rate arithmetic; replace rate_from, rate_to, rate_date, and rate_source with your own dated, cited quotes (for example the ECB euro reference rates page).' }, expected: { answer: '250.00 AUD' }, check: 'By hand: cross_rate = 1.35/1.35 = 1 exactly, so result = amount unchanged = 250.00.' }, ], };