New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better support for currency rounding #1689

Merged
merged 1 commit into from May 15, 2018
Jump to file or symbol
Failed to load files and symbols.
+73 −13
Diff settings

Always

Just for now

@@ -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);
ProTip! Use n and p to navigate between commits in a pull request.