If you want to use rblncr
to rebalance a portfolio
periodically, you might want to just keep calling
rebalance_portfolio()
until the portfolio is balanced. You
can achieve this with a while
loop.
First we set our connection details.
trading_mode = "paper"
alpaca_paper_key <- Sys.getenv("ALPACA_PAPER_KEY")
alpaca_paper_secret <- Sys.getenv("ALPACA_PAPER_SECRET")
alpaca_live_key <- Sys.getenv("ALPACA_LIVE_KEY")
alpaca_live_secret <- Sys.getenv("ALPACA_LIVE_SECRET")
t_conn <- alpaca_connect(trading_mode,
alpaca_paper_key,
alpaca_paper_secret)
d_conn <- alpaca_connect("data",
alpaca_live_key,
alpaca_live_secret)
Then we create or load our model. Here we want a portoflio that is 70.% AAPL, and 19.5% GOOG. The remaining 10% will sit in cash.
name <- "sample_portfolio"
description <- "create from function"
cash <- list(percent = 10)
assets <- data.frame(symbol = c("AAPL","GOOG"), percent = c(60,30))
tolerance <- list(percent = 5)
cooldown <- list(days = 365)
model <- create_portfolio_model(name = name,
description = description,
cash = cash,
assets = assets,
tolerance = tolerance,
cooldown = cooldown)
balanced <- FALSE
i <- 1
attempts <- list()
while(!balanced) {
attempt <- balance_portfolio(model,
trading_connection = t_conn,
pricing_connection = d_conn,
min_order_size = 1000,
max_order_size = 10000,
daily_vol_pct_limit = 0.02,
pricing_spread_tolerance = 0.01,
pricing_overrides = NULL,
trader_life = 60,
buy_only = FALSE,
resubmit_interval = 10,
verbose = FALSE)
balanced <- attempt$portfolio_balanced
attempts[[i]] <- attempt
i <- i + 1
}
if(length(attempts) > 0) {
drift_changes <- purrr::map_df(attempts, ~ .x$drift, .id = "run")
drift_changes <- dplyr::mutate(drift_changes, run = as.integer(run))
}
These are the trades attempted by the trader()
. The
orders with NA
timestamps were not even submitted to the
broker because they didn’t have sufficient information. Generally this
happens when the order quantity is zero, or the data connection did not
return sufficient information to create a limit order.
trades <- purrr::map_df(attempts, ~ .x$trades, .id = "run")
trades
#> run timestamp symbol order limit filled status
#> 1 1 2024-03-12 14:45:13 AAPL -57 172.66 -57 filled
#> 2 1 2024-03-12 14:45:13 GOOG 71 139.67 71 filled
#> 3 2 2024-03-12 14:45:31 AAPL -57 172.68 -57 filled
#> 4 2 2024-03-12 14:45:32 GOOG 71 139.10 0 canceled
#> 5 2 <NA> GOOG 71 NA 0 no_limit
#> 6 2 2024-03-12 14:46:00 GOOG 71 139.05 0 canceled
#> 7 2 <NA> GOOG 71 NA 0 no_limit
#> 8 2 2024-03-12 14:46:28 GOOG 71 139.62 71 filled
We can see how the portfolio drift converges to zero over time.
if(length(attempts) > 0) {
ggplot(drift_changes, aes(x = run, y = drift)) +
geom_line(aes(color = symbol))
}
Here are the portfolio weights post-rebalance. You can see that we have managed to achieve our target balances (within tolerance).
get_portfolio_current(t_conn) |>
price_portfolio(d_conn) |>
magrittr::extract2("assets") |>
dplyr::select(symbol, percent_held)
#> symbol percent_held
#> 1 AAPL 59.97
#> 2 GOOG 29.97