18

我有一个 BigDecimal 计算结果,我需要将其四舍五入到最接近的指定间隔(在这种情况下,它是金融市场的刻度大小)。

例如价格 [Tick Size] -> 四舍五入的价格

100.1 [0.25] -> 100
100.2 [0.25] -> 100.25
100.1 [0.125] -> 100.125
100.2 [0.125] -> 100.25

谢谢。

更新:schnaader 的解决方案,翻译成 Java/BigDecimal 术语:

price = price.divide(tick).setScale(0, RoundingMode.HALF_UP).multiply(tick)
4

3 回答 3

14

您可以标准化刻度大小,然后使用通常的舍入方法:

100.1 [0.25] -> * (1/0.25) -> 400.4 [1]  -> round -> 400 -> / (1/0.25) -> 100
100.2 [0.25] -> * (1/0.25) -> 400.8 [1] -> round -> 401 -> / (1/0.25) -> 100.25

所以应该是:

Price = Round(Price / Tick) * Tick;

另请注意,您似乎必须为 BigDecimals 设置正确的舍入模式。例如,请参阅BigDecimal 文档。所以你应该确保设置正确并编写一些测试来检查你的代码的正确性。

于 2009-03-13T08:49:16.960 回答
2

这与“将股票价格四舍五入到最接近的刻度大小”更相关。

schnaader 提供的答案是正确的,但是缺少一些内容。

  • 首先,你必须检查股价是否需要四舍五入。不必要的舍入会弄乱小数部分。
  • 然后你还需要处理在divide函数ArithmeticException中可能出现的问题BigDecimal

这是我的解决方案。解释它需要很多时间。我建议尝试一些样品来感受一下。寻找功能roundTick()

import static java.math.RoundingMode.HALF_UP;

import java.math.BigDecimal;

/**
 * Utility class for stock price related operations.
 */
public final class PriceFormatter {

    public static final float DELTA = 0.0001f;

    private PriceFormatter() {
    }

    /**
     * Rounds the price to the nearest tick size.
     *
     * @param price    price
     * @param tickSize tick size
     * @return price rounded to the nearest tick size
     */
    public static final float roundTick(final float price, final float tickSize) {
        if (tickSize < DELTA) {
            return price;
        }

        if (!isRoundingNeeded(price, tickSize)) {
            return price;
        }

        final BigDecimal p = new BigDecimal(price);
        final BigDecimal t = new BigDecimal(tickSize);

        final BigDecimal roundedPrice = p.divide(t, 0, HALF_UP).multiply(t);

        return roundedPrice.floatValue();
    }

    /**
     * Checks whether price needs rounding to the nearest tick size.
     *
     * @param price    price
     * @param tickSize tick size
     * @return true, if rounding is needed; false otherwise
     */
    public static final boolean isRoundingNeeded(final float price, final float tickSize) {
        final int mult = calculateTickMultiplier(tickSize);
        final int mod = (int) (tickSize * mult);
        final float reminder = (((price * mult) % mult) % mod);
        final boolean needsRounding = reminder > DELTA;
        return needsRounding;
    }

    public static final int calculateTickMultiplier(final float tickSize) {
        int result = 1;
        while (((tickSize * result) < 1) || (((tickSize * result) - (int) (tickSize * result)) > DELTA)) {
            result *= 10;
        }

        return result;
    }

}
于 2020-04-24T18:36:13.553 回答
1
p= p - p % t + ((p % t < t / 2) ? 0.0 : t);

//其中 p= 价格和 t= 刻度增量

于 2013-12-06T01:44:42.480 回答