ProBacktest/probacktest · proorder

ROUNDEDUP

ROUNDEDUP in ProBacktest and ProOrder rounds a value up to the next whole number, used when order quantities must round upward. Syntax, examples, and gotchas.

Syntax

probuilder
ROUNDEDUP(value)

Parameters

NameTypeDefaultDescription
valuenumbernoneValue to round. Any literal, variable, or arithmetic expression that evaluates to a number.

How it works

ROUNDEDUP takes a numeric value and returns the next higher whole number whenever the value has a fractional part. A value that is already whole is returned unchanged. Since order instructions in ProBacktest and ProOrder work with whole quantities of shares, contracts, or lots, any sizing formula that involves division needs a rounding step before its result can be placed as an order.

Rounding up is the right direction when the computed value represents a minimum that has to be met, for example the number of shares needed so a position reaches a target exposure, or the quantity required to hedge another position completely. In those cases rounding down would leave the position undersized.

The trade-off is cost: rounding up means the order can require slightly more cash than the raw calculation suggested. When the calculation represents a budget that must not be exceeded, ROUNDEDDOWN is the correct counterpart.

Examples

Example 1, Whole shares from a cash amount (ProBacktest)

probuilder
// Convert a cash amount into a whole number of shares
myCash = 1000
stockPrice = 123.45
maxShares = ROUNDEDUP(myCash / stockPrice)

The division yields roughly 8.1 and ROUNDEDUP raises it to 9. Note that buying 9 shares costs slightly more than the 1000 in cash; see the gotchas below. This is the example from the official reference.

Example 2, Reaching a minimum exposure (ProOrder)

probuilder
DEFPARAM CumulateOrders = false

// Size the position so exposure is at least 10000 in notional value
targetExposure = 10000
qty = ROUNDEDUP(targetExposure / close)

IF NOT onmarket AND close CROSSES OVER Average[100](close) THEN
  BUY qty SHARES AT MARKET
ENDIF

Because the quantity is rounded up, the notional value of the position always reaches the 10000 target rather than stopping just below it.

Example 3, Matching a short hedge to a long position (ProOrder)

probuilder
DEFPARAM CumulateOrders = false

// Hedge ratio derived from relative volatility
hedgeRatio = 1.6
IF NOT onmarket AND close CROSSES UNDER Average[50](close) THEN
  // Round up so the hedge is never undersized
  SELLSHORT ROUNDEDUP(hedgeRatio * 2) SHARES AT MARKET
ENDIF

A fractional hedge ratio is rounded up to the next whole quantity, so the short leg fully covers the intended exposure.

Common errors and gotchas

  • Rounding up can exceed the budget. Applied to a cash-per-price division, ROUNDEDUP produces a quantity that costs more than the available cash, 9 shares at 123.45 is 1111.05 against a 1000 budget. For budget-capped sizing use ROUNDEDDOWN instead.
  • Not available in indicators. ROUNDEDUP belongs to the strategy languages. In indicator or screener code the equivalent is CEIL; ROUNDEDUP there fails to compile.
  • Whole values stay unchanged. ROUNDEDUP(8) is 8, not 9. Logic that expects the function to always add one behaves incorrectly on exact whole numbers.
  • Round once, at the end. Rounding intermediate values, such as the price or the ratio, before the final division compounds the rounding error. Apply ROUNDEDUP only to the final quantity.
  • ROUNDEDDOWN, rounds a value down to the nearest whole number.
  • ROUND, rounds to the nearest whole number.
  • CEIL, rounds up, available in all sub-languages.
  • FLOOR, rounds down, available in all sub-languages.
  • SHARES, quantity unit keyword for stock orders.
  • CASH, cash-based position sizing keyword.
  • BUY, opens a long position with the computed quantity.
  • SELLSHORT, opens a short position with the computed quantity.