#' @name portfolio
#' @aliases portfolio
#' @docType class
#' @title Portfolio Object Manager
#' @description {
#' Manage your portfolio never be so easy. This object will save all your portfolio and help you manage them all at once.
#' You can do backtesting by combining this object with powerful tools such as TTR package to generate a technical analysis.
#' }
#' @author Suberlin Sinaga @2021
#' @importFrom dplyr rename
#' @return Object of type \code{\link{portfolio}}
portfolio <- R6Class(
"portfolio",
private = list(init = NULL),
public = list(
#' @description Add portfolio that you have into the object. Each portfolio will be stored using prefix \code{portfolio.}
#' @aliases add_portfolio
#' @param data: The portfolio that you add
#' @param symbol: The name of the portfolio you were added
#' @return Object of type \code{\link{portfolio}}
add_portfolio = function(data, symbol = deparse(substitute(data))){
if (!all(c("o", "l", "h", "c", "t", "v") %in% names(data))){
stop("Please provide tolhcv data!!")
}
private[[paste0("portfolio.", symbol)]] = data %>%
rename(time = t,
open = o,
close = c,
high = h,
low = l,
volume = v)
},
#' @description Add colum to your portfolio data. In some cases, you have your own custom column. In that case, you can add some by using this method.
#' @aliases add_col
#' @param x: vector for the data
#' @param symbol: {The name of the portfolio you want to add to. Please be aware, if you set this leave as NULL, it may not work as expected. It is
#' because it will add the column to all portfolio that may have different dimension.}
#' @return Object of type \code{\link{portfolio}}
add_col = function(x, colname, symbols = NULL) {
if (missing(symbols)) {
names = grep("portfolio.", names(private), value = TRUE)
} else {
if (length(symbols) == 1) {
names = grep(paste0("portfolio.", symbols), names(private), value = TRUE)
} else {
names = c()
for (symbol in symbols) {
name = grep(paste0("portfolio.", symbol), names(private), value = TRUE)
names = c(names, name)
}
}
}
for (name in names) {
private[[name]][[colname]] = x
}
invisible(self)
},
#' @description {Instead of adding a column, you might
#' want to add an indicator to your portfolio. Using this method you can directly calculate the indicator and add the data to your portfolio.}
#' @aliases add_indicator
#' @param .fun: the function to calculate the desired indicator
#' @param colnames: The name of the column to store the new indikator. If left blank, it will take the name of the function.
#' @param to_vector: To indicate you want to drop the dataframe using \code{drop = TRUE} argument.
#' @param ...: This ellipsis used to store the arguments needed by the function. Refers to each function to use it.
#' @return Object of type \code{\link{portfolio}}
add_indicator = function(.fun, colnames, indicator_name = deparse(substitute(.fun)), to_vector = FALSE, ...) {
if (class(.fun) != "function") stop("Please privide a function")
names = grep("portfolio.", names(private), value = TRUE)
if (length(names) == 0) stop("You hadn't registered any symbol and the data. Please register it first.")
for (name in names) {
if (to_vector) {
private[[name]][[indicator_name]] = .fun(private[[name]][, colnames, drop = TRUE], ...)
} else {
private[[name]][[indicator_name]] = .fun(private[[name]][, colnames], ...)
}
}
invisible(self)
},
#' @description {In trading data, the famous indicators are EMA, SMA or so on that in fact need to lag data. The backwards is that it leaves so many NAs.
#' Call this method to clean the messy.}
#' @aliases remove_na
#' @return Object of type \code{\link{portfolio}}
remove_na = function() {
names = grep("portfolio.", names(private), value = TRUE)
if (length(names) == 0) stop("You hadn't registered any symbol and the data. Please register it first.")
for (name in names) {
private[[name]] = private[[name]][complete.cases(private[[name]]),]
}
invisible(self)
}
),
lock_objects = FALSE
)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.