Simple Exchange Rate Information File Format (SERIFF)
This document specifies a text-based file format for representing currency exchange rates.
Applications which work with more than one currency need access to up-to-date exchange rates. While more sophisticated and dedicated systems already employ automatic management of exchange rate updates, among the public at large the traditional method of entering exchange rates by hand still prevails. Thanks to the internet (and television teletext before that), users can access a variety of sites providing exchange rate information. Events like the introduction of the euro currency have increased demand for currency conversion applications (e.g. "currency converters"). However, as the first version of this text is being written, no specification has succeeded in linking all these services and demands.
SERIFF was designed to meet certain objectives using simple and established solutions.
SERIFF uses and considers existing standards and specifications wherever possible.
Example 1: eur.ini
As an introduction to this specification, here is the first of a series of practical examples. The following text shows the contents of a file named "eur.ini". The file was named after the base currency, and contains exchange rates for 1 EUR.
PublicationTime = 1999-01-07T18:42:05Z
ExpirationTime = 1999-01-08T07:00:00Z
Source = "European Central Fantasy Bank"
Message = "Currency rates provided by European Central Fantasy Bank (www.example.com). No liability accepted."
AUD = 1.8474
CAD = 1.7602
CHF = 1.6165
CYP = 0.58187
CZK = 34.886
DKK = 7.4431
EEK = 15.6466
GBP = 0.70585
HUF = 250.09
ISK = 81.0553
KRW = 1337.155
MTL = 0.44132
MXN = 11.5511
NOK = 8.6295
NZD = 2.1531
PLN = 4.0165
ROL = 13092.4
SEK = 9.18
SIT = 188.8
SKK = 42.76455
TRL = 370147
ZAR = 6.82828
Example 2: eur.ini
The following is a simple fariation of the previous example, illustrating how bid and ask pairs can be used in place of the mid rates. A value of 0 indicates an undefined or missing element.
PublicationTime = 1999-01-07T19:00:00Z
ExpirationTime = 1999-01-08T08:00:00Z
Source = "Galaxy FX Buy and Sell"
Message = "Currency rates provided by Galaxy FX Buy and Sell (www.example.com). No liability accepted."
AUD = 1.8289,1.8659
CAD = 1.7426,1.7778
CHF = 1.6003,0
Example 3: rates.ini
The following example shows a file which contains exchange rates relative to a variety of base currencies, all in the same file. In practice, it is desirable that a specific client application only load and use the section relative to one particular base currency (otherwise due to rounding differences the different rates would produce slightly different results).
PublicationTime = 1999-01-21T11:10:32Z
Message = "Currency rates provided by Fantasy Television (www.example.com). No liability accepted."
Copyright = "Copyright © 1999 Fantasy Television"
EUR = 0.8648
JPY = 112.85
GBP = 0.6074
CHF = 1.3891
USD = 1.1563
JPY = 130.49
GBP = 0.7024
CHF = 1.6062
USD = 1.6462
EUR = 1.4237
JPY = 185.78
CHF = 2.2867
USD = 0.008861
EUR = 0.007663
GBP = 0.005383
CHF = 0.012308
USD = 0.7199
EUR = 0.6226
JPY = 81.245
GBP = 0.4373
Example 4: eur.ini
The following example shows a file which contains no data, but simply points to a new location. This may be useful for example for centralized administration in an organization using this format on several computers, or after a reorganization on the web server of a provider of exchange rate data. This example also displays an optional message, which is not necessary or desired in all cases where redirection is useful. Note that the "Next" link acts after the full page has been processed.
Next = http://www.example.com/rates/eur.ini
Message = "The currency data has moved, and your software will now be redirected to the new address. This redirection will work for 29 more days. Please set the new address in your software: http://www.example.com/rates/eur.ini."
Example 5: euroconv.ini
The following example involves an imaginary "Euro Converter" program, which uses a local .ini file to store the exchange rates of the euro member currencies (which are constant) and then has a private and application-specific part with program settings, including the address of an eur.ini file used to load "fresh" exchange rates, located on a network server. If the external file cannot be accessed, or does not include the constant rates, the Euro Converter will at least have these constant rates.
The Smallest section indicates the smallest unit and the decimal precision to use for final results. The default is 0.01 (one cent).
Next = file://SERVER/rates/eur.ini
ATS = 13.7603
BEF = 40.3399
DEM = 1.95583
ESP = 166.386
FIM = 5.94573
FRF = 6.55957
IEP = 0.787564
ITL = 1936.27
LUF = 40.3399
NLG = 2.20371
PTE = 200.482
BEF = 0.50
ESP = 1
ITL = 1
PTE = 0.10
Display = USD, GBP, DEM, FRF, ITL
AutoUpdate = Yes
General File Structure
A SERIFF file is an 8-bit text file divided into sections, each containing zero or more keys. Each key contains zero or more values. SERIFF files are designed to be compatible with parsers designed for the .INI file format, defined by Microsoft in the Windows for Workgroups Resource Kit.
The companion document which describes the INI file format used by SERIFF is located at https://cloanto.com/specs/ini/.
In numerical values, trailing zeroes are sometimes used in SERIFF to express precision. For example, "0.50", opposed to "0.5", may indicate that the smallest currency unit is equal to fifty "cents", as opposed to five "tenths" of the full unit, and "1.234000" may indicate to use a precision of six decimal digits in partial or total results.
Files, Sections and Keys
A SERIFF file contains one or more sections. All sections are optional. Except for the General section and application-specific sections, all sections contain keys named after the currency they refer to. It is strongly advised to use ISO 4217 names for all currency names. For consistency these should be all-upper case, although the names are not case-sensitive. SERIFF can in theory also be used to represent non-currency keys, such as for example "GoldOunce", or ticker symbols. Suggestions in this direction are welcome.
SERIFF files are processed from the beginning of the file to the end of the file. If a section or key appears more than once (e.g. as a result of chaining multiple files), then the last-read value of duplicate keys prevails. After the full file has been processed, the client may begin to process a new file referenced by the Next key in the General section.
The following sections are defined as part of SERIFF:
For consistency, and with consideration to file-sensitive file systems, it is recommended that SERIFF file names (and, if possible, the entire URL path) be in lower case, and use the ".ini" suffix. If an .ini file is specific to a particular base unit, it is recommended to name the file after the base unit (e.g. "usd.ini", "eur.ini", etc.) If a provider maintains a single file with multiple base units, it is recommended to name the file "rates.ini". If the files (e.g. the message, comments and extended currency names) are localized in any language other than English, it is recommended to have the file names end with "-XX.ini", where XX is the language code, based on ISO 639-1 (e.g. "eur-de.ini", which could in turn link to exchange rates stored in a language-neutral "eur.ini"). It should be considered that consistency in file names is an important benefit to end users and for all parties involved in maintenance.
Three-character section names are reserved for BaseCurrency sections, named after ISO 4217. All BaseCurrency sections consist of three characters delimited by square brackets.
When a parser encounters an unrecognized section name, the entire section (with all its keys) should be skipped. Within a known section, only unrecognized keys should be skipped.
The sections and keys are described in detail in the following parts.
The [General] section contains general information about the entire data set.
This is an example [General] section:
DataContentTime = 2000-01-07T18:42:05Z
PublicationTime = 2000-01-07T12:00:00Z
ExpirationTime = 2000-01-08T12:00:00Z
Source = "European Central Fantasy Bank"
Message = "Hello World."
Copyright = "Copyright © 2000 European Central Fantasy Bank"
Next = http://www.example.com/rates/eur.ini
SERIFF clients should support at least the Message and Next keys. The keys are explained in the following sections.
This key indicates the date and time of the last update of the exchange rate information. If the data was fetched from a specific source, the key may reference time elements contained in the original feed. Clients may use this field to display it to the user in an information window, to compare it with the ExpirationTime key, to see which information from multiple sources is newer, or simply ignore it. If the file contains no exchange rate or other "perishable" information, then this key should not be used.
The date and time are expressed using a particular extended notation of the ISO 8601 format (more compact and easier to parse than RFC 822/1123), where "T" between the date and time indicates that this is an ISO 8601 notation, and the "Z" after the time indicates that the time is Universal Time (UT is the new name for the former GMT time zone). All time indications used by SERIFF are expressed as Universal Time. It is up to the clients and servers to convert this time information to and from local time, if necessary. The month, day, hour, minute and second are expressed with two digits. The hours range from 0 to 23. Midnight is "00:00:00". The year is expressed using four digits if it is in the range 1000-9999. The "-" and ":" separators are required.
This key, which has the same format as the DataContentTime key, indicates the official date and time of publication, if known.
The value of PublicationTime cannot be higher than EffectiveTime.
This key, which has the same format as the DataContentTime key, indicates the "Effective date" of the currency information contained in the file. For example, a national bank could publish, every day at noon, rates which only become effective at midnight. This traditional mechanism allows newspapers to publish rates that are valid on the day in which they appear in print.
The value of EffectiveTime cannot be smaller than PublicationTime.
This key, which has the same format as the PublicationTime key, indicates the "Expires date" of the currency information contained in the file. For example, in an organization which requires up-to-date currency information the ExpirationTime field could be set to 1 minute (or even less) after the PublicationTime field. After the markets close, it could be set to the opening time on the following working day. In general, this field should match the frequency with which the file is updated. Information services oriented to the general public will probably want to set a value which is 24 hours after that of the PublicationTime field. It is recommended that the server updates the data slightly before (one or more seconds, or even a few minutes, depending on the overall validity of the data) the expiration time, because some clients may reload the information at exactly the time indicated by the ExpirationTime key (or even earlier, if they rely on an incorrect clock).
A SERIFF file may contain information about different currencies, each with a different validity (e.g. because different markets are open at different hours). In this case, the ExpirationTime key indicates the time in which the first piece of information listed in the file expires. In practice, in most cases an entire SERIFF file can fit in a single network packet, so it does not make much difference whether one currency or 20 currencies are re-loaded.
The value of ExpirationTime cannot be smaller than PublicationTime or EffectiveTime.
This key indicates the original source (e.g. a national central bank) of the data contained in the file. A client may display this information in an information window.
This key contains a string intended to be brought to the attention of the user after the SERIFF file has been loaded. The message should contain proper punctuation (end with a period, etc.) All-capitals should be avoided. Clients should be prepared to display a scroll bar depending on the size of the message.
This key is similar to Message in that it contains a string intended to be brought to the attention of the user after the SERIFF file has been loaded. This key is however to be used only for error notifications, and overrides any message notification settings in the software which may normally cause identical messages to be displayed only once. Error messages are displayed each time they occur, even if they occur more than once. Also, the software should interpret the presence of an Error key as an error condition, and act accordingly.
This key can be used for a copyright notice referring to the data. An introduction such as "Copyright" or "©" is not implicit, i.e. it should be expressed in full in the string, as part of a complete copyright statement.
This key allows multiple SERIFF files to be chained together, which is useful for centralized administration and for an information provider to refer to a different or new address to complete an operation. The string value is a URL as per RFC 1738, not delimited by angle brackets and not introduced by "URL:".
A file URL is expressed in the format "file://<host>/<path>". Clients should support at least file and http URLs. Clients must be able to detect a loop of chained files. This is preferably done keeping a list of the URLs already accessed, loading a new file only if it has not already been loaded.
This section contains the actual exchange rates, and is named after the base unit to which the exchange rates indicated in the keys refer. For example, if the values in the section are expressed relative to 1 Swiss franc, then the section would be named [CHF]. The section name consists of three upper case characters, consistent with ISO 4217 currency names. If the file contains only one section with exchange rates, it is recommended to name the file after this section name (without square brackets, in lower case, and with ".ini" suffix, e.g. "chf.ini").
Each key indicates the rate of the currency (relative to 1 BaseCurrency unit), defined either as the mid rate, or as a bid (sell) and ask (buy) pair:
CurrencyCode = Mid Rate
CurrencyCode = Bid Rate, Ask Rate
If a value of a bid/ask pair is undefined, it should be set to 0. Trailing zero characters may be used to indicate the precision of the data (e.g. 123.4560 vs. 123.456).
The number of digits in which the values are expressed can be used by some applications to apply that precision for intermediate calculations. For example, a value of "5.8000" could give different and more precise results than "5.8". While this behavior is application-specific, the information provider should be careful to at least maintain a consistent number of significant digits (i.e. the number of digits excluding initial zeros) for all exchange rates, and especially when generating tables with cross rates.
With particular relation to the euro, applications doing currency conversions should consider the Council Regulation (EC) 1103/97, which among other things states that "The rates will be adopted with six significant figures... Only the conversion rates may be used for conversions from the euro unit into a national currency unit (NCU) and vice versa... It is not permissible to calculate in a first step the inverse rate expressed in decimals and subsequently to multiply the NCU amount by the inverse rate... because inverse rates necessarily imply rounding of the rates... Monetary amounts to be converted from one national currency unit into another shall first be converted into a monetary amount expressed in the euro unit, which amount may be rounded to not less than three decimals and shall then be converted into the other national currency unit. No alternative method of calculation may be used unless it produces the same results."
This format makes it possible to list multiple exchange rate data sets, each in their own timestamped section, in place of a single [BaseCurrency] section. This could be useful, for example, to describe data from a source that publishes data sets consisting of multiple daily rates once per month (for the entire previous month) or once per week (for the entire previous week).
The date should be in the YYYYMMDD or YYYYMMDDTHHMMSSZ notation. It is up to the application to process one or more specific sets, or only the most recent one.
The keys in this section indicate the granularity to be used for final results for a given currency, expressed as the smallest unit. Client applications should use these values only for display purposes, and never for intermediate calculations. In practice, this key indicates the value of the smallest coin or scriptural unit for each currency, expressed with the desired precision.
The use of this key is normally application-dependent. In some cases (e.g. when generating an invoice) the preferred rounding will be to the smallest scriptural payment unit, while in others (e.g. in a supermarket) it may be preferable to round based on the smallest coin in circulation. If this section is used in a file for public use, i.e. not with a specific application in mind, then the values should reflect the smallest possible unit with consideration to both scriptural units and coins.
For currencies for which there is no matching key in this section, clients should set a default value of one "cent", i.e. 0.01 of the main unit. This makes it possible to reduce the size of this section, since for most currencies in the world the smallest sub-unit is 0.01 of the base unit.
It should be noted that, for example, values of "0.5" and "0.50" would lead to correspondingly different types of representation, as in "1234.5" and "1234.50".
BEF = 0.50
ESP = 1
GRD = 5
ITL = 50
PTE = 0.10
This section contains currency-specific comment strings. An application may display this data in a currency-specific information section.
GBP = "New rate for GBP. The previous rate supplied by the Bank of England was incorrect."
KRW = "Not a reference rate. For indicative purposes only."
USD = "Rate of the previous day."
This section indicates how certain currencies are related to others as part of monetary unions, for which special conversion rules may apply. For example, national currency units of the euro member nations should only be converted through a specific triangulation process. As new national currency units are added to the system, they become subject to the euro-specific conversion rules. Applications which can handle these special procedures need to know not only the exchange rates, but also which currencies have joined which monetary unions.
Each key represents a base currency, and one or more values indicate the member currencies (national expressions of the base currency).
A scenario could for example be:
EUR = ATS, BEF, DEM, ESP, FIM, FRF, GRD, IEP, ITL, LUF, NLG, PTE, SIT
MED = ARS, BRL, CLP, PYG, UYP
XXX = EUR, JPY, USD
This section indicates which currencies have been replaced by other currencies.
For example, as part of participation in the European Economic and Monetary Union, a currency may at first join the union at a constant conversion rate (and be listed in the [Unions] section described above), and then, following a transition phase, be completely replaced by the euro. At the end of the transition period the fact that the national currency ceases to be legal tender can be expressed by the [Replaced] section.
Each key represents the code of a valid currency, and one or more codes of currencies which have been replaced by it.
A possible scenario could be:
EUR = ATS, BEF, DEM, ESP, FIM, FRF, GRD, IEP, ITL, LUF, NLG, PTE
This section contains the extended names associated to the three-character currency names.
USD = "US dollar"
JPY = "Japanese yen"
The [Service] section contains service expiration and renewal information, so that it is possible for the client application to inform the user before the current feed subscription expires, and to include a quick renewal link. If the service is not provided as a subscription, then this section may be omitted.
This is an example [Service] section:
ExpirationTime = 2007-12-31T23:59:59Z
Renewal = http://www.example.com/renew/?account=12345
The keys are explained in the following sections.
This key indicates the date and time of the end of the current service subscription.
The date and time are expressed in the same format as the PublicationTime key of the [General] section.
This key indicates the URL, preferably with account-specific information, which can be used by the service customer to renew the current subscription.
Section names beginning with "Private-" are used and reserved for private, application-specific purposes. The application part of the name should preferably consist of the organization or company name followed by the application name, so as to be as descriptive and unique as possible.
Private sections should appear at the end of the file, after the public sections. Section and keys which are not documented in this specification should be placed in private sections.
The keys in these sections could control, for example, some program settings, such as the list of currencies which can be selected on a currency converter (as opposed to the probably longer list of currencies for which exchange rates exist), or whether to use the ExpirationTime key to automatically reload new rates.
Client applications may want to prevent public SERIFF files from changing private keys by means of an appropriate option.
This could be an example section:
Display = USD, GBP, DEM, FRF, ITL
AutoUpdate = Yes
Client applications are encouraged to issue appropriate warning and error messages when loops are detected in the links, when a particular currency has fluctuated beyond a certain margin since the previous update (which could indicate an error in the data), or when the rates for some or all of the currencies used by the application could not be loaded. Applications may also want to keep a local copy of the most recent exchange rate data, so as to be able to use it when a network connection is not available.
Clients should be prepared to handle cases such as an outdated file (not updated after expiration date), and files that cannot be loaded. No user would be happy to see a program trying to get a file every two seconds, and each time display an error message.
On the server side, it is recommended that an extremely high priority be placed on the long-term stability of the URLs. Once the files are first published, their URL will be programmed by users in currency converters, calculators, accounting and financial applications, etc. One proposed internet-based reference URL is "http://domain/rates/xxx.ini", where domain indicates the server and xxx is the code of the base currency (e.g. "http://www.fantasy-bank.com/rates/eur.ini"). It is a common practice to use only lower case characters in internet URLs, in consideration of case-sensitive systems. More sophisticated client applications may go as far as try and normalize a URL to lower text if a first attempt to load the file gives a "file not found" error.
If there are doubts about which sections should be supported for data intended for the general public, it is recommended to implement at least one [BaseCurrency] section, and optionally some keys in [General], and to add other sections and keys once there is proven demand for them.
The main purpose of SERIFF is to support the automated retrieval of daily currency exchange rates. More sophisticated and diverse implementations may require the definition of new sections and keys. Proposals to expand and improve this specification are always welcome. Whatever the changes will be, if any, it is however guaranteed that applications supporting SERIFF version 1.00 will remain compatible with future versions. At the same time, newer versions of Currency Server increasingly use an XML-based format, which is more flexible and robust.