private double getBatchPrice(int startStock, int endStock) {
        // Gets the current base price for the items at stock levels from
        // startStock to endStock.
        // NOTE: Does not check stockLowest/stockHighest transaction limits.

        int lowStock = Math.min(startStock, endStock);
        int highStock = Math.max(startStock, endStock);
        int numTerms = highStock - lowStock + 1;
        double lowStockPrice;
        double highStockPrice;
        int fixedStockLimit;

        // End calculation if volatility == 0. Price does not change, so all
        // items are the same value.
        if (volatility == 0)
            return (numTerms * getStockPrice(stock));

        // End calculation if highStock <= stockFloor (All below floor)
        if (highStock <= stockFloor)
            return (numTerms * getStockPrice(stockFloor));

        // End calculation if lowStock >= stockCeil (All above ceiling)
        if (lowStock >= stockCeiling)
            return (numTerms * getStockPrice(stockCeiling));

        // Split calculation if stockFloor reached by lowStock (Some below
        // floor)
        if (lowStock < stockFloor)
            return (((stockFloor - lowStock + 1) * getStockPrice(stockFloor)) + getBatchPrice(stockFloor + 1,
                                                                                              highStock));

        // Split calculation if stockCeil reached by highStock (Some above
        // ceiling)
        if (highStock > stockCeiling)
            return (((highStock - stockCeiling + 1) * getStockPrice(stockCeiling)) + getBatchPrice(lowStock,
                                                                                                   stockCeiling - 1));

        lowStockPrice = getStockPrice(lowStock); // highest price in range
        highStockPrice = getStockPrice(highStock); // lowest price in range

        // WARNING in this section: Highest stock level corresponds to lowest
        // price,
        // and lowest stock level corresponds to highest price.

        // End calculation if lowStockPrice <= priceFloor (All below floor)
        if (lowStockPrice <= priceFloor)
            return (numTerms * priceFloor);

        // End calculation if highStockPrice >= priceCeil (All above ceiling)
        if (highStockPrice >= priceCeiling)
            return (numTerms * priceCeiling);

        // Split calculation if highStockPrice < priceFloor (Some below floor)
        if (highStockPrice < priceFloor) {
            fixedStockLimit = (int) Math.round(Math.floor(stockAtPrice(priceFloor)));
            return (((highStock - fixedStockLimit + 1) * priceFloor) + getBatchPrice(lowStock,
                                                                                     fixedStockLimit - 1));
        }

        // Split calculation if lowStockPrice > priceCeil (Some above ceiling)
        if (lowStockPrice > priceCeiling) {
            fixedStockLimit = (int) Math.round(Math.ceil(stockAtPrice(priceCeiling)));
            return (((fixedStockLimit - lowStock + 1) * priceCeiling) + getBatchPrice(fixedStockLimit + 1,
                                                                                      highStock));
        }

        // All range limits handled? Find the sum of terms of a finite geometric
        // series.
        // return Math.round(this.basePrice * Math.pow(getVolFactor(),-lowStock)
        // * (Math.pow(getVolFactor(),numTerms) - 1) / (getVolFactor()-1));
        // return math.round(firstTerm * (1 - (ratio ^ terms)) / (1 - ratio));
        return round(lowStockPrice * (1 - (Math.pow(1 / getVolFactor(), numTerms)))
                     / (1 - (1 / getVolFactor())), 2);
    }