Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
com.snowplowanalytics:scala-forex_2.10
Advanced tools
High-performance Scala library for performing currency conversions using Open Exchange Rates
[ ![Build Status] travis-image ] travis [ ![Release] release-image ] releases [ license-image ] license
Scala Forex is a high-performance Scala library for performing exchange rate lookups and currency conversions, using Joda-Money joda-money and Joda-Time joda-time.
It includes configurable LRU (Least Recently Used) caches to minimize calls to the API; this makes the library usable in high-volume environments such as Hadoop and Storm.
Currently Scala Forex uses the [Open Exchange Rates API] oer-signup to perform currency lookups.
First [sign up] oer-signup to Open Exchange Rates to get your App ID for API access.
There are three types of accounts supported by OER API, Unlimited, Enterprise and Developer levels. See the [sign up] oer-signup page for specific account descriptions. For Scala Forex, we recommend an Enterprise or Unlimited account, unless all of your conversions are to or from USD (see section 4.5 OER accounts for an explanation). For 10-minute rate updates, you will need an Unlimited account (other accounts are hourly).
The latest version of Scala Forex is 0.5.0, which is cross-built against 2.10.x and 2.11.x.
If you're using SBT, add the following lines to your build file:
libraryDependencies ++= Seq(
"com.snowplowanalytics" %% "scala-forex" % "0.5.0"
)
Note the double percent (%%
) between the group and artifactId. That'll ensure you get the right package for your Scala version.
The Scala Forex supports two types of usage:
Both usage types support live, near-live or historical (end-of-day) exchange rates.
Scala Forex is configured via two case classes:
ForexConfig
contains general configurationOerClientConfig
contains Open Exchange Rates-specific configurationCase class with defaults:
case class ForexConfig(
nowishCacheSize: Int = 13530,
nowishSecs: Int = 300,
eodCacheSize: Int = 405900,
getNearestDay: EodRounding = EodRoundDown,
baseCurrency: String = "USD"
)
To go through each in turn:
nowishCacheSize
is the size configuration for near-live(nowish) lookup cache, it can be disabled by setting its value to 0. The key to nowish cache is a currency pair so the size of the cache equals to the number of pairs of currencies available.
nowishSecs
is the time configuration for near-live lookup. Nowish call will use the exchange rates stored in nowish cache if its time stamp is less than or equal to nowishSecs
old.
eodCacheSize
is the size configuration for end-of-day(eod) lookup cache, it can be disabled by setting its value to 0. The key to eod cache is a tuple of currency pair and time stamp, so the size of eod cache equals to the number of currency pairs times the days which the cache will remember the data for.
getNearestDay
is the rounding configuration for latest eod(at) lookup. The lookup will be performed on the next day if the rounding mode is set to EodRoundUp, and on the previous day if EodRoundDown.
baseCurrency
can be configured to different currencies by the users.
For an explanation for the default values please see section 4.4 Explanation of defaults below.
Case class with defaults:
case class OerClientConfig(
appId: String,
accountLevel: AccountType
) extends ForexClientConfig
To go through each in turn:
appId
is the unique key for the user's accountaccountLevel
is the account type provided by the user which should obviously be consistent with the app ID.
There are three types of account levels, users should provide the exact account type name to configure the OER Client:For the required imports, please see section 4.2 REPL setup below.
Lookup a live rate (no cacheing available):
// USD => JPY
val fx = Forex(ForexConfig(), OerClientConfig(appId, DeveloperAccount))
val usd2jpy = fx.rate.to("JPY").now // => Right(JPY 105)
Lookup a near-live rate (cacheing available):
// JPY => GBP
val fx = Forex(ForexConfig(), OerClientConfig(appId, DeveloperAccount))
val jpy2gbp = fx.rate("JPY").to("GBP").nowish // => Right(GBP 0.01)
Lookup a near-live rate (uses cache selectively):
// JPY => GBP
val fx = Forex(ForexConfig(nowishCacheSize = 0), OerClientConfig(appId, DeveloperAccount))
val jpy2gbp = fx.rate("JPY").to("GBP").nowish // => Right(GBP 0.01)
Lookup the latest EOD (end-of-date) rate prior to your event (cacheing available):
import org.joda.time.{DateTime, DateTimeZone}
// USD => JPY at the end of 12/03/2011
val fx = Forex(ForexConfig(), OerClientConfig(appId, DeveloperAccount)) // round down to previous day by default
val tradeDate = new DateTime(2011, 3, 13, 11, 39, 27, 567, DateTimeZone.forID("America/New_York"))
val usd2yen = fx.rate.to("JPY").at(tradeDate) // => Right(JPY 82)
Lookup the latest EOD (end-of-date) rate post to your event (cacheing available):
import org.joda.time.{DateTime, DateTimeZone}
import com.snowplowanalytics.forex.EodRoundUp
// USD => JPY at the end of 13/03/2011
val fx = Forex(ForexConfig(getNearestDay = EodRoundUp), OerClientConfig(appId, DeveloperAccount))
val tradeDate = new DateTime(2011, 3, 13, 11, 39, 27, 567, DateTimeZone.forID("America/New_York"))
val usd2yen = fx.rate.to("JPY").at(tradeDate) // => Right(JPY 82)
Lookup the EOD rate for a specific date (cacheing available):
import org.joda.time.DateTime
// GBP => JPY at the end of 13/03/2011
val fx = Forex(ForexConfig(baseCurrency="GBP"), OerClientConfig(appId, EnterpriseAccount)) // Your app ID should be an Enterprise account
val eodDate = new DateTime(2011, 3, 13, 0, 0)
val gbp2jpy = fx.rate.to("JPY").eod(eodDate) // => Right(JPY 131)
Lookup the EOD rate for a specific date (no cacheing):
import org.joda.time.DateTime
// GBP => JPY at the end of 13/03/2011
val fx = Forex(ForexConfig(eodCacheSize = 0, baseCurrency="GBP"), OerClientConfig(appId, EnterpriseAccount)) // Your app ID should be an Enterprise account
val eodDate = new DateTime(2011, 3, 13, 0, 0)
val gbp2jpy = fx.rate.to("JPY").eod(eodDate) // => Right(JPY 131)
For the required imports, please see section 4.2 REPL setup below.
Conversion using the live exchange rate (no cacheing available):
// 9.99 USD => EUR
val fx = Forex(ForexConfig(), OerClientConfig(appId, DeveloperAccount))
val priceInEuros = fx.convert(9.99).to("EUR").now
Conversion using a near-live exchange rate with 500 seconds nowishSecs (cacheing available):
// 9.99 GBP => EUR
val fx = Forex(ForexConfig(nowishSecs = 500), OerClientConfig(appId, DeveloperAccount))
val priceInEuros = fx.convert(9.99, "GBP").to("EUR").nowish
Note that this will be a live rate conversion if cache is not available. Conversion using a live exchange rate with 500 seconds nowishSecs, this conversion will be done via HTTP request:
// 9.99 GBP => EUR
val fx = Forex(ForexConfig(nowishSecs = 500, nowishCacheSize = 0), OerClientConfig(appId, DeveloperAccount))
val priceInEuros = fx.convert(9.99, "GBP").to("EUR").nowish
Conversion using the latest EOD (end-of-date) rate prior to your event (cacheing available):
import org.joda.time.{DateTime, DateTimeZone}
// 10000 GBP => JPY at the end of 12/03/2011
val fx = Forex(ForexConfig(), OerClientConfig(appId, DeveloperAccount))
val tradeDate = new DateTime(2011, 3, 13, 11, 39, 27, 567, DateTimeZone.forID("America/New_York"))
val tradeInYen = fx.convert(10000, "GBP").to("JPY").at(tradeDate)
Lookup the latest EOD (end-of-date) rate following your event (cacheing available):
import org.joda.time.{DateTime, DateTimeZone}
import com.snowplowanalytics.forex.EodRoundUp
// 10000 GBP => JPY at the end of 13/03/2011
val fx = Forex(ForexConfig(getNearestDay = EodRoundUp), OerClientConfig(appId, DeveloperAccount))
val tradeDate = new DateTime(2011, 3, 13, 11, 39, 27, 567, DateTimeZone.forID("America/New_York"))
val usd2yen = fx.convert(10000, "GBP").to("JPY").at(tradeDate)
Conversion using the EOD rate for a specific date (cacheing available):
import org.joda.time.DateTime
// 10000 GBP => JPY at the end of 13/03/2011
val fx = Forex(ForexConfig(baseCurrency="GBP"), OerClientConfig(appId, DeveloperAccount))
val eodDate = new DateTime(2011, 3, 13, 0, 0)
val tradeInYen = fx.convert(10000).to("JPY").eod(eodDate)
Conversion using the EOD rate for a specific date, (no cacheing):
import org.joda.time.DateTime
// 10000 GBP => JPY at the end of 13/03/2011
val fx = Forex(ForexConfig(eodCacheSize = 0, baseCurrency="GBP"), OerClientConfig(appId, DeveloperAccount))
val eodDate = new DateTime(2011, 3, 13, 0, 0)
val tradeInYen = fx.convert(10000).to("JPY").eod(eodDate)
The lruCache
value determines the maximum number of values to keep in the LRU cache, which the Client will check prior to making an API lookup. To disable the LRU cache, set its size to zero, i.e. lruCache = 0
.
A default "from currency" can be specified for all operations, using the baseCurrency
argument to the ForexConfig
object.
If not specified, baseCurrency
is set to USD by default.
Assuming git, [Vagrant] vagrant-install and [VirtualBox] virtualbox-install installed:
host> git clone https://github.com/snowplow/scala-forex
host> cd scala-forex
host> vagrant up && vagrant ssh
guest> cd /vagrant
guest> sbt build
To try out Scala Forex in the Scala REPL:
guest> sbt console
...
scala> val appId = "<<key>>"
scala> import com.snowplowanalytics.forex.{Forex, ForexConfig}
scala> import com.snowplowanalytics.forex.oerclient.{OerClientConfig, DeveloperAccount}
scala> val fx = Forex(ForexConfig(), OerClientConfig(appId, DeveloperAccount))
scala> val usd2jpy = fx.rate.to("JPY").now
You must export your OER_KEY
or else the test suite will fail. To run the test suite locally:
$ export OER_KEY=<<key>>
$ git clone https://github.com/snowplow/scala-forex.git
$ cd scala-forex
$ sbt test
The end of today is 00:00 on the next day.
When .now
is specified, the live exchange rate available from Open Exchange Rates is used.
When .nowish
is specified, a cached version of the live exchange rate is used, if the timestamp of that exchange rate is less than or equal to nowishSecs
(see above) ago. Otherwise a new lookup is performed.
When .at(...)
is specified, the latest end-of-day rate prior to the datetime is used by default. Or users can configure that Scala Forex "round up" to the end of the occurring day.
When .eod(...)
is specified, the end-of-day rate for the specified day is used. Any hour/minute/second/etc portion of the datetime is ignored.
We recommend trying different LRU cache sizes to see what works best for you.
Please note that the LRU cache implementation is not thread-safe ([see this note] twitter-lru-cache). Switch it off if you are working with threads.
nowishCache
= (165 * 164 / 2) = 13530There are 165 currencies provided by the OER API, hence 165 * 164 pairs of currency combinations. The key in nowish cache is a tuple of source currency and target currency, and the nowish cache was implemented in a way such that a lookup from CurrencyA to CurrencyB or from CurrencyB to CurrencyA will use the same exchange rate, so we don't need to store both in the caches. Hence there are (165 * 164 / 2) pairs of currencies for nowish cache.
eodCache
= (165 * 164 / 2) * 30 = 405900Assume the eod cache stores the rates to each pair of currencies for 1 month(i.e. 30 days). There are 165 * 164 / 2 pairs of currencies, hence (165 * 164 / 2) * 30 entries.
nowishSecs
= 300Assume nowish cache stores data for 5 mins.
getNearestDay
= EodRoundDownBy convention, we are always interested in the exchange rates prior to the query date, hence EodRoundDown.
baseCurrency
= USDWe selected USD for the base currency because this is the OER default as well.
With Open Exchange Rates' Unlimited and Enterprise accounts, Scala Forex can specify the base currency to use when looking up exchange rates; Developer-level accounts will always retrieve rates against USD, so a rate lookup from e.g. GBY to EUR will require two conversions (GBY -> USD -> EUR). For this reason, we recommend Unlimited and Enterprise-level accounts for slightly more accurate non-USD-related lookups.
Scala Forex is copyright 2013-2016 Snowplow Analytics Ltd.
Licensed under the [Apache License, Version 2.0] license (the "License"); you may not use this software except in compliance with the License.
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
FAQs
High-performance Scala library for performing currency conversions using Open Exchange Rates
We found that com.snowplowanalytics:scala-forex_2.10 demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.