#' @title Calculate Annualized Return
#' @param ret data.frame or tibble containing returns organized by column
#' @param freq string to specify periodicity
#' @return tibble with column names of \code{ret} and corresponding geometric means
#' @examples
#' data(ret)
#' annRet(ret, 'd')
#' @export
annRet <- function(ret, freq) {
a <- freqToScale(freq)
n_obs <- nrow(ret)
ret %>%
tidyRet() %>%
replace_na(list(ret = 0)) %>%
group_by(asset) %>%
summarize_at('ret', list(~prod(. + 1)^(a / n_obs) - 1)) %>%
rename(ann_ret = ret)
}
#' @title Calculate Annualized Standard Deviation
#' @param ret data.frame or tibble containing returns organized by column
#' @param freq string to specify periodicity
#' @return tibble with column names of \code{ret} and corresponing standard deviations
#' @examples
#' data(ret)
#' annSd(ret, 'd')
#' @export
annSd <- function(ret, freq) {
a <- freqToScale(freq)
ret %>%
tidyRet() %>%
replace_na(list(ret = 0)) %>%
group_by(asset) %>%
summarize_at('ret', list(~sd(.) * sqrt(a))) %>%
rename(sd = ret)
}
#' @title Calculated Downside Volatility
#' @param ret data.frame or tibble containing returns organized by column
#' @param rf data.frame or tibble containing risk-free time-series
#' @param freq string to specifiy periodicity
#' @examples
#' data(ret)
#' annDownSd(ret, rf, 'd')
#' @export
annDownSd <- function(ret, rf, freq) {
a <- freqToScale(freq)
rf <- changeFreq(rf, freq)
ret <- changeFreq(ret, freq)
colnames(rf)[2] <- '.y'
if (any('.y' %in% colnames(ret))) {
ret <- ret %>% rename('..y' = '.y')
}
models <- tidyRet(ret) %>%
group_by(asset) %>%
nest()
down_sd <- models$data %>%
map(left_join, y = rf, by = 'date') %>%
map(filter, ret - .y > 0) %>%
map(summarize_at, .vars = 'ret', .funs = list(~sd(.) * sqrt(a))) %>%
unlist()
tibble(asset = ret %>% select(-date) %>% colnames(),
down_sd = down_sd)
}
#' @title Utility to Calculate Annualized Return
#' @param x numeric vector of returns
#' @param a numeric periodicity scale (e.g., monthly = 12)
#' @return annualized return of the vector \code{x}
#' @export
vecAnnRet <- function(x, a) {
prod(1 + x, na.rm = TRUE)^(a / length(x)) - 1
}
#' @export
excessMean <- function(ret, rf, freq) {
a <- freqToScale(freq)
colnames(rf)[2] <- '.y'
if (any('.y' %in% colnames(ret))) {
ret <- ret %>% rename('..y' = '.y')
}
comb <- combineRet(ret, rf, freq = freq)
rf_mu <- comb %>%
filter(asset == '.y') %>%
summarize_at('ret', vecAnnRet, a = a) %>%
.$ret
comb %>%
filter(asset != '.y') %>%
group_by(asset) %>%
summarize_at('ret', vecAnnRet, a = a) %>%
mutate(excess_ret = ret - rf_mu)
}
#' @export
sharpeRatio <- function(ret, rf, freq) {
a <- freqToScale(freq)
colnames(rf)[2] <- '.y'
if (any('.y' %in% colnames(ret))) {
ret <- ret %>% rename('..y' = '.y')
}
vol <- combineRet(ret, rf, freq = freq) %>%
filter(asset != '.y') %>%
group_by(asset) %>%
summarize_at('ret', sd, na.rm = TRUE) %>%
mutate(vol = ret * sqrt(a)) %>%
.$vol
excessMean(ret, rf, freq) %>%
select(asset, excess_ret) %>%
mutate(vol = vol, sharpe = excess_ret / vol)
}
#' @export
sortinoRatio <- function(ret, rf, freq) {
down_vol <- annDownSd(ret, rf, freq) %>%
.$down_sd
excessMean(ret, rf, freq) %>%
select(asset, excess_ret) %>%
mutate(down_vol = down_vol, sortino = excess_ret / down_vol)
}
#' @export
trackingError <- function(ret, bench, freq) {
a <- freqToScale(freq)
colnames(bench)[2] <- '.y'
bench <- changeFreq(bench, freq)
if (any('.y' %in% colnames(ret))) {
ret <- ret %>% rename('..y' = '.y')
}
combineRet(ret, bench, freq = freq) %>%
filter(asset != '.y') %>%
group_by(asset) %>%
nest() %>%
.$data %>%
map(left_join, y = bench, by = 'date') %>%
lapply(calcTE) %>%
unlist() %>%
tibble() %>%
add_column(asset = ret %>% select(-date) %>% colnames, .before = 1) %>%
rename('TE' = '.') %>%
mutate(TE = TE * sqrt(a))
}
#' @export
calcTE <- function(x) {
sd(x[[2]] - x[[3]])
}
#' @export
infoRatio <- function(ret, bench, rf, freq) {
te <- trackingError(ret, bench, freq)
excessMean(ret, bench, freq) %>%
left_join(te, by = 'asset') %>%
mutate(IR = excess_ret / TE)
}
#' @export
maxDrawdown <- function(ret, rf) {
max_dd <- drawdown(ret) %>%
select(-date) %>%
apply(2, min) %>%
tibble() %>%
add_column(asset = ret %>% select(-date) %>% colnames()) %>%
rename('max_dd' = '.')
excessMean(ret, rf, freq) %>%
left_join(max_dd, by = 'asset') %>%
mutate(ratio = excess_ret / abs(max_dd))
}
#' @export
upDownStat <- function(ret, bench, freq) {
colnames(bench)[2] <- '.y'
colnames(rf)[2] <- '.rf'
if (any('.y' %in% colnames(ret))) {
ret <- ret %>% rename('..y' = '.y')
}
ret <- changeFreq(ret, freq)
bench <- changeFreq(bench, freq)
all_ret <- combineRet(ret, bench, freq = freq)
ret_trunc <- ret %>%
filter(date %in% all_ret$date)
up_date <- all_ret %>%
filter(asset == '.y' & ret >= 0) %>%
.$date
ret_up_down <- ret_trunc %>%
tidyRet() %>%
mutate(direction = ifelse(date %in% up_date, 'up', 'down'),
direction = as.factor(direction)) %>%
group_by(direction, asset) %>%
nest()
models <- map(ret_up_down$data, left_join, y = bench, by = 'date')
reg <- models %>%
map(select, -date) %>%
map(~lm(ret ~ .y, data = .))
coeff <- sapply(reg, '[[', 'coefficients')
odd <- seq(from = 1, to = ncol(coeff), by = 2)
even <- seq(from = 2, to = ncol(coeff), by = 2)
up_beta <- coeff[2, odd]
down_beta <- coeff[2, even]
calcCapt <- function(model, freq) {
geo_ret <- annRet(model, freq)
geo_ret$ann_ret[1] / geo_ret$ann_ret[2]
}
capt <- sapply(models, calcCapt, freq = freq)
up_capt <- capt[odd]
down_capt <- capt[even]
nUp <- function(x) {
sum(x >= 0)
}
n_up <- apply(ret_trunc[, 2:ncol(ret_trunc), drop = FALSE], 2, nUp)
n_down <- nrow(ret_trunc) - n_up
tibble(Asset = ret %>% select(-date) %>% colnames(),
UpCapture = up_capt,
DownCapture = down_capt,
UpBeta = up_beta,
DownBeta = down_beta,
UpPeriods = n_up,
DownPeriods = n_down)
}
#' @export
multiReg <- function(ret, xfact, rf, freq, net_rf = TRUE) {
ret <- checkRet(ret)
xfact <- checkRet(xfact)
rf <- checkRet(rf)
date_start <- max(ret$date[1], xfact$date[1])
date_end <- min(ret$date[nrow(ret)], xfact$date[nrow(xfact)])
if (net_rf) {
ret <- excessRet(ret, rf, freq = freq)
}
fact_nm <- colnames(xfact)[2:ncol(xfact)]
ret_nm <- colnames(ret)[2:ncol(ret)]
ydat <- ret %>%
filter(date >= date_start, date <= date_end) %>%
reshape2::melt(id = 'date') %>%
group_by(variable) %>%
nest()
xdat <- filter(xfact, date >= date_start, date <= date_end)
if (any(colnames(xdat) == 'value')) {
xdat <- rename(xdat, value.x = value)
}
fit <- map(ydat$data, left_join, y = xdat, by = 'date') %>%
map(select, -date) %>%
map(~ lm(value ~., data = .))
sfit <- map(fit, summary)
r2 <- map_dbl(sfit, 'adj.r.squared')
coeff <- map(sfit, 'coefficients') %>%
lapply(as.tibble)
est <- sapply(coeff, '[[', 'Estimate') %>% t()
colnames(est) <- c('resid', fact_nm)
tval <- sapply(coeff, '[[', 't value') %>% t()
colnames(tval) <- colnames(est)
est <- as_tibble(est) %>%
select(-resid, everything()) %>%
add_column('Adj R^2' = r2) %>%
add_column('Asset' = ret_nm, .before = 1) %>%
mutate(resid = resid * freqToScale(freq))
tval <- as_tibble(tval) %>% select(-resid, everything())
est_fmt <- est %>%
mutate_at(fact_nm, fNum) %>%
mutate_at(c('resid', 'Adj R^2'), fPercent)
res <- list()
res$fit <- fit
res$est <- est
res$est_fmt <- est_fmt
res$tval <- tval
return(res)
}
#' @export
factRiskWgt <- function(xbeta, cov_fact, variance_y) {
xbeta <- matrix(xbeta, nrow = length(xbeta), ncol = 1)
risk_wgt <- (xbeta * (cov_fact %*% xbeta)) / variance_y[1]
return(risk_wgt)
}
#' @export
rollReg <- function(fund, xfact, rf, freq, net_rf = TRUE, roll_win = 90) {
ret <- changeFreq(fund, freq)
xfact <- changeFreq(xfact, freq)
rf <- changeFreq(rf, freq)
date_start <- max(ret$date[1], xfact$date[1])
date_end <- min(ret$date[nrow(ret)], xfact$date[nrow(xfact)])
if (net_rf) {
ret <- excessRet(ret, rf, freq = freq)
}
fact_nm <- colnames(xfact)[2:ncol(xfact)]
ret_nm <- colnames(ret)[2:ncol(ret)]
ydat <- ret %>%
filter(date >= date_start, date <= date_end) %>%
reshape2::melt(id = 'date') %>%
tsibble::as_tsibble(key = variable, index = date) %>%
group_by(variable) %>%
nest()
xdat <- filter(xfact, date >= date_start, date <= date_end) %>%
tsibble::as_tsibble(index = date)
models <- map(ydat$data, left_join, y = xdat, by = 'date')
reg <- function(...) {
dat <- tibble(...) %>%
select(-date)
fit <- lm(value ~., data = dat)
list(coeff = fit$coefficients, adj_r_2 = summary(fit)$adj.r.square)
}
nest_models <- tibble(ret_nm, models)
res <- nest_models %>%
mutate(reg = map(models, ~slide::pslide_dfr(., reg, .before = roll_win,
.complete = TRUE)))
res_list <- lapply(res$reg, '[[', 'coeff') %>%
lapply(do.call, what = 'rbind') %>%
lapply(as.data.frame) %>%
lapply(add_column,
date = res$models[[1]]$date[(roll_win+1):nrow(res$models[[1]])],
.before = 1)
adj_r_2 <- lapply(res$reg, '[[', 'adj_r_2') %>%
lapply(do.call, what = 'rbind')
res_list <- mapply(add_column, .data = res_list, Adj.R.Sqr = adj_r_2,
SIMPLIFY = FALSE)
return(res_list)
}
#' @export
turbulence <- function(ret) {
turb <- data.frame(date = ret$date)
mu <- ret %>%
select(-date) %>%
colMeans()
xcov <- ret %>%
select(-date) %>%
cov()
turb %>%
mutate(val = mahalanobis(select(ret, -date), center = mu, cov = xcov),
pct = rank(turb) / (nrow(ret) + 1))
}
#' @export
rollAbsorption <- function(ret, n_pc = 2, roll_win = 252,
cov_win = c(252, 63, 21),
cov_wgt = c(0.25, 0.25, 0.5),
short_win = 15, long_win = 252) {
roll_ar <- slide::slide(ret,
~absorptionCalc(.x, n_pc, cov_win[1], cov_win[2],
cov_win[3], cov_wgt),
.before = roll_win, .complete = TRUE) %>%
unlist()
delta_ar <- slide::slide(roll_ar, ~stdChange(.x, short_win, long_win),
.before = long_win, .complete = TRUE) %>%
unlist()
tibble(date = ret$date,
ar = c(rep(NA, roll_win), roll_ar),
delta = c(rep(NA, roll_win + long_win), delta_ar))
}
#' @export
absorptionCalc <- function(ret, n_pc = 2, long_win = 252, med_win = 63,
short_win = 21, wgt = c(0.25, 0.25, 0.5)) {
xcov <- covWgtAvg(ret, long_win, med_win, short_win, wgt)
eig <- cov2cor(xcov) %>%
svd %>%
.$d
sum(eig[1:n_pc]) / sum(eig)
}
#' @export
rollTurbulance <- function(ret, roll_win = 252, short_win = 15, long_win = 252) {
roll_turb <- slide::slide(ret, ~calcTurbulence(.x), .before = roll_win,
.complete = TRUE) %>%
unlist()
delta_turb <- slide::slide(roll_turb, ~stdChange(.x, short_win, long_win),
.before = long_win, .complete = TRUE) %>%
unlist()
tibble(date = ret$date,
turb = c(rep(NA, roll_win), roll_turb),
delta = c(rep(NA, roll_win + long_win), delta_turb),
percentile = c(rep(NA, roll_win), rank(roll_turb, na.last = 'keep') /
(1 + length(roll_turb))))
}
#' @export
calcTurbulence <- function(ret) {
xret <- ret %>%
select(-date)
mahalanobis(xret, colMeans(xret), cov(xret))[nrow(xret)]
}
#' @export
sysRiskPerf <- function(ret, sys_risk, freq = 'w') {
ret <- changeFreq(ret, freq)
sys_risk <- changeFreq(sys_risk, freq, 'level')
high_turb_date <- sys_risk %>%
filter(percentile >= 0.90) %>%
.$date
high_ar_date <- sys_risk %>%
filter(delta.ar >= 1.75) %>%
.$date
high_turb_ar_date <- sys_risk %>%
filter(delta.ar >= 1.75,
percentile >= 0.90) %>%
.$date
ret_high_turb <- ret %>%
filter(date %in% high_turb_date) %>%
select(-date) %>%
mutate_all(mean) %>%
slice(1) %>%
as.numeric()
ret_high_ar <- ret %>%
filter(date %in% high_ar_date) %>%
select(-date) %>%
mutate_all(mean) %>%
slice(1) %>%
as.numeric()
ret_high_turb_ar <- ret %>%
filter(date %in% high_turb_ar_date) %>%
select(-date) %>%
mutate_all(mean) %>%
slice(1) %>%
as.numeric()
tibble(Asset = ret %>% select(-date) %>% colnames(),
`High Turbulence` = ret_high_turb,
`High Fragility` = ret_high_ar,
`High Turb. and Frag.` = ret_high_turb_ar)
}
#' @export
stdChange <- function(x, short_win, long_win) {
(mean(x[1:short_win]) - mean(x[1:long_win])) / sd(x[1:long_win])
}
#' @export
covWgtAvg <- function(ret, long_win = 252, med_win = 63, short_win = 21,
wgt = c(0.25, 0.25, 0.5)) {
ret_desc <- arrange(ret, desc(date))
xret <- ret %>%
select(-date)
long_cov <- xret %>%
slice(1:long_win) %>%
cov()
med_cov <- xret %>%
slice(1:med_win) %>%
cov()
short_cov <- xret %>%
slice(1:short_win) %>%
cov()
long_cov * wgt[1] + med_cov * wgt[2] + short_cov * wgt[3]
}
#' @export
covEWMA <- function(ret, freq) {
ret <- checkRet(ret)
retn <- ret[, 2:ncol(ret)] %>%
replace(is.na(.), 0)
freq <- checkFreq(freq)
mult <- freqToScale(freq)
n_obs <- nrow(retn)
n_assets <- ncol(retn)
mu <- colMeans(retn)
mu_mat <- matrix(mu, nrow = n_obs, ncol = n_assets, byrow = TRUE)
retc <- retn - mu_mat
lambda <- 1 - 2 / (n_obs + 1)
exp_cov <- matrix(0, nrow = n_assets, ncol = n_assets)
for (t in 1:n_obs) {
roll_ret <- retc[t, ]
eps <- t(roll_ret) %*% as.numeric(roll_ret) * mult
exp_cov <- lambda * exp_cov + (1 - lambda) * eps
}
return(exp_cov)
}
#' @export
wealthIndex <- function(ret, init_val = 1) {
ret <- checkRet(ret)
addOne <- function(x) x + 1
row_zero <- data.frame(ret$date[1] - 1,
matrix(init_val, ncol = ncol(ret) - 1))
colnames(row_zero) <- colnames(ret)
wi <- ret %>%
replace(is.na(.), 0) %>%
mutate_at(vars(-date), addOne) %>%
bind_rows(row_zero) %>%
arrange(date) %>%
mutate_at(vars(-date), cumprod)
return(wi)
}
#' @export
drawdown <- function(ret) {
ret <- checkRet(ret)
drawdownCalc <- function(x) {
wi <- cumprod(x + 1)
wi_peaks <- cummax(wi)
dd <- wi / wi_peaks - 1
return(dd)
}
dd <- ret %>%
replace(is.na(.), 0) %>%
mutate_at(vars(-date), drawdownCalc)
return(dd)
}
#' @export
rollSd <- function(ret, freq, roll_win = 63) {
a <- freqToScale(freq)
ret <- checkRet(ret)
roll_sd <- apply(ret[, 2:ncol(ret)], 2, RcppRoll::roll_sdr, n = roll_win) %>%
as.data.frame() %>%
add_column(date = ret$date, .before = 1)
roll_sd %>%
mutate_at(vars(-date), ~(. * sqrt(a)))
}
#' @export
portRet <- function(mu_vec, wgt_vec, rf) {
mu <- matrix(mu_vec, ncol = 1)
wgt <- matrix(wgt_vec, ncol = 1)
if (nrow(mu) != nrow(wgt)) {
stop('mu_vec must be the same length as wgt_vec')
}
rf_ctr <- (1 - sum(wgt)) * rf
res <- t(wgt) %*% mu + rf_ctr
return(as.numeric(res))
}
#' @export
portSd <- function(wgt_vec, cov_mat) {
wgt <- matrix(wgt_vec, ncol = 1)
if (nrow(wgt) != nrow(cov_mat)) {
stop('wgt_vec and cov_mat must be the same length')
}
return(sqrt(t(wgt) %*% cov_mat %*% wgt))
}
#' @export
portCorr <- function(wgt_vec_1, wgt_vec_2, cov_mat) {
w1 <- as.matrix(wgt_vec_1, ncol = 1)
w2 <- as.matrix(wgt_vec_2, ncol = 1)
(t(w1) %*% cov_mat %*% w2) /
(sqrt(t(w1) %*% cov_mat %*% w1) * sqrt(t(w2) %*% cov_mat %*% w2))
}
#' @export
portBeta <- function(wgt_vec_1, wgt_vec_2, cov_mat) {
w1 <- as.matrix(wgt_vec_1, ncol = 1)
w2 <- as.matrix(wgt_vec_2, ncol = 1)
(t(w2) %*% cov_mat %*% w1) / (t(w2) %*% cov_mat %*% w2)
}
#' @export
sdWgt <- function(wgt_vec, cov_mat) {
wgt <- matrix(wgt_vec, ncol = 1)
risk_wgt <- (wgt * (cov_mat %*% wgt)) / (t(wgt) %*% cov_mat %*% wgt)[1]
return(risk_wgt)
}
#' @export
contrToRet <-function(p, date_start = NA, date_end = NA) {
if (is.na(date_start)) {
date_start <- as.Date('0000-01-01')
}
if (is.na(date_end)) {
date_end <- Sys.Date()
}
asset_index <- p$reb$asset_index
if (is.null(asset_index)) {
stop('p must be the result of the rebal function, see rebal for details')
}
before_start <- asset_index$date >= date_start
if (sum(before_start) == 0) {
warning('last date in asset time-series is before date_start')
return(rep(NA, nrow(p$reb$curr_df) + 1))
}
if (min(asset_index$date) > date_start) {
warning('date_start is before asset time-series')
return(rep(NA, nrow(p$reb$curr_df) + 1))
}
num_seq <- 1:length(before_start)
before_index <- min(num_seq[before_start]) - 1
before_index <- max(before_index, 1)
asset_index <- asset_index[before_index:nrow(asset_index), ] %>%
filter(date <= date_end)
asset_ret <- p$reb$asset_ret %>%
filter(date >= date_start) %>%
filter(date <= date_end)
port_index <- p$reb$port_index
port_index <- port_index[before_index:nrow(port_index), ] %>%
filter(date_end <= date_end)
contr_mat <- asset_index[1:(nrow(asset_index) - 1), 2:ncol(asset_ret)] *
asset_ret[, 2:ncol(asset_ret)]
contr_tbl <- tibble(date = asset_ret$date, contr_mat) %>%
filter(date >= date_start) %>%
filter(date <= date_end)
contr <- apply(contr_tbl[, -1], 2, sum, na.rm = TRUE) / port_index$value[1]
resid <- port_index$value[nrow(port_index)] /
port_index$value[1] - 1 - sum(contr)
res <- c(contr, resid)
names(res) <- c(colnames(p$reb$asset_ret[, 2:ncol(p$reb$asset_index)]), 'resid.')
return(res)
}
#' @export
pcaCov <- function(cov_mat) {
s <- svd(cov_mat)
latent <- s$d
raw_coeff <- s$v
p <- dim(raw_coeff)[1]
d <- dim(raw_coeff)[2]
max_index <- max.col(t(abs(raw_coeff)))
col_sign <- sign(raw_coeff[max_index + seq(from = 0, to = (d - 1) * p, by = p)])
coeff <- matrix(col_sign, nrow = p, ncol = d, byrow = TRUE) * raw_coeff
res <- list()
res$latent <- latent
res$coeff <- coeff
return(res)
}
#' @export
tblCalRet <- function(ret, as_of = Sys.Date()) {
xwin <- c('dtd', 'wtd', 'mtd', 'qtd', 'ytd', 'ttm', '3 yr', '5 yr', '10 yr',
'20 yr', '30 yr')
date_start <- lapply(xwin, calTime, asof = as_of) %>%
unlist() %>%
as.Date(origin = '1970-01-01')
date_start_vec <- rep(date_start, ncol(ret) - 1) %>%
sort(decreasing = TRUE)
models <- ret %>%
tidyRet() %>%
group_by(asset) %>%
nest()
retmat <- mapply(calRet, models$data, date_start = date_start_vec,
date_end = as_of, SIMPLIFY = TRUE) %>%
matrix(ncol = 11)
colnames(retmat) <- xwin
num <- as_tibble(retmat) %>%
mutate(`3 yr` = (1 + `3 yr`)^(1/3) - 1,
`5 yr` = (1 + `5 yr`)^(1/5) - 1,
`10 yr` = (1 + `10 yr`)^(1/10) - 1,
`20 yr` = (1 + `20 yr`)^(1/20) - 1,
`30 yr` = (1 + `30 yr`)^(1/30) - 1) %>%
add_column(asset = ret %>% select(-date) %>% colnames, .before = 1)
fmt <- num %>%
mutate_at(vars(-asset), fPercent)
res <- list()
res$num <- num
res$fmt <- fmt
return(res)
}
#' @export
tblContrCalRet <- function(p, as_of = Sys.Date()) {
xwin <- c('dtd', 'wtd', 'mtd', 'qtd', 'ytd', 'ttm', '3 yr', '5 yr', '10 yr',
'20 yr', '30 yr')
date_start <- lapply(xwin, calTime, asof = as_of) %>%
unlist() %>%
as.Date(origin = '1970-01-01')
ctr <- lapply(date_start, contrToRet, p = p) %>%
as.data.frame()
colnames(ctr) <- xwin
num <- add_column(ctr, asset = rownames(num), .before = 1) %>%
as_tibble()
fmt <- num %>%
mutate_at(vars(-asset), fPercent)
res <- list()
res$num <- num
res$fmt <- fmt
return(res)
}
#' @export
calRet <- function(ret, date_start, date_end) {
if (date_start < min(ret$date)) {
return(NA)
}
if (date_end > max(ret$date)) {
return(NA)
}
truncReturns(ret, date_start, date_end) %>%
select(-date) %>%
mutate_all(~(1 + .x)) %>%
apply(2, prod, na.rm = TRUE) - 1
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.