In a real world scenario, you don’t want to be manually executing rebalancing scripts all the time. You want to create a scheduled script that runs automatically on a periodic basis. Your choice of scheduler depends on your computing environment. Here are some options:
cron
You can see an example of a GitHub Actions-scheduled rblncr workflow at riazarbi/rblncr-demo.
You’ll want to use rblncr
in a script that triggers
trades if:
cooldown
period has elapsed
ANDThe script should also record when your portfolio rebalances
so that the cooldown
evaluation on the next run resets.
Here is a script that achieves the above objectives. It persists the assets percentage drifts to a csv file for downstream analysis, and records the rebalance dates to a text file for evaluation in the next run.
# Load libraries ----
library(rblncr)
# Set parameters from ENV variables ----
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")
# Create backend connections -----
t_conn <- alpaca_connect(trading_mode,
alpaca_paper_key,
alpaca_paper_secret)
d_conn <- alpaca_connect("data",
alpaca_live_key,
alpaca_live_secret)
# Read in portfolio model and rebalancing history ----
portfolio_model <- read_portfolio_model("inst/extdata/sample_portfolio.yaml")
rebalance_dates_file <- "last_rebalance"
# Extract last_rebalance timestamp ----
if(file.exists(rebalance_dates_file)) {
rebalance_dates <- readLines(rebalance_dates_file) |>
lubridate::as_datetime()
last_rebalance <-max(rebalance_dates)
} else {
last_rebalance <- NULL
}
# Check cooldown period ----
still_cooldown <- !(cooldown_elapsed(last_rebalance, portfolio_model$cooldown$days))
# Balance portfolio (if cooldown elapsed) ----
if(still_cooldown) {
message("Cooldown period still in force.")
} else {
balanced <- FALSE
cooldown_elapsed
i <- 1
attempts <- list()
while(!balanced) {
attempt <- balance_portfolio(portfolio_model,
trading_connection = t_conn,
pricing_connection = d_conn,
min_order_size = 1000,
max_order_size = 100000,
daily_vol_pct_limit = 0.02,
pricing_spread_tolerance = 0.01,
pricing_overrides = NULL,
trader_life = 30,
buy_only = FALSE,
resubmit_interval = 5,
verbose = TRUE)
# Record drift change
# (We assume you can get the order log from your broker. Else save those as well.)
current_timestamp <- lubridate::now()
attempt$drift |>
dplyr::mutate(timestamp = current_timestamp) |>
dplyr::relocate(timestamp, .before = symbol) |>
readr::write_csv(file = "drift_changes.csv", append = TRUE)
balanced <- attempt$portfolio_balanced
attempts[[i]] <- attempt
i <- i + 1
}
# Record rebalance date for cooldown tracking
current_timestamp <- lubridate::now()
nowtext <- strftime(current_timestamp,"%Y-%m-%d %H:%M:%S")
write(nowtext, rebalance_dates_file, append = TRUE)
}