Code Monkey home page Code Monkey logo

portfoliobacktest's Introduction

portfolioBacktest

CRAN_Status_Badge CRAN Downloads CRAN Downloads Total

Automated backtesting of multiple portfolios over multiple datasets of stock prices in a rolling-window fashion. Intended for researchers and practitioners to backtest a set of different portfolios, as well as by a course instructor to assess the students in their portfolio design in a fully automated and convenient manner, with results conveniently formatted in tables and plots. Each portfolio design is easily defined as a function that takes as input a window of the stock prices and outputs the portfolio weights. Multiple portfolios can be easily specified as a list of functions or as files in a folder. Multiple datasets can be conveniently extracted randomly from different markets, different time periods, and different subsets of the stock universe. The results can be later assessed and ranked with tables based on a number of performance criteria (e.g., expected return, volatility, Sharpe ratio, drawdown, turnover rate, return on investment, computational time, etc.), as well as plotted in a number of ways with nice barplots and boxplots.

Installation

The package can be installed from CRAN or GitHub:

# install stable version from CRAN
install.packages("portfolioBacktest")

# install development version from GitHub
devtools::install_github("dppalomar/portfolioBacktest")

To get help:

library(portfolioBacktest)
help(package = "portfolioBacktest")
?portfolioBacktest

To cite portfolioBacktest in publications:

citation("portfolioBacktest")

Quick Start

Do the backtest on your own portfolio following few steps:

  • Step 1 - load package & 10 datasets
library(portfolioBacktest)
data("dataset10")
  • Step 2 - define your own portfolio
my_portfolio <- function(dataset, w_current) {
  prices <- dataset$adjusted
  N <- ncol(prices)
  return(rep(1/N, N))
}
  • Step 3 - do backtest
bt <- portfolioBacktest(my_portfolio, dataset10)
  • Step 4 - check your portfolio performance (e.g., median of the 10 individual backtests)
backtestSummary(bt)$performance
#>                            fun1
#> Sharpe ratio       1.476203e+00
#> max drawdown       8.937890e-02
#> annual return      1.594528e-01
#> annual volatility  1.218623e-01
#> Sortino ratio      2.057677e+00
#> downside deviation 8.351402e-02
#> Sterling ratio     2.122653e+00
#> Omega ratio        1.295090e+00
#> VaR (0.95)         1.101934e-02
#> CVaR (0.95)        1.789425e-02
#> rebalancing period 1.000000e+00
#> turnover           8.641594e-03
#> ROT (bps)          7.334458e+02
#> cpu time           1.230769e-03
#> failure rate       0.000000e+00

For a more detailed explanation on how to use the package with all the features, check the vignette.

Package Snapshot

This package backtests a list of portfolios over multiple datasets on a rolling-window basis, producing final results as in the following.

  • Performance table:

  • Barplot:

  • Boxplot:

Documentation

For more detailed information, please check the vignette.

Links

Package: CRAN and GitHub.

README file: GitHub-readme.

Vignette: CRAN-vignette and GitHub-vignette.

portfoliobacktest's People

Contributors

dppalomar avatar mirca avatar ruihkust avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

portfoliobacktest's Issues

Allow for different rebalancing schedules

In the current package version, one can specify every how many days the portfolio needs to be rebalanced/reoptimized (with the arguments optimize_every and rebalance_every. However, one may want to specify a different rebalancing schedule, like every Monday or every last day of the month.

This feature will be added, hopefully in a way that the interface is still clean and simple.

Wealth not correctly calculated by portfolioBacktest?

The wealth series calculated by portfolioBacktest() looks odd to me.

I have a simple portfolio function which always returns a weight of 1.
I call portfolioBacktest() with the following parameters:

bt <- portfolioBacktest(portfolio_funs = list("rwf-long-only" = rwf_long_only),
, dataset_list = list(data_bt) # Enclose flat dataset in list()
, price_name = "close"
, show_progress_bar = TRUE
, shortselling = F
, lookback = 13
, optimize_every = 1
, rebalance_every = 1
, execution = "same period" #c("same period", "next period")
, cost = list(buy = 0, sell = 0, short = 0, long_leverage = 0)
)

Here are the results:

t1=cbind(bt$"rwf-long-only"$data1$w_rebalanced, bt$"rwf-long-only"$data1$X_lin, bt$"rwf-long-only"$data1$w_bop, bt$"rwf-long-only"$data1$wealth)
setlastcolnames(t1, c("w_rebalanced", "X_lin", "w_bop", "wealth"))
w_rebalanced X_lin w_bop wealth
2022-02-23 NA NA NA NA
2022-02-24 NA 0.015049063 NA NA
2022-02-25 NA 0.022064003 NA NA
2022-02-28 NA -0.002558613 NA NA
2022-03-01 NA -0.015230200 NA NA
2022-03-02 NA 0.018396181 NA NA
2022-03-03 NA -0.004978448 NA NA
2022-03-04 NA -0.008124677 NA NA
2022-03-07 NA -0.029479220 NA NA
2022-03-08 NA -0.007581580 NA NA
2022-03-09 NA 0.026810758 NA NA
2022-03-10 NA -0.004515496 NA NA
2022-03-11 1 -0.012715083 NA 1.0000000
2022-03-14 1 -0.007308275 1 0.9926917
2022-03-15 1 0.021990454 1 1.0145215
2022-03-16 NA 0.022174131 1 1.0370176

I think wealth[x] should be: wealth[x-1] + (w_bop[x] * X_lin[x]).

So i would expect the wealth series to look like:
1.0000000
0.9926917 (1.0000000 + (1 * -0.007308275))
1.014682 (0.9926917 + (1 * 0.021990454))
1.036856 (1.014682 + (1 * 0.022174131))

But the last 2 values are different in the wealth series produced by portfolioBacktest()!

What am i missing here?

Error in plotPerformanceVsParams(bt) : No portfolio found in backtest!

plotPerformanceVsParams(bt) throws the error: No portfolio found in backtest!

In the code for this function on line 7 (N_portfolios <- length(attr(bt_all_portfolios, "portfolio_index"))) it is looking for an attribute called "portfolio_index" in the backtest object, but there is none.

I am using the portfolioBacktest package which is on CRAN.

Saving state inside portfolio functions

It would be a great help if it was possible to save/access state inside portfolio functions, especially for more complex portfolio functions.

Using the .GlobalEnv with assign() does not seem to work for this purpose, even when setting the paral_datasets parameter.

Unable to see if the annual return using daily/weekly or monthly return

issue

Hi Team,

Using the function "backtestSummary", Could you advise if the annual return accounts whether daily or weekly or monthly data is used?
There is no visibility of how it is calculated and it is not mentioned in the document.

If i use the daily data points versus if i were to use weekly data points, does the annual return take into account if the frequency of the data?

Please advise

The reoptimization period has to be a multiple of the rebalancing period.

I would like to backtest simple momentum strategy. I would like to buy 10% osf stocks with highest mmentum (say half year return).

I would like to rebalance every month (buy on the begining of the month).

Here is my try:

data("dataset10")
quintile_portfolio_fun <- function(dataset, w_current) {
  X <- diff(log(dataset$adjusted))[-1]  # compute log returns
  N <- ncol(X)
  # design quintile portfolio
  ranking <- sort(colMeans(X), decreasing = TRUE, index.return = TRUE)$ix
  w <- rep(0, N)
  w[ranking[1:round(N/5)]] <- 1/round(N/5)
  return(w)
}
portfolios <- list("Quintile"  = quintile_portfolio_fun)
bt <- portfolioBacktest(portfolios, 
                        my_dataset_list, 
                        benchmark = c("1/N", "index"), 
                        lookback = 252 / 2, 
                        rebalance_every = 22)

but I get an error:

Backtesting 1 portfolios over 5 datasets (periodicity = daily data)...
Error in (function (portfolio_fun, data, price_name, shortselling, leverage,  : 
  The reoptimization period has to be a multiple of the rebalancing period.

I set rebalance_every = 22 because I wnt monthly rebalancing and I set ookback = 252 / 2 because I want to look half year momentum. Or should I set half year inside quintile_portfolio_fun function, something like:

ranking <- sort(colMeans(tail(X, 22)), decreasing = TRUE, index.return = TRUE)$ix

Backtest strategy with only one asset and positions

Finally there is some activity on backtesting in R community :) There are multiplie options in python but not so many in R.

I am aware your package is more about portfloio backtesting, but I am curious is there a simple way to backtetst strategy in which I hold / not hold one asset (0 and 1 without short selling). So I have a vector of prices on 1 minute basis and I know dates on which I hold the position. I would need the performance, expecialy relative performance (relative to banschmark).

Object Structure

Hi,

I have access to database returns, fundamentals and estimates. Could you show how to import data into the relevant format for the backtest in a vignette or a file?

Allow each portfolio to have different rebalancing parameters

In the current package version, the rebalancing parameters are common for all the list of portfolio functions to be backtested. However, it may be interesting to be able to specify different parameters for each strategy function. One example of use would be to try the same strategy but for different rebalancing frequencies.

This feature will be included, hopefully in a nice way that doesn't destroy the simplicity of the interface.

Allow download data from a local database

Allow download data from a local database. Either directly in stockDataDownload() or as another function. This will be great for speed (only download once) and also so that one can clean and curate the data once and then just load.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.