{"id":13741466,"url":"https://github.com/braverock/quantstrat","last_synced_at":"2025-04-06T12:07:21.484Z","repository":{"id":8525481,"uuid":"58736659","full_name":"braverock/quantstrat","owner":"braverock","description":null,"archived":false,"fork":false,"pushed_at":"2023-09-14T21:17:04.000Z","size":15066,"stargazers_count":293,"open_issues_count":51,"forks_count":116,"subscribers_count":40,"default_branch":"master","last_synced_at":"2025-03-30T11:06:17.076Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/braverock.png","metadata":{"files":{"readme":"README.Rmd","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2016-05-13T12:07:31.000Z","updated_at":"2025-02-21T12:32:22.000Z","dependencies_parsed_at":"2024-01-25T05:09:25.210Z","dependency_job_id":"1df8ddd9-e204-46ae-bf41-bcc659d027ce","html_url":"https://github.com/braverock/quantstrat","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/braverock%2Fquantstrat","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/braverock%2Fquantstrat/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/braverock%2Fquantstrat/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/braverock%2Fquantstrat/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/braverock","download_url":"https://codeload.github.com/braverock/quantstrat/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247478318,"owners_count":20945266,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T04:00:59.510Z","updated_at":"2025-04-06T12:07:21.463Z","avatar_url":"https://github.com/braverock.png","language":"R","funding_links":[],"categories":["R"],"sub_categories":["Backtesting"],"readme":"---\noutput: github_document\n---\n\n\u003c!-- README.md is generated from README.Rmd. Please edit that file --\u003e\n\n```{r setup, include = FALSE}\nknitr::opts_chunk$set(\n  collapse = TRUE,\n  comment = \"#\u003e\",\n  fig.path = \"man/figures/README-\",\n  out.width = \"100%\"\n)\n```\n\n[![Travis Build Status](https://travis-ci.org/braverock/quantstrat.svg?branch=master)](https://travis-ci.org/braverock/quantstrat)\n[![Codecov test coverage](https://codecov.io/gh/braverock/quantstrat/branch/master/graph/badge.svg)](https://codecov.io/gh/braverock/quantstrat?branch=master)\n\n# quantstrat\n\nTransaction-oriented infrastructure for constructing trading systems and\nsimulation. Provides support for multi-asset class and multi-currency\nportfolios for backtesting and other financial research.\n\n## Overview\n\nquantstrat provides a generic infrastructure to model and backtest\nsignal-based quantitative strategies. It is a high-level abstraction layer\n(built on xts, FinancialInstrument, blotter, etc.) that allows you to build\nand test strategies in very few lines of code. quantstrat is still under\nheavy development but is being used every day on real portfolios. We\nencourage you to send contributions and test cases via the appropriate GitHub mediums (Pull requests and Issue tracker).\n\n## Installation\n\nIn order to install [quantstrat](https://github.com/braverock/quantstrat) from [GitHub](https://github.com/), you will first need to install devtools and blotter from GitHub.\n\n``` r\ninstall.packages(\"devtools\") # if not installed\ninstall.packages(\"FinancialInstrument\") #if not installed\ninstall.packages(\"PerformanceAnalytics\") #if not installed\n\n# next install blotter from GitHub\ndevtools::install_github(\"braverock/blotter\")\n# next install quantstrat from GitHub\ndevtools::install_github(\"braverock/quantstrat\")\n```\n## Example: maCross\n\nThe demos in the [demo](https://github.com/braverock/quantstrat/tree/master/demo) folder are great for learning how to use quantstrat specifically. Below is an example of the [maCross](https://github.com/braverock/quantstrat/blob/master/demo/maCross.R) strategy, a simple moving average strategy using a short-term SMA of 50 days and a long-term SMA of 200 days.\n\n```{r demo_maCross, include=FALSE}\nrequire(quantstrat)\nrequire(blotter)\n# workaround to xts Date handling, remove later\nttz\u003c-Sys.getenv('TZ')\nSys.setenv(TZ='UTC')\n\nsuppressWarnings(rm(\"order_book.macross\",pos=.strategy))\nsuppressWarnings(rm(\"account.macross\",\"portfolio.macross\",pos=.blotter))\nsuppressWarnings(rm(\"account.st\",\"portfolio.st\",\"stock.str\",\"stratMACROSS\",'start_t','end_t'))\n```\n\nWe specify the symbol/s and currency/ies before defining the stock metadata using the stock() function from the [FinancialInstrument](https://cran.r-project.org/web/packages/FinancialInstrument/FinancialInstrument.pdf) package, available on CRAN.\n\n```{r FinancialInstrument, echo=TRUE, message=FALSE}\nstock.str='AAPL' # what are we trying it on\ncurrency('USD')\nstock(stock.str,currency='USD',multiplier=1)\n```\n\nNext we set up the rest of the backtest charateristics:\n\n- start date\n- initial equity\n- portfolio and account names\n- initialize Portfolio, Account and Orders objects\n- assign strategy object to \"stratMACROSS\"\n\n```{r setup_backtest, echo=TRUE, message=FALSE}\nstartDate=\"1999-12-31\"\ninitEq=1000000\nportfolio.st='macross'\naccount.st='macross'\ninitPortf(portfolio.st,symbols=stock.str)\ninitAcct(account.st,portfolios=portfolio.st, initEq=initEq)\ninitOrders(portfolio=portfolio.st)\nstratMACROSS\u003c- strategy(portfolio.st)\n```\n\nWe are now ready to add indicators, signals and rules. For more information on the theory of this approach, see below sections \"About Signal-Based Strategy Modeling\" and \"How quantstrat Models Strategies\".\n\n```{r indicators_rules_signals, echo=TRUE, message=FALSE}\nstratMACROSS \u003c- add.indicator(strategy = stratMACROSS, name = \"SMA\", arguments = list(x=quote(Cl(mktdata)), n=50),label= \"ma50\" )\nstratMACROSS \u003c- add.indicator(strategy = stratMACROSS, name = \"SMA\", arguments = list(x=quote(Cl(mktdata)[,1]), n=200),label= \"ma200\")\n\nstratMACROSS \u003c- add.signal(strategy = stratMACROSS,name=\"sigCrossover\",arguments = list(columns=c(\"ma50\",\"ma200\"), relationship=\"gte\"),label=\"ma50.gt.ma200\")\nstratMACROSS \u003c- add.signal(strategy = stratMACROSS,name=\"sigCrossover\",arguments = list(column=c(\"ma50\",\"ma200\"),relationship=\"lt\"),label=\"ma50.lt.ma200\")\n\nstratMACROSS \u003c- add.rule(strategy = stratMACROSS,name='ruleSignal', arguments = list(sigcol=\"ma50.gt.ma200\",sigval=TRUE, orderqty=100, ordertype='market', orderside='long'),type='enter')\nstratMACROSS \u003c- add.rule(strategy = stratMACROSS,name='ruleSignal', arguments = list(sigcol=\"ma50.lt.ma200\",sigval=TRUE, orderqty='all', ordertype='market', orderside='long'),type='exit')\n\n# if you want a long/short Stops and Reverse MA cross strategy, you would add two more rules for the short side:\n\n# stratMACROSS \u003c- add.rule(strategy = stratMACROSS,name='ruleSignal', arguments = list(sigcol=\"ma50.lt.ma200\",sigval=TRUE, orderqty=-100, ordertype='market', orderside='short'),type='enter')\n# stratMACROSS \u003c- add.rule(strategy = stratMACROSS,name='ruleSignal', arguments = list(sigcol=\"ma50.gt.ma200\",sigval=TRUE, orderqty=100, ordertype='market', orderside='short'),type='exit')\n```\n\nNow all we need to do is add our market data before calling the applyStrategy function to initiate the backtest.\n\n```{r mktdata_applyStrategy, echo=TRUE, message=FALSE, warning=FALSE}\ngetSymbols(stock.str,from=startDate)\nfor(i in stock.str)\n  assign(i, adjustOHLC(get(i),use.Adjusted=TRUE))\n\nstart_t\u003c-Sys.time()\nout\u003c-applyStrategy(strategy=stratMACROSS , portfolios=portfolio.st)\nend_t\u003c-Sys.time()\nprint(end_t-start_t)\n```\n\nBefore we can review results using chart.Posn(), we update the portfolio.\n\n```{r update_review, echo=TRUE, message=FALSE, warning=FALSE}\nstart_t\u003c-Sys.time()\nupdatePortf(Portfolio='macross',Dates=paste('::',as.Date(Sys.time()),sep=''))\nend_t\u003c-Sys.time()\nprint(\"trade blotter portfolio update:\")\nprint(end_t-start_t)\n\nchart.Posn(Portfolio='macross',Symbol=stock.str, TA=c(\"add_SMA(n=50,col='red')\",\"add_SMA(n=200,col='blue')\"))\n```\n\nIf you would like to zoom into a particular period, you can use quantmod's zoomChart().\n\n## quantmod::zoomChart()\n```{r charts3, echo=TRUE, warning=FALSE}\nzoom_Chart('2014::2018')\n```\n\n## Warning\n\nA backtest cannot be unseen. In the words of Lopez de Prado from his book Advances in Financial Machine Learning, \"Backtesting is one of the most essential, and yet least understood, techniques in the quant arsenal. A common misunderstanding is to think of backtesting as a research tool. Researching and backtesting is like drinking and driving. Do not research under the influence of a backtest. ...A good backtest can be extremely helpful, but backtesting well is extremely hard.\"\n\nFor a comprehensive overview of an hypothesis based approach to research and backtesting, see [Developing \u0026 Backtesting Systematic Trading Strategies](https://www.researchgate.net/publication/319298448_Developing_Backtesting_Systematic_Trading_Strategies).\n\n## Resources\n\nBelow is a growing list of resources (some actively being developed) as relates to quantstrat:\n\n- The demo scripts in the demo folder\n- [Datacamp course](https://www.datacamp.com/community/blog/financial-trading-in-r-with-ilya-kipnis) presented by quantstrat contributor Ilya Kipnis covering the basics of strategy development using quantstrat and R.\n- [2018 R/Finance quantstrat seminar](http://past.rinfinance.com/agenda/2018/BrianPeterson.html) workshop presented at R/Finance 2018. The markdown source for this workshop is included with quantstrat in the vignettes directory. \n- [Backtesting Strategies with R](https://timtrice.github.io/backtesting-strategies/index.html) by Tim Trice\n- Guy Yollin [presentations](http://www.r-programming.org/papers)\n- 2013 [presentation](https://docs.google.com/presentation/d/1fGzDc-LFfCQJKHHzaonspuX1_TTm1EB5hlvCEDsz7zw/pub#slide=id.p) by quantstrat authors Jan Humme and Brian Peterson\n\n## About Signal-Based Strategy Modeling\n\nA signal-based strategy model first generates indicators. Indicators are\nquantitative values derived from market data (e.g. moving averages, RSI,\nvolatility bands, channels, momentum, etc.). Indicators should be applied\nto market data in a vectorized (for fast backtesting) or streaming (for live\nexecution) fashion, and are assumed to be path-independent (i.e. they do not\ndepend on account / portfolio characteristics, current positions, or\ntrades).\n\nThe interaction between indicators and market data are used to generate\nsignals (e.g. crossovers, thresholds, multiples, etc.). These signals are\npoints in time at which you may want to take some action, even though you\nmay not be able to.  Like indicators, signals may be applied in a vectorized\nor streaming fashion, and are assumed to be path-independent.\n\nRules use market data, indicators, signals, and current account / portfolio\ncharacteristics to generate orders. Notice that rules about position\nsizing, fill simulation, order generation / management, etc. are separate\nfrom the indicator and signal generation process. Unlike indicators and\nsignals, rules are generally evaluated in a path-dependent fashion\n(path-independent rules are supported but are rare in real life) and are\naware of all prior market data and current positions at the time of\nevaluation. Rules may either generate new or modify existing orders (e.g.\nrisk management, fill, rebalance, entry, exit).\n\n## How quantstrat Models Strategies\n\nquantstrat uses FinancialInstrument to specify instruments (including their\ncurrencies) and uses blotter to keep track of transactions, valuations, and\nP\u0026L across portfolios and accounts.\n\nIndicators are often standard technical analysis functions like those found\nin TTR; and signals are often specified by the quantstrat sig* functions\n(i.e. sigComparison, sigCrossover, sigFormula, sigPeak, sigThreshold).\nRules are typically specified with the quantstrat ruleSignal function.\n\nThe functions used to specify indicators, signals, and rules are not limited to those mentioned previously. The name parameter to add.indicator, add.signal, and add.rule can be any R function. Because the supporting toolchain is built using xts objects, custom functions will integrate most easily if they return xts objects.\n\nThe strategy model is created in layers and makes use of delayed execution.\nThis means strategies can be applied--unmodified--to several different\nportfolios. Before execution, quantstrat strategy objects do not know what\ninstruments they will be applied to or what parameters will be passed to\nthem.\n\nFor example, indicator parameters such as moving average periods or\nthresholds are likely to affect strategy performance. Default values for\nparameters may (optionally) be set in the strategy object, or set at\ncall-time via the parameters argument of applyStrategy (parameters is a\nnamed list, used like the arguments lists).\n\nquantstrat models orders, which may or may not become transactions. This\nprovides a lot of extra ability to evaluate how the strategy is actually\nworking, not working, or could be improved. For example, the performance of\nstrategies are often affected by how often resting limit orders are changed\n/ replaced / canceled. An order book allows the quantitative strategist to\nexamine market conditions at the time these decisions are made. Also, the\norder history allows for easy computation of things that are important for\nmany strategies, like order-to-fill ratios.\n\n### Contributing\n\nPlease see the [contributing guide](.github/CONTRIBUTING.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbraverock%2Fquantstrat","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbraverock%2Fquantstrat","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbraverock%2Fquantstrat/lists"}