Permalink
Browse files

Better support for currency rounding (#1689)

This makes HalfUpRounding package scoped, as it should have been
Just use the the methods on Rounding instead
  • Loading branch information...
jodastephen authored and cjkent committed May 15, 2018
1 parent 97fdbd7 commit 5ec4e080501f8736ee3f43959a381d18f265d3b3
@@ -6,6 +6,8 @@
package com.opengamma.strata.basics.currency;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -401,6 +403,29 @@ public Currency getTriangulationCurrency() {
return Currency.of(triangulationCurrency);
}
//-------------------------------------------------------------------------
/**
* Rounds the specified amount according to the minor units.
* <p>
* For example, 'USD' has 2 minor digits, so 63.347 will be rounded to 63.35.
*
* @return the rounded amount
*/
public double roundMinorUnits(double amount) {
return roundMinorUnits(BigDecimal.valueOf(amount)).doubleValue();
}
/**
* Rounds the specified amount according to the minor units.
* <p>
* For example, 'USD' has 2 minor digits, so 63.347 will be rounded to 63.35.
*
* @return the rounded amount
*/
public BigDecimal roundMinorUnits(BigDecimal amount) {
return amount.setScale(minorUnitDigits, RoundingMode.HALF_UP);
}
//-------------------------------------------------------------------------
/**
* Compares this currency to another.
@@ -7,7 +7,6 @@
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import org.joda.convert.FromString;
@@ -54,10 +53,7 @@
* @return the currency amount
*/
public static Money of(CurrencyAmount currencyAmount) {
Currency currency = currencyAmount.getCurrency();
BigDecimal roundedAmount = BigDecimal.valueOf(currencyAmount.getAmount())
.setScale(currency.getMinorUnitDigits(), RoundingMode.HALF_UP);
return new Money(currency, roundedAmount);
return new Money(currencyAmount.getCurrency(), BigDecimal.valueOf(currencyAmount.getAmount()));
}
/**
@@ -68,9 +64,7 @@ public static Money of(CurrencyAmount currencyAmount) {
* @return the currency amount
*/
public static Money of(Currency currency, double amount) {
BigDecimal roundedAmount = BigDecimal.valueOf(amount)
.setScale(currency.getMinorUnitDigits(), RoundingMode.HALF_UP);
return new Money(currency, roundedAmount);
return new Money(currency, BigDecimal.valueOf(amount));
}
/**
@@ -81,8 +75,7 @@ public static Money of(Currency currency, double amount) {
* @return the currency amount
*/
public static Money of(Currency currency, BigDecimal amount) {
BigDecimal roundedAmount = amount.setScale(currency.getMinorUnitDigits(), RoundingMode.HALF_UP);
return new Money(currency, roundedAmount);
return new Money(currency, amount);
}
//-------------------------------------------------------------------------
@@ -121,7 +114,7 @@ private Money(Currency currency, BigDecimal amount) {
ArgChecker.notNull(currency, "currency");
ArgChecker.notNull(amount, "amount");
this.currency = currency;
this.amount = amount;
this.amount = currency.roundMinorUnits(amount);
}
//-------------------------------------------------------------------------
@@ -40,7 +40,7 @@
* For example, the value 0.1 cannot be exactly represented in a {@code double}.
*/
@BeanDefinition(builderScope = "private")
public final class HalfUpRounding
final class HalfUpRounding
implements Rounding, ImmutableBean, Serializable {
/**
@@ -243,7 +243,7 @@ public int getFraction() {
/**
* The meta-bean for {@code HalfUpRounding}.
*/
public static final class Meta extends DirectMetaBean {
static final class Meta extends DirectMetaBean {
/**
* The singleton instance of the meta-bean.
*/
@@ -8,6 +8,8 @@
import java.math.BigDecimal;
import java.math.RoundingMode;
import com.opengamma.strata.basics.currency.Currency;
/**
* A convention defining how to round a number.
* <p>
@@ -34,6 +36,19 @@ public static Rounding none() {
return NoRounding.INSTANCE;
}
/**
* Obtains an instance that rounds to the number of minor units in the currency.
* <p>
* This returns a convention that rounds for the specified currency.
* Rounding follows the normal {@link RoundingMode#HALF_UP} convention.
*
* @param currency the currency
* @return the rounding convention
*/
public static Rounding of(Currency currency) {
return HalfUpRounding.ofDecimalPlaces(currency.getMinorUnitDigits());
}
/**
* Obtains an instance that rounds to the specified number of decimal places.
* <p>
@@ -12,6 +12,7 @@
import static org.testng.Assert.assertSame;
import static org.testng.Assert.assertTrue;
import java.math.BigDecimal;
import java.util.Set;
import org.testng.annotations.DataProvider;
@@ -149,6 +150,23 @@ public void test_triangulatonCurrency() {
assertEquals(Currency.of("CAD").getTriangulationCurrency(), Currency.USD);
}
//-----------------------------------------------------------------------
public void test_roundMinorUnits_double() {
assertEquals(Currency.USD.roundMinorUnits(63.347d), 63.35d, 0d);
assertEquals(Currency.USD.roundMinorUnits(63.34500001d), 63.35d, 0d);
assertEquals(Currency.USD.roundMinorUnits(63.34499999d), 63.34d, 0d);
assertEquals(Currency.JPY.roundMinorUnits(63.347d), 63d, 0d);
assertEquals(Currency.JPY.roundMinorUnits(63.5347d), 64d, 0d);
}
public void test_roundMinorUnits_BigDecimal() {
assertEquals(Currency.USD.roundMinorUnits(new BigDecimal(63.347d)), new BigDecimal("63.35"));
assertEquals(Currency.USD.roundMinorUnits(new BigDecimal(63.34500001d)), new BigDecimal("63.35"));
assertEquals(Currency.USD.roundMinorUnits(new BigDecimal(63.34499999d)), new BigDecimal("63.34"));
assertEquals(Currency.JPY.roundMinorUnits(new BigDecimal(63.347d)), new BigDecimal("63"));
assertEquals(Currency.JPY.roundMinorUnits(new BigDecimal(63.5347d)), new BigDecimal("64"));
}
//-----------------------------------------------------------------------
public void test_compareTo() {
Currency a = Currency.EUR;
@@ -97,6 +97,7 @@ public void testToString() throws Exception {
@Test
public void testParse() throws Exception {
assertEquals(Money.parse("RON 200.23"), MONEY_200_RON);
assertEquals(Money.parse("RON 200.2345"), MONEY_200_RON);
}
@Test(expectedExceptions = IllegalArgumentException.class,
@@ -16,12 +16,20 @@
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import com.opengamma.strata.basics.currency.Currency;
/**
* Test {@link HalfUpRounding}.
*/
@Test
public class HalfUpRoundingTest {
public void test_of_Currency() {
Rounding test = Rounding.of(Currency.USD);
assertEquals(test.round(63.455d), 63.46d, 0d);
assertEquals(test.round(63.454d), 63.45d, 0d);
}
public void test_ofDecimalPlaces() {
HalfUpRounding test = HalfUpRounding.ofDecimalPlaces(4);
assertEquals(test.getDecimalPlaces(), 4);

0 comments on commit 5ec4e08

Please sign in to comment.