Skip to contents

ledgr_target_rebalance() converts long-only weights into a full-universe ledgr_target. It uses current pulse equity and current close prices at decision time; fills still occur at the next open, so small drift between decision-time sizing and fill-time value is expected.

Usage

ledgr_target_rebalance(weights, ctx, equity_fraction = 1, keep = NULL)

Arguments

weights

A ledgr_weights object.

ctx

ledgr strategy context.

equity_fraction

Fraction of allocatable equity to allocate, between 0 and 1.

keep

Current decision-axis positions to preserve. Kept IDs must not also appear in weights, even at zero weight.

Value

A full-universe ledgr_target object.

Details

In a dense run, allocatable equity is current equity. In an availability-aware run, ledgr first reserves the absolute marked exposure of ineligible holdings, held nonmembers and target-restricted members alike, and preserves their current quantities; weights may name eligible instruments only. IDs named in keep are likewise preserved and reserved exactly once. Weights and equity_fraction apply to the residual capital after those reservations. Share quantities are floored to whole numbers with floor(weight * equity_fraction * allocation_equity / close_price). An exact zero member weight targets zero without consulting that instrument's sizing close.

In an availability-aware run, an eligible member with a positive weight but no positive current close is skipped for that rebalance: it keeps its current quantity (zero if not held) and its weight is not redistributed. Priced members keep their fully priced size, unless the skipped members' held exposure at their risk marks plus the priced value would exceed allocatable equity; then the priced quantities are scaled down, before flooring, by max(0, allocatable - held_exposure) / priced_value. Each skip is recorded as a sizing_unavailable decision row in ledgr_results(bt, "diagnostics").

Warning and error classes:

  • ledgr_invalid_target_price when a selected instrument has missing, non-finite, or non-positive close price in a dense run, which targets zero;

  • ledgr_target_sizing_unavailable when an availability-aware rebalance must keep a held member, or reserve a preserved holding, that has no permissible valuation mark;

  • ledgr_negative_weights for negative weights;

  • ledgr_levered_weights when sum(abs(weights)) > 1.

Articles

Strategy helper pipelines: vignette("strategy-development", package = "ledgr") system.file("doc", "strategy-development.html", package = "ledgr")

Examples

weights <- ledgr_weights(c(AAA = 0.5, BBB = 0.5),
                         universe = c("AAA", "BBB"))
ctx <- list(
  universe = c("AAA", "BBB"),
  equity = 1000,
  vec = list(close = c(AAA = 50, BBB = 100))
)
ledgr_target_rebalance(weights, ctx, equity_fraction = 0.5)
#> <ledgr_target> [2 assets]
#> non-NA: 2/2
#> AAA BBB 
#>   5   2 

ctx$vec$position <- c(AAA = 2, BBB = 0)
weights <- ledgr_weights(c(BBB = 1), universe = c("AAA", "BBB"))
ledgr_target_rebalance(weights, ctx, keep = "AAA")
#> <ledgr_target> [2 assets]
#> non-NA: 2/2
#> AAA BBB 
#>   2   9