Skip to content

Commit c031c84

Browse files
committed
Issue #6 first cut for bid/ask rounding
1 parent c10cd43 commit c031c84

File tree

5 files changed

+102
-27
lines changed

5 files changed

+102
-27
lines changed

fxcalc/src/main/java/net/objectlab/kit/fxcalc/CrossRateCalculator.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ private CrossRateCalculator() {
3131
* @throws IllegalArgumentException if the 2 fx1 and fx2 do not share a common cross currency or either currencies in the targetPair
3232
*/
3333
public static FxRate calculateCross(final CurrencyPair targetPair, final FxRate fx1, final FxRate fx2, final int precision,
34-
final MajorCurrencyRanking ranking) {
34+
final int precisionForInverseFxRate, final MajorCurrencyRanking ranking, final int bidRounding, final int askRounding) {
3535
final Optional<String> crossCcy = fx1.getCurrencyPair().findCommonCcy(fx2.getCurrencyPair());
3636
final String xCcy = crossCcy.orElseThrow(() -> new IllegalArgumentException("The 2 FXRates do not share a ccy " + fx1.getCurrencyPair() + " "
3737
+ fx2.getCurrencyPair()));
@@ -55,14 +55,18 @@ public static FxRate calculateCross(final CurrencyPair targetPair, final FxRate
5555
final FxRate denominatorFx = numeratorFx == fx1 ? fx2 : fx1;
5656
LOG.debug("CALC {} / {}", numeratorFx, denominatorFx);
5757

58-
bid = BigDecimalUtil.divide(precision, numeratorFx.getBid(), denominatorFx.getAsk(), BigDecimal.ROUND_HALF_UP);
59-
ask = BigDecimalUtil.divide(precision, numeratorFx.getAsk(), denominatorFx.getBid(), BigDecimal.ROUND_HALF_UP);
58+
bid = BigDecimalUtil.divide(precision, numeratorFx.getBid(), denominatorFx.getAsk(), bidRounding);
59+
ask = BigDecimalUtil.divide(precision, numeratorFx.getAsk(), denominatorFx.getBid(), askRounding);
6060
} else {
6161
final boolean inverse = targetPair.getCcy1().equals(fx2Ccy2) || targetPair.getCcy1().equals(fx1Ccy2);
6262
LOG.debug("CALC {} x {}", fx1, fx2);
6363
if (inverse) {
64-
ask = BigDecimalUtil.setScale(BigDecimalUtil.inverse(BigDecimalUtil.multiply(fx1.getBid(), fx2.getBid())), precision);
65-
bid = BigDecimalUtil.setScale(BigDecimalUtil.inverse(BigDecimalUtil.multiply(fx1.getAsk(), fx2.getAsk())), precision);
64+
ask = BigDecimalUtil.setScale(
65+
BigDecimalUtil.inverse(BigDecimalUtil.multiply(fx1.getBid(), fx2.getBid()), precisionForInverseFxRate, bidRounding),
66+
precision);
67+
bid = BigDecimalUtil.setScale(
68+
BigDecimalUtil.inverse(BigDecimalUtil.multiply(fx1.getAsk(), fx2.getAsk()), precisionForInverseFxRate, askRounding),
69+
precision);
6670
} else {
6771
bid = BigDecimalUtil.setScale(BigDecimalUtil.multiply(fx1.getBid(), fx2.getBid()), precision);
6872
ask = BigDecimalUtil.setScale(BigDecimalUtil.multiply(fx1.getAsk(), fx2.getAsk()), precision);

fxcalc/src/main/java/net/objectlab/kit/fxcalc/FxRateCalculatorBuilder.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package net.objectlab.kit.fxcalc;
22

3+
import java.math.BigDecimal;
34
import java.util.ArrayList;
45
import java.util.Collection;
56
import java.util.Collections;
@@ -64,6 +65,14 @@ public class FxRateCalculatorBuilder {
6465
* If using the baseFxRateProvider, should the rate be cached in the calculator, defaulted to true.
6566
*/
6667
private boolean cacheBaseRates = true;
68+
/**
69+
* The Rounding to use for BID, default HALF_UP
70+
*/
71+
private int bidRounding = BigDecimal.ROUND_HALF_UP;
72+
/**
73+
* The Rounding to use for ASK, default HALF_UP
74+
*/
75+
private int askRounding = BigDecimal.ROUND_HALF_UP;
6776

6877
public FxRateCalculatorBuilder() {
6978
orderedCurrenciesForCross.add("USD");
@@ -167,6 +176,22 @@ public FxRateCalculatorBuilder precisionForInverseFxRate(final int precisionForI
167176
return this;
168177
}
169178

179+
/**
180+
* Rounding for BID calculations.
181+
*/
182+
public FxRateCalculatorBuilder bidRounding(final int bidRounding) {
183+
this.bidRounding = bidRounding;
184+
return this;
185+
}
186+
187+
/**
188+
* Rounding for BID calculations.
189+
*/
190+
public FxRateCalculatorBuilder askRounding(final int askRounding) {
191+
this.askRounding = askRounding;
192+
return this;
193+
}
194+
170195
/**
171196
* If the rate required from the calculator is not immediately available, use a cross currency to calculate it; this
172197
* gives you the opportunity to select which currencies to use in which order. Defaulted to USD and then EUR.
@@ -212,4 +237,13 @@ public FxRateCalculatorBuilder addRateSnapshot(final FxRate rate) {
212237
public Map<CurrencyPair, FxRate> getRatesSnapshot() {
213238
return ratesSnapshot;
214239
}
240+
241+
public int getBidRounding() {
242+
return bidRounding;
243+
}
244+
245+
public int getAskRounding() {
246+
return askRounding;
247+
}
248+
215249
}

fxcalc/src/main/java/net/objectlab/kit/fxcalc/FxRateCalculatorImpl.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ public class FxRateCalculatorImpl implements FxRateCalculator {
2121
private final List<String> orderedCurrenciesForCross;
2222
private final int precisionForFxRate;
2323
private final int precisionForInverseFxRate;
24+
private final int bidRounding;
25+
private final int askRounding;
2426
private final boolean cacheResults;
2527
private final boolean cacheBaseRates;
2628

@@ -35,6 +37,8 @@ public FxRateCalculatorImpl(final FxRateCalculatorBuilder builder) {
3537
this.precisionForInverseFxRate = builder.getPrecisionForInverseFxRate();
3638
this.cacheBaseRates = builder.isCacheBaseRates();
3739
this.cacheResults = builder.isCacheResults();
40+
this.bidRounding = builder.getBidRounding();
41+
this.askRounding = builder.getAskRounding();
3842
}
3943

4044
private FxRate getBaseRate(final CurrencyPair ccyPair) {
@@ -102,7 +106,8 @@ private FxRate findViaCrossCcy(final CurrencyPair ccyPair, final String crossCcy
102106
}
103107
}
104108
if (xCcy2 != null) {
105-
return CrossRateCalculator.calculateCross(ccyPair, xCcy1, xCcy2, precisionForFxRate, majorCurrencyRanking);
109+
return CrossRateCalculator.calculateCross(ccyPair, xCcy1, xCcy2, precisionForFxRate, precisionForInverseFxRate, majorCurrencyRanking,
110+
bidRounding, askRounding);
106111
}
107112
}
108113
return null;

0 commit comments

Comments
 (0)