├── data ├── AAPL.rda ├── spx.rda ├── luxor-p066.RData ├── stratBBands.rda ├── stratFaber.rda ├── luxor.wfa.ples.RData ├── luxor.parameters.1-10.30-55.RData └── luxor.timespan.24x24.2002-2008.RData ├── luxor.wfa.ples.RData ├── tests ├── run-all.R └── testthat │ ├── test_demo_bbandsWFA.R │ ├── test_demo_macdWFA.R │ ├── test_demo_bbands.R │ ├── test_demo_macd.R │ ├── test_paramsets.R │ ├── test_demo_macdParameters.R │ ├── test_demo_maCross_stoptrailing.R │ ├── test_blotter_break.R │ └── test_demo_rsi.R ├── vignettes ├── toolchain.png ├── cc_by_88x31.png ├── building_blocks.png ├── hypothesis_process.png └── walk_forward_gantt.png ├── inst └── extdata │ ├── luxor.RData │ └── GBPUSD │ ├── 2002.10.21.GBPUSD.rda │ ├── 2002.10.22.GBPUSD.rda │ ├── 2002.10.23.GBPUSD.rda │ ├── 2002.10.24.GBPUSD.rda │ ├── 2002.10.25.GBPUSD.rda │ ├── 2002.10.27.GBPUSD.rda │ ├── 2002.10.28.GBPUSD.rda │ ├── 2002.10.29.GBPUSD.rda │ ├── 2002.10.30.GBPUSD.rda │ └── 2002.10.31.GBPUSD.rda ├── sandbox ├── ES │ ├── 2011.01.02.ES.rda │ ├── 2011.01.03.ES.rda │ ├── 2011.01.04.ES.rda │ ├── 2011.01.05.ES.rda │ ├── 2011.01.06.ES.rda │ ├── 2011.01.07.ES.rda │ ├── 2011.01.09.ES.rda │ ├── 2011.01.10.ES.rda │ ├── 2011.01.11.ES.rda │ ├── 2011.01.12.ES.rda │ ├── 2011.01.13.ES.rda │ ├── 2011.01.14.ES.rda │ ├── 2011.01.16.ES.rda │ ├── 2011.01.17.ES.rda │ ├── 2011.01.18.ES.rda │ ├── 2011.01.19.ES.rda │ ├── 2011.01.20.ES.rda │ ├── 2011.01.21.ES.rda │ ├── 2011.01.23.ES.rda │ ├── 2011.01.24.ES.rda │ ├── 2011.01.25.ES.rda │ ├── 2011.01.26.ES.rda │ ├── 2011.01.27.ES.rda │ ├── 2011.01.28.ES.rda │ ├── 2011.01.30.ES.rda │ └── 2011.01.31.ES.rda ├── backtest_musings │ ├── .directory │ ├── MAE.png │ ├── OOS_det.png │ ├── boxplot.png │ ├── gamlss.png │ ├── histogram.png │ ├── cc-by-nc-sa.pdf │ ├── param_region.png │ ├── resampling1.png │ ├── building_blocks.png │ ├── gd_pres_backtest.pdf │ ├── strat_dev_process.pdf │ ├── hypothesis_process.pdf │ ├── walk_forward_chart.png │ ├── walk_forward_gantt.png │ └── research_replication.pdf └── QuantstratWorkshop.pdf ├── man ├── figures │ ├── README-charts3-1.png │ └── README-update_review-1.png ├── spx.Rd ├── is.strategy.Rd ├── portfolio.luxor.Rd ├── luxoraudit.Rd ├── stats.Rd ├── print.dof.Rd ├── get.strategy.Rd ├── put.strategy.Rd ├── print.haircutSR.Rd ├── print.profitHurdle.Rd ├── load.strategy.Rd ├── save.strategy.Rd ├── put.orderbook.Rd ├── signal.path.plot.Rd ├── expand.distributions.Rd ├── sample_random_multests.Rd ├── sigPeak.Rd ├── Federov.constraints.Rd ├── getPosLimit.Rd ├── delete.paramset.Rd ├── dotprofitHurdle.Rd ├── rm.strat.Rd ├── signal.generate.statistics.Rd ├── sigTimestamp.Rd ├── initSymbol.Rd ├── strategy.Rd ├── clone.orderbook.Rd ├── getOrderBook.Rd ├── applyIndicatorSignals.Rd ├── clone.portfolio.Rd ├── initOrders.Rd ├── osNoOp.Rd ├── sigThreshold.Rd ├── AAPL.Rd ├── enable.rule.Rd ├── signal.obj.slope.Rd ├── install.param.combo.Rd ├── applySignals.Rd ├── sigComparison.Rd ├── paramConstraint.Rd ├── post.signal.returns.Rd ├── sigCrossover.Rd ├── distributional.boxplot.Rd ├── tradeGraphs.Rd ├── match.names.Rd ├── getParameterTable.Rd ├── add.distribution.constraint.Rd ├── chart.forward.training.Rd ├── sigFormula.Rd ├── chart.forward.Rd ├── applyStrategy.rebalancing.Rd ├── getOrders.Rd ├── setParameterConstraint.Rd ├── ruleRevoke.Rd ├── beanplot.signals.Rd ├── osMaxPos.Rd ├── applyIndicators.Rd ├── signal.plot.Rd ├── add.init.Rd ├── initStrategy.Rd ├── add.signal.Rd ├── rulePctEquity.Rd ├── updateOrders.Rd ├── tradeOrderStats.Rd ├── addPosLimit.Rd ├── SharpeRatio.deflated.Rd ├── add.distribution.Rd ├── stratBBands.Rd ├── applyStrategy.Rd ├── ruleOrderProc.Rd ├── updateStrategy.Rd ├── Federov.paramset.Rd ├── setParameterDistribution.Rd ├── profitHurdle.Rd └── apply.paramset.signal.analysis.Rd ├── R ├── zzz.R ├── multi.objective.R ├── data.R ├── match.names.R ├── ruleRevoke.R ├── tradeGraphs.R ├── utils.R ├── tradeOrderStats.R └── chart.forward.training.R ├── codecov.yml ├── .Rbuildignore ├── .github ├── pull_request_template.md └── issue_template.md ├── demo ├── luxor.sample.walk.forward.R ├── luxor.sample.MAE.stoploss.R ├── luxor.sample.MAE.stoptrailing.R ├── luxor.sample.MFE.takeprofit.R ├── luxor.sample.tradeGraphs.sma.R ├── demo_test_blotter_break.R ├── luxor.getSymbols.R ├── luxor.sample.tradeGraphs.timespan.R ├── luxor.3.paramset.sma.R ├── luxor.4.paramset.timespan.R ├── luxor.include.R ├── luxor.6.paramset.stoploss.R ├── luxor.6.paramset.takeprofit.R ├── luxor.6.paramset.stoptrailing.R ├── luxor.7.exit.and.risk.R ├── bbandParameters.R ├── macdParameters.R ├── luxor.2.add.paramsets.R ├── macdWFA.R ├── 00Index ├── luxor.8.walk.forward.R └── luxor.1.strategy.basic.R ├── quantstrat.Rproj ├── src └── init.c ├── .gitignore ├── DESCRIPTION ├── .travis.yml └── NAMESPACE /data/AAPL.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/data/AAPL.rda -------------------------------------------------------------------------------- /data/spx.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/data/spx.rda -------------------------------------------------------------------------------- /data/luxor-p066.RData: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/data/luxor-p066.RData -------------------------------------------------------------------------------- /data/stratBBands.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/data/stratBBands.rda -------------------------------------------------------------------------------- /data/stratFaber.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/data/stratFaber.rda -------------------------------------------------------------------------------- /luxor.wfa.ples.RData: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/luxor.wfa.ples.RData -------------------------------------------------------------------------------- /tests/run-all.R: -------------------------------------------------------------------------------- 1 | require(testthat) 2 | require(quantstrat) 3 | 4 | test_check("quantstrat") 5 | -------------------------------------------------------------------------------- /vignettes/toolchain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/vignettes/toolchain.png -------------------------------------------------------------------------------- /data/luxor.wfa.ples.RData: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/data/luxor.wfa.ples.RData -------------------------------------------------------------------------------- /inst/extdata/luxor.RData: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/inst/extdata/luxor.RData -------------------------------------------------------------------------------- /vignettes/cc_by_88x31.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/vignettes/cc_by_88x31.png -------------------------------------------------------------------------------- /sandbox/ES/2011.01.02.ES.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/ES/2011.01.02.ES.rda -------------------------------------------------------------------------------- /sandbox/ES/2011.01.03.ES.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/ES/2011.01.03.ES.rda -------------------------------------------------------------------------------- /sandbox/ES/2011.01.04.ES.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/ES/2011.01.04.ES.rda -------------------------------------------------------------------------------- /sandbox/ES/2011.01.05.ES.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/ES/2011.01.05.ES.rda -------------------------------------------------------------------------------- /sandbox/ES/2011.01.06.ES.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/ES/2011.01.06.ES.rda -------------------------------------------------------------------------------- /sandbox/ES/2011.01.07.ES.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/ES/2011.01.07.ES.rda -------------------------------------------------------------------------------- /sandbox/ES/2011.01.09.ES.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/ES/2011.01.09.ES.rda -------------------------------------------------------------------------------- /sandbox/ES/2011.01.10.ES.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/ES/2011.01.10.ES.rda -------------------------------------------------------------------------------- /sandbox/ES/2011.01.11.ES.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/ES/2011.01.11.ES.rda -------------------------------------------------------------------------------- /sandbox/ES/2011.01.12.ES.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/ES/2011.01.12.ES.rda -------------------------------------------------------------------------------- /sandbox/ES/2011.01.13.ES.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/ES/2011.01.13.ES.rda -------------------------------------------------------------------------------- /sandbox/ES/2011.01.14.ES.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/ES/2011.01.14.ES.rda -------------------------------------------------------------------------------- /sandbox/ES/2011.01.16.ES.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/ES/2011.01.16.ES.rda -------------------------------------------------------------------------------- /sandbox/ES/2011.01.17.ES.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/ES/2011.01.17.ES.rda -------------------------------------------------------------------------------- /sandbox/ES/2011.01.18.ES.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/ES/2011.01.18.ES.rda -------------------------------------------------------------------------------- /sandbox/ES/2011.01.19.ES.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/ES/2011.01.19.ES.rda -------------------------------------------------------------------------------- /sandbox/ES/2011.01.20.ES.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/ES/2011.01.20.ES.rda -------------------------------------------------------------------------------- /sandbox/ES/2011.01.21.ES.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/ES/2011.01.21.ES.rda -------------------------------------------------------------------------------- /sandbox/ES/2011.01.23.ES.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/ES/2011.01.23.ES.rda -------------------------------------------------------------------------------- /sandbox/ES/2011.01.24.ES.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/ES/2011.01.24.ES.rda -------------------------------------------------------------------------------- /sandbox/ES/2011.01.25.ES.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/ES/2011.01.25.ES.rda -------------------------------------------------------------------------------- /sandbox/ES/2011.01.26.ES.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/ES/2011.01.26.ES.rda -------------------------------------------------------------------------------- /sandbox/ES/2011.01.27.ES.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/ES/2011.01.27.ES.rda -------------------------------------------------------------------------------- /sandbox/ES/2011.01.28.ES.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/ES/2011.01.28.ES.rda -------------------------------------------------------------------------------- /sandbox/ES/2011.01.30.ES.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/ES/2011.01.30.ES.rda -------------------------------------------------------------------------------- /sandbox/ES/2011.01.31.ES.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/ES/2011.01.31.ES.rda -------------------------------------------------------------------------------- /sandbox/backtest_musings/.directory: -------------------------------------------------------------------------------- 1 | [Dolphin] 2 | Timestamp=2014,10,20,6,40,13 3 | Version=3 4 | ViewMode=1 5 | -------------------------------------------------------------------------------- /sandbox/QuantstratWorkshop.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/QuantstratWorkshop.pdf -------------------------------------------------------------------------------- /vignettes/building_blocks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/vignettes/building_blocks.png -------------------------------------------------------------------------------- /man/figures/README-charts3-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/man/figures/README-charts3-1.png -------------------------------------------------------------------------------- /sandbox/backtest_musings/MAE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/backtest_musings/MAE.png -------------------------------------------------------------------------------- /vignettes/hypothesis_process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/vignettes/hypothesis_process.png -------------------------------------------------------------------------------- /vignettes/walk_forward_gantt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/vignettes/walk_forward_gantt.png -------------------------------------------------------------------------------- /sandbox/backtest_musings/OOS_det.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/backtest_musings/OOS_det.png -------------------------------------------------------------------------------- /sandbox/backtest_musings/boxplot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/backtest_musings/boxplot.png -------------------------------------------------------------------------------- /sandbox/backtest_musings/gamlss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/backtest_musings/gamlss.png -------------------------------------------------------------------------------- /data/luxor.parameters.1-10.30-55.RData: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/data/luxor.parameters.1-10.30-55.RData -------------------------------------------------------------------------------- /man/figures/README-update_review-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/man/figures/README-update_review-1.png -------------------------------------------------------------------------------- /sandbox/backtest_musings/histogram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/backtest_musings/histogram.png -------------------------------------------------------------------------------- /data/luxor.timespan.24x24.2002-2008.RData: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/data/luxor.timespan.24x24.2002-2008.RData -------------------------------------------------------------------------------- /inst/extdata/GBPUSD/2002.10.21.GBPUSD.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/inst/extdata/GBPUSD/2002.10.21.GBPUSD.rda -------------------------------------------------------------------------------- /inst/extdata/GBPUSD/2002.10.22.GBPUSD.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/inst/extdata/GBPUSD/2002.10.22.GBPUSD.rda -------------------------------------------------------------------------------- /inst/extdata/GBPUSD/2002.10.23.GBPUSD.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/inst/extdata/GBPUSD/2002.10.23.GBPUSD.rda -------------------------------------------------------------------------------- /inst/extdata/GBPUSD/2002.10.24.GBPUSD.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/inst/extdata/GBPUSD/2002.10.24.GBPUSD.rda -------------------------------------------------------------------------------- /inst/extdata/GBPUSD/2002.10.25.GBPUSD.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/inst/extdata/GBPUSD/2002.10.25.GBPUSD.rda -------------------------------------------------------------------------------- /inst/extdata/GBPUSD/2002.10.27.GBPUSD.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/inst/extdata/GBPUSD/2002.10.27.GBPUSD.rda -------------------------------------------------------------------------------- /inst/extdata/GBPUSD/2002.10.28.GBPUSD.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/inst/extdata/GBPUSD/2002.10.28.GBPUSD.rda -------------------------------------------------------------------------------- /inst/extdata/GBPUSD/2002.10.29.GBPUSD.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/inst/extdata/GBPUSD/2002.10.29.GBPUSD.rda -------------------------------------------------------------------------------- /inst/extdata/GBPUSD/2002.10.30.GBPUSD.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/inst/extdata/GBPUSD/2002.10.30.GBPUSD.rda -------------------------------------------------------------------------------- /inst/extdata/GBPUSD/2002.10.31.GBPUSD.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/inst/extdata/GBPUSD/2002.10.31.GBPUSD.rda -------------------------------------------------------------------------------- /sandbox/backtest_musings/cc-by-nc-sa.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/backtest_musings/cc-by-nc-sa.pdf -------------------------------------------------------------------------------- /sandbox/backtest_musings/param_region.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/backtest_musings/param_region.png -------------------------------------------------------------------------------- /sandbox/backtest_musings/resampling1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/backtest_musings/resampling1.png -------------------------------------------------------------------------------- /sandbox/backtest_musings/building_blocks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/backtest_musings/building_blocks.png -------------------------------------------------------------------------------- /sandbox/backtest_musings/gd_pres_backtest.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/backtest_musings/gd_pres_backtest.pdf -------------------------------------------------------------------------------- /sandbox/backtest_musings/strat_dev_process.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/backtest_musings/strat_dev_process.pdf -------------------------------------------------------------------------------- /sandbox/backtest_musings/hypothesis_process.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/backtest_musings/hypothesis_process.pdf -------------------------------------------------------------------------------- /sandbox/backtest_musings/walk_forward_chart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/backtest_musings/walk_forward_chart.png -------------------------------------------------------------------------------- /sandbox/backtest_musings/walk_forward_gantt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/backtest_musings/walk_forward_gantt.png -------------------------------------------------------------------------------- /sandbox/backtest_musings/research_replication.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braverock/quantstrat/HEAD/sandbox/backtest_musings/research_replication.pdf -------------------------------------------------------------------------------- /R/zzz.R: -------------------------------------------------------------------------------- 1 | .onUnload <- function(libpath) { 2 | library.dynam.unload("quantstrat", libpath) 3 | } 4 | 5 | .onLoad <- function(lib, pkg) { 6 | if(!exists('.strategy')) 7 | .strategy <<- new.env() 8 | } -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | comment: false 2 | 3 | coverage: 4 | status: 5 | project: 6 | default: 7 | target: auto 8 | threshold: 1% 9 | patch: 10 | default: 11 | target: auto 12 | threshold: 1% 13 | -------------------------------------------------------------------------------- /man/spx.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/quantstrat-package.R 3 | \docType{data} 4 | \name{spx} 5 | \alias{spx} 6 | \title{sample spx daily OHLCVA data set 1970:1971} 7 | \description{ 8 | sample spx daily OHLCVA data set 1970:1971 9 | } 10 | \keyword{data} 11 | -------------------------------------------------------------------------------- /.Rbuildignore: -------------------------------------------------------------------------------- 1 | sandbox 2 | generatechangelog\.sh 3 | ChangeLog\.1\.0\.0 4 | ^.*[.]Rproj.*$ 5 | ^\.Rproj\.user$ 6 | ^.Rhistory$ 7 | \.travis\.yml 8 | ^.*_cache$ 9 | ^.*_files$ 10 | tiingoapi\.R 11 | ^.*\.bak$ 12 | ^.*\.sav$ 13 | ^README\.Rmd$ 14 | ^.*\.Rproj$ 15 | ^\.vimrc 16 | ^codecov\.yml$ 17 | \.git 18 | \.github 19 | \.gitignore 20 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | Please review the [contributing guide](CONTRIBUTING.md) before submitting your pull request. Please pay special attention to the [pull request](CONTRIBUTING.md#want-to-submit-a-pull-request) and [commit message](CONTRIBUTING.md#commit-messages) sections. Thanks for your contribution and interest in the project! 2 | -------------------------------------------------------------------------------- /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | ### Description 2 | 3 | [Describe the issue] 4 | 5 | ### Expected behavior 6 | 7 | [Describe the behavior/output you expected] 8 | 9 | ### Minimal, reproducible example 10 | 11 | ```r 12 | [Insert sample data and code] 13 | ``` 14 | 15 | ### Session Info 16 | 17 | ```r 18 | [Insert your sessionInfo() output] 19 | ``` 20 | 21 | -------------------------------------------------------------------------------- /man/is.strategy.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/strategy.R 3 | \name{is.strategy} 4 | \alias{is.strategy} 5 | \title{test to see if object is of type 'strategy'} 6 | \usage{ 7 | is.strategy(x) 8 | } 9 | \arguments{ 10 | \item{x}{object to be tested} 11 | } 12 | \description{ 13 | test to see if object is of type 'strategy' 14 | } 15 | -------------------------------------------------------------------------------- /man/portfolio.luxor.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/quantstrat-package.R 3 | \docType{data} 4 | \name{portfolio.luxor} 5 | \alias{portfolio.luxor} 6 | \title{sample portfolio output from running luxor demo in file data/luxor-p066.RData} 7 | \description{ 8 | sample portfolio output from running luxor demo in file data/luxor-p066.RData 9 | } 10 | \keyword{data} 11 | -------------------------------------------------------------------------------- /man/luxoraudit.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/quantstrat-package.R 3 | \docType{data} 4 | \name{luxoraudit} 5 | \alias{luxoraudit} 6 | \title{sample audit environment output from running luxor demo in file data/luxor.wfa.ples.RData} 7 | \description{ 8 | sample audit environment output from running luxor demo in file data/luxor.wfa.ples.RData 9 | } 10 | \keyword{data} 11 | -------------------------------------------------------------------------------- /man/stats.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/quantstrat-package.R 3 | \docType{data} 4 | \name{stats} 5 | \alias{stats} 6 | \title{sample tradeStats output from running luxor demo in file data/luxor.parameters.1-10.30-55.RData} 7 | \description{ 8 | sample tradeStats output from running luxor demo in file data/luxor.parameters.1-10.30-55.RData 9 | } 10 | \keyword{data} 11 | -------------------------------------------------------------------------------- /demo/luxor.sample.walk.forward.R: -------------------------------------------------------------------------------- 1 | #!/usr/bin/Rscript --vanilla 2 | # 3 | # Jan Humme (@opentrades) - August 2012 4 | # 5 | # Tested and found to work correctly using blotter r1457 6 | # 7 | # After Jaekle & Tamasini: A new approach to system development and portfolio optimisation (ISBN 978-1-905641-79-6) 8 | # 9 | # Walk forward chart sample 10 | 11 | require('quantstrat') 12 | 13 | chart.forward.training(paste0(path.package("quantstrat"),'/data/luxor.wfa.ples.RData')) 14 | 15 | -------------------------------------------------------------------------------- /quantstrat.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | BuildType: Package 16 | PackageUseDevtools: Yes 17 | PackageInstallArgs: --no-multiarch --with-keep.source 18 | PackageBuildArgs: --no-build-vignettes 19 | PackageCheckArgs: --no-build-vignettes --ignore-vignettes 20 | PackageRoxygenize: rd,namespace 21 | -------------------------------------------------------------------------------- /man/print.dof.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/degfreedom.R 3 | \name{print.dof} 4 | \alias{print.dof} 5 | \title{print method for strategy degrees of freedom object} 6 | \usage{ 7 | \method{print}{dof}(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{an object of type \code{dof} to be printed} 11 | 12 | \item{...}{any other passthough parameters} 13 | } 14 | \description{ 15 | print method for strategy degrees of freedom object 16 | } 17 | \seealso{ 18 | \code{\link{degrees.of.freedom}} 19 | } 20 | -------------------------------------------------------------------------------- /man/get.strategy.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/strategy.R 3 | \name{get.strategy} 4 | \alias{get.strategy} 5 | \alias{getStrategy} 6 | \title{retrieve strategy from the container environment} 7 | \usage{ 8 | get.strategy(x, envir = .strategy) 9 | } 10 | \arguments{ 11 | \item{x}{string name of object to be retrieved} 12 | 13 | \item{envir}{the environment to retrieve the strategy object from, defaults to .strategy} 14 | } 15 | \description{ 16 | retrieve strategy from the container environment 17 | } 18 | -------------------------------------------------------------------------------- /man/put.strategy.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/strategy.R 3 | \name{put.strategy} 4 | \alias{put.strategy} 5 | \title{put a strategy object in .strategy env} 6 | \usage{ 7 | put.strategy(strategy, envir = .strategy) 8 | } 9 | \arguments{ 10 | \item{strategy}{object; name will be extracted as strategy$name} 11 | 12 | \item{envir}{the environment to store the strategy in, defaults to .strategy} 13 | } 14 | \description{ 15 | put a strategy object in .strategy env 16 | } 17 | \seealso{ 18 | getStrategy 19 | } 20 | -------------------------------------------------------------------------------- /R/multi.objective.R: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # R (http://r-project.org/) Quantitative Strategy Model Framework 3 | # 4 | # Copyright (c) 2009-2022 5 | ############################################################################### 6 | # 7 | # Authors: Brian G. Peterson 8 | # 9 | ############################################################################### 10 | # 11 | # Tools for multi-objective parameter optimization 12 | # 13 | ############################################################################### 14 | 15 | -------------------------------------------------------------------------------- /man/print.haircutSR.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/haircut.Sharpe.R 3 | \name{print.haircutSR} 4 | \alias{print.haircutSR} 5 | \title{print method for Harvey and Liu Haircut Sharpe Ratio} 6 | \usage{ 7 | \method{print}{haircutSR}(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{an object of type \code{haircutSR} to be printed} 11 | 12 | \item{...}{any other passthough parameters} 13 | } 14 | \description{ 15 | print method for Harvey and Liu Haircut Sharpe Ratio 16 | } 17 | \seealso{ 18 | \code{\link{SharpeRatio.haircut}} 19 | } 20 | -------------------------------------------------------------------------------- /man/print.profitHurdle.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/profit.hurdle.R 3 | \name{print.profitHurdle} 4 | \alias{print.profitHurdle} 5 | \title{print method for Harvey and Liu Haircut Sharpe Ratio} 6 | \usage{ 7 | \method{print}{profitHurdle}(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{an object of type \code{profitHurdle} to be printed} 11 | 12 | \item{...}{any other passthough parameters} 13 | } 14 | \description{ 15 | print method for Harvey and Liu Haircut Sharpe Ratio 16 | } 17 | \seealso{ 18 | \code{\link{profit.hurdle}} 19 | } 20 | -------------------------------------------------------------------------------- /man/load.strategy.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/strategy.R 3 | \name{load.strategy} 4 | \alias{load.strategy} 5 | \title{load a strategy object from disk into memory} 6 | \usage{ 7 | load.strategy(strategy.name, file = NULL) 8 | } 9 | \arguments{ 10 | \item{strategy.name}{a string specifying the name of the strategy object; may also be used to create a file name} 11 | 12 | \item{file}{string specifying the filename to use, if NULL, a default will be created} 13 | } 14 | \description{ 15 | load a strategy object from disk into memory 16 | } 17 | -------------------------------------------------------------------------------- /man/save.strategy.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/strategy.R 3 | \name{save.strategy} 4 | \alias{save.strategy} 5 | \title{save a strategy object from memory onto disk} 6 | \usage{ 7 | save.strategy(strategy.name, file = NULL) 8 | } 9 | \arguments{ 10 | \item{strategy.name}{a string specifying the name of the strategy object; may also be used to create a file name} 11 | 12 | \item{file}{string specifying the filename to use, if NULL, a default will be created} 13 | } 14 | \description{ 15 | save a strategy object from memory onto disk 16 | } 17 | -------------------------------------------------------------------------------- /man/put.orderbook.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/orders.R 3 | \name{put.orderbook} 4 | \alias{put.orderbook} 5 | \title{put an orderbook object in .strategy env} 6 | \usage{ 7 | put.orderbook(portfolio.st, orderbook, envir = .strategy) 8 | } 9 | \arguments{ 10 | \item{portfolio.st}{string identifying portfolio} 11 | 12 | \item{orderbook}{orderbook object} 13 | 14 | \item{envir}{the environment to store the orderbook object in, defaults to .strategy} 15 | } 16 | \description{ 17 | put an orderbook object in .strategy env 18 | } 19 | \seealso{ 20 | getOrderBook 21 | } 22 | \concept{order book} 23 | -------------------------------------------------------------------------------- /demo/luxor.sample.MAE.stoploss.R: -------------------------------------------------------------------------------- 1 | #!/usr/bin/Rscript --vanilla 2 | # 3 | # Jan Humme (@opentrades) - August 2012 4 | # 5 | # Tested and found to work correctly using blotter r1457 6 | # 7 | # After Jaekle & Tamasini: A new approach to system development and portfolio optimisation (ISBN 978-1-905641-79-6) 8 | # 9 | # Figure 3.11: MAE graph of Luxor system 10 | 11 | require('blotter') 12 | 13 | data('luxor-p066', package='quantstrat', envir=.blotter) 14 | 15 | currency(c('GBP', 'USD')) 16 | exchange_rate(c('GBPUSD'), tick_size=0.0001) 17 | 18 | chart.ME( 19 | Portfolio='luxor', 20 | Symbol='GBPUSD', 21 | type='MAE', 22 | scale='cash' 23 | ) 24 | -------------------------------------------------------------------------------- /demo/luxor.sample.MAE.stoptrailing.R: -------------------------------------------------------------------------------- 1 | #!/usr/bin/Rscript --vanilla 2 | # 3 | # Jan Humme (@opentrades) - August 2012 4 | # 5 | # Tested and found to work correctly using blotter r1457 6 | # 7 | # After Jaekle & Tamasini: A new approach to system development and portfolio optimisation (ISBN 978-1-905641-79-6) 8 | # 9 | # Figure 3.12: MAE graph in percentage terms 10 | 11 | require('blotter') 12 | 13 | data('luxor-p066', package='quantstrat', envir=.blotter) 14 | 15 | currency(c('GBP', 'USD')) 16 | exchange_rate(c('GBPUSD'), tick_size=0.0001) 17 | 18 | chart.ME( 19 | Portfolio='luxor', 20 | Symbol='GBPUSD', 21 | type='MAE', 22 | scale='percent' 23 | ) 24 | -------------------------------------------------------------------------------- /demo/luxor.sample.MFE.takeprofit.R: -------------------------------------------------------------------------------- 1 | #!/usr/bin/Rscript --vanilla 2 | # 3 | # Jan Humme (@opentrades) - August 2012 4 | # 5 | # Tested and found to work correctly using blotter r1457 6 | # 7 | # After Jaekle & Tamasini: A new approach to system development and portfolio optimisation (ISBN 978-1-905641-79-6) 8 | # 9 | # Figure 3.16: MFE graph in percentage terms 10 | 11 | require('blotter') 12 | 13 | data('luxor-p066', package='quantstrat', envir=.blotter) 14 | 15 | currency(c('GBP', 'USD')) 16 | exchange_rate(c('GBPUSD'), tick_size=0.0001) 17 | 18 | chart.ME( 19 | Portfolio='luxor', 20 | Symbol='GBPUSD', 21 | type='MFE', 22 | scale='percent' 23 | ) 24 | -------------------------------------------------------------------------------- /man/signal.path.plot.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/signals.R 3 | \name{signal.path.plot} 4 | \alias{signal.path.plot} 5 | \title{Visualization of Signal Path} 6 | \usage{ 7 | signal.path.plot(data, main = "Cumulative Return Paths") 8 | } 9 | \arguments{ 10 | \item{data}{signal data} 11 | 12 | \item{main}{plot title} 13 | } 14 | \value{ 15 | plot 16 | } 17 | \description{ 18 | This function creates a rChart - hplot that is interactive. It displays 19 | } 20 | \examples{ 21 | \dontrun{ 22 | signal.plot.path(results$sigret.by.asset$RTH$paramset.1.5[1:10,]) 23 | } 24 | } 25 | \author{ 26 | Michael Guan 27 | } 28 | -------------------------------------------------------------------------------- /src/init.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* Function definitions */ 6 | SEXP firstCross(SEXP x, SEXP th, SEXP rel, SEXP start); 7 | 8 | static const 9 | R_CallMethodDef callMethods[] = { 10 | {"firstCross", (DL_FUNC) &firstCross, 4}, 11 | {NULL, NULL, 0} 12 | }; 13 | 14 | void R_init_quantstrat(DllInfo *info) 15 | { 16 | R_registerRoutines(info, 17 | NULL, 18 | callMethods, 19 | NULL, 20 | NULL); 21 | 22 | R_useDynamicSymbols(info, FALSE); 23 | R_forceSymbols(info, TRUE); /* C code not callable outside blotter */ 24 | } 25 | -------------------------------------------------------------------------------- /man/expand.distributions.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/paramsets.R 3 | \name{expand.distributions} 4 | \alias{expand.distributions} 5 | \title{given a distributions object expand all options to a full factorial representation} 6 | \usage{ 7 | expand.distributions(distributions) 8 | } 9 | \arguments{ 10 | \item{distributions}{distributions slot from a strtaegy object} 11 | } 12 | \value{ 13 | expanded grid of all distributions as a `data.frame` by distribution labels 14 | } 15 | \description{ 16 | given a distributions object expand all options to a full factorial representation 17 | } 18 | \seealso{ 19 | expand.grid 20 | } 21 | -------------------------------------------------------------------------------- /man/sample_random_multests.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/haircut.Sharpe.R 3 | \name{sample_random_multests} 4 | \alias{sample_random_multests} 5 | \title{Generate empirical p-value distributions} 6 | \usage{ 7 | sample_random_multests(rho, m_tot, p_0, lambda, M_simu) 8 | } 9 | \arguments{ 10 | \item{rho}{average correlation among returns} 11 | 12 | \item{m_tot}{total number of trials} 13 | 14 | \item{p_0}{probability for a random factor to have a zero mean} 15 | 16 | \item{lambda}{average of monthly mean returns for true strategies} 17 | 18 | \item{M_simu}{number of simulations to perform} 19 | } 20 | \description{ 21 | Generate empirical p-value distributions 22 | } 23 | -------------------------------------------------------------------------------- /man/sigPeak.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/signals.R 3 | \name{sigPeak} 4 | \alias{sigPeak} 5 | \title{signal function for peak/valley signals} 6 | \usage{ 7 | sigPeak(label, data, column, direction = c("peak", "bottom")) 8 | } 9 | \arguments{ 10 | \item{label}{text label to apply to the output} 11 | 12 | \item{data}{data to apply comparison to} 13 | 14 | \item{column}{named column to apply comparison to} 15 | 16 | \item{direction}{one of "peak" or "bottom" to calculate peaks for} 17 | } 18 | \description{ 19 | This function tests to see if the mktdata or indicator \code{column} observations 20 | on either side are lower(higher) creating a local peak(bottom). 21 | } 22 | -------------------------------------------------------------------------------- /man/Federov.constraints.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/Federov.design.R 3 | \name{Federov.constraints} 4 | \alias{Federov.constraints} 5 | \title{test a single parameter set to determine if it passes constraints} 6 | \usage{ 7 | Federov.constraints(param.vec, ...) 8 | } 9 | \arguments{ 10 | \item{param.vec}{a vector (named or unamed) containing a trial parameter set} 11 | 12 | \item{...}{any other passthrough parameters} 13 | } 14 | \value{ 15 | boolean - TRUE if param.vec passes constraints, FALSE otherwise 16 | } 17 | \description{ 18 | test a single parameter set to determine if it passes constraints 19 | } 20 | \seealso{ 21 | Federov.paramset MonteCarlo.paramset apply.constraints 22 | } 23 | -------------------------------------------------------------------------------- /man/getPosLimit.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/osFUNs.R 3 | \name{getPosLimit} 4 | \alias{getPosLimit} 5 | \title{get position and level limits on timestamp} 6 | \usage{ 7 | getPosLimit(portfolio, symbol, timestamp) 8 | } 9 | \arguments{ 10 | \item{portfolio}{text name of the portfolio to place orders in} 11 | 12 | \item{symbol}{identifier of the instrument to place orders for. The name of any associated price objects (xts prices, usually OHLC) should match these} 13 | 14 | \item{timestamp}{timestamp coercible to POSIXct that will be the time the order will be inserted on} 15 | } 16 | \description{ 17 | get position and level limits on timestamp 18 | } 19 | \seealso{ 20 | \code{\link{addPosLimit}},\code{\link{osMaxPos}} 21 | } 22 | -------------------------------------------------------------------------------- /tests/testthat/test_demo_bbandsWFA.R: -------------------------------------------------------------------------------- 1 | # A test for walk.forward() using the bbandsWFA demo 2 | # 3 | # See issue #101 - https://github.com/braverock/quantstrat/issues/101 4 | 5 | options(warn=-1) 6 | stopifnot(require(testthat)) 7 | stopifnot(require(quantstrat)) 8 | context("deom/bbandsWFA.R") 9 | 10 | source(paste0(path.package("quantstrat"),"/demo/bbandsWFA.R")) 11 | 12 | test_that("results environment has 11 objects", { 13 | expect_equal(length(results), 11) 14 | }) 15 | 16 | test_that("test TradeStats End.Equity equals -2835", { 17 | expect_equal(round(results$tradeStats$End.Equity), -2835) 18 | }) 19 | 20 | # Commands for running this test file from the console if required: 21 | # 22 | # require(testthat) 23 | # test_file("~/quantstrat/tests/testthat/test_demo_bbandsWFA.R") 24 | -------------------------------------------------------------------------------- /tests/testthat/test_demo_macdWFA.R: -------------------------------------------------------------------------------- 1 | # A test for walk.forward() using the macdWFA demo 2 | # 3 | # 4 | 5 | options(warn=-1) 6 | stopifnot(require(testthat)) 7 | stopifnot(require(quantstrat)) 8 | context("deom/macdWFA.R") 9 | 10 | source(paste0(path.package("quantstrat"),"/demo/macdWFA.R")) 11 | 12 | test_that("wfresults environment has 12 objects", { 13 | expect_equal(length(wfresults), 12) 14 | }) 15 | 16 | # Cannot test End.Equity since we use a random sample of all possible parameter combinations, 17 | # but testing for the number of objects in wfresults should suffice to identify breaking 18 | # walk.forward code 19 | 20 | # Commands for running this test file from the console if required: 21 | # 22 | # require(testthat) 23 | # test_file("~/quantstrat/tests/testthat/test_demo_macdWFA.R") 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # History files 2 | .Rhistory 3 | .Rapp.history 4 | .directory 5 | #object files 6 | *.o 7 | *.so 8 | # Session Data files 9 | .RData 10 | # Example code in package build process 11 | *-Ex.R 12 | # Output files from R CMD build 13 | /*.tar.gz 14 | # Output files from R CMD check 15 | /*.Rcheck/ 16 | # RStudio files 17 | .Rproj.user/ 18 | # produced vignettes 19 | vignettes/*.html 20 | vignettes/*.pdf 21 | # OAuth2 token, see https://github.com/hadley/httr/releases/tag/v0.3 22 | .httr-oauth 23 | # knitr and R markdown default cache directories 24 | /*_cache/ 25 | /cache/ 26 | # Temporary files created by R markdown 27 | *.utf8.md 28 | *.knit.md 29 | .Rproj.user 30 | inst/doc 31 | *_cache* 32 | *_files* 33 | *.bak 34 | *.sav 35 | .vimrc 36 | 37 | #tiingoapi file 38 | vignettes/tiingoapi.R 39 | 40 | -------------------------------------------------------------------------------- /man/delete.paramset.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/paramsets.R 3 | \name{delete.paramset} 4 | \alias{delete.paramset} 5 | \title{Delete a paramset from a strategy} 6 | \usage{ 7 | delete.paramset(strategy, paramset.label, store = TRUE) 8 | } 9 | \arguments{ 10 | \item{strategy}{the name of the strategy object} 11 | 12 | \item{paramset.label}{a label uniquely identifying the paramset within the strategy} 13 | 14 | \item{store}{indicates whether to store the strategy in the .strategy environment} 15 | } 16 | \description{ 17 | Delete a paramset from a strategy, including its distributions and constraints. 18 | } 19 | \seealso{ 20 | \code{\link{add.distribution}}, 21 | \code{\link{add.distribution.constraint}}, 22 | \code{\link{apply.paramset}} 23 | } 24 | \author{ 25 | Jan Humme 26 | } 27 | -------------------------------------------------------------------------------- /demo/luxor.sample.tradeGraphs.sma.R: -------------------------------------------------------------------------------- 1 | #!/usr/bin/Rscript --vanilla 2 | # 3 | # Jan Humme (@opentrades) - August 2012, revised April 2013 4 | # 5 | # Tested and found to work correctly using blotter r1457 6 | # 7 | # After Jaekle & Tamasini: A new approach to system development and portfolio optimisation (ISBN 978-1-905641-79-6) 8 | # 9 | # 3D SMA graph example 10 | 11 | require(quantstrat) 12 | require(rgl) 13 | 14 | ### load 'stats' back into .GlobalEnv 15 | 16 | load(paste0( 17 | path.package('quantstrat'), 18 | '/data/luxor.parameters.1-10.30-55.RData') 19 | ) 20 | 21 | ### show trade graphs from stats 22 | 23 | tradeGraphs ( 24 | stats = stats, 25 | free.params = c("Param.indicator.1.nFast", "Param.indicator.2.nSlow"), 26 | statistics = c("Net.Trading.PL", "maxDrawdown", "Avg.Trade.PL", "Num.Trades", "Profit.Factor"), 27 | title = 'Luxor SMA Parameter Scan' 28 | ) 29 | -------------------------------------------------------------------------------- /man/dotprofitHurdle.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/profit.hurdle.R 3 | \name{.profitHurdle} 4 | \alias{.profitHurdle} 5 | \title{internal implementation of profit hurdle code, see \code{\link{profit.hurdle}}} 6 | \usage{ 7 | .profitHurdle(sm_fre, num_tests, num_obs, alpha_sig, vol_annual, RHO) 8 | } 9 | \arguments{ 10 | \item{sm_fre}{Sampling frequency; [1,2,3,4,5] = [Daily, Weekly, Monthly, Quarterly, Annual]} 11 | 12 | \item{num_tests}{No. of tests one allows for in multiple tests} 13 | 14 | \item{num_obs}{No. of monthly observations for a strategy} 15 | 16 | \item{alpha_sig}{Significance level (e.g., 5#)} 17 | 18 | \item{vol_annual}{Annual return volatility (e.g., 0.05 or 5#)} 19 | 20 | \item{RHO}{Assumed average correlation, default 0.2} 21 | } 22 | \description{ 23 | internal implementation of profit hurdle code, see \code{\link{profit.hurdle}} 24 | } 25 | -------------------------------------------------------------------------------- /man/rm.strat.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/wrapup.R 3 | \name{rm.strat} 4 | \alias{rm.strat} 5 | \title{Remove objects associated with a strategy} 6 | \usage{ 7 | rm.strat(name = "default", silent = TRUE) 8 | } 9 | \arguments{ 10 | \item{name}{name of the portfolio/account/order book to clean up. (Default='default')} 11 | 12 | \item{silent}{silence warnings about trying to remove objects that do not exist. (Default=TRUE)} 13 | } 14 | \value{ 15 | invisible -- called for side-effect 16 | } 17 | \description{ 18 | Remove the order_book, account, and portfolio of given \code{name}. 19 | } 20 | \examples{ 21 | \dontrun{ 22 | # make some things to remove 23 | strategy("example", store=TRUE) 24 | initPortf('example', stock('SPY', currency("USD"))) 25 | initAcct('example', 'example') 26 | initOrders('example', 'SPY') 27 | #Now remove them 28 | rm.strat('example') 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /man/signal.generate.statistics.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/signals.R 3 | \name{signal.generate.statistics} 4 | \alias{signal.generate.statistics} 5 | \title{Signal Objective Function Calculation} 6 | \usage{ 7 | signal.generate.statistics(post.ret, obj.fun = NULL, decreasing = TRUE) 8 | } 9 | \arguments{ 10 | \item{post.ret}{\code{matrix} of parameter set of post signal price deltas} 11 | 12 | \item{obj.fun}{custom objective function for measuring signal goodness} 13 | 14 | \item{decreasing}{if \code{TRUE} (the default), larger objective function values are better} 15 | } 16 | \value{ 17 | objective function values 18 | } 19 | \description{ 20 | This function takes a list of matrix of post signal price changes and 21 | applies an user defined objective function on it. 22 | } 23 | \seealso{ 24 | \code{\link{apply.paramset.signal.analysis}} 25 | } 26 | \author{ 27 | Michael Guan 28 | } 29 | -------------------------------------------------------------------------------- /R/data.R: -------------------------------------------------------------------------------- 1 | #' AAPL time series of daily OHLCVA bars 2 | #' 3 | #' A dataset containing the daily OHLCVA values of AAPL from 2017-01-03 to 4 | #' 2018-12-28. The code to reproduce the dataset from yahoo is: 5 | #' 6 | #' getSymbols(symbol,from=start_date, to = end_date, auto.assign = T, index.class = "POSIXct", src = 'yahoo') 7 | #' for(i in symbols) assign(i, adjustOHLC(get(i),use.Adjusted=TRUE)) 8 | #' 9 | #' We have chosen to fix the dataset, since we have no control over changes at 10 | #' the source, which would break our tests. 11 | #' 12 | #' @usage data(AAPL) 13 | #' 14 | #' @format An xts object with 501 rows and 6 variables: 15 | #' \describe{ 16 | #' \item{Open}{Daily Open prices} 17 | #' \item{High}{Daily High prices} 18 | #' \item{Low}{Daily Low prices} 19 | #' \item{Close}{Daily Close prices} 20 | #' \item{Volume}{Aggregate Daily volume traded} 21 | #' \item{Adjusted}{Adjusted prices} 22 | #' } 23 | #' 24 | "AAPL" 25 | 26 | -------------------------------------------------------------------------------- /man/sigTimestamp.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/signals.R 3 | \name{sigTimestamp} 4 | \alias{sigTimestamp} 5 | \title{generate a signal on a timestamp} 6 | \usage{ 7 | sigTimestamp(label, data = mktdata, timestamp, on = "days") 8 | } 9 | \arguments{ 10 | \item{label}{text label to apply to the output} 11 | 12 | \item{data}{data to apply formula to} 13 | 14 | \item{timestamp}{either a POSIXct-based object, or a character string denoting a 24-hour time (e.g. "09:00", "16:00")} 15 | 16 | \item{on}{only used if \code{timestamp} is character; passed to \code{\link[xts]{split.xts}}, therefore \code{on} 17 | may be a character describing the time period as listed in \code{\link[xts]{endpoints}}, or a vector coercible to 18 | factor (e.g. \code{\link[xts]{.indexday}})} 19 | } 20 | \description{ 21 | This will generate a signal on a specific timestamp or at a specific time every day, week, weekday, etc. 22 | } 23 | -------------------------------------------------------------------------------- /man/initSymbol.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/initialize.R 3 | \name{initSymbol} 4 | \alias{initSymbol} 5 | \title{Run standard and custom symbol initialization functions} 6 | \usage{ 7 | initSymbol(strategy, symbol, ...) 8 | } 9 | \arguments{ 10 | \item{strategy}{an object (or the name of an object) of type 'strategy' to add the init function definition to} 11 | 12 | \item{symbol}{symbol} 13 | 14 | \item{\dots}{any other passthrough parameters} 15 | } 16 | \description{ 17 | \code{initSymbol} will load a symbol and run user-defined functions to pre-process the symbol's data 18 | before constructing indicators. 19 | } 20 | \details{ 21 | The custom initialization must be defined as named list containing 22 | \describe{ 23 | \item{name}{function name} 24 | \item{argument}{list of arguments} 25 | \item{enabled}{TRUE or FALSE} 26 | } 27 | and included as the slot \code{init_symbol} of the strategy object. 28 | } 29 | -------------------------------------------------------------------------------- /tests/testthat/test_demo_bbands.R: -------------------------------------------------------------------------------- 1 | # # A test for indicators, signals and rules using the bbands demo 2 | # # 3 | # # 4 | # 5 | # stopifnot(require(testthat)) 6 | # stopifnot(require(quantstrat)) 7 | # context("demo/bbands.R") 8 | # 9 | # devAskNewPage(ask = FALSE) # dont prompt for new page, mainly for R CMD check 10 | # source(paste0(path.package("quantstrat"),"/demo/bbands.R")) # source demo 11 | # 12 | # test_that("bbands End.Equity equals 9378", { 13 | # expect_equal(round(tradeStats('bbands','IBM')$End.Equity), 9378) 14 | # }) 15 | # 16 | # test_that("bbands num txns equals 340", { 17 | # expect_equal(nrow(getTxns('bbands','IBM')), 340) 18 | # }) 19 | # 20 | # test_that("macd num orders equals 340", { 21 | # expect_equal(nrow(as.data.frame(getOrderBook('bbands')[[1]])), 340) 22 | # }) 23 | # 24 | # # Commands for running this test file from the console if required: 25 | # # 26 | # # require(testthat) 27 | # # test_file("~/quantstrat/tests/testthat/test_demo_bbands.R") 28 | -------------------------------------------------------------------------------- /tests/testthat/test_demo_macd.R: -------------------------------------------------------------------------------- 1 | # # A test for indicators, signals and rules using the macd demo 2 | # # 3 | # # 4 | # 5 | # stopifnot(require(testthat)) 6 | # stopifnot(require(quantstrat)) 7 | # context("demo/macd.R") 8 | # 9 | # devAskNewPage(ask = FALSE) # dont prompt for new page, mainly for R CMD check 10 | # source(paste0(path.package("quantstrat"),"/demo/macd.R")) # source demo 11 | # 12 | # test_that("macd End.Equity equals 7202", { 13 | # expect_equal(round(tradeStats('macd','AAPL')$End.Equity), 7202) 14 | # }) 15 | # 16 | # test_that("macd num txns equals 38", { # one more than orders since we pad the start with zeros on 1950-01-01 17 | # expect_equal(nrow(getTxns('macd','AAPL')), 38) 18 | # }) 19 | # 20 | # test_that("macd num orders equals 37", { 21 | # expect_equal(nrow(obook$macd$AAPL), 37) 22 | # }) 23 | # 24 | # # Commands for running this test file from the console if required: 25 | # # 26 | # # require(testthat) 27 | # # test_file("~/quantstrat/tests/testthat/test_demo_macd.R") 28 | -------------------------------------------------------------------------------- /man/strategy.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/strategy.R 3 | \name{strategy} 4 | \alias{strategy} 5 | \title{constructor for objects of type 'strategy'} 6 | \usage{ 7 | strategy(name, ..., assets = NULL, constraints = NULL, store = FALSE) 8 | } 9 | \arguments{ 10 | \item{name}{character string naming the strategy} 11 | 12 | \item{...}{any other passthru parameters} 13 | 14 | \item{assets}{optional list of assets to apply the strategy to, should normally be defined in the portfolio, not here} 15 | 16 | \item{constraints}{optional portfolio constraints object matching assets} 17 | 18 | \item{store}{TRUE/FALSE whether to store the strategy in the .strategy environment, or return it. default FALSE} 19 | } 20 | \description{ 21 | variables passed in dots will be added to the strategy object, and may 22 | be used by initialization and wrapup functions, as well as 23 | indicators, signals, and rules. 24 | } 25 | \seealso{ 26 | \code{\link{applyStrategy}} 27 | } 28 | -------------------------------------------------------------------------------- /man/clone.orderbook.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/paramsets.R 3 | \name{clone.orderbook} 4 | \alias{clone.orderbook} 5 | \title{clone a orderbook object, potentially stripping all history} 6 | \usage{ 7 | clone.orderbook( 8 | orderbook.st, 9 | cloned.orderbook.st, 10 | strip.history = TRUE, 11 | src_envir = .strategy, 12 | target_envir = .strategy 13 | ) 14 | } 15 | \arguments{ 16 | \item{orderbook.st}{string identifying the source orderbook} 17 | 18 | \item{cloned.orderbook.st}{string naming the target orderbook} 19 | 20 | \item{strip.history}{boolean, default TRUE, whether to remove all orderbook history, keeping only the structure (e.g. assets)} 21 | 22 | \item{src_envir}{environment to get the source orderbook from, default \code{.strategy}} 23 | 24 | \item{target_envir}{environment to put the cloned orderbook in, passed to \code{\link{put.orderbook}}} 25 | } 26 | \description{ 27 | creates a copy of a orderbook, stripping all history (orders etc) 28 | } 29 | -------------------------------------------------------------------------------- /man/getOrderBook.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/orders.R 3 | \name{get.orderbook} 4 | \alias{get.orderbook} 5 | \alias{getOrderBook} 6 | \title{get the order book object} 7 | \usage{ 8 | get.orderbook(portfolio, envir = .strategy) 9 | } 10 | \arguments{ 11 | \item{portfolio}{text name of the portfolio the order book is associated with} 12 | 13 | \item{envir}{the environment to retrieve the orderbook object from, defaults to .strategy} 14 | } 15 | \value{ 16 | A \code{data.frame} containing: 17 | 18 | \describe{ 19 | \item{Order.Qty}{} 20 | \item{Order.Price}{} 21 | \item{Order.Type}{} 22 | \item{Order.Side}{} 23 | \item{Order.Threshold}{} 24 | \item{Order.Status}{} 25 | \item{Order.StatusTime}{} 26 | \item{Prefer}{} 27 | \item{Order.Set}{} 28 | \item{Txn.Fees}{} 29 | \item{Rule}{} 30 | } 31 | } 32 | \description{ 33 | get the order book object 34 | } 35 | \seealso{ 36 | addOrder 37 | 38 | getOrders 39 | } 40 | \concept{order book} 41 | -------------------------------------------------------------------------------- /man/applyIndicatorSignals.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/signals.R 3 | \name{applyIndicatorSignals} 4 | \alias{applyIndicatorSignals} 5 | \title{Calculate Indicators and Signals for a Strategy} 6 | \usage{ 7 | applyIndicatorSignals(strategy, portfolio, mktdata, sigcol, ...) 8 | } 9 | \arguments{ 10 | \item{strategy}{an object (or the name of an object) type 'strategy' to add the indicator to} 11 | 12 | \item{portfolio}{text name of the portfolio to associate the order book with} 13 | 14 | \item{mktdata}{market data} 15 | 16 | \item{sigcol}{String name of signal to use for analysis} 17 | 18 | \item{...}{any other passthru parameters} 19 | } 20 | \value{ 21 | \code{xts} object with columns representing signals for each symbol 22 | } 23 | \description{ 24 | Calculate signals given indicators and signal definitions. 25 | } 26 | \seealso{ 27 | \code{\link{apply.paramset.signal.analysis}} 28 | \code{\link{applyIndicators}} 29 | \code{\link{applySignals}} 30 | } 31 | \author{ 32 | Michael Guan 33 | } 34 | -------------------------------------------------------------------------------- /man/clone.portfolio.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/paramsets.R 3 | \name{clone.portfolio} 4 | \alias{clone.portfolio} 5 | \title{clone a portfolio object, potentially stripping all history} 6 | \usage{ 7 | clone.portfolio( 8 | portfolio.st, 9 | cloned.portfolio.st, 10 | strip.history = TRUE, 11 | src_envir = .blotter, 12 | target_envir = .blotter 13 | ) 14 | } 15 | \arguments{ 16 | \item{portfolio.st}{string identifying the source portfolio} 17 | 18 | \item{cloned.portfolio.st}{string naming the target portfolio} 19 | 20 | \item{strip.history}{boolean, default TRUE, whether to remove all transaction and portfolio history, keeping only the structure (e.g. assets)} 21 | 22 | \item{src_envir}{environment to get the portfolio to be cloned from, default \code{.blotter}} 23 | 24 | \item{target_envir}{environment to put the cloned portfolio in, passed to \code{\link[blotter]{put.portfolio}}} 25 | } 26 | \description{ 27 | creates a copy of a portfolio, stripping all history (transactions etc) 28 | } 29 | -------------------------------------------------------------------------------- /man/initOrders.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/orders.R 3 | \name{initOrders} 4 | \alias{initOrders} 5 | \title{initialize order container} 6 | \usage{ 7 | initOrders(portfolio = NULL, symbols = NULL, initDate = "1950-01-01", ...) 8 | } 9 | \arguments{ 10 | \item{portfolio}{text name of the portfolio to associate the order book with} 11 | 12 | \item{symbols}{a list of identifiers of the instruments to be contained in the Portfolio. The name of any associated price objects (xts prices, usually OHLC) should match these} 13 | 14 | \item{initDate}{date (ISO8601) prior to the first close price given in mktdata, used to initialize the order book with a dummy order} 15 | 16 | \item{\dots}{any other passthrough parameters} 17 | } 18 | \description{ 19 | This function sets up the order container by portfolio. 20 | } 21 | \details{ 22 | If no symbols list is provided (the default) the function will attempt 23 | to retrieve the symbols list from the portfolio in the trade blotter. 24 | } 25 | \concept{order book} 26 | -------------------------------------------------------------------------------- /man/osNoOp.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/osFUNs.R 3 | \name{osNoOp} 4 | \alias{osNoOp} 5 | \title{default order sizing function} 6 | \usage{ 7 | osNoOp(timestamp, orderqty, portfolio, symbol, ruletype, ...) 8 | } 9 | \arguments{ 10 | \item{timestamp}{timestamp coercible to POSIXct that will be the time the order will be inserted on} 11 | 12 | \item{orderqty}{numeric quantity of the desired order, modified by osFUN} 13 | 14 | \item{portfolio}{text name of the portfolio to place orders in} 15 | 16 | \item{symbol}{identifier of the instrument to place orders for. The name of any associated price objects (xts prices, usually OHLC) should match these} 17 | 18 | \item{ruletype}{one of "risk","order","rebalance","exit","enter", see \code{\link{add.rule}}} 19 | 20 | \item{...}{any other passthru parameters} 21 | } 22 | \description{ 23 | default function performs no operation (NoOp), returns orderqty 24 | } 25 | \details{ 26 | if orderqty 'all', will only work on an exit rule type, otherwize orderqty is zero. 27 | } 28 | -------------------------------------------------------------------------------- /man/sigThreshold.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/signals.R 3 | \name{sigThreshold} 4 | \alias{sigThreshold} 5 | \title{generate a threshold signal} 6 | \usage{ 7 | sigThreshold( 8 | label, 9 | data = mktdata, 10 | column, 11 | threshold = 0, 12 | relationship = c("gt", "lt", "eq", "gte", "lte"), 13 | cross = FALSE 14 | ) 15 | } 16 | \arguments{ 17 | \item{label}{text label to apply to the output} 18 | 19 | \item{data}{data to apply comparison to} 20 | 21 | \item{column}{named column to apply comparison to} 22 | 23 | \item{threshold}{numeric threshold to test for} 24 | 25 | \item{relationship}{one of c("gt","lt","eq","gte","lte") or reasonable alternatives} 26 | 27 | \item{cross}{if TRUE, will return TRUE only for the first observation to cross the threshold in a run} 28 | } 29 | \description{ 30 | Many strategies, including RSI or MACD styles, make trading decisions when an indicator 31 | is over or under a specific threshold. 32 | This function generates the appropriate signal based on such a threshold. 33 | } 34 | -------------------------------------------------------------------------------- /man/AAPL.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{AAPL} 5 | \alias{AAPL} 6 | \title{AAPL time series of daily OHLCVA bars} 7 | \format{ 8 | An xts object with 501 rows and 6 variables: 9 | \describe{ 10 | \item{Open}{Daily Open prices} 11 | \item{High}{Daily High prices} 12 | \item{Low}{Daily Low prices} 13 | \item{Close}{Daily Close prices} 14 | \item{Volume}{Aggregate Daily volume traded} 15 | \item{Adjusted}{Adjusted prices} 16 | } 17 | } 18 | \usage{ 19 | data(AAPL) 20 | } 21 | \description{ 22 | A dataset containing the daily OHLCVA values of AAPL from 2017-01-03 to 23 | 2018-12-28. The code to reproduce the dataset from yahoo is: 24 | } 25 | \details{ 26 | getSymbols(symbol,from=start_date, to = end_date, auto.assign = T, index.class = "POSIXct", src = 'yahoo') 27 | for(i in symbols) assign(i, adjustOHLC(get(i),use.Adjusted=TRUE)) 28 | 29 | We have chosen to fix the dataset, since we have no control over changes at 30 | the source, which would break our tests. 31 | } 32 | \keyword{datasets} 33 | -------------------------------------------------------------------------------- /man/enable.rule.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/rules.R 3 | \name{enable.rule} 4 | \alias{enable.rule} 5 | \title{enable a rule in the strategy} 6 | \usage{ 7 | enable.rule( 8 | strategy, 9 | type = c(NULL, "risk", "order", "rebalance", "exit", "enter", "chain"), 10 | label, 11 | enabled = TRUE, 12 | store = FALSE 13 | ) 14 | } 15 | \arguments{ 16 | \item{strategy}{an object of type 'strategy' which contains the rule} 17 | 18 | \item{type}{one of "risk","order","rebalance","exit","enter","chain"} 19 | 20 | \item{label}{the label for the rule; grep will be used to match, so multiple rules may be enabled (disabled) as a result} 21 | 22 | \item{enabled}{TRUE/FALSE whether the rule is enabled for use in applying the strategy, default TRUE} 23 | 24 | \item{store}{TRUE/FALSE whether to store the updated strategy in the .strategy environment, or return it. default FALSE} 25 | } 26 | \description{ 27 | function to make it easy to enable (or disable) a specific rule in a strategy 28 | } 29 | \seealso{ 30 | \code{\link{add.rule}} \code{\link{applyStrategy}} 31 | } 32 | -------------------------------------------------------------------------------- /man/signal.obj.slope.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/signals.R 3 | \name{signal.obj.slope} 4 | \alias{signal.obj.slope} 5 | \title{Signal Objective Function} 6 | \usage{ 7 | signal.obj.slope(x) 8 | } 9 | \arguments{ 10 | \item{x}{Return matrix, each row represents price deltas for a single signal, each column represents periods} 11 | } 12 | \value{ 13 | Single Objective Value 14 | } 15 | \description{ 16 | Simple example of objective function that can can be used to measure the effectiveness of various parameter combinations. 17 | } 18 | \details{ 19 | Calculates the slope of the Cumulative Equity line. Higher the better. 20 | 21 | It is important to note that all objective functions are called within \code{signal.generate.statistics}. What gets 22 | passed in to it as parameter is an matrix of post signal price changes or cumulative equity for each signal. The matrix 23 | is of N-by-M dimensions. N being the row representing the Nth signal. M being the column representing Mth period. 24 | } 25 | \seealso{ 26 | \code{\link{apply.paramset.signal.analysis}} 27 | } 28 | \author{ 29 | Michael Guan 30 | } 31 | -------------------------------------------------------------------------------- /man/install.param.combo.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/paramsets.R 3 | \name{install.param.combo} 4 | \alias{install.param.combo} 5 | \title{insert a specific parameter combo into a strategy object} 6 | \usage{ 7 | install.param.combo(strategy, param.combo, paramset.label) 8 | } 9 | \arguments{ 10 | \item{strategy}{strategy object} 11 | 12 | \item{param.combo}{single parameter combination to be inserted} 13 | 14 | \item{paramset.label}{label for the paramset to use to determine slot locations inside the strategy object} 15 | } 16 | \description{ 17 | In order to test \code{\link{applyStrategy}} with a specific parameter 18 | combination, it is necessary to insert those parameters into a copy of the 19 | strategy specification object. 20 | } 21 | \details{ 22 | This internal, non-exported function examines the paramset specification, 23 | and then uses that to insert the chosen parameters into a copy of the strategy 24 | object. It will search the strategy object, component by component, and 25 | attempt to locate the components named in the paramset, so that the individual 26 | parameter values may be changed. 27 | } 28 | -------------------------------------------------------------------------------- /man/applySignals.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/signals.R 3 | \name{applySignals} 4 | \alias{applySignals} 5 | \title{apply the signals in the strategy to arbitrary market data} 6 | \usage{ 7 | applySignals(strategy, mktdata, indicators = NULL, parameters = NULL, ...) 8 | } 9 | \arguments{ 10 | \item{strategy}{an object of type 'strategy' to add the signal to} 11 | 12 | \item{mktdata}{an xts object containing market data. depending on signals, may need to be in OHLCV or BBO formats} 13 | 14 | \item{indicators}{if indicator output is not contained in the mktdata object, it may be passed separately as an xts object or a list.} 15 | 16 | \item{parameters}{named list of parameters to be applied during evaluation of the strategy} 17 | 18 | \item{...}{any other passthru parameters} 19 | } 20 | \description{ 21 | This funcion is called internally by \code{\link{applyStrategy}} in normal 22 | operation, but it is also useful for nanual testing during development. 23 | 24 | If you are using this function to test your strategy, note that the 'mktdata' 25 | argument should likely contain the output of \code{\link{applyIndicators}}. 26 | } 27 | -------------------------------------------------------------------------------- /demo/demo_test_blotter_break.R: -------------------------------------------------------------------------------- 1 | # demo script for testing purposes 2 | 3 | Sys.setenv(TZ = "GMT") 4 | require(blotter) 5 | require(testthat) 6 | 7 | port = "testBreak" 8 | acct = "testBreak" 9 | symbol = c("IBM") 10 | 11 | data(IBM) 12 | 13 | startDate = first(index(IBM)) 14 | endDate = last(index(IBM)) 15 | 16 | lines = "date,shrs,price,symbol 17 | 2007-01-10,100,98.0,IBM 18 | 2007-01-16,-200,99.5,IBM 19 | 2007-01-17,150,99.45,IBM 20 | 2007-01-18,-50,99.0,IBM" 21 | con = textConnection(lines) 22 | tt.trades = read.csv(con, as.is = TRUE) 23 | 24 | tt.trades[,"date"] = make.time.unique(as.POSIXct(tt.trades[,"date"])) 25 | 26 | currency("USD") 27 | stock(symbol,"USD") 28 | 29 | initPortf(port, 30 | symbol, 31 | initDate = startDate) 32 | initAcct(port, 33 | portfolios = c(port), 34 | initDate = startDate, 35 | initEq=10^6) 36 | 37 | for(i in 1:nrow(tt.trades)){ 38 | addTxn(port,Symbol = tt.trades[i,"symbol"], 39 | TxnDate = tt.trades[i,"date"], 40 | TxnPrice = tt.trades[i,"price"], 41 | TxnQty = tt.trades[i,"shrs"]) 42 | } 43 | 44 | updatePortf(port) 45 | updateAcct(acct) 46 | updateEndEq(acct) 47 | -------------------------------------------------------------------------------- /demo/luxor.getSymbols.R: -------------------------------------------------------------------------------- 1 | #!/usr/bin/Rscript --vanilla 2 | # 3 | # Jan Humme (@opentrades) - August 2012, revised April 2013 4 | # 5 | # Tested and found to work correctly using blotter r1457 6 | # 7 | # After Jaekle & Tamasini: A new approach to system development and portfolio optimisation (ISBN 978-1-905641-79-6) 8 | # 9 | # loading symbol data 10 | 11 | Sys.setenv(TZ="UTC") 12 | 13 | ### packages 14 | # 15 | # quantstrat package will pull in some other packages: 16 | # FinancialInstrument, quantmod, blotter, xts 17 | 18 | require(quantstrat) 19 | 20 | ### FinancialInstrument 21 | 22 | currency(c('GBP', 'USD')) 23 | 24 | exchange_rate('GBPUSD', tick_size=0.0001) 25 | 26 | ### quantmod 27 | 28 | getSymbols.FI(Symbols='GBPUSD', 29 | dir=system.file('extdata',package='quantstrat'), 30 | # dir='~/R/OHLC', 31 | from=.from, to=.to 32 | , extension = 'rda' 33 | , use_identifier=NA 34 | ) 35 | 36 | # ALTERNATIVE WAY TO FETCH SYMBOL DATA 37 | #setSymbolLookup.FI(system.file('extdata',package='quantstrat'), 'GBPUSD') 38 | #getSymbols('GBPUSD', from=.from, to=.to, verbose=FALSE) 39 | 40 | ### xts 41 | 42 | GBPUSD = to.minutes30(GBPUSD) 43 | GBPUSD = align.time(GBPUSD, 1800) 44 | 45 | -------------------------------------------------------------------------------- /man/sigComparison.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/signals.R 3 | \name{sigComparison} 4 | \alias{sigComparison} 5 | \title{generate comparison signal} 6 | \usage{ 7 | sigComparison( 8 | label, 9 | data = mktdata, 10 | columns, 11 | relationship = c("gt", "lt", "eq", "gte", "lte"), 12 | offset1 = 0, 13 | offset2 = 0 14 | ) 15 | } 16 | \arguments{ 17 | \item{label}{text label to apply to the output} 18 | 19 | \item{data}{data to apply comparison to} 20 | 21 | \item{columns}{named columns to apply comparison to} 22 | 23 | \item{relationship}{one of c("gt","lt","eq","gte","lte","op") or reasonable alternatives} 24 | 25 | \item{offset1}{numeric offset to be added to the first column prior to comparison} 26 | 27 | \item{offset2}{numeric offset to be added to the second column prior to comparison} 28 | } 29 | \description{ 30 | Currently, this function compares two columns. 31 | Patches to compare an arbitrary number of columns would be gladly accepted. 32 | } 33 | \details{ 34 | Comparison will be applied from the first to the second column in the \code{columns} vector. 35 | 36 | Relationship 'op' means 'opposite' side. Reasonable attempt will be made to match. 37 | } 38 | -------------------------------------------------------------------------------- /man/paramConstraint.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/parameters.R 3 | \name{paramConstraint} 4 | \alias{paramConstraint} 5 | \title{Internal function used in applyParameter function for process constraints on relationship between two parameter values. (deprecated)} 6 | \usage{ 7 | paramConstraint( 8 | label, 9 | data = mktdata, 10 | columns, 11 | relationship = c("gt", "lt", "eq", "gte", "lte", "op") 12 | ) 13 | } 14 | \arguments{ 15 | \item{label}{text label to apply to the constraint} 16 | 17 | \item{data}{data to apply comparison to} 18 | 19 | \item{columns}{named columns to apply comparison to} 20 | 21 | \item{relationship}{one of c("gt","lt","eq","gte","lte","op") or reasonable alternatives} 22 | } 23 | \description{ 24 | Basically is the same as sigComparison function in signal.R written by Brian, with minor change. 25 | } 26 | \details{ 27 | Currently, this function compares two columns. 28 | Patches to compare an arbitrary number of columns would be gladly accepted. 29 | 30 | Comparison will be applied from the first to the second column in the \code{columns} vector. 31 | 32 | Relationship 'op' means 'opposite' side. Reasonable attempt will be made to match. 33 | } 34 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: quantstrat 2 | Type: Package 3 | Title: Quantitative Strategy Model Framework 4 | Version: 0.25 5 | Date: 2023-01-24 $Date$ 6 | Author: Brian G. Peterson, Joshua Ulrich, Jasen Mackie, Jan Humme, Peter Carl 7 | Depends: 8 | R(>= 4.0), 9 | quantmod, 10 | xts(>= 0.10), 11 | blotter(>= 0.14.0), 12 | FinancialInstrument(>= 0.12.5), 13 | foreach(>= 1.4.0) 14 | Imports: 15 | methods, 16 | iterators, 17 | zoo, 18 | TTR, 19 | MASS 20 | Suggests: 21 | PerformanceAnalytics, 22 | PortfolioAnalytics, 23 | rgl, 24 | testthat, 25 | rCharts, 26 | gamlss, 27 | reshape2, 28 | beanplot, 29 | knitr, 30 | rmarkdown, 31 | pander, 32 | xtable, 33 | covr, 34 | usethis, 35 | AlgDesign 36 | Remotes: 37 | github::braverock/blotter 38 | Maintainer: Brian G. Peterson 39 | Description: Specify, build, and back-test quantitative 40 | financial trading and portfolio strategies. 41 | Contributors: Yu Chen, Joe Dunn, Dirk Eddelbuettel, 42 | Michael Guan, Jeffrey A. Ryan, Garrett See 43 | LazyLoad: yes 44 | License: GPL-3 45 | Copyright: (c) 2009-2019 46 | ByteCompile: TRUE 47 | Encoding: UTF-8 48 | RoxygenNote: 7.1.2 49 | VignetteBuilder: knitr 50 | -------------------------------------------------------------------------------- /man/post.signal.returns.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/signals.R 3 | \name{post.signal.returns} 4 | \alias{post.signal.returns} 5 | \title{Generate Post Signal Returns} 6 | \usage{ 7 | post.signal.returns( 8 | signals, 9 | sigval, 10 | on = NULL, 11 | forward.days, 12 | cum.sum = TRUE, 13 | include.day.of.signal = FALSE, 14 | mktdata = NULL 15 | ) 16 | } 17 | \arguments{ 18 | \item{signals}{xts object with signals, one column} 19 | 20 | \item{sigval}{signal value to match against} 21 | 22 | \item{on}{the periods endpoints to find as a character string} 23 | 24 | \item{forward.days}{number of days to look forward after signal (days to exit post signal)} 25 | 26 | \item{cum.sum}{\code{TRUE},\code{FALSE}; cumulative sum of price changes} 27 | 28 | \item{include.day.of.signal}{whether to analyze the return on signal day} 29 | 30 | \item{mktdata}{market data} 31 | } 32 | \value{ 33 | \code{matrix} of post signal price changes; rows = nth signal, column = nth period since signal 34 | } 35 | \description{ 36 | This function collects and aggregates post signal price changes for N days forward. 37 | } 38 | \seealso{ 39 | \code{\link{apply.paramset.signal.analysis}} 40 | } 41 | \author{ 42 | Michael Guan 43 | } 44 | -------------------------------------------------------------------------------- /man/sigCrossover.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/signals.R 3 | \name{sigCrossover} 4 | \alias{sigCrossover} 5 | \title{generate a crossover signal} 6 | \usage{ 7 | sigCrossover( 8 | label, 9 | data = mktdata, 10 | columns, 11 | relationship = c("gt", "lt", "eq", "gte", "lte"), 12 | offset1 = 0, 13 | offset2 = 0 14 | ) 15 | } 16 | \arguments{ 17 | \item{label}{text label to apply to the output} 18 | 19 | \item{data}{data to apply crossover to} 20 | 21 | \item{columns}{named columns to apply crossover of the first against the second} 22 | 23 | \item{relationship}{one of c("gt","lt","eq","gte","lte") or reasonable alternatives} 24 | 25 | \item{offset1}{numeric offset to be added to the first column prior to comparison} 26 | 27 | \item{offset2}{numeric offset to be added to the second column prior to comparison} 28 | } 29 | \description{ 30 | This will generate a crossover signal, which is a dimension-reduced version 31 | of a comparison signal \code{\link{sigComparison}}. 32 | } 33 | \details{ 34 | It will return TRUE on the period in which there is a crossover in the 35 | direction specified by \code{relationship}, and NA otherwise. 36 | 37 | If you want all the information, use a comparison instead. 38 | } 39 | -------------------------------------------------------------------------------- /man/distributional.boxplot.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/signals.R 3 | \name{distributional.boxplot} 4 | \alias{distributional.boxplot} 5 | \title{Visualization of Single Signal} 6 | \usage{ 7 | distributional.boxplot( 8 | signal, 9 | x.val = seq(1, 50, 5), 10 | val = 10, 11 | ylim = c(-5, 5), 12 | xlim = c(0, 50), 13 | mai = c(1, 1, 0.3, 0.5), 14 | h = 0, 15 | ... 16 | ) 17 | } 18 | \arguments{ 19 | \item{signal}{list of paramset forward looking price changes by asset} 20 | 21 | \item{x.val}{he values of the explanatory variable where we want to see the distribution} 22 | 23 | \item{val}{this parameter determines how the plotted distribution is shown, increase/decrease it if the distribution is not shown properly} 24 | 25 | \item{ylim}{the y limits in the plot} 26 | 27 | \item{xlim}{the x limits in the plot} 28 | 29 | \item{mai}{A numerical vector of the form c(bottom, left, top, right) which gives the margin size specified in inches.} 30 | 31 | \item{h}{the y-value(s) for horizontal line(s).} 32 | 33 | \item{...}{any other passthru parameters} 34 | } 35 | \value{ 36 | plot 37 | } 38 | \description{ 39 | This function employs \code{plotSimpleGamlss} in package \code{gamlss.util}. 40 | } 41 | \author{ 42 | Michael Guan 43 | } 44 | -------------------------------------------------------------------------------- /demo/luxor.sample.tradeGraphs.timespan.R: -------------------------------------------------------------------------------- 1 | #!/usr/bin/Rscript --vanilla 2 | # 3 | # Jan Humme (@opentrades) - August 2012, revised April 2013 4 | # 5 | # Tested and found to work correctly using blotter r1457 6 | # 7 | # After Jaekle & Tamasini: A new approach to system development and portfolio optimisation (ISBN 978-1-905641-79-6) 8 | # 9 | # 3D timespan graph example 10 | 11 | require(quantstrat) 12 | require(rgl) 13 | 14 | load(paste0( 15 | path.package('quantstrat'), 16 | '/data/luxor.timespan.24x24.2002-2008.RData') 17 | ) 18 | 19 | names(stats)[names(stats)=='testPackListPRL[[k]]$parameters']<-'timespan' 20 | 21 | stats$tmp = strsplit(as.character(stats$timespan),'/') 22 | 23 | stats$from<-sapply(stats$tmp,FUN='[',1) 24 | stats$to<-sapply(stats$tmp,FUN='[',2) 25 | 26 | stats$start<-as.numeric(gsub('T([0-9]+):[0-9]+',x=stats$from,'\\1')) 27 | stats$stop<-(as.numeric(gsub('T([0-9]+):[0-9]+',x=stats$to,'\\1'))+1)%%24 28 | 29 | # trading data is in EST (GMT-4): move 4 hours to adjust to GMT 30 | #stats$start<-(stats$start+4)%%24 31 | #stats$stop<-(stats$stop+4)%%24 32 | 33 | tradeGraphs( 34 | stats, 35 | free.params=c('start','stop'), 36 | statistics=c('Net.Trading.PL','maxDrawdown',"Avg.Trade.PL",'Num.Trades',"Profit.Factor"), 37 | title = 'Luxor Intraday TimeWindow Scan' 38 | ) 39 | -------------------------------------------------------------------------------- /man/tradeGraphs.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/tradeGraphs.R 3 | \name{tradeGraphs} 4 | \alias{tradeGraphs} 5 | \title{Draw 3D graphs from tradeStats results using rgl} 6 | \usage{ 7 | tradeGraphs(stats, free.params, params.filter = NULL, statistics, title = NULL) 8 | } 9 | \arguments{ 10 | \item{stats}{a data frame generated by tradeStats()} 11 | 12 | \item{free.params}{a vector of length 2, containing the column names for the data to use on the x and z axes} 13 | 14 | \item{params.filter}{- a regular expression to reduce dimensions by filtering on certain columns} 15 | 16 | \item{statistics}{a vector containing the column names to produce graphs for} 17 | 18 | \item{title}{an optional title to be printed above each graph} 19 | } 20 | \value{ 21 | invisible -- called for side-effect 22 | } 23 | \description{ 24 | Draw 3D graphs from tradeStats results using rgl 25 | } 26 | \examples{ 27 | \dontrun{ 28 | tradeGraphs ( 29 | stats = stats, 30 | free.params = c("Param.indicator.1.nFast", "Param.indicator.2.nSlow"), 31 | params.filter = "Param.indicator.2.nSlow < 40 & Param.indicator.1.nFast > 5" 32 | statistics = c("Net.Trading.PL", "maxDrawdown", "Avg.Trade.PL", "Num.Trades") 33 | title = 'Luxor' 34 | ) 35 | } 36 | } 37 | \author{ 38 | Jan Humme, rewritten by Chinmay Patil 39 | } 40 | -------------------------------------------------------------------------------- /man/match.names.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/match.names.R 3 | \name{match.names} 4 | \alias{match.names} 5 | \title{match names in data to a list of partial name matches} 6 | \usage{ 7 | match.names(match_names, data_names) 8 | } 9 | \arguments{ 10 | \item{match_names}{names to match} 11 | 12 | \item{data_names}{names for the data to be matched to} 13 | } 14 | \description{ 15 | Often, the generic definition of a signal or indicator will include 16 | partial name matches. In financial data, common partial matches include 17 | 'Close', 'Open', and 'Volume', but there are many more. 18 | } 19 | \details{ 20 | In complex data, additional name information may be added to column names 21 | for example, a symbol or an indicator of some adjustment may be added. 22 | 23 | This small utility exists to do the matching in a centralized location 24 | so that more robust error handling and reporting can be conducted. 25 | 26 | The process to be followed is that first, \code{\link{grep}} will 27 | be called without modification, assuming that a unique match has 28 | been supplied by the user. If this fails, a match will be attempted 29 | by appending '$' to the regex, searching for a match at the end of the 30 | column name, as would be constructed by the \code{\link{paste}} in 31 | e.g. \code{\link{applyIndicators}}. 32 | } 33 | -------------------------------------------------------------------------------- /demo/luxor.3.paramset.sma.R: -------------------------------------------------------------------------------- 1 | #!/usr/bin/Rscript --vanilla 2 | # 3 | # Jan Humme (@opentrades) - August 2012, revised April 2013 4 | # 5 | # Tested and found to work correctly using blotter r1457 6 | # 7 | # After Jaekle & Tamasini: A new approach to system development and portfolio optimisation (ISBN 978-1-905641-79-6) 8 | # 9 | # Paragraph 3.3: luxor SMA paramset optimization 10 | 11 | ### 12 | require(quantstrat) 13 | 14 | source(paste0(path.package("quantstrat"),"/demo/luxor.include.R")) 15 | source(paste0(path.package("quantstrat"),"/demo/luxor.getSymbols.R")) 16 | 17 | ### blotter 18 | 19 | initPortf(portfolio.st, symbols='GBPUSD', currency='USD') 20 | initAcct(account.st, portfolios=portfolio.st, currency='USD') 21 | 22 | ### quantstrat 23 | 24 | initOrders(portfolio.st) 25 | 26 | load.strategy(strategy.st) 27 | 28 | ### doMC 29 | if (!"doMC" %in% installed.packages()[,1]) { 30 | install.packages("doMC") 31 | } 32 | require(doMC) 33 | registerDoMC(cores=8) 34 | 35 | #require(doParallel) 36 | #registerDoParallel(cores=2) 37 | 38 | #require(doRedis) 39 | #registerDoRedis('jobs') 40 | 41 | results <- apply.paramset(strategy.st, paramset.label='SMA', portfolio.st=portfolio.st, account.st=account.st, nsamples=.nsamples, verbose=TRUE) 42 | 43 | ### 44 | 45 | stats <- results$tradeStats 46 | 47 | print(stats) 48 | 49 | save(stats, file='luxor.3.paramset.sma.RData') 50 | 51 | -------------------------------------------------------------------------------- /man/getParameterTable.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/parameters.R 3 | \name{getParameterTable} 4 | \alias{getParameterTable} 5 | \title{Extract the parameter structure from a strategy object. (deprecated)} 6 | \usage{ 7 | getParameterTable(strategy) 8 | } 9 | \arguments{ 10 | \item{strategy}{The strategy object.} 11 | } 12 | \value{ 13 | A list of objects that contains the parameter structure information 14 | \describe{ 15 | \item{paramNameList}{the list of parameters used in the strategy, for printing or viewing as a table.} 16 | \item{strategyName}{ string name of the strategy} 17 | \item{structure}{the detailed paramter structure in the input strategy, can be used when user wants to look into more details of the parameter structure.} 18 | } 19 | } 20 | \description{ 21 | Users can use this function to extract the parameters used in a strategy, and use the output as a reminder/ cheatsheet 22 | when they create the parameter distribution or parameter constraints. But it's not required to run to specify the distribution or constraints of parameters. 23 | } 24 | \examples{ 25 | # When strategy object stratMACD has already been created by demo macd.R: 26 | # following line will return object x that contains the parameter information. 27 | \dontrun{ 28 | x<-getParameterTable(stratMACD) 29 | } 30 | } 31 | \author{ 32 | Yu Chen 33 | } 34 | -------------------------------------------------------------------------------- /demo/luxor.4.paramset.timespan.R: -------------------------------------------------------------------------------- 1 | #!/usr/bin/Rscript --vanilla 2 | # 3 | # Jan Humme (@opentrades) - August 2012, revised April 2013 4 | # 5 | # Tested and found to work correctly using blotter r1457 6 | # 7 | # After Jaekle & Tamasini: A new approach to system development and portfolio optimisation (ISBN 978-1-905641-79-6) 8 | # 9 | # Paragraph 3.4: luxor timespan paramset optimization 10 | 11 | require(quantstrat) 12 | 13 | source(paste0(path.package("quantstrat"),"/demo/luxor.include.R")) 14 | source(paste0(path.package("quantstrat"),"/demo/luxor.getSymbols.R")) 15 | 16 | ### blotter 17 | 18 | initPortf(portfolio.st, symbols='GBPUSD', currency='USD') 19 | initAcct(account.st, portfolios=portfolio.st, currency='USD') 20 | 21 | ### quantstrat 22 | 23 | initOrders(portfolio.st) 24 | 25 | load.strategy(strategy.st) 26 | 27 | ### doMC 28 | if (!"doMC" %in% installed.packages()[,1]) { 29 | install.packages("doMC") 30 | } 31 | require(doMC) 32 | registerDoMC(cores=8) 33 | 34 | #require(doParallel) 35 | #registerDoParallel(cores=2) 36 | 37 | #require(doRedis) 38 | #registerDoRedis('jobs') 39 | 40 | results <- apply.paramset(strategy.st, paramset.label='Timespan', portfolio.st=portfolio.st, account.st=account.st, nsamples=.nsamples, verbose=TRUE) 41 | 42 | ### 43 | 44 | stats <- results$tradeStats 45 | 46 | print(stats) 47 | 48 | save(stats, file='luxor.4.paramset.timespan.RData') 49 | 50 | -------------------------------------------------------------------------------- /tests/testthat/test_paramsets.R: -------------------------------------------------------------------------------- 1 | require(testthat) 2 | context("paramset warnings") 3 | 4 | options(in_test=TRUE) 5 | 6 | require(quantstrat) 7 | strategy.st <- "paramset_test" 8 | strategy(strategy.st, store=TRUE) 9 | .timespans <- c("T08:00/T10:00") 10 | 11 | add.distribution(strategy.st, 12 | paramset.label = 'Timespan', 13 | component.type = 'enter', 14 | component.label = 'EnterLONG', 15 | variable = list(timespan = .timespans), 16 | label = 'Timespan') 17 | 18 | test_that("Replacing paramset distribution warns", expect_warning({ 19 | add.distribution(strategy.st, 20 | paramset.label = 'Timespan', 21 | component.type = 'enter', 22 | component.label = 'EnterLONG', 23 | variable = list(timespan = .timespans), 24 | label = 'Timespan') 25 | })) 26 | 27 | add.distribution.constraint(strategy.st, 28 | paramset.label = 'Timespan', 29 | distribution.label.1 = 'EnterLong', 30 | distribution.label.2 = 'EnterShort', 31 | operator = '==', 32 | label = 'Timespan') 33 | 34 | test_that("Replacing paramset constraint warns", expect_warning({ 35 | add.distribution.constraint(strategy.st, 36 | paramset.label = 'Timespan', 37 | distribution.label.1 = 'EnterLong', 38 | distribution.label.2 = 'EnterShort', 39 | operator = '==', 40 | label = 'Timespan') 41 | })) 42 | 43 | test_that("Deleting unknown paramset warns", expect_warning({ 44 | delete.paramset(strategy.st, "Timespans") 45 | })) 46 | 47 | -------------------------------------------------------------------------------- /man/add.distribution.constraint.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/paramsets.R 3 | \name{add.distribution.constraint} 4 | \alias{add.distribution.constraint} 5 | \title{Adds a constraint on 2 distributions within a paramset} 6 | \usage{ 7 | add.distribution.constraint( 8 | strategy, 9 | paramset.label, 10 | distribution.label.1, 11 | distribution.label.2, 12 | operator, 13 | label, 14 | store = TRUE 15 | ) 16 | } 17 | \arguments{ 18 | \item{strategy}{the name of the strategy object to add the constraint to} 19 | 20 | \item{paramset.label}{a label uniquely identifying the paramset within the strategy} 21 | 22 | \item{distribution.label.1}{a label identifying the first distribution} 23 | 24 | \item{distribution.label.2}{a label identifying the second distribution} 25 | 26 | \item{operator}{an operator specifying the relational constraint between the 2 distributions} 27 | 28 | \item{label}{a label uniquely identifying the constraint within the paramset} 29 | 30 | \item{store}{indicates whether to store the strategy in the .strategy environment} 31 | } 32 | \description{ 33 | Creates a constraint on 2 distributions in a paramset, i.e. a restriction limiting the allowed 34 | combinations from the ranges for distribution 1 and distribution 2. 35 | } 36 | \seealso{ 37 | \code{\link{add.distribution}}, 38 | \code{\link{delete.paramset}}, 39 | \code{\link{apply.paramset}} 40 | } 41 | \author{ 42 | Jan Humme 43 | } 44 | -------------------------------------------------------------------------------- /man/chart.forward.training.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/chart.forward.training.R 3 | \name{chart.forward.training} 4 | \alias{chart.forward.training} 5 | \title{Chart to analyse walk.forward() objective function} 6 | \usage{ 7 | chart.forward.training(audit.filename) 8 | } 9 | \arguments{ 10 | \item{audit.filename}{name of .audit environment file as produced by walk.forward(). 11 | Filename will match pattern [audit.prefix].[symbol].[start timestamp].[end timestamp].RData.} 12 | } 13 | \description{ 14 | The \code{\link{walk.forward}} function creates an audit environment, written 15 | out as a results file, which contains the out of sample results of the (chosen) 16 | parameter set. It also writes out in-sample audit environment files for each 17 | training period. 18 | } 19 | \details{ 20 | This function reads one of those training files and will construct a performance 21 | chart of the in-sample performance of all the parameter sets during the training 22 | period, including the in-sample performance of the chosen parameter set. 23 | 24 | Note that parameter \code{audit filename} may also be an audit environment 25 | which is already loaded in \R, for ease of development and debugging. Little 26 | checking is done to ensure the correct structure of this environment, so passing 27 | an unsuitable environment (such as the .blotter environment) will result in 28 | errors. 29 | } 30 | \seealso{ 31 | \code{\link{walk.forward}}, \code{\link{chart.forward}} 32 | } 33 | -------------------------------------------------------------------------------- /man/sigFormula.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/signals.R 3 | \name{sigFormula} 4 | \alias{sigFormula} 5 | \title{generate a signal from a formula} 6 | \usage{ 7 | sigFormula(label, data = mktdata, formula, cross = FALSE) 8 | } 9 | \arguments{ 10 | \item{label}{text label to apply to the output} 11 | 12 | \item{data}{data to apply formula to} 13 | 14 | \item{formula}{a logical expression like that used in an if statement, will typically reference column names in \code{mktdata}} 15 | 16 | \item{cross}{if TRUE, will return TRUE only for the first observation to match the formula in a run} 17 | } 18 | \description{ 19 | This code takes advantage of some base R functionality that can treat an R object (in this case the internal mktdata object in quantstrat) as an environment or 'frame' using \code{\link{parent.frame}}. 20 | This allows the columns of the data to be addressed without any major manipulation, simply by column name. In most cases in quantstrat, this will be either the price/return columns, or columns added by indicators or prior signals. 21 | The formula will return TRUE/FALSE for each row comparison as a time series column which can then be used for rule execution. The \code{formula} will be evaluated using \code{\link{eval}} as though in an if statement. 22 | } 23 | \details{ 24 | This code is adapted from the approach used by Vijay Vaidyanthan in his PAST(AAII/SIPRO) code to construct arbitrary, formulaic, comparisons. Many thanks to Vijay for sharing his expertise. 25 | } 26 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: r 2 | 3 | # dist: bionic 4 | 5 | # need sudo 6 | sudo: true 7 | 8 | # cache packages because devtools is a beast 9 | cache: packages 10 | 11 | # Be strict when checking our package 12 | warnings_are_errors: true 13 | 14 | # don't build the vignette 15 | r_build_args: "--no-build-vignettes" 16 | r_check_args: "--no-build-vignettes --ignore-vignettes --as-cran" 17 | 18 | # System dependencies 19 | #apt_packages: 20 | # - libcurl4-openssl-dev 21 | # - libxml2-dev 22 | 23 | before_install: 24 | # - Rscript -e 'install.packages(c("shiny","utf8","curl","openssl","git2r","rjsonio"),lib="/home/travis/R-bin/lib/R/library/")' 25 | - sudo add-apt-repository -ry ppa:marutter/rrutter4.0 26 | - sudo apt install libftgl2 libcgal-dev libglu1-mesa-dev libglu1-mesa-dev libx11-dev libfreetype6-dev 27 | 28 | # Binaries from Michael Rutter's ppa 29 | # r_binary_packages: 30 | # - magrittr 31 | # - ggplot2 32 | # - plyr 33 | # - Rcpp 34 | # - RCurl 35 | # # - shiny 36 | # - stringr 37 | # - stringi 38 | # - MASS 39 | # - RColorBrewer 40 | # # - utf8 41 | # - digest 42 | # - colorspace 43 | # # - curl 44 | # # - openssl 45 | # # - git2r 46 | # - foreach 47 | # - iterators 48 | # # - RJSONIO 49 | # - yaml 50 | # - testthat 51 | # - rgl 52 | 53 | # Done via install.packages 54 | #r_packages: 55 | 56 | # Install the bleeding edge version of a package from github (eg to pick 57 | # up a not-yet-released bugfix) 58 | r_github_packages: 59 | - joshuaulrich/xts 60 | - braverock/blotter 61 | - ramnathv/rCharts 62 | # - r-lib/covr 63 | 64 | after_success: 65 | - travis_wait 30 Rscript -e 'covr::codecov()' 66 | -------------------------------------------------------------------------------- /man/chart.forward.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/chart.forward.R 3 | \name{chart.forward} 4 | \alias{chart.forward} 5 | \title{Chart to analyse walk.forward() objective function} 6 | \usage{ 7 | chart.forward(audit.filename, portfolio.st = NULL) 8 | } 9 | \arguments{ 10 | \item{audit.filename}{name of .audit environment file as produced by \code{\link{walk.forward}} 11 | Filename will often match pattern [audit.prefix].results.RData. Alternately, an 12 | audit environment provided by the output of \code{\link{walk.forward}}} 13 | 14 | \item{portfolio.st}{string defining which portfolio should be used for out of sample, default NULL} 15 | } 16 | \description{ 17 | The \code{\link{walk.forward}} function creates an audit environment, potentially written 18 | out as a results file, which contains the out of sample results of the (chosen) 19 | parameter set. This function parses that file or environment and generates a chart to 20 | compare the performance of all parameter sets against the optimal one. 21 | } 22 | \details{ 23 | \code{\link{chart.forward.training}} uses the audit environment for a single 24 | in-sample training period to draw a chart for that in-sample data. 25 | 26 | Note that parameter \code{audit filename} may also be an audit environment 27 | which is already loaded in \R, for ease of development and debugging. Little 28 | checking is done to ensure the correct structure of this environment, so passing 29 | an unsuitable environment (such as the .blotter environment) will result in 30 | errors. 31 | } 32 | \seealso{ 33 | \code{\link{walk.forward}}, \code{\link{chart.forward.training}} 34 | } 35 | -------------------------------------------------------------------------------- /man/applyStrategy.rebalancing.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/applyStrategy.rebalancing.R 3 | \name{applyStrategy.rebalancing} 4 | \alias{applyStrategy.rebalancing} 5 | \title{apply the strategy to arbitrary market data, with periodic rebalancing} 6 | \usage{ 7 | applyStrategy.rebalancing( 8 | strategy, 9 | portfolios, 10 | mktdata = NULL, 11 | parameters = NULL, 12 | ..., 13 | verbose = TRUE, 14 | symbols = NULL, 15 | initStrat = FALSE, 16 | updateStrat = FALSE 17 | ) 18 | } 19 | \arguments{ 20 | \item{strategy}{an object of type 'strategy' or the name of a stored strategy to apply} 21 | 22 | \item{portfolios}{a list of portfolios to apply the strategy to} 23 | 24 | \item{mktdata}{an xts object containing market data. depending on indicators, may need to be in OHLCV or BBO formats, default NULL} 25 | 26 | \item{parameters}{named list of parameters to be applied during evaluation of the strategy, default NULL} 27 | 28 | \item{...}{any other passthru parameters} 29 | 30 | \item{verbose}{if TRUE, return output list} 31 | 32 | \item{symbols}{character vector identifying symbols to initialize a portfolio for, default NULL} 33 | 34 | \item{initStrat}{whether to use (experimental) initialization code, default FALSE} 35 | 36 | \item{updateStrat}{whether to use (experimental) wrapup code, default FALSE} 37 | } 38 | \description{ 39 | This function is the wrapper that holds together the execution of a strategy with rebalancing rules. 40 | } 41 | \seealso{ 42 | \code{\link{strategy}}, \code{\link{applyIndicators}}, 43 | \code{\link{applySignals}}, \code{\link{applyRules}}, 44 | \code{\link{initStrategy}}, \code{\link{applyStrategy}} 45 | } 46 | -------------------------------------------------------------------------------- /tests/testthat/test_demo_macdParameters.R: -------------------------------------------------------------------------------- 1 | # A test for apply.paramset() using the macdParameters demo 2 | # 3 | # 4 | 5 | options(warn=-1) 6 | stopifnot(require(testthat)) 7 | stopifnot(require(quantstrat)) 8 | context("deom/macdParameters.R") 9 | 10 | source(paste0(path.package("quantstrat"),"/demo/macdParameters.R")) 11 | 12 | test_that("results environment has 33 objects", { 13 | expect_equal(length(results), 33) 14 | }) 15 | 16 | # Cannot test End.Equity since we use a random sample of all possible parameter combinations, 17 | # but testing for the number of objects in results should suffice to identify breaking 18 | # apply.paramset() code 19 | # 20 | # Since we call various overfitting functions in this demo, we could test those results 21 | # too, in order to catch other hidden errors related to those functions, namely: 22 | # 23 | # 1. degrees.of.freedom() 24 | # 2. SharpeRatio.deflated() 25 | # 3. SharpeRatio.haircut() 26 | # 27 | # However, for the same reason we cannot test End.Equity, we cannot test asserts for actual 28 | # values returned by the overfitting functions so we will limit the test to number of 29 | # objects returned. Since these functions are mostly complete, these tests should not need 30 | # to be modified in the foreseeable future 31 | 32 | test_that("df list has 12 objects", { 33 | expect_equal(length(df), 12) 34 | }) 35 | 36 | test_that("defSR list has 5 objects", { 37 | expect_equal(length(defSR), 5) 38 | }) 39 | 40 | test_that("hcSR list has 16 objects", { 41 | expect_equal(length(hcSR), 16) 42 | }) 43 | 44 | # Commands for running this test file from the console if required: 45 | # 46 | # require(testthat) 47 | # test_file("~/quantstrat/tests/testthat/test_demo_macdParameters.R") 48 | -------------------------------------------------------------------------------- /man/getOrders.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/orders.R 3 | \name{getOrders} 4 | \alias{getOrders} 5 | \title{get orders by time span, status, type, and side} 6 | \usage{ 7 | getOrders( 8 | portfolio, 9 | symbol, 10 | status = "open", 11 | timespan = NULL, 12 | ordertype = NULL, 13 | side = NULL, 14 | qtysign = NULL, 15 | orderset = NULL, 16 | which.i = FALSE 17 | ) 18 | } 19 | \arguments{ 20 | \item{portfolio}{text name of the portfolio to associate the order book with} 21 | 22 | \item{symbol}{identifier of the instrument to find orders for. The name of any associated price objects (xts prices, usually OHLC) should match these} 23 | 24 | \item{status}{one of "open", "closed", "canceled", "revoked", or "replaced", default "open"} 25 | 26 | \item{timespan}{xts-style character timespan to be the period to find orders of the given status and ordertype} 27 | 28 | \item{ordertype}{one of NULL, "market","limit","stoplimit", "stoptrailing" or "iceberg" default NULL} 29 | 30 | \item{side}{one of NULL, "long" or "short", default NULL} 31 | 32 | \item{qtysign}{one of NULL, -1,0,1 ; could be useful when all qty's are reported as positive numbers and need to be identified other ways, default NULL} 33 | 34 | \item{orderset}{a tag identifying the orderset} 35 | 36 | \item{which.i}{if TRUE, return the row index numbers rather than the order rows matching the criteria, default FALSE} 37 | } 38 | \description{ 39 | This function exists so that other code can find open orders, potentially to update or cancel them. 40 | } 41 | \details{ 42 | It has some use as a reporting or post-hoc analytics tool, but it may not always be exported. 43 | } 44 | \seealso{ 45 | getOrderBook 46 | 47 | addOrder 48 | } 49 | \concept{order book} 50 | -------------------------------------------------------------------------------- /tests/testthat/test_demo_maCross_stoptrailing.R: -------------------------------------------------------------------------------- 1 | # A test for indicators, signals and rules using the macd demo 2 | # 3 | # 4 | stopifnot(require(testthat)) 5 | stopifnot(require(quantstrat)) 6 | context("demo/test_maCross_stoptrailing.R") 7 | 8 | devAskNewPage(ask = FALSE) # dont prompt for new page, mainly for R CMD check 9 | source(paste0(path.package("quantstrat"),"/demo/maCross_stoptrailing.R")) # source demo 10 | 11 | test_that("End.Equity equals 7809", { 12 | expect_equal(round(tradeStats('Port.Luxor','AAPL')$End.Equity), 2771) 13 | }) 14 | 15 | test_that("num txns equals 11", { # note we pad the start with zeros 16 | expect_equal(nrow(getTxns('Port.Luxor','AAPL')), 11) 17 | }) 18 | 19 | test_that("num orders equals 19", { 20 | expect_equal(nrow(obook$Port.Luxor$AAPL), 19) 21 | }) 22 | 23 | test_that("sum closed order prices equals sum txn prices", { 24 | expect_equal(sum(as.numeric(getOrderBook("Port.Luxor")$Port.Luxor$AAPL$Order.Price[which(getOrderBook("Port.Luxor")$Port.Luxor$AAPL$Order.Status == "closed")])), 25 | sum(getTxns("Port.Luxor","AAPL")$Txn.Price)) 26 | }) 27 | 28 | test_that("stoptrailing order prices equal 138.7663, 141.5517, 141.6479, 150.7013, 144.4037, 147.0306, 147.0788, 148.2753, 149.5006, 151.4304, 151.2416, 163.0308, 164.8702, 168.1434", { 29 | expect_equal(round(as.numeric(getOrderBook("Port.Luxor")$Port.Luxor$AAPL$Order.Price[which(getOrderBook("Port.Luxor")$Port.Luxor$AAPL$Order.Type == "stoptrailing")]$Order.Price), 4), 30 | 31 | c(138.7663, 141.5517, 141.6479, 150.7013, 144.4037, 147.0306, 147.0788, 148.2753, 149.5006, 151.4304, 151.2416, 163.0308, 164.8702, 168.1434)) 32 | }) 33 | 34 | # Commands for running this test file from the console if required: 35 | # 36 | # require(testthat) 37 | # test_file("~/quantstrat/tests/testthat/test_demo_maCross_stoptrailing.R") 38 | -------------------------------------------------------------------------------- /demo/luxor.include.R: -------------------------------------------------------------------------------- 1 | ### 2 | 3 | options(width = 240) 4 | #options(warn=1) 5 | 6 | Sys.setenv(TZ="UTC") 7 | 8 | ### 9 | 10 | startDate = '2002-10-21' 11 | 12 | .from=startDate 13 | 14 | #.to='2008-07-04' 15 | .to='2002-10-31' 16 | 17 | ### 18 | 19 | strategy.st = 'luxor' 20 | portfolio.st = 'forex' 21 | account.st = 'IB' 22 | 23 | ### 24 | 25 | .orderqty = 100000 26 | .threshold = 0.0005 27 | .txnfees = -6 # round-trip fee 28 | 29 | ### Distributions for paramset analysis 30 | 31 | .nsamples=80 32 | 33 | .FastSMA = (1:20) 34 | .SlowSMA = (30:80) 35 | 36 | .StopLoss = seq(0.05, 2.4, length.out=48)/100 37 | .StopTrailing = seq(0.05, 2.4, length.out=48)/100 38 | .TakeProfit = seq(0.1, 4.8, length.out=48)/100 39 | 40 | .FastWFA = c(1, 3, 5, 7, 9) 41 | .SlowWFA = c(42, 44, 46) 42 | 43 | # generate 24x24h ISO8601 timespan vector 44 | # this includes non-ISO8601 elements (e.g. "T01:00/T00:59") 45 | # that are discarded at processing 46 | 47 | .timespans.start<-paste(sprintf("T%02d",0:23),':00',sep='') 48 | .timespans.stop<-paste(sprintf("T%02d",0:23),':59',sep='') 49 | 50 | .timespans<-outer(.timespans.start, .timespans.stop, FUN=paste, sep='/') 51 | 52 | # in order to run the full 24x24 hour scan above, comment out the following line: 53 | .timespans<-c('T06:00/T10:00', 'T07:00/T11:00', 'T08:00/T12:00', 'T09:00/T13:00', 'T10:00/T14:00', 'T11:00/T15:00', 'T12:00/T16:00') 54 | 55 | ### Actual arameters 56 | 57 | .fast = 6 58 | .slow = 44 59 | 60 | #.timespan = 'T09:00/T13:00' 61 | #.timespan = 'T00:00/T23:59' 62 | .timespan = NULL 63 | 64 | .stoploss <- 0.40/100 65 | .stoptrailing <- 0.8/100 66 | .takeprofit <- 2.0/100 67 | 68 | suppressWarnings(rm(list = c(paste("account", account.st, sep='.'), paste("portfolio", portfolio.st, sep='.')), pos=.blotter)) 69 | suppressWarnings(rm(list = c(strategy.st, paste("order_book", portfolio.st, sep='.')), pos=.strategy)) 70 | -------------------------------------------------------------------------------- /man/setParameterConstraint.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/parameters.R 3 | \name{setParameterConstraint} 4 | \alias{setParameterConstraint} 5 | \title{Function to construct parameter constraint object. (deprecated)} 6 | \usage{ 7 | setParameterConstraint( 8 | paramConstraintObj = list(), 9 | constraintLabel, 10 | paramList, 11 | relationship 12 | ) 13 | } 14 | \arguments{ 15 | \item{paramConstraintObj}{the ParameterConstraint object to be updated, if missing, funtion will create a new one.} 16 | 17 | \item{constraintLabel}{string label to apply to the constraint.} 18 | 19 | \item{paramList}{the two name of the prameters as a list contains two strings.} 20 | 21 | \item{relationship}{relationship between the 1st parameter and 2nd one. ('gt' means 1st parameter > 2nd parameter).} 22 | } 23 | \value{ 24 | The returned object is a structure contains the constraints on pairs of parameters, if the input argument 'paramConstraintObj' is provided, the function update the input paramConstraintObj object and return the updated one. When specify the constraints of several pairs of parameters, usually the first returned object is passed to the next several call of the function as input argument 'paramConstraintObj'. See example. 25 | } 26 | \description{ 27 | Function to construct parameter constraint object. The returned value will be one of the inputs to the applyParameter function. 28 | } 29 | \examples{ 30 | #(For complete demo see parameterTestMACD.R) 31 | #In a MACD strategy, we want to fast macd calcuated from less time periods (days) 32 | #than slow macd signal: 33 | \dontrun{ 34 | x<-setParameterConstraint(constraintLabel='macdPC', 35 | paramList=c('nFast','nSlow'),relationship='lt') 36 | } 37 | #The object x then can be used as one of the inputs to applyParameter function to specify the 38 | #constraints between parameters. 39 | 40 | } 41 | \author{ 42 | Yu Chen 43 | } 44 | -------------------------------------------------------------------------------- /demo/luxor.6.paramset.stoploss.R: -------------------------------------------------------------------------------- 1 | #!/usr/bin/Rscript --vanilla 2 | # 3 | # Jan Humme (@opentrades) - August 2012 4 | # 5 | # Tested and found to work correctly using blotter r1457 6 | # 7 | # After Jaekle & Tamasini: A new approach to system development and portfolio optimisation (ISBN 978-1-905641-79-6) 8 | # 9 | # compute StopLoss percentage for various paramsets 10 | 11 | require(quantstrat) 12 | 13 | source(paste0(path.package("quantstrat"),"/demo/luxor.include.R")) 14 | source(paste0(path.package("quantstrat"),"/demo/luxor.getSymbols.R")) 15 | 16 | ### 17 | 18 | initPortf(portfolio.st, symbols='GBPUSD', currency='USD') 19 | addPosLimit( 20 | portfolio=portfolio.st, 21 | symbol='GBPUSD', 22 | timestamp=startDate, 23 | maxpos=.orderqty) 24 | 25 | initAcct(account.st, portfolios=portfolio.st, currency='USD') 26 | 27 | ### 28 | 29 | initOrders(portfolio.st) 30 | 31 | load.strategy(strategy.st) 32 | 33 | ### BEGIN uncomment lines to activate StopLoss and/or StopTrailing and/or TakeProfit rules 34 | 35 | enable.rule('luxor', 'chain', 'StopLoss') 36 | #enable.rule('luxor', 'chain', 'StopTrailing') 37 | #enable.rule('luxor', 'chain', 'TakeProfit') 38 | 39 | ### END uncomment lines to activate StopLoss and/or StopTrailing and/or TakeProfit rules 40 | require(foreach) 41 | #registerDoSEQ() 42 | 43 | if (!"doMC" %in% installed.packages()[,1]) { 44 | install.packages("doMC") 45 | } 46 | require(doMC) 47 | registerDoMC(cores=8) 48 | 49 | #require(doParallel) 50 | #registerDoParallel(cores=2) 51 | 52 | #require(doRedis) 53 | #registerDoRedis('jobs') 54 | 55 | ############################ 56 | 57 | results <- apply.paramset(strategy.st, paramset.label='StopLoss', portfolio.st=portfolio.st, account.st=account.st, nsamples=80, verbose=TRUE) 58 | 59 | stats <- results$tradeStats 60 | 61 | print(t(stats)) 62 | 63 | plot(100*stats$StopLossLONG, stats$Net.Trading.PL, type='b', xlab='Stoploss %', ylab='Net.Trading.PL', main='Luxor') 64 | -------------------------------------------------------------------------------- /demo/luxor.6.paramset.takeprofit.R: -------------------------------------------------------------------------------- 1 | #!/usr/bin/Rscript --vanilla 2 | # 3 | # Jan Humme (@opentrades) - August 2012 4 | # 5 | # Tested and found to work correctly using blotter r1457 6 | # 7 | # After Jaekle & Tamasini: A new approach to system development and portfolio optimisation (ISBN 978-1-905641-79-6) 8 | # 9 | # compute TakeProfit percentage for various paramsets 10 | 11 | require(quantstrat) 12 | 13 | source(paste0(path.package("quantstrat"),"/demo/luxor.include.R")) 14 | source(paste0(path.package("quantstrat"),"/demo/luxor.getSymbols.R")) 15 | 16 | ### 17 | 18 | initPortf(portfolio.st, symbols='GBPUSD', currency='USD') 19 | addPosLimit( 20 | portfolio=portfolio.st, 21 | symbol='GBPUSD', 22 | timestamp=startDate, 23 | maxpos=.orderqty) 24 | 25 | initAcct(account.st, portfolios=portfolio.st, currency='USD') 26 | 27 | ### 28 | 29 | initOrders(portfolio.st) 30 | 31 | load.strategy(strategy.st) 32 | 33 | ### BEGIN uncomment lines to activate StopLoss and/or StopTrailing and/or TakeProfit rules 34 | 35 | enable.rule('luxor', 'chain', 'StopLoss') 36 | #enable.rule('luxor', 'chain', 'StopTrailing') 37 | enable.rule('luxor', 'chain', 'TakeProfit') 38 | 39 | ### END uncomment lines to activate StopLoss and/or StopTrailing and/or TakeProfit rules 40 | require(foreach) 41 | #registerDoSEQ() 42 | 43 | if (!"doMC" %in% installed.packages()[,1]) { 44 | install.packages("doMC") 45 | } 46 | require(doMC) 47 | registerDoMC(cores=8) 48 | 49 | #require(doParallel) 50 | #registerDoParallel(cores=2) 51 | 52 | #require(doRedis) 53 | #registerDoRedis('jobs') 54 | 55 | ############################ 56 | 57 | results <- apply.paramset(strategy.st, paramset.label='TakeProfit', portfolio.st=portfolio.st, account.st=account.st, nsamples=80, verbose=TRUE) 58 | 59 | stats <- results$tradeStats 60 | 61 | print(t(stats)) 62 | 63 | plot(100*stats$TakeProfitLONG, stats$Net.Trading.PL, type='b', xlab='TakeProfit %', ylab='Net.Trading.PL', main='Luxor') 64 | -------------------------------------------------------------------------------- /demo/luxor.6.paramset.stoptrailing.R: -------------------------------------------------------------------------------- 1 | #!/usr/bin/Rscript --vanilla 2 | # 3 | # Jan Humme (@opentrades) - August 2012 4 | # 5 | # Tested and found to work correctly using blotter r1457 6 | # 7 | # After Jaekle & Tamasini: A new approach to system development and portfolio optimisation (ISBN 978-1-905641-79-6) 8 | # 9 | # compute StopTrailing percentage for various paramsets 10 | 11 | require(quantstrat) 12 | 13 | source(paste0(path.package("quantstrat"),"/demo/luxor.include.R")) 14 | source(paste0(path.package("quantstrat"),"/demo/luxor.getSymbols.R")) 15 | 16 | ### 17 | 18 | initPortf(portfolio.st, symbols='GBPUSD', currency='USD') 19 | addPosLimit( 20 | portfolio=portfolio.st, 21 | symbol='GBPUSD', 22 | timestamp=startDate, 23 | maxpos=.orderqty) 24 | 25 | initAcct(account.st, portfolios=portfolio.st, currency='USD') 26 | 27 | ### 28 | 29 | initOrders(portfolio.st) 30 | 31 | load.strategy(strategy.st) 32 | 33 | ### BEGIN uncomment lines to activate StopLoss and/or StopTrailing and/or TakeProfit rules 34 | 35 | enable.rule('luxor', 'chain', 'StopLoss') 36 | enable.rule('luxor', 'chain', 'StopTrailing') 37 | #enable.rule('luxor', 'chain', 'TakeProfit') 38 | 39 | ### END uncomment lines to activate StopLoss and/or StopTrailing and/or TakeProfit rules 40 | require(foreach) 41 | #registerDoSEQ() 42 | 43 | if (!"doMC" %in% installed.packages()[,1]) { 44 | install.packages("doMC") 45 | } 46 | require(doMC) 47 | registerDoMC(cores=2) 48 | 49 | #require(doParallel) 50 | #registerDoParallel(cores=2) 51 | 52 | #require(doRedis) 53 | #registerDoRedis('jobs') 54 | 55 | ############################ 56 | 57 | results <- apply.paramset(strategy.st, paramset.label='StopTrailing', portfolio.st=portfolio.st, account.st=account.st, nsamples=80, verbose=TRUE) 58 | 59 | stats <- results$tradeStats 60 | 61 | print(t(stats)) 62 | 63 | plot(100*stats$StopTrailingLONG, stats$Net.Trading.PL, type='b', xlab='StopTrailing %', ylab='Net.Trading.PL', main='Luxor') 64 | -------------------------------------------------------------------------------- /man/ruleRevoke.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ruleRevoke.R 3 | \name{ruleRevoke} 4 | \alias{ruleRevoke} 5 | \alias{ruleCancel} 6 | \title{rule to revoke(cancel) an unfilled limit order on a signal} 7 | \usage{ 8 | ruleRevoke( 9 | data = mktdata, 10 | timestamp, 11 | sigcol, 12 | sigval, 13 | orderside = NULL, 14 | orderset = NULL, 15 | portfolio, 16 | symbol, 17 | ruletype, 18 | ... 19 | ) 20 | } 21 | \arguments{ 22 | \item{data}{an xts object containing market data. depending on rules, may need to be in OHLCV or BBO formats, and may include indicator and signal information} 23 | 24 | \item{timestamp}{timestamp coercible to POSIXct that will be the time the order will be inserted on} 25 | 26 | \item{sigcol}{column name to check for signal} 27 | 28 | \item{sigval}{signal value to match against} 29 | 30 | \item{orderside}{one of either "long" or "short", default NULL, see details} 31 | 32 | \item{orderset}{tag to identify an orderset} 33 | 34 | \item{portfolio}{text name of the portfolio to place orders in} 35 | 36 | \item{symbol}{identifier of the instrument to revoke orders for} 37 | 38 | \item{ruletype}{must be 'risk' for ruleRevoke, see \code{\link{add.rule}}} 39 | 40 | \item{...}{any other passthru parameters} 41 | } 42 | \description{ 43 | As described elsewhere in the documentation, quantstrat models 44 | \emph{orders}. All orders in quantstrat are GTC orders, unless a 45 | time in force is specified, which means that unfilled limit orders 46 | have to be canceled manually or replaced by other orders. 47 | } 48 | \details{ 49 | This function is used for revoking or canceling the orders based on a signal. 50 | Order status will be changed to 'revoked', to separate it from cancelations or 51 | replacements from other causes. This may make it easier it decipher the order book 52 | to figure out what the strategy ewas doing. 53 | } 54 | \seealso{ 55 | \code{\link{osNoOp}} , \code{\link{add.rule}} 56 | } 57 | \author{ 58 | Niklas Kolster, Jan Humme 59 | } 60 | -------------------------------------------------------------------------------- /man/beanplot.signals.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/signals.R 3 | \name{beanplot.signals} 4 | \alias{beanplot.signals} 5 | \title{Visualization of Signal Across Lookback with Beanplots} 6 | \usage{ 7 | beanplot.signals( 8 | signals, 9 | rows = NULL, 10 | columns = NULL, 11 | mai = c(0.1, 0.4, 0.2, 0.1), 12 | mgp = c(1, 1, 0), 13 | xlab = "", 14 | ylab = "", 15 | cex.main = 0.6, 16 | xaxt = "n", 17 | cex.axis = 0.5, 18 | h = 0, 19 | hlinecol = "red", 20 | ... 21 | ) 22 | } 23 | \arguments{ 24 | \item{signals}{list of paramset forward looking price changes by asset} 25 | 26 | \item{rows}{number of rows for plot} 27 | 28 | \item{columns}{number of columns for plot} 29 | 30 | \item{mai}{A numerical vector of the form c(bottom, left, top, right) which gives the margin size specified in inches.} 31 | 32 | \item{mgp}{The margin line (in mex units) for the axis title, axis labels and axis line. Note that mgp[1] affects title whereas mgp[2:3] affect axis. The default is c(3, 1, 0).} 33 | 34 | \item{xlab}{a title for the x axis} 35 | 36 | \item{ylab}{a title for the y axis} 37 | 38 | \item{cex.main}{The magnification to be used for main titles relative to the current setting of cex.} 39 | 40 | \item{xaxt}{A character which specifies the x axis type. Specifying "n" suppresses plotting of the axis. The standard value is "s": for compatibility with S values "l" and "t" are accepted but are equivalent to "s": any value other than "n" implies plotting.} 41 | 42 | \item{cex.axis}{The magnification to be used for axis annotation relative to the current setting of cex.} 43 | 44 | \item{h}{the y-value(s) for horizontal line(s).} 45 | 46 | \item{hlinecol}{A specification for the default plotting color. See section \sQuote{Color Specification}.} 47 | 48 | \item{...}{any other passthru parameters} 49 | } 50 | \value{ 51 | plot 52 | } 53 | \description{ 54 | This function is similar to \code{signal.plot} but uses beanplots 55 | instead of barplots. Requires 'beanplot' package 56 | } 57 | \author{ 58 | Michael Guan 59 | } 60 | -------------------------------------------------------------------------------- /man/osMaxPos.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/osFUNs.R 3 | \name{osMaxPos} 4 | \alias{osMaxPos} 5 | \title{order sizing function for position limits and level sizing} 6 | \usage{ 7 | osMaxPos( 8 | data, 9 | timestamp, 10 | orderqty, 11 | ordertype, 12 | orderside, 13 | portfolio, 14 | symbol, 15 | ruletype, 16 | digits = 0, 17 | ... 18 | ) 19 | } 20 | \arguments{ 21 | \item{data}{an xts object containing market data. depending on rules, may need to be in OHLCV or BBO formats, and may include indicator and signal information} 22 | 23 | \item{timestamp}{timestamp coercible to POSIXct that will be the time the order will be inserted on} 24 | 25 | \item{orderqty}{numeric quantity of the desired order, modified by osFUN} 26 | 27 | \item{ordertype}{one of "market","limit","stoplimit", or "stoptrailing"} 28 | 29 | \item{orderside}{one of either "long" or "short"} 30 | 31 | \item{portfolio}{text name of the portfolio to place orders in} 32 | 33 | \item{symbol}{identifier of the instrument to place orders for. The name of any associated price objects (xts prices, usually OHLC) should match these} 34 | 35 | \item{ruletype}{one of "risk","order","rebalance","exit","enter", see \code{\link{add.rule}}} 36 | 37 | \item{digits}{call \code{\link{round}} to round min/max clip size to specified number of digits after decimal place} 38 | 39 | \item{...}{any other passthru parameters} 40 | } 41 | \description{ 42 | levels are a simplification of more complex (proprietary) 43 | techniques sometimes used for order sizing. 44 | the max orderqty returned will be the limit/levels 45 | Obviously the strategy rules could ask for smaller order sizes, 46 | but this is the default. If you don't want to use levels, set 47 | them to 1. 48 | } 49 | \details{ 50 | \code{orderqty='all'} in a risk rule will return an order size 51 | appropriate to flatten the current position. 52 | } 53 | \note{ 54 | TODO integrate orderqty='all' into osMaxPos for non-risk exit orders by combining side and pos for exits 55 | } 56 | \seealso{ 57 | \code{\link{addPosLimit}},\code{\link{getPosLimit}} 58 | } 59 | -------------------------------------------------------------------------------- /man/applyIndicators.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/indicators.R 3 | \name{applyIndicators} 4 | \alias{applyIndicators} 5 | \title{apply the indicators in the strategy to arbitrary market data} 6 | \usage{ 7 | applyIndicators(strategy, mktdata, parameters = NULL, ...) 8 | } 9 | \arguments{ 10 | \item{strategy}{an object of type 'strategy' to add the indicator to} 11 | 12 | \item{mktdata}{an xts object containing market data. depending on indicators, may need to be in OHLCV or BBO formats} 13 | 14 | \item{parameters}{named list of parameters to be applied during evaluation of the strategy} 15 | 16 | \item{...}{any other passthru parameters} 17 | } 18 | \value{ 19 | \code{mktdata} with indicators colums added. 20 | } 21 | \description{ 22 | \code{applyIndicators} will take the \code{mktdata} object, 23 | and will apply each indicator specified in the strategy definition to it. 24 | } 25 | \details{ 26 | If the indicator function returns an xts object or a vector of the same length 27 | as mktdata, the columns created by the indicator function will be added to the 28 | mktdata object via \code{\link{cbind}}. 29 | 30 | If the indicator function returns multiple columns, the label will be 31 | \code{\link{paste}}'d to the end of either the returned column names or the 32 | respective column number when applying it to \code{mktdata}. 33 | 34 | If the indicator returns some more complexobject, it will be added to a list 35 | in the $indicators slot inside the \code{\link{applyStrategy}} execution frame. 36 | If you want your indicators to return a more complex object, 37 | (such as a model specification and output from a regression), be advised 38 | that your signal generator, and potentially your rule function, will need 39 | to understand, anticipate, and know how to manipulate the internal strategy frame. 40 | } 41 | \examples{ 42 | \dontrun{ 43 | strategy("example", store=TRUE) 44 | getSymbols("SPY", src='yahoo') 45 | add.indicator('example', 'SMA', arguments=list(x=quote(Ad(SPY)), n=20)) 46 | str(getStrategy('example')$indicators) 47 | out <- applyIndicators('example', SPY) 48 | tail(out) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /man/signal.plot.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/signals.R 3 | \name{signal.plot} 4 | \alias{signal.plot} 5 | \title{Visualization of Signal Across Lookback} 6 | \usage{ 7 | signal.plot( 8 | signals, 9 | rows = NULL, 10 | columns = NULL, 11 | mai = c(0.1, 0.4, 0.2, 0.1), 12 | mgp = c(1, 1, 0), 13 | xlab = "", 14 | ylab = "", 15 | cex.main = 0.6, 16 | xaxt = "n", 17 | cex.axis = 0.5, 18 | h = 0, 19 | hlinecol = "red", 20 | ... 21 | ) 22 | } 23 | \arguments{ 24 | \item{signals}{list of paramset forward looking price changes by asset} 25 | 26 | \item{rows}{number of rows for plot} 27 | 28 | \item{columns}{number of columns for plot} 29 | 30 | \item{mai}{A numerical vector of the form c(bottom, left, top, right) which gives the margin size specified in inches.} 31 | 32 | \item{mgp}{The margin line (in mex units) for the axis title, axis labels and axis line. Note that mgp[1] affects title whereas mgp[2:3] affect axis. The default is c(3, 1, 0).} 33 | 34 | \item{xlab}{a title for the x axis} 35 | 36 | \item{ylab}{a title for the y axis} 37 | 38 | \item{cex.main}{The magnification to be used for main titles relative to the current setting of cex.} 39 | 40 | \item{xaxt}{A character which specifies the x axis type. Specifying "n" suppresses plotting of the axis. The standard value is "s": for compatibility with S values "l" and "t" are accepted but are equivalent to "s": any value other than "n" implies plotting.} 41 | 42 | \item{cex.axis}{The magnification to be used for axis annotation relative to the current setting of cex.} 43 | 44 | \item{h}{the y-value(s) for horizontal line(s).} 45 | 46 | \item{hlinecol}{A specification for the default plotting color. See section \sQuote{Color Specification}.} 47 | 48 | \item{...}{any other passthru parameters} 49 | } 50 | \description{ 51 | This function takes a list of matrix of post signal price changes and 52 | plots boxplots. Note function plots whatever is given to it therefore when 53 | there are lots paramsets, it is best to plot a smaller portion so the 54 | information can be displayed clearly. 55 | } 56 | \author{ 57 | Michael Guan 58 | } 59 | -------------------------------------------------------------------------------- /demo/luxor.7.exit.and.risk.R: -------------------------------------------------------------------------------- 1 | #!/usr/bin/Rscript --vanilla 2 | # 3 | # Jan Humme (@opentrades) - April 2013 4 | # 5 | # Tested and found to work correctly using blotter r1457 6 | # 7 | # After Jaekle & Tamasini: A new approach to system development and portfolio optimisation (ISBN 978-1-905641-79-6) 8 | # 9 | # Paragraph 3.5: determination of appropriate exit and risk management 10 | 11 | require(quantstrat) 12 | 13 | source(paste0(path.package("quantstrat"),"/demo/luxor.include.R")) 14 | 15 | source(paste0(path.package("quantstrat"),"/demo/luxor.getSymbols.R")) 16 | 17 | ### blotter 18 | 19 | initPortf(portfolio.st, symbols='GBPUSD', currency='USD') 20 | initAcct(account.st, portfolios=portfolio.st, currency='USD') 21 | 22 | ### quantstrat 23 | 24 | load.strategy('luxor') 25 | 26 | ### BEGIN uncomment lines to activate StopLoss and/or StopTrailing and/or TakeProfit rules 27 | 28 | #enable.rule('luxor', 'chain', 'StopLoss') 29 | #enable.rule('luxor', 'chain', 'StopTrailing') 30 | #enable.rule('luxor', 'chain', 'TakeProfit') 31 | 32 | ### END uncomment lines to activate StopLoss and/or StopTrailing and/or TakeProfit rules 33 | 34 | addPosLimit( 35 | portfolio=portfolio.st, 36 | symbol='GBPUSD', 37 | timestamp=startDate, 38 | maxpos=.orderqty) 39 | 40 | initOrders(portfolio.st) 41 | 42 | applyStrategy(strategy.st, portfolio.st, prefer='Open') 43 | 44 | print(getOrderBook(portfolio.st)[[portfolio.st]]$GBPUSD) 45 | 46 | ############################################################################### 47 | 48 | updatePortf(portfolio.st, Symbols='GBPUSD', Dates=paste('::',as.Date(Sys.time()),sep='')) 49 | 50 | chart.Posn(portfolio.st, "GBPUSD") 51 | 52 | ############################################################################### 53 | 54 | print(t(tradeStats(portfolio.st, 'GBPUSD'))) 55 | 56 | ############################################################################### 57 | 58 | print(tradeQuantiles('forex', 'GBPUSD')) 59 | 60 | dev.new() 61 | 62 | ### Uncomment to choose appropriate MAE of MFE graph 63 | 64 | chart.ME(portfolio.st, 'GBPUSD', scale='percent', type='MAE') 65 | dev.new() 66 | chart.ME(portfolio.st, 'GBPUSD', scale='percent', type='MFE') 67 | -------------------------------------------------------------------------------- /tests/testthat/test_blotter_break.R: -------------------------------------------------------------------------------- 1 | # test_blotter_break.R 2 | # test for breaking trade with another trade that day in blotter 3 | # Author: Brian M Bielinski 4 | 5 | options(warn=-1) 6 | stopifnot(require(testthat)) 7 | stopifnot(require(blotter)) 8 | stopifnot(require(quantstrat)) 9 | 10 | # Sys.setenv(TZ = "GMT") 11 | # require(blotter) 12 | # require(testthat) 13 | # 14 | # port = "testBreak" 15 | # acct = "testBreak" 16 | # symbol = c("IBM") 17 | # 18 | # data(IBM) 19 | # 20 | # startDate = first(index(IBM)) 21 | # endDate = last(index(IBM)) 22 | # 23 | # lines = "date,shrs,price,symbol 24 | # 2007-01-10,100,98.0,IBM 25 | # 2007-01-16,-200,99.5,IBM 26 | # 2007-01-17,150,99.45,IBM 27 | # 2007-01-18,-50,99.0,IBM" 28 | # con = textConnection(lines) 29 | # tt.trades = read.csv(con, as.is = TRUE) 30 | # 31 | # tt.trades[,"date"] = make.time.unique(as.POSIXct(tt.trades[,"date"])) 32 | # 33 | # currency("USD") 34 | # stock(symbol,"USD") 35 | # 36 | # initPortf(port, 37 | # symbol, 38 | # initDate = startDate) 39 | # initAcct(port, 40 | # portfolios = c(port), 41 | # initDate = startDate, 42 | # initEq=10^6) 43 | # 44 | # for(i in 1:nrow(tt.trades)){ 45 | # addTxn(port,Symbol = tt.trades[i,"symbol"], 46 | # TxnDate = tt.trades[i,"date"], 47 | # TxnPrice = tt.trades[i,"price"], 48 | # TxnQty = tt.trades[i,"shrs"]) 49 | # } 50 | # 51 | # updatePortf(port) 52 | # updateAcct(acct) 53 | # updateEndEq(acct) 54 | 55 | context("check that trades are accounted for correctly.") 56 | source(paste0(path.package("quantstrat"),"/demo/demo_test_blotter_break.R")) 57 | 58 | # should be flat 59 | test_that("input trades position is flat", { 60 | expect_equal(sum(tt.trades[,"shrs"]), 0) 61 | }) 62 | 63 | test_that("recorded trades position in Txns is flat", { 64 | expect_equal(sum(getTxns(port,"IBM")[,"Txn.Qty"]), 0) 65 | }) 66 | 67 | test_that("times of the trades are unique", { 68 | expect_equal(length(tt.trades[,"date"]), length(unique(tt.trades[,"date"]))) 69 | }) 70 | 71 | test_that("calculated position is flat", { 72 | expect_equal(getPosQty(port,"IBM",Date = endDate), 0) 73 | }) 74 | 75 | 76 | #chart.Posn(port,"IBM") 77 | -------------------------------------------------------------------------------- /R/match.names.R: -------------------------------------------------------------------------------- 1 | #' match names in data to a list of partial name matches 2 | #' 3 | #' Often, the generic definition of a signal or indicator will include 4 | #' partial name matches. In financial data, common partial matches include 5 | #' 'Close', 'Open', and 'Volume', but there are many more. 6 | #' 7 | #' In complex data, additional name information may be added to column names 8 | #' for example, a symbol or an indicator of some adjustment may be added. 9 | #' 10 | #' This small utility exists to do the matching in a centralized location 11 | #' so that more robust error handling and reporting can be conducted. 12 | #' 13 | #' The process to be followed is that first, \code{\link{grep}} will 14 | #' be called without modification, assuming that a unique match has 15 | #' been supplied by the user. If this fails, a match will be attempted 16 | #' by appending '$' to the regex, searching for a match at the end of the 17 | #' column name, as would be constructed by the \code{\link{paste}} in 18 | #' e.g. \code{\link{applyIndicators}}. 19 | #' 20 | #' @param data_names names for the data to be matched to 21 | #' @param match_names names to match 22 | #' @export 23 | match.names <- function(match_names,data_names) { 24 | loc<-NULL 25 | for (mname in match_names){ 26 | t<-grep(mname,data_names) 27 | if(length(t)>1){ 28 | t<-grep(paste(mname,"$",sep=""),data_names) 29 | } 30 | if(is.null(loc)) loc<-t 31 | else loc <- c(loc,t) 32 | } 33 | if ( !identical(length(loc),length(match_names)) ) { 34 | mstr<-paste(match_names,collapse=' ') 35 | dstr<-paste(data_names,collapse=' ') 36 | warning(paste("all columns not located in",mstr,"for",dstr)) 37 | } 38 | return(loc) 39 | } 40 | 41 | ############################################################################### 42 | # R (http://r-project.org/) Quantitative Strategy Model Framework 43 | # 44 | # Copyright (c) 2009-2015 45 | # Peter Carl, Dirk Eddelbuettel, Brian G. Peterson, Jeffrey Ryan, and Joshua Ulrich 46 | # 47 | # This library is distributed under the terms of the GNU Public License (GPL) 48 | # for full details see the file COPYING 49 | # 50 | # $Id$ 51 | # 52 | ############################################################################### 53 | -------------------------------------------------------------------------------- /man/add.init.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/initialize.R 3 | \name{add.init} 4 | \alias{add.init} 5 | \title{add arbitrary initialization functions to a strategy} 6 | \usage{ 7 | add.init( 8 | strategy, 9 | name, 10 | arguments, 11 | parameters = NULL, 12 | label = NULL, 13 | ..., 14 | enabled = TRUE, 15 | indexnum = NULL, 16 | store = FALSE 17 | ) 18 | } 19 | \arguments{ 20 | \item{strategy}{an object (or the name of an object) of type 'strategy' to add the init function definition to} 21 | 22 | \item{name}{name of the init, must correspond to an R function} 23 | 24 | \item{arguments}{named list of default arguments to be passed to an init function when executed} 25 | 26 | \item{parameters}{vector of strings naming parameters to be saved for apply-time definition,default NULL, only needed if you need special names to avoid argument collision} 27 | 28 | \item{label}{arbitrary text label for init output, default NULL} 29 | 30 | \item{...}{any other passthru parameters} 31 | 32 | \item{enabled}{TRUE/FALSE whether the init is enabled for use in applying the strategy, default TRUE} 33 | 34 | \item{indexnum}{if you are updating a specific init, the index number in the $init list to update} 35 | 36 | \item{store}{TRUE/FALSE whether to store the strategy in the .strategy environment, or return it. default FALSE} 37 | } 38 | \value{ 39 | if \code{strategy} was the name of a strategy, the name. It it was a strategy, the updated strategy. 40 | } 41 | \description{ 42 | \code{\link{initStrategy}} will run a series of common initialization functions at the 43 | beginning of an \code{\link{applyStrategy}} call. This function allows the user to 44 | add arbitrary initialization functions to the sequence. 45 | } 46 | \details{ 47 | These arbitrary functions will be added to the \code{init} slot of the strategy object 48 | and when \code{applyStrategy} is evaluated, the arbitrary initialization functions will 49 | be evaluated after the standardized functions. 50 | 51 | For example, if your strategy uses a synthetic basket instrument, you could use this 52 | initialization slot to add a custom constructor to build the basket instrument time 53 | series and modify the symbols slot(s) of the strategy and portfolio. 54 | } 55 | -------------------------------------------------------------------------------- /man/initStrategy.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/initialize.R 3 | \name{initStrategy} 4 | \alias{initStrategy} 5 | \title{run standard and custom strategy initialization functions} 6 | \usage{ 7 | initStrategy( 8 | strategy, 9 | portfolio, 10 | symbols, 11 | parameters = NULL, 12 | get.Symbols = FALSE, 13 | init.Portf = TRUE, 14 | init.Acct = TRUE, 15 | init.Orders = TRUE, 16 | unique = TRUE, 17 | ... 18 | ) 19 | } 20 | \arguments{ 21 | \item{strategy}{object of type \code{strategy} to initialize data/containers for} 22 | 23 | \item{portfolio}{portfolio} 24 | 25 | \item{symbols}{symbols} 26 | 27 | \item{parameters}{named list of parameters to be applied during evaluation of the strategy, default NULL} 28 | 29 | \item{get.Symbols}{TRUE/FALSE, default FALSE} 30 | 31 | \item{init.Portf}{TRUE/FALSE, default TRUE} 32 | 33 | \item{init.Acct}{TRUE/FALSE, default TRUE} 34 | 35 | \item{init.Orders}{TRUE/FALSE, default TRUE} 36 | 37 | \item{unique}{TRUE/FALSE, default TRUE} 38 | 39 | \item{\dots}{any other passthrough parameters} 40 | } 41 | \description{ 42 | \code{initStrategy} will run a series of common initialization functions at the 43 | beginning of an \code{\link{applyStrategy}} call. 44 | } 45 | \details{ 46 | \describe{ 47 | \item{get.Symbols}{if TRUE, will call \code{\link[quantmod]{getSymbols}} 48 | on all symbols included in the \code{symbols} vector} 49 | \item{init.Portf}{if TRUE, will call \code{\link[blotter]{initPortf}} 50 | to initialize the portfolio object} 51 | \item{init.Acct}{if TRUE, will call \code{\link[blotter]{initAcct}} 52 | to initialize the account object} 53 | \item{init.Orders}{if TRUE, will call \code{\link{initOrders}} 54 | to initialize the order book for this test} 55 | \item{unique}{not yet implemented, will force a unique portfolio and account name 56 | if the portfolio, account, or order book already exist} 57 | } 58 | 59 | If used in conjuction with \code{initBySymbol}, \code{get.Symbols} should be \code{FALSE}. 60 | } 61 | \seealso{ 62 | \code{\link{applyStrategy}}, \code{\link{add.init}}, 63 | } 64 | \author{ 65 | Garrett See, Brian Peterson 66 | } 67 | -------------------------------------------------------------------------------- /man/add.signal.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/signals.R 3 | \name{add.signal} 4 | \alias{add.signal} 5 | \title{add a signal to a strategy} 6 | \usage{ 7 | add.signal( 8 | strategy, 9 | name, 10 | arguments, 11 | parameters = NULL, 12 | label = NULL, 13 | ..., 14 | enabled = TRUE, 15 | indexnum = NULL, 16 | store = FALSE 17 | ) 18 | } 19 | \arguments{ 20 | \item{strategy}{an object (or the name of an object) of type 'strategy' to add the signal to} 21 | 22 | \item{name}{name of the signal, must correspond to an R function} 23 | 24 | \item{arguments}{named list of default arguments to be passed to an signal function when executed} 25 | 26 | \item{parameters}{vector of strings naming parameters to be saved for apply-time definition,default NULL, only needed if you need special names to avoid argument collision} 27 | 28 | \item{label}{arbitrary text label for signal output, default NULL} 29 | 30 | \item{...}{any other passthru parameters} 31 | 32 | \item{enabled}{TRUE/FALSE whether the signal is enabled for use in applying the strategy, default TRUE} 33 | 34 | \item{indexnum}{if you are updating a specific signal, the index number in the $signals list to update} 35 | 36 | \item{store}{TRUE/FALSE whether to store the strategy in the .strategy environment, or return it. default FALSE} 37 | } 38 | \value{ 39 | if \code{strategy} was the name of a strategy, the name. It it was a strategy, the updated strategy. 40 | } 41 | \description{ 42 | This adds a signal definition to a strategy object. 43 | } 44 | \details{ 45 | Signals denote times at which the strategy \emph{may} want to 46 | take action. Common signals types from the literature include 47 | crossovers, thresholds, or other interactions between your \code{mktdata} 48 | and your indicators. 49 | 50 | if \code{label} is not supplied, NULL default will be converted to '.sig' 51 | if the signal function returns one named column, we use that, and ignore the label. 52 | If the signal function returns multiple columns, the label will be 53 | \code{\link{paste}}'d to either the returned column names or the 54 | respective column number. 55 | } 56 | \seealso{ 57 | \code{\link{applySignals}} 58 | \code{\link{add.indicator}} 59 | \code{link{add.rule}} 60 | \code{\link{sigComparison}} 61 | \code{\link{sigCrossover}} 62 | \code{\link{sigFormula}} 63 | \code{\link{sigPeak}} 64 | \code{\link{sigThreshold}} 65 | } 66 | -------------------------------------------------------------------------------- /man/rulePctEquity.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/rebalance.rules.R 3 | \name{rulePctEquity} 4 | \alias{rulePctEquity} 5 | \title{rule to base trade size on a percentage of available equity.} 6 | \usage{ 7 | rulePctEquity( 8 | trade.percent = 0.02, 9 | ..., 10 | longlevels = 1, 11 | shortlevels = 1, 12 | digits = NULL, 13 | refprice = NULL, 14 | portfolio, 15 | account = NULL, 16 | symbol, 17 | timestamp 18 | ) 19 | } 20 | \arguments{ 21 | \item{trade.percent}{max percentage of equity to allow the strategy to trade in this symbol} 22 | 23 | \item{\dots}{any other passthrough parameters} 24 | 25 | \item{longlevels}{numeric number of levels} 26 | 27 | \item{shortlevels}{numeric number of short levels, default longlevels} 28 | 29 | \item{digits}{if not NULL(the default), will call \code{\link{round}} with specified number of digits} 30 | 31 | \item{refprice}{if not NULL(the default), will divide the calculated trade size by the reference price} 32 | 33 | \item{portfolio}{text name of the portfolio to place orders in, typically set automatically} 34 | 35 | \item{account}{text name of the account to fetch initial equity from, defaults to initEq in the search path} 36 | 37 | \item{symbol}{identifier of the instrument to cancel orders for, typically set automatically} 38 | 39 | \item{timestamp}{timestamp coercible to POSIXct that will be the time the order will be inserted on, typically set automatically} 40 | } 41 | \description{ 42 | This rule works with \code{\link{applyStrategy.rebalancing}} to set the 43 | maximum trade size by calling \code{\link{addPosLimit}}. 44 | } 45 | \details{ 46 | To use it, you need to specify it as (part of) a rule of type 'rebalance'. 47 | note that \code{\link{applyStrategy.rebalancing}} will expect a 48 | 'rebalance_on' argument to be included in the \code{arguments=list(...)} 49 | of the rule definition. 50 | } 51 | \examples{ 52 | # example rule definition 53 | \dontrun{ 54 | add.rule(strategy.name, 'rulePctEquity', 55 | arguments=list(rebalance_on='months', 56 | trade.percent=.02, 57 | refprice=quote(last(getPrice(mktdata)[paste('::',curIndex,sep='')])[,1]), 58 | digits=0 59 | ), 60 | type='rebalance', 61 | label='rebalance') 62 | } 63 | } 64 | \seealso{ 65 | \code{\link{osMaxPos}} , 66 | \code{\link{applyStrategy.rebalancing}}, 67 | \code{\link{addPosLimit}}, 68 | \code{\link{add.rule}} 69 | } 70 | -------------------------------------------------------------------------------- /man/updateOrders.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/orders.R 3 | \name{updateOrders} 4 | \alias{updateOrders} 5 | \title{update an order or orders} 6 | \usage{ 7 | updateOrders( 8 | portfolio, 9 | symbol, 10 | timespan, 11 | ordertype = NULL, 12 | side = NULL, 13 | qtysign = NULL, 14 | orderset = NULL, 15 | oldstatus = "open", 16 | newstatus, 17 | statustimestamp 18 | ) 19 | } 20 | \arguments{ 21 | \item{portfolio}{text name of the portfolio to associate the order book with} 22 | 23 | \item{symbol}{identfier of the instrument to find orders for. The name of any associated price objects (xts prices, usually OHLC) should match these} 24 | 25 | \item{timespan}{xts-style character timespan to be the period to find orders of the given status and ordertype} 26 | 27 | \item{ordertype}{one of NULL, "market","limit","stoplimit" or "stoptrailing" default NULL} 28 | 29 | \item{side}{one of NULL, "long" or "short", default NULL} 30 | 31 | \item{qtysign}{one of NULL, -1,0,1 ; could be useful when all qty's are reported as positive numbers and need to be identified other ways, default NULL} 32 | 33 | \item{orderset}{set a tag identifying the orderset} 34 | 35 | \item{oldstatus}{one of NULL, "open", "closed", "canceled", "revoked", or "replaced", default "open"} 36 | 37 | \item{newstatus}{one of "open", "closed", "canceled", "revoked", or "replaced"} 38 | 39 | \item{statustimestamp}{timestamp of a status update, will be blank when order is initiated} 40 | } 41 | \description{ 42 | When an order gets filled, it should have its status moved to 'closed'. 43 | } 44 | \details{ 45 | When an order is updated with a new order, the order status should change to 'replaced' 46 | with a StatusTime that is the same as the one for the new order. This could happen in 47 | the case of a traditional Cancel/Replace, because of a trailing stop, or in the 48 | case of a partial fill that needs to enter a replaced order for the remainder. 49 | 50 | When a risk event or over-limit event happens, typically open orders will be 'revoked'. 51 | Possibly new orders will be added to close open positions. 52 | Many models will also want to run a process at the close of market that will cancel all open orders. 53 | 54 | If orderset is passed to updateOrders, all orders with oldstatus 55 | for the orderset will be updated, regardless of their other parameters. 56 | } 57 | \seealso{ 58 | addOrder 59 | 60 | getOrders 61 | 62 | getOrderBook 63 | } 64 | \concept{order book} 65 | -------------------------------------------------------------------------------- /man/tradeOrderStats.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/tradeOrderStats.R 3 | \name{tradeOrderStats} 4 | \alias{tradeOrderStats} 5 | \title{get order information associated with closing positions} 6 | \usage{ 7 | tradeOrderStats(portfolio, symbol, ...) 8 | } 9 | \arguments{ 10 | \item{portfolio}{text name of the portfolio the order book is associated with} 11 | 12 | \item{symbol}{text string defining the symbol to get trades and orders for} 13 | 14 | \item{...}{any other passthrough parameters} 15 | } 16 | \value{ 17 | A \code{xts} object containing: 18 | 19 | \describe{ 20 | \item{Order.Qty}{} 21 | \item{Order.Price}{} 22 | \item{Order.Type}{} 23 | \item{Order.Side}{} 24 | \item{Order.Threshold}{} 25 | \item{Order.Status}{should be 'closed' only} 26 | \item{Order.StatusTime}{time of the closing trade, should match 'End' column} 27 | \item{Prefer}{prefer argument for \code{getPrice}} 28 | \item{Order.Set}{order set of the closing trade} 29 | \item{Txn.Fees}{and fees applied to the closing trade} 30 | \item{Rule}{the name of the rule that generated the order which closed the position} 31 | \item{Start}{the \code{POSIXct} timestamp of the start of the trade} 32 | \item{Init.Pos}{the initial position on opening the trade} 33 | \item{Max.Pos}{the maximum (largest) position held during the open trade} 34 | \item{Num.Txns}{ the number of transactions included in this trade} 35 | \item{Max.Notional.Cost}{ the largest notional investment cost of this trade} 36 | \item{Net.Trading.PL}{ net trading P&L in the currency of \code{Symbol}} 37 | \item{MAE}{ Maximum Adverse Excursion (MAE), in the currency of \code{Symbol}} 38 | \item{MFE}{ Maximum Favorable Excursion (MFE), in the currency of \code{Symbol}} 39 | \item{Pct.Net.Trading.PL}{ net trading P&L in percent of invested \code{Symbol} price gained or lost} 40 | \item{Pct.MAE}{ Maximum Adverse Excursion (MAE), in percent} 41 | \item{Pct.MFE}{ Maximum Favorable Excursion (MFE), in percent} 42 | \item{tick.Net.Trading.PL}{ net trading P&L in ticks} 43 | \item{tick.MAE}{ Maximum Adverse Excursion (MAE) in ticks} 44 | \item{tick.MFE}{ Maximum Favorable Excursion (MFE) in ticks} 45 | } 46 | } 47 | \description{ 48 | Combine perTradeStats output with closed order information. 49 | } 50 | \details{ 51 | TODO: decide which of these columns are actually important 52 | TODO: add option for opening order/trade pairing rather than closing 53 | } 54 | -------------------------------------------------------------------------------- /demo/bbandParameters.R: -------------------------------------------------------------------------------- 1 | # Parameter example for BBands demo 2 | ############################################################################### 3 | 4 | require(foreach,quietly=TRUE) 5 | require(iterators) 6 | require(quantstrat) 7 | 8 | # example parallel initialization for doParallel. this or doMC, or doRedis are 9 | # most probably preferable to doSMP 10 | #require(doParallel) 11 | #registerDoParallel() # by default number of physical cores -1 12 | 13 | demo('bbands',ask=FALSE) 14 | strategy.st='bbands' 15 | 16 | ### User Set up pf parameter ranges to test 17 | .nlist = 10:40 18 | .sdlist = 1:4 19 | 20 | # number of random samples of the parameter distribution to use for random run 21 | .nsamples = 10 22 | 23 | add.distribution(strategy.st, 24 | paramset.label = 'BBparams', 25 | component.type = 'indicator', 26 | component.label = 'BBands', #this is the label given to the indicator in the strat 27 | variable = list(n = .nlist), 28 | label = 'nFAST' 29 | ) 30 | 31 | add.distribution(strategy.st, 32 | paramset.label = 'BBparams', 33 | component.type = 'indicator', 34 | component.label = 'BBands', #this is the label given to the indicator in the strat 35 | variable = list(sd = .sdlist), 36 | label = 'nSLOW' 37 | ) 38 | 39 | 40 | results <- apply.paramset(strategy.st, 41 | paramset.label='BBparams', 42 | portfolio.st=portfolio.st, 43 | account.st=account.st, 44 | nsamples=.nsamples, 45 | verbose=TRUE) 46 | 47 | stats <- results$tradeStats 48 | 49 | print(stats) 50 | 51 | 52 | 53 | ##### PLACE THIS BLOCK AT END OF DEMO SCRIPT ################### 54 | # book = getOrderBook(port) 55 | # stats = tradeStats(port) 56 | # rets = PortfReturns(acct) 57 | ################################################################ 58 | 59 | ############################################################################### 60 | # R (http://r-project.org/) Quantitative Strategy Model Framework 61 | # 62 | # Copyright (c) 2009-2012 63 | # Peter Carl, Dirk Eddelbuettel, Brian G. Peterson, Jeffrey Ryan, and Joshua Ulrich 64 | # 65 | # This library is distributed under the terms of the GNU Public License (GPL) 66 | # for full details see the file COPYING 67 | # 68 | # $Id: bbands.R 1097 2012-07-01 00:30:39Z braverock $ 69 | # 70 | ############################################################################### 71 | -------------------------------------------------------------------------------- /demo/macdParameters.R: -------------------------------------------------------------------------------- 1 | # Parameter demo for MACD 2 | ############################################################################### 3 | 4 | require(foreach,quietly=TRUE) 5 | require(iterators) 6 | require(quantstrat) 7 | 8 | demo('macd',ask=FALSE) 9 | 10 | # example parallel initialization for doParallel. this or doMC, or doRedis are 11 | # most probably preferable to doSMP 12 | #require(doParallel) 13 | #registerDoParallel() # by default number of physical cores -1 14 | 15 | 16 | #please run macd demo before all these... 17 | 18 | #retrieve the strategy from the environment, since the 'macd' strategy uses store=TRUE 19 | strategy.st <- 'macd' 20 | 21 | ### Set up Parameter Values 22 | .FastMA = (1:20) 23 | .SlowMA = (30:80) 24 | .nsamples = 30 #for random parameter sampling, less important if you're using doParallel or doMC 25 | 26 | 27 | ### MA paramset 28 | 29 | add.distribution(strategy.st, 30 | paramset.label = 'MA', 31 | component.type = 'indicator', 32 | component.label = '_', #this is the label given to the indicator in the strat 33 | variable = list(n = .FastMA), 34 | label = 'nFAST' 35 | ) 36 | 37 | add.distribution(strategy.st, 38 | paramset.label = 'MA', 39 | component.type = 'indicator', 40 | component.label = '_', #this is the label given to the indicator in the strat 41 | variable = list(n = .SlowMA), 42 | label = 'nSLOW' 43 | ) 44 | 45 | add.distribution.constraint(strategy.st, 46 | paramset.label = 'MA', 47 | distribution.label.1 = 'nFAST', 48 | distribution.label.2 = 'nSLOW', 49 | operator = '<', 50 | label = 'MA' 51 | ) 52 | 53 | 54 | ### 55 | 56 | .audit <- new.env() 57 | 58 | results <- apply.paramset(strategy.st, 59 | paramset.label='MA', 60 | portfolio.st=portfolio.st, 61 | account.st=account.st, 62 | nsamples=.nsamples, 63 | audit=.audit, 64 | store=TRUE, 65 | verbose=TRUE) 66 | 67 | df <- degrees.of.freedom('macd','macd') 68 | 69 | tstats <- results$tradeStats 70 | 71 | defSR <- SharpeRatio.deflated('macd',strategy='macd',audit=.audit) 72 | 73 | hcSR <- SharpeRatio.haircut('macd',strategy='macd',audit=.audit) 74 | 75 | print(tstats) 76 | 77 | print(df) 78 | 79 | print(defSR) 80 | 81 | print(hcSR) 82 | -------------------------------------------------------------------------------- /man/addPosLimit.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/osFUNs.R 3 | \name{addPosLimit} 4 | \alias{addPosLimit} 5 | \title{add position and level limits at timestamp} 6 | \usage{ 7 | addPosLimit( 8 | portfolio, 9 | symbol, 10 | timestamp, 11 | maxpos, 12 | longlevels = 1, 13 | minpos = -maxpos, 14 | shortlevels = longlevels 15 | ) 16 | } 17 | \arguments{ 18 | \item{portfolio}{text name of the portfolio to place orders in} 19 | 20 | \item{symbol}{identifier of the instrument to place orders for. The name of any associated price objects (xts prices, usually OHLC) should match these} 21 | 22 | \item{timestamp}{timestamp coercible to POSIXct that will be the time the order will be inserted on} 23 | 24 | \item{maxpos}{numeric maximum long position for symbol} 25 | 26 | \item{longlevels}{numeric number of levels} 27 | 28 | \item{minpos}{numeric minimum position, default -minpos (short allowed use negative number)} 29 | 30 | \item{shortlevels}{numeric number of short levels, default longlevels} 31 | } 32 | \description{ 33 | Many strategies will not be allowed to trade unconstrained. 34 | Typically, constraints will include position sizing limits. 35 | } 36 | \details{ 37 | \code{addPosLimit} works with \code{\link{osMaxPos}} to set 38 | and enforce position sizing limits. If \code{levels=1}, 39 | then all order sizing will be in the complete control of 40 | the strategy rules, up to the maximum position specified 41 | using \code{addPosLimit}'s \code{maxpos} and \code{minpos} 42 | arguments. 43 | 44 | Simply setting a position limit will not do anything. 45 | The strategy entry rules also need to specify an 46 | the use of order sizing function \code{\link{osMaxPos}}, 47 | most typically as an argument to \code{\link{ruleSignal}}. 48 | 49 | levels are a simplification of more complex (proprietary) 50 | techniques sometimes used for order sizing. 51 | the max orderqty returned will be the limit/levels. 52 | Obviously the strategy rules could ask for smaller order sizes, 53 | but this is the default. If you don't want to use levels, set 54 | them to 1. 55 | 56 | It is also important to note that position limits 57 | may be time-varying. 58 | If you only want one static maximum position limit, then 59 | call \code{addPosLimit} with a \code{timestamp} argument 60 | before your first trade. If you want time varying limits, 61 | typically in response to some rebalancing rule or risk 62 | rule, set the \code{timestamp} at the time which you wish 63 | the limit to take effect. 64 | } 65 | \seealso{ 66 | \code{\link{osMaxPos}} 67 | \code{\link{getPosLimit}} 68 | } 69 | -------------------------------------------------------------------------------- /man/SharpeRatio.deflated.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/deflated.Sharpe.R 3 | \name{deflatedSharpe} 4 | \alias{deflatedSharpe} 5 | \alias{SharpeRatio.deflated} 6 | \alias{.deflatedSharpe} 7 | \title{Calculate a Deflated Sharpe Ratio using number of trials and portfolio moments} 8 | \usage{ 9 | deflatedSharpe( 10 | portfolios, 11 | ..., 12 | strategy = NULL, 13 | trials = NULL, 14 | audit = NULL, 15 | env = .GlobalEnv 16 | ) 17 | 18 | .deflatedSharpe( 19 | sharpe, 20 | nTrials, 21 | varTrials, 22 | skew, 23 | kurt, 24 | numPeriods, 25 | periodsInYear = 252 26 | ) 27 | } 28 | \arguments{ 29 | \item{portfolios}{string name of portfolio, or optionally a vector of portfolios, see DETAILS} 30 | 31 | \item{...}{any other passtrhrough parameters} 32 | 33 | \item{strategy}{optional strategy specification that would contain more information on the process, default NULL} 34 | 35 | \item{trials}{optional number of trials,default NULL} 36 | 37 | \item{audit}{optional audit environment containing the results of parameter optimization or walk forward, default NULL} 38 | 39 | \item{env}{optional environment to find market data in, if required.} 40 | 41 | \item{sharpe}{candidate (annualized) Sharpe Ratio} 42 | 43 | \item{nTrials}{numeric number or trials} 44 | 45 | \item{varTrials}{variance of Sharpe ratios of the trials} 46 | 47 | \item{skew}{skewness of the candidate} 48 | 49 | \item{kurt}{non-excess kurtosis} 50 | 51 | \item{numPeriods}{total periods in the backtest} 52 | 53 | \item{periodsInYear}{number of periods in a year, default 252 (daily)} 54 | } 55 | \value{ 56 | a \code{data.frame} containing: 57 | 58 | \itemize{ 59 | \item{original observed Sharpe ratio} 60 | \item{deflated Sharpe ratio} 61 | \item{p-value of the deflated Sharpe ratio} 62 | \item{number of trials used for adjustment} 63 | } 64 | 65 | this object may change in the future, and may be classed so that we can include more information 66 | } 67 | \description{ 68 | Per Bailey and Lopex de Prado (2014), construct a Deflated Sharpe Ratio and 69 | associated p-value based on an observed Sharpe ratio and information drawn 70 | from a series of trials (e.g. parameter optimization or other strategies tried 71 | before the candidate strategy) 72 | } 73 | \references{ 74 | Bailey, David H, and Marcos Lopez de Prado. 2014. "The Deflated Sharpe Ratio: 75 | Correcting for Selection Bias, Backtest Overfitting and Non-Normality." 76 | Journal of Portfolio Management 40 (5): 94-107. 77 | http://www.davidhbailey.com/dhbpapers/deflated-sharpe.pdf 78 | 79 | https://quantstrattrader.wordpress.com/2015/09/24/ 80 | } 81 | \seealso{ 82 | \code{\link{SharpeRatio.haircut}} 83 | } 84 | \author{ 85 | Brian G. Peterson 86 | 87 | Ilya Kipnis, Brian G. Peterson 88 | } 89 | -------------------------------------------------------------------------------- /man/add.distribution.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/paramsets.R 3 | \name{add.distribution} 4 | \alias{add.distribution} 5 | \title{Adds a distribution to a paramset in a strategy} 6 | \usage{ 7 | add.distribution( 8 | strategy, 9 | paramset.label, 10 | component.type, 11 | component.label, 12 | variable, 13 | variable.dist = NULL, 14 | weight = NULL, 15 | label, 16 | store = TRUE 17 | ) 18 | } 19 | \arguments{ 20 | \item{strategy}{the name of the strategy object to add the distribution to} 21 | 22 | \item{paramset.label}{a label uniquely identifying the paramset within the strategy} 23 | 24 | \item{component.type}{one of c('indicator', 'signal', 'order', 'enter', 'exit', 'chain')} 25 | 26 | \item{component.label}{a label identifying the component. must be unique per component type} 27 | 28 | \item{variable}{the name of the variable in the component, and optionally, it's distribution} 29 | 30 | \item{variable.dist}{the distribution to be applied to variable} 31 | 32 | \item{weight}{vector} 33 | 34 | \item{label}{a label uniquely identifying the distribution within the paramset} 35 | 36 | \item{store}{indicates whether to store the strategy in the .strategy environment} 37 | } 38 | \description{ 39 | Creates a distribution in paramset, where a distribution consists of the name of a variable in 40 | a strategy component plus a range of values for this variable. 41 | } 42 | \details{ 43 | In the original version of this function `variable` was defined as a named 44 | list that contained the distribution directly. e.g. 45 | 46 | ` variable = list(mVAR = 1:50)` 47 | 48 | In order to more efficiently support equality constraints, we have optionally 49 | separated `variable` and `variable.dist`: 50 | 51 | `variable = 'mVAR',` 52 | `variable.dist = 1:50` 53 | 54 | and for an equality-constrained distribution: 55 | 56 | `variable=c('mVAR','mOtherVAR'),` 57 | `variable.dist=1:50` 58 | 59 | The old formulation is still supported for backwards compatibility if 60 | `variable.dist=NULL`, the default. 61 | 62 | Variables that should be equal, or equality-constrained, should be defined by 63 | creating a vector of the same length for `component.label` and `variable`. 64 | There is currently no error checking for getting this wrong, please be careful, patches welcome. 65 | The equal-length vectors will then apply the same distribution to one or more 66 | `variable`s in the same `component.type`. This is far more efficient than 67 | testing the constraints utilizing `apply.constraints`, and ensures the 68 | equality of the parameters. 69 | } 70 | \seealso{ 71 | \code{\link{add.distribution.constraint}}, 72 | \code{\link{delete.paramset}}, 73 | \code{\link{apply.paramset}} 74 | } 75 | \author{ 76 | Jan Humme, Brian Peterson 77 | } 78 | -------------------------------------------------------------------------------- /demo/luxor.2.add.paramsets.R: -------------------------------------------------------------------------------- 1 | #!/usr/bin/Rscript --vanilla 2 | # 3 | # Jan Humme (@opentrades) - August 2012, revised April 2013 4 | # 5 | # Tested and found to work correctly using blotter r1457 6 | # 7 | # After Jaekle & Tamasini: A new approach to system development and portfolio optimisation (ISBN 978-1-905641-79-6) 8 | 9 | require(quantstrat) 10 | 11 | source(paste0(path.package("quantstrat"),"/demo/luxor.include.R")) 12 | 13 | ### 14 | 15 | strategy.st <- 'luxor' 16 | 17 | ### 18 | 19 | load.strategy(strategy.st) 20 | 21 | ### SMA paramset 22 | 23 | add.distribution(strategy.st, 24 | paramset.label = 'SMA', 25 | component.type = 'indicator', 26 | component.label = 'nFast', 27 | variable = list(n = .FastSMA), 28 | label = 'nFAST' 29 | ) 30 | 31 | add.distribution(strategy.st, 32 | paramset.label = 'SMA', 33 | component.type = 'indicator', 34 | component.label = 'nSlow', 35 | variable = list(n = .SlowSMA), 36 | label = 'nSLOW' 37 | ) 38 | 39 | add.distribution.constraint(strategy.st, 40 | paramset.label = 'SMA', 41 | distribution.label.1 = 'nFAST', 42 | distribution.label.2 = 'nSLOW', 43 | operator = '<', 44 | label = 'SMA' 45 | ) 46 | 47 | ### Timespan paramset 48 | 49 | add.distribution(strategy.st, 50 | paramset.label = 'Timespan', 51 | component.type = 'enter', 52 | component.label = 'EnterLONG', 53 | variable = list(timespan = .timespans), 54 | label = 'EnterLong' 55 | ) 56 | 57 | add.distribution(strategy.st, 58 | paramset.label = 'Timespan', 59 | component.type = 'enter', 60 | component.label = 'EnterSHORT', 61 | variable = list(timespan = .timespans), 62 | label = 'EnterShort' 63 | ) 64 | 65 | add.distribution(strategy.st, 66 | paramset.label = 'Timespan', 67 | component.type = 'exit', 68 | component.label = 'Exit2LONG', 69 | variable = list(timespan = .timespans), 70 | label = 'ExitLong' 71 | ) 72 | 73 | add.distribution(strategy.st, 74 | paramset.label = 'Timespan', 75 | component.type = 'exit', 76 | component.label = 'Exit2SHORT', 77 | variable = list(timespan = .timespans), 78 | label = 'ExitShort' 79 | ) 80 | 81 | add.distribution.constraint(strategy.st, 82 | paramset.label = 'Timespan', 83 | distribution.label.1 = 'EnterLong', 84 | distribution.label.2 = 'EnterShort', 85 | operator = '==', 86 | label = 'EnterTimespan' 87 | ) 88 | 89 | add.distribution.constraint(strategy.st, 90 | paramset.label = 'Timespan', 91 | distribution.label.1 = 'ExitLong', 92 | distribution.label.2 = 'ExitShort', 93 | operator = '==', 94 | label = 'ExitTimespan' 95 | ) 96 | 97 | add.distribution.constraint(strategy.st, 98 | paramset.label = 'Timespan', 99 | distribution.label.1 = 'EnterLong', 100 | distribution.label.2 = 'ExitShort', 101 | operator = '==', 102 | label = 'EnterExitTimespan' 103 | ) 104 | 105 | ### 106 | 107 | save.strategy(strategy.st) 108 | -------------------------------------------------------------------------------- /tests/testthat/test_demo_rsi.R: -------------------------------------------------------------------------------- 1 | # # A test for indicators, signals and rules using the rsi demo 2 | # # 3 | # # 4 | # 5 | # stopifnot(require(testthat)) 6 | # stopifnot(require(quantstrat)) 7 | # context("demo/rsi.R") 8 | # 9 | # devAskNewPage(ask = FALSE) # dont prompt for new page, mainly for R CMD check 10 | # source(paste0(path.package("quantstrat"),"/demo/rsi.R")) # source demo 11 | # 12 | # test_that("rsi End.Equity for 'XLB' equals 8329", { 13 | # expect_equal(round(tradeStats('RSI','XLB')$End.Equity), 8329) 14 | # }) 15 | # 16 | # test_that("rsi num txns for 'XLB' equals 2356", { 17 | # expect_equal(nrow(getTxns('RSI','XLB')), 2356) 18 | # }) 19 | # 20 | # test_that("rsi End.Equity for 'XLE' equals 26003", { 21 | # expect_equal(round(tradeStats('RSI','XLE')$End.Equity), 26003) 22 | # }) 23 | # 24 | # test_that("rsi num txns for 'XLE' equals 2376", { 25 | # expect_equal(nrow(getTxns('RSI','XLE')), 2376) 26 | # }) 27 | # 28 | # test_that("rsi End.Equity for 'XLF' equals 11397", { 29 | # expect_equal(round(tradeStats('RSI','XLF')$End.Equity), 11397) 30 | # }) 31 | # 32 | # test_that("rsi num txns for 'XLF' equals 2414", { 33 | # expect_equal(nrow(getTxns('RSI','XLF')), 2414) 34 | # }) 35 | # 36 | # test_that("rsi End.Equity for 'XLI' equals 2260", { 37 | # expect_equal(round(tradeStats('RSI','XLI')$End.Equity), 2260) 38 | # }) 39 | # 40 | # test_that("rsi num txns for 'XLI' equals 2345", { 41 | # expect_equal(nrow(getTxns('RSI','XLI')), 2345) 42 | # }) 43 | # 44 | # test_that("rsi End.Equity for 'XLK' equals 12316", { 45 | # expect_equal(round(tradeStats('RSI','XLK')$End.Equity), 12316) 46 | # }) 47 | # 48 | # test_that("rsi num txns for 'XLK' equals 2372", { 49 | # expect_equal(nrow(getTxns('RSI','XLK')), 2372) 50 | # }) 51 | # 52 | # test_that("rsi End.Equity for 'XLP' equals 6491", { 53 | # expect_equal(round(tradeStats('RSI','XLP')$End.Equity), 6491) 54 | # }) 55 | # 56 | # test_that("rsi num txns for 'XLP' equals 2439", { 57 | # expect_equal(nrow(getTxns('RSI','XLP')), 2439) 58 | # }) 59 | # 60 | # test_that("rsi End.Equity for 'XLU' equals 12432", { 61 | # expect_equal(round(tradeStats('RSI','XLU')$End.Equity), 12432) 62 | # }) 63 | # 64 | # test_that("rsi num txns for 'XLU' equals 2417", { 65 | # expect_equal(nrow(getTxns('RSI','XLU')), 2417) 66 | # }) 67 | # 68 | # test_that("rsi End.Equity for 'XLV' equals 11352", { 69 | # expect_equal(round(tradeStats('RSI','XLV')$End.Equity), 11352) 70 | # }) 71 | # 72 | # test_that("rsi num txns for 'XLV' equals 2404", { 73 | # expect_equal(nrow(getTxns('RSI','XLV')), 2404) 74 | # }) 75 | # 76 | # test_that("rsi End.Equity for 'XLY' equals 14080", { 77 | # expect_equal(round(tradeStats('RSI','XLY')$End.Equity), 14080) 78 | # }) 79 | # 80 | # test_that("rsi num txns for 'XLY' equals 2340", { 81 | # expect_equal(nrow(getTxns('RSI','XLY')), 2340) 82 | # }) 83 | # 84 | # # Commands for running this test file from the console if required: 85 | # # 86 | # # require(testthat) 87 | # # test_file("~/quantstrat/tests/testthat/test_demo_rsi.R") 88 | -------------------------------------------------------------------------------- /demo/macdWFA.R: -------------------------------------------------------------------------------- 1 | # Walk Forward demo for MACD 2 | ############################################################################### 3 | 4 | require(foreach,quietly=TRUE) 5 | require(iterators) 6 | require(quantstrat) 7 | 8 | # run the macd demo in this session to set things up 9 | # use source rather than demo so that everything will be local in this session 10 | source(system.file('demo/macd.R',package='quantstrat'),echo = TRUE) 11 | 12 | # example parallel initialization for doParallel. this or doMC, or doRedis are 13 | # most probably preferable to doSMP 14 | #require(doParallel) 15 | #registerDoParallel() # by default number of physical cores -1 16 | 17 | 18 | #please run macd demo before all these... 19 | 20 | #retrieve the strategy from the environment, since the 'macd' strategy uses store=TRUE 21 | strategy.st <- 'macd' 22 | 23 | ### Set up Parameter Values 24 | .FastMA = (1:10) 25 | .SlowMA = (5:25) 26 | .nsamples = 15 #for random parameter sampling, less important if you're using doParallel or doMC 27 | 28 | 29 | ### MA paramset 30 | 31 | add.distribution(strategy.st, 32 | paramset.label = 'MA', 33 | component.type = 'indicator', 34 | component.label = '_', #this is the label given to the indicator in the strat 35 | variable = list(n = .FastMA), 36 | label = 'nFAST' 37 | ) 38 | 39 | add.distribution(strategy.st, 40 | paramset.label = 'MA', 41 | component.type = 'indicator', 42 | component.label = '_', #this is the label given to the indicator in the strat 43 | variable = list(n = .SlowMA), 44 | label = 'nSLOW' 45 | ) 46 | 47 | add.distribution.constraint(strategy.st, 48 | paramset.label = 'MA', 49 | distribution.label.1 = 'nFAST', 50 | distribution.label.2 = 'nSLOW', 51 | operator = '<', 52 | label = 'MA' 53 | ) 54 | 55 | 56 | ### 57 | wfportfolio <- "wf.macd" 58 | initPortf(wfportfolio,symbols=stock.str) 59 | initOrders(portfolio=wfportfolio) 60 | wf_start <- Sys.time() 61 | wfresults <- walk.forward(strategy.st, 62 | paramset.label = 'MA', 63 | portfolio.st = wfportfolio, 64 | account.st = account.st, 65 | nsamples = .nsamples, 66 | period = 'months', 67 | k.training = 36, 68 | k.testing = 12, 69 | verbose =TRUE, 70 | anchored = TRUE, 71 | include.insamples = TRUE, 72 | savewf = FALSE 73 | ) 74 | wf_end <-Sys.time() 75 | 76 | cat("\n Running the walk forward search: \n ") 77 | print(wf_end-wf_start) 78 | cat(" Total trials:",.strategy$macd$trials,"\n") 79 | 80 | wfa.stats <- wfresults$tradeStats 81 | 82 | print(wfa.stats) 83 | 84 | chart.forward(wfresults) 85 | -------------------------------------------------------------------------------- /man/stratBBands.Rd: -------------------------------------------------------------------------------- 1 | \name{stratBBands} 2 | \docType{data} 3 | \alias{stratBBands} 4 | \alias{BBands} 5 | \title{Bollinger Bands Strategy} 6 | \description{ 7 | Strategy object implementing a Bollinger Bands strategy. 8 | } 9 | \section{Indicators}{ 10 | This strategy uses only a single indicator, comprised of the TTR function \code{BBands}. 11 | Parameters for this indicator include number of MA periods, and the size of the bands in standard deviations. 12 | 13 | If constructed from scratch, the indicators would consist of: 14 | \describe{ 15 | \item{moving average}{a moving average parameterized by MA type (simple, exponential, Kalman, etc.) and MA periods to smooth over} 16 | \item{upper band}{ the upper band constructed classically by standard deviations from the moving average, or alternately by some other upper band generating function, and parameterized chiefly by the amplitude of the band, typically number of standard deviations from the midpoint or moving average indicator} 17 | \item{lower band}{ the lower band traditionally constructed to be symmetrical and opposite the upper band, but potentially constructed via a different function or parameterized differently than the upper band function} 18 | } 19 | } 20 | \section{Signals}{ 21 | The classic Bollinger Bands strategy depends on crossover events (signals) for the upper and lower band and the midpoint. 22 | \describe{ 23 | \item{Cl.gt.UpperBand}{type \code{\link{sigCrossover}}, if the Close price is greater than the upper band value.} 24 | \item{Cl.lt.LowerBand}{type \code{\link{sigCrossover}}, if the Close price is less than the lower band value.} 25 | \item{Cross.mid}{type \code{\link{sigCrossover}}, if the price at any point crossed the midpoint moving average.} 26 | 27 | } 28 | } 29 | \section{Rules}{ 30 | In this strategy, each signal has a corresponding entry or exit rule. 31 | \describe{ 32 | \item{enter}{\itemize{ 33 | \item type \code{\link{ruleSignal}}, enter a sell order at market on \code{Cl.gt.UpperBand} signal. 34 | \item type \code{\link{ruleSignal}}, enter a buy order at market on \code{Cl.lt.LowerBand} signal. 35 | }} 36 | 37 | \item{exit}{\itemize{ 38 | \item type \code{\link{ruleSignal}}, enter a market order to close any open position at market on \code{Cross.mid} signal. 39 | }} 40 | } 41 | } 42 | \section{Notes}{ 43 | This strategy may be improved in practice by: 44 | \itemize{ 45 | \item utilizing trailing entry or exit orders 46 | 47 | \item using a different smoothing mechanism other than SMA 48 | 49 | \item the addition of stop-loss rules 50 | } 51 | } 52 | \usage{data('stratBBands')} 53 | \references{ 54 | \url{http://www.investopedia.com/articles/trading/07/bollinger.asp} 55 | 56 | \url{http://www.mysmp.com/technical-analysis/bollinger-bands.html} 57 | 58 | \url{http://trading-strategies.netfirms.com/trading/bollingerbandtactics.htm} 59 | } 60 | \keyword{datasets} 61 | \keyword{ ts } 62 | -------------------------------------------------------------------------------- /R/ruleRevoke.R: -------------------------------------------------------------------------------- 1 | #' rule to revoke(cancel) an unfilled limit order on a signal 2 | #' 3 | #' As described elsewhere in the documentation, quantstrat models 4 | #' \emph{orders}. All orders in quantstrat are GTC orders, unless a 5 | #' time in force is specified, which means that unfilled limit orders 6 | #' have to be canceled manually or replaced by other orders. 7 | #' 8 | #' This function is used for revoking or canceling the orders based on a signal. 9 | #' Order status will be changed to 'revoked', to separate it from cancelations or 10 | #' replacements from other causes. This may make it easier it decipher the order book 11 | #' to figure out what the strategy ewas doing. 12 | #' 13 | #' @param data an xts object containing market data. depending on rules, may need to be in OHLCV or BBO formats, and may include indicator and signal information 14 | #' @param timestamp timestamp coercible to POSIXct that will be the time the order will be inserted on 15 | #' @param sigcol column name to check for signal 16 | #' @param sigval signal value to match against 17 | #' @param orderside one of either "long" or "short", default NULL, see details 18 | #' @param orderset tag to identify an orderset 19 | #' @param portfolio text name of the portfolio to place orders in 20 | #' @param symbol identifier of the instrument to revoke orders for 21 | #' @param ruletype must be 'risk' for ruleRevoke, see \code{\link{add.rule}} 22 | #' @param ... any other passthru parameters 23 | #' @author Niklas Kolster, Jan Humme 24 | #' @seealso \code{\link{osNoOp}} , \code{\link{add.rule}} 25 | #' @aliases ruleCancel 26 | #' @export ruleRevoke 27 | #' @export ruleCancel 28 | ruleRevoke <- ruleCancel <- function(data=mktdata, timestamp, sigcol, sigval, orderside=NULL, orderset=NULL, portfolio, symbol, ruletype, ...) 29 | { 30 | if (ruletype != 'risk') { 31 | stop('Ruletype for ruleRevoke or ruleCancel must be "risk".') 32 | } 33 | 34 | # Get row index of timestamp for faster subsetting 35 | if (hasArg(curIndex)) { 36 | curIndex <- eval(match.call(expand.dots=TRUE)$curIndex, parent.frame()) 37 | } else { 38 | curIndex <- mktdata[timestamp,which.i=TRUE] 39 | } 40 | 41 | if (curIndex > 0 && curIndex <= nrow(mktdata) && 42 | !is.na(mktdata[curIndex,sigcol]) && mktdata[curIndex,sigcol] == sigval) 43 | { 44 | updateOrders(portfolio=portfolio, 45 | symbol=symbol, 46 | timespan=timespan, 47 | side=orderside, 48 | orderset=orderset, 49 | oldstatus='open', 50 | newstatus='canceled', 51 | statustimestamp=timestamp 52 | ) 53 | } 54 | } 55 | 56 | ############################################################################### 57 | # R (http://r-project.org/) Quantitative Strategy Model Framework 58 | # 59 | # Copyright (c) 2009-2015 60 | # Niklas Kolster, Jan Humme 61 | # 62 | # This library is distributed under the terms of the GNU Public License (GPL) 63 | # for full details see the file COPYING 64 | # 65 | # $Id: ruleRevoke.R 1233 2012-11-01 12:52:25Z braverock $ 66 | # 67 | ############################################################################### 68 | -------------------------------------------------------------------------------- /R/tradeGraphs.R: -------------------------------------------------------------------------------- 1 | #' Draw 3D graphs from tradeStats results using rgl 2 | #' 3 | #' @param stats a data frame generated by tradeStats() 4 | #' @param free.params a vector of length 2, containing the column names for the data to use on the x and z axes 5 | #' @param params.filter - a regular expression to reduce dimensions by filtering on certain columns 6 | #' @param statistics a vector containing the column names to produce graphs for 7 | #' @param title an optional title to be printed above each graph 8 | #' @return invisible -- called for side-effect 9 | #' @examples 10 | #' \dontrun{ 11 | #' tradeGraphs ( 12 | #' stats = stats, 13 | #' free.params = c("Param.indicator.1.nFast", "Param.indicator.2.nSlow"), 14 | #' params.filter = "Param.indicator.2.nSlow < 40 & Param.indicator.1.nFast > 5" 15 | #' statistics = c("Net.Trading.PL", "maxDrawdown", "Avg.Trade.PL", "Num.Trades") 16 | #' title = 'Luxor' 17 | #' ) 18 | #' } 19 | #' @author Jan Humme, rewritten by Chinmay Patil 20 | #' @export 21 | 22 | tradeGraphs <- function(stats, free.params, params.filter = NULL, statistics, title = NULL) 23 | { 24 | # TODO: fix axes to use non scientific notation 25 | # TODO: fix use of full rainbow for small fractions (eg. Profit.Factor, now only uses red) 26 | 27 | if(!requireNamespace("rgl", quietly=TRUE)) 28 | stop('The "rgl" package is required to use this function') 29 | 30 | if(!requireNamespace("reshape2", quietly=TRUE)) 31 | stop('The "reshape2" package is required to use this function') 32 | 33 | if(missing(stats)) stop('stats undefined') 34 | 35 | if(missing(free.params)) stop('free.params undefined') 36 | if(length(free.params) != 2) stop('free.params must be a vector of length 2') 37 | 38 | if(missing(statistics)) stop('must specify at least one statistics column to draw graph') 39 | 40 | var1 <- free.params[1] 41 | var2 <- free.params[2] 42 | 43 | for(var3 in statistics) { 44 | if (length(params.filter) == 0 ) { 45 | data <- stats[,c(var1, var2, var3)] 46 | } else { 47 | data <- subset(stats, eval(parse(text=params.filter)), select = c(var1, var2, var3)) 48 | } 49 | 50 | data_r <- reshape2::recast(data, as.formula(paste0(var1, " ~ ", var2)), 51 | id.var=c(var1,var2), measure.var=c(var3)) 52 | x <- data_r[, 1] 53 | y <- as.numeric(colnames(data_r)[-1]) 54 | z <- unlist(data_r[, -1]) 55 | 56 | col <- heat.colors(length(z))[rank(z)] 57 | 58 | rgl::open3d() 59 | rgl::persp3d(x,y,z, color=col, xlab=var1, ylab=var2, zlab=var3, main = title) 60 | } 61 | } 62 | 63 | ############################################################################### 64 | # R (http://r-project.org/) Quantitative Strategy Model Framework 65 | # 66 | # Copyright (c) 2009-2015 67 | # Peter Carl, Dirk Eddelbuettel, Brian G. Peterson, Jeffrey Ryan, Garrett See, and Joshua Ulrich 68 | # 69 | # This library is distributed under the terms of the GNU Public License (GPL) 70 | # for full details see the file COPYING 71 | # 72 | # $Id$ 73 | # 74 | ############################################################################### 75 | -------------------------------------------------------------------------------- /man/applyStrategy.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/strategy.R 3 | \name{applyStrategy} 4 | \alias{applyStrategy} 5 | \title{apply the strategy to arbitrary market data} 6 | \usage{ 7 | applyStrategy( 8 | strategy, 9 | portfolios, 10 | mktdata = NULL, 11 | parameters = NULL, 12 | ..., 13 | debug = FALSE, 14 | symbols = NULL, 15 | initStrat = FALSE, 16 | updateStrat = FALSE, 17 | initBySymbol = FALSE, 18 | gc = FALSE, 19 | delorders = FALSE, 20 | rule.subset = NULL, 21 | mdenv = NULL 22 | ) 23 | } 24 | \arguments{ 25 | \item{strategy}{an object of type 'strategy' to add the indicator to} 26 | 27 | \item{portfolios}{a list of portfolios to apply the strategy to} 28 | 29 | \item{mktdata}{an xts object containing market data. depending on indicators, may need to be in OHLCV or BBO formats, default NULL} 30 | 31 | \item{parameters}{named list of parameters to be applied during evaluation of the strategy, default NULL} 32 | 33 | \item{...}{any other passthru parameters} 34 | 35 | \item{debug}{if TRUE, return output list} 36 | 37 | \item{symbols}{character vector identifying symbols to initialize a portfolio for, default NULL} 38 | 39 | \item{initStrat}{whether to use (experimental) initialization code, default FALSE} 40 | 41 | \item{updateStrat}{whether to use (experimental) wrapup code, default FALSE} 42 | 43 | \item{initBySymbol}{whether to load and initialize each instrument within the \code{Symbols} loop. See \code{\link{initSymbol}} for details on how 44 | to run a custom function. Moreover, if the argument \code{Interval} is available (as passthrough to \code{updatePortf} via \code{updateStrat}), 45 | each instrument is downsampled to the frequency specified by \code{Interval} for the purpose of marking the Portfolio. 46 | Notice that this happenes only after the strategy has been applied.} 47 | 48 | \item{gc}{if TRUE, call \code{\link{gc}} after each symbol run, default FALSE (experimental)} 49 | 50 | \item{delorders}{if TRUE, delete the order book for a symbol at the end of the symbols loop, will cause issues with rebalancing, default FALSE (experimental)} 51 | 52 | \item{rule.subset}{ISO-8601 subset for period to execute rules over, default NULL} 53 | 54 | \item{mdenv}{environment to look in for market data, default NULL which expands to .GlobalEnv} 55 | } 56 | \description{ 57 | This function is the wrapper that holds together the execution of a strategy. 58 | } 59 | \details{ 60 | After the straetgy object has been created, it may be applied to any 61 | combination of symbols and parameters. 62 | 63 | The symbols to be utilized will be defined in one of two ways, either by 64 | specifying a name of a portfolio that has already been initialized 65 | with the \code{portfolios} argument, or be specifying a 66 | \code{symbols} argument in addition to setting \code{initStrat=TRUE}. 67 | 68 | \code{applyStrategy} will use the \R core function \code{\link{get}} 69 | to load market data for each symbol during stategy evaluation unless 70 | the user passes \code{mktdata} in the call to \code{applyStrategy} 71 | } 72 | \seealso{ 73 | \code{\link{strategy}}, \code{\link{applyIndicators}}, 74 | \code{\link{applySignals}}, \code{\link{applyRules}}, 75 | \code{\link{initStrategy}}, 76 | } 77 | -------------------------------------------------------------------------------- /man/ruleOrderProc.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ruleOrderProc.R 3 | \name{ruleOrderProc} 4 | \alias{ruleOrderProc} 5 | \title{process open orders at time \emph{t}, generating transactions or new orders} 6 | \usage{ 7 | ruleOrderProc( 8 | portfolio, 9 | symbol, 10 | mktdata, 11 | timestamp = NULL, 12 | ordertype = NULL, 13 | ..., 14 | slippageFUN = NULL 15 | ) 16 | } 17 | \arguments{ 18 | \item{portfolio}{text name of the portfolio to associate the order book with} 19 | 20 | \item{symbol}{identfier of the instrument to find orders for. The name of any associated price objects (xts prices, usually OHLC or BBO) should match these} 21 | 22 | \item{mktdata}{an xts object containing market data. depending on indicators, may need to be in OHLCV or BBO formats, default NULL} 23 | 24 | \item{timestamp}{timestamp coercible to POSIXct that will be the time the order will be processed on} 25 | 26 | \item{ordertype}{one of NULL, "market","limit","stoplimit", or "stoptrailing" default NULL} 27 | 28 | \item{...}{any other passthru parameters} 29 | 30 | \item{slippageFUN}{default NULL, not yet implemented} 31 | } 32 | \description{ 33 | The ruleOrderProc function is effectively the default fill simulator for quantstrat. 34 | This function is meant to be sufficient for backtesting most strategies, 35 | but would need to be replaced for production use. It provides the interface 36 | for taking the order book and determining when orders become trades. 37 | 38 | In this version, in contrast with an earlier version, 39 | this function will allow a transaction to cross your current 40 | position through zero. The accounting rules for realizing gains in such cases 41 | are quite complicated, so blotter will split this transaction into two transactions. 42 | Many brokers will break, revise, or split such transactions for the same reason. 43 | } 44 | \details{ 45 | This function would need to be revised or replaced for connection to a live trading infrastructure. 46 | In a production mode, you would replace the \code{\link{addOrder}} function 47 | with a custom function to connect to your market infrastructure. 48 | In that case, you might need to add additional code to your strategy, 49 | or overload functions for checking position. 50 | 51 | Note that this function is called by default in the 'orders' slot of the 52 | \code{\link{applyRules}} processing. If you have defined another order 53 | processing rule, it will \emph{replace} this function. If you want your 54 | custom order rule and ruleOrderProc to both be called, you will need 55 | explicitly add a rule to call ruleOrderProc either before or after your 56 | custom order processing function. 57 | 58 | We would like to model slippage here via \code{slippageFUN}. Code contributions, suggestions, 59 | and requests appreciated. 60 | } 61 | \seealso{ 62 | add.rule 63 | 64 | applyRules 65 | 66 | getOrderBook 67 | 68 | addOrder 69 | 70 | updateOrders 71 | } 72 | \concept{backtest} 73 | \concept{fill simulator} 74 | \concept{fills 75 | 76 | This function is meant to be sufficient for backtesting many/most strategies, 77 | but would need to be replaced for production use. It provides the interface 78 | for taking the order book and determining when orders become trades.} 79 | \concept{orders} 80 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | S3method(print,dof) 4 | S3method(print,haircutSR) 5 | S3method(print,profitHurdle) 6 | export(Federov.constraints) 7 | export(Federov.paramset) 8 | export(SharpeRatio.deflated) 9 | export(SharpeRatio.haircut) 10 | export(add.distribution) 11 | export(add.distribution.constraint) 12 | export(add.indicator) 13 | export(add.init) 14 | export(add.rule) 15 | export(add.signal) 16 | export(addOrder) 17 | export(addPosLimit) 18 | export(apply.paramset) 19 | export(apply.paramset.signal.analysis) 20 | export(applyIndicatorSignals) 21 | export(applyIndicators) 22 | export(applyRules) 23 | export(applySignals) 24 | export(applyStrategy) 25 | export(applyStrategy.rebalancing) 26 | export(beanplot.signals) 27 | export(chart.forward) 28 | export(chart.forward.training) 29 | export(deflatedSharpe) 30 | export(degrees.of.freedom) 31 | export(degreesOfFreedom) 32 | export(delete.paramset) 33 | export(distributional.boxplot) 34 | export(dof) 35 | export(enable.rule) 36 | export(get.orderbook) 37 | export(get.strategy) 38 | export(getOrderBook) 39 | export(getOrders) 40 | export(getPosLimit) 41 | export(getStrategy) 42 | export(haircutSharpe) 43 | export(initOrders) 44 | export(initStrategy) 45 | export(initSymbol) 46 | export(is.strategy) 47 | export(load.strategy) 48 | export(match.names) 49 | export(osMaxPos) 50 | export(osNoOp) 51 | export(post.signal.returns) 52 | export(profit.hurdle) 53 | export(profitHurdle) 54 | export(put.orderbook) 55 | export(put.strategy) 56 | export(rm.strat) 57 | export(ruleCancel) 58 | export(ruleOrderProc) 59 | export(rulePctEquity) 60 | export(ruleRevoke) 61 | export(ruleSignal) 62 | export(save.strategy) 63 | export(sigComparison) 64 | export(sigCrossover) 65 | export(sigFormula) 66 | export(sigPeak) 67 | export(sigThreshold) 68 | export(sigTimestamp) 69 | export(signal.generate.statistics) 70 | export(signal.obj.slope) 71 | export(signal.path.plot) 72 | export(signal.plot) 73 | export(strategy) 74 | export(tradeGraphs) 75 | export(tradeOrderStats) 76 | export(updateOrders) 77 | export(updateStrategy) 78 | export(walk.forward) 79 | import(FinancialInstrument) 80 | import(blotter) 81 | import(foreach) 82 | import(methods) 83 | import(quantmod) 84 | import(xts) 85 | import(zoo) 86 | importFrom(MASS,mvrnorm) 87 | importFrom(TTR,ROC) 88 | importFrom(grDevices,dev.new) 89 | importFrom(grDevices,heat.colors) 90 | importFrom(graphics,abline) 91 | importFrom(graphics,boxplot) 92 | importFrom(graphics,lines) 93 | importFrom(graphics,par) 94 | importFrom(graphics,plot) 95 | importFrom(iterators,iter) 96 | importFrom(methods,hasArg) 97 | importFrom(stats,acf) 98 | importFrom(stats,as.formula) 99 | importFrom(stats,coef) 100 | importFrom(stats,end) 101 | importFrom(stats,lm) 102 | importFrom(stats,median) 103 | importFrom(stats,na.omit) 104 | importFrom(stats,pnorm) 105 | importFrom(stats,pt) 106 | importFrom(stats,qnorm) 107 | importFrom(stats,qt) 108 | importFrom(stats,rexp) 109 | importFrom(stats,runif) 110 | importFrom(stats,start) 111 | importFrom(stats,time) 112 | importFrom(stats,toeplitz) 113 | importFrom(stats,var) 114 | importFrom(utils,glob2rx) 115 | importFrom(utils,globalVariables) 116 | importFrom(utils,head) 117 | importFrom(utils,installed.packages) 118 | useDynLib(quantstrat, .registration=TRUE, .fixes="C_") 119 | -------------------------------------------------------------------------------- /demo/00Index: -------------------------------------------------------------------------------- 1 | bbands Build a simple Bollinger Bands strategy using one indicator, three signals, and three trade rules 2 | bbandsWFA run walk forward analysis on a simple Bollinger Bands strategy 3 | faber demonstrate a simple long term trend model using a 10-month SMA on a small portfolio of ETFs based on Mebane Faber paper 4 | faberMC apply the Faber 10-month SMA strategy to a three-currency index portfolio 5 | faber_rebal apply the Faber 10-month SMA strategy, rebalance quarterly 6 | macd example of Moving Average Convergence/Divergence (MACD) used as a trend indicator 7 | maCross classic 'Golden Cross' 50/200 period moving average cross strategy, long only, with long/short extra rules commented out 8 | pair_trade simple two-instrument long-short equity strategy demonstrating custom indicator and extended order sizing functionality 9 | rsi Relative Strength Index (RSI) strategy demonstrating long-only threshold actions 10 | bee Milktrader's Bumblebee FastMA/BBands cross system 11 | bbandParameters example of parameter test on bbands demo strategy 12 | macdParameters example of parameter test on macd demo strategy 13 | macdRebalancing example of applyStrategy.rebalancing on macd demo strategy 14 | macdWFA Walk Forward Analysis on simple macd strategy 15 | rocema Rate-of-Change EMA strategy: demonstrating ternary indicator, ordersets to handle simultaneous stop-loss and take-profit orders 16 | luxor.1.strategy.basic Jaekle & Tomasini; Sections 3.2: basic luxor strategy not using ordersets or orderchains 17 | luxor.2.add.paramsets Jaekle & Tomasini; Sections 3.3: variation of the input parameters 18 | luxor.3.paramset.sma Jaekle & Tomasini; Sections 3.3: variation of the input parameters 19 | luxor.4.paramset.timespan Jaekle & Tomasini; Sections 3.4: inserting an intraday time filter 20 | luxor.5.strategy.ordersets Jaekle & Tomasini; Sections 3.5: strategy implementation using ordersets and orderchains 21 | luxor.6.paramset.stoploss Jaekle & Tomasini; Sections 3.5: paramset implementation for stoploss optimization 22 | luxor.6.paramset.stoptrailing Jaekle & Tomasini; Sections 3.5: paramset implementation for stop trailing optimization 23 | luxor.6.paramset.takeprofit Jaekle & Tomasini; Sections 3.5: paramset implementation for take profit optimization 24 | luxor.7.exit.and.risk Jaekle & Tomasini; Sections 3.5: running with stoploss and/or stoptrailing and/or takeprofit 25 | luxor.8.walk.forward Jaekle & Tomasini; Sections 6: walk forward analysis 26 | luxor.getSymbols Jaekle & Tomasini; reading symbols 27 | luxor.include Jaekle & Tomasini; Sections constants 28 | luxor.sample.MAE.stoploss Jaekle & Tomasini; sample MAE stoploss graph 29 | luxor.sample.MAE.stoptrailing Jaekle & Tomasini; sample MAE stoptrailing graph 30 | luxor.sample.MFE.takeprofit Jaekle & Tomasini; sample MFE take profit graph 31 | luxor.sample.tradeGraphs.sma Jaekle & Tomasini; sample 3D SMA graph 32 | luxor.sample.tradeGraphs.timespan Jaekle & Tomasini; sample 3D timespan graph 33 | luxor.sample.walk.forward Jaekle & Tomasini; walk forward chart sample 34 | signal.SMA SMA Cross Strategy with Signal Analysis Example; See maCross.R 35 | signal.RSI RSI Cross Strategy with Signal Analysis Example; See rsi.R 36 | maCross_stoptrailing maCross demo with stoptrailing ordertype used in tests/testthat/test_demo_maCross_stoptrailing.R 37 | demo_test_blotter_break test code sourced in the test_blotter_break.R test file 38 | -------------------------------------------------------------------------------- /man/updateStrategy.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/wrapup.R 3 | \name{updateStrategy} 4 | \alias{updateStrategy} 5 | \title{run standard and custom strategy wrapup functions such as updating portfolio, account, and ending equity} 6 | \usage{ 7 | updateStrategy( 8 | strategy, 9 | portfolio = "default", 10 | account = portfolio, 11 | Symbols = NULL, 12 | parameters = NULL, 13 | Dates = NULL, 14 | Prices = NULL, 15 | update.Portf = TRUE, 16 | update.Acct = TRUE, 17 | update.EndEq = TRUE, 18 | showEq = TRUE, 19 | chart = TRUE, 20 | ... 21 | ) 22 | } 23 | \arguments{ 24 | \item{strategy}{object of type \code{strategy} to initialize data/containers for} 25 | 26 | \item{portfolio}{string identifying a portfolio} 27 | 28 | \item{account}{string identifying an account. Same as \code{portfolio} by default} 29 | 30 | \item{Symbols}{character vector of names of symbols whose portfolios will be updated} 31 | 32 | \item{parameters}{named list of parameters to be applied during evaluation of the strategy, default NULL} 33 | 34 | \item{Dates}{optional xts-style ISO-8601 time range to run updatePortf over, default NULL (will use times from Prices)} 35 | 36 | \item{Prices}{optional xts object containing prices and timestamps to mark the book on, default NULL} 37 | 38 | \item{update.Portf}{TRUE/FALSE if TRUE (default) a call will be made to \code{updatePortf}} 39 | 40 | \item{update.Acct}{TRUE/FALSE if TRUE (default) a call will be made to \code{updateAcct}} 41 | 42 | \item{update.EndEq}{TRUE/FALSE if TRUE (default) a call will be made to \code{updateEndEq}} 43 | 44 | \item{showEq}{TRUE/FALSE if TRUE (default) ending equity will be printed to the screen} 45 | 46 | \item{chart}{TRUE/FALSE if TRUE (default) a call will be made to \code{chart.Posn}} 47 | 48 | \item{\dots}{any other passthrough parameters} 49 | } 50 | \description{ 51 | \code{\link{updateStrategy}} will run a series of common wrapup functions at the 52 | beginning of an \code{\link{applyStrategy}} call. This function allows the user to 53 | add arbitrary wrapup functions to the sequence. 54 | } 55 | \details{ 56 | These arbitrary functions will be added to the \code{update} slot of the strategy object 57 | and when \code{applyStrategy} is evaluated, the arbitrary wrapup functions will 58 | be evaluated \emph{before} the standardized functions. 59 | 60 | For example, if you are working with high frequency data, it would be common 61 | to \emph{mark the book} on a lower frequency, perhaps minutes, hours, or even days, 62 | rather than tick. A custom wrapup function could take your high frequency 63 | data and transform it to lower frequency data before the call to \code{\link{updatePortf}}. 64 | 65 | The 'standard wrapup functions included are: 66 | \describe{ 67 | \item{update.Portf}{ if TRUE, will call \code{\link[blotter]{updatePortf}} 68 | to mark the book in the portfolio. 69 | } 70 | \item{update.Acct}{ if TRUE, will call \code{\link[blotter]{updateAcct}} 71 | to mark the blotter account for this test. 72 | } 73 | \item{update.EndEq}{ if TRUE, will call \code{\link[blotter]{updateEndEq}} 74 | to update the account equity after all other accounting has been completed. 75 | } 76 | } 77 | } 78 | \seealso{ 79 | \code{\link{updatePortf}}, \code{\link{updateAcct}}, \code{\link{updateEndEq}}, \code{\link{chart.Posn}} 80 | } 81 | \author{ 82 | Garrett See, Brian Peterson 83 | } 84 | -------------------------------------------------------------------------------- /demo/luxor.8.walk.forward.R: -------------------------------------------------------------------------------- 1 | #!/usr/bin/Rscript --vanilla 2 | # 3 | # Jan Humme (@opentrades) - April 2013 4 | # 5 | # Tested and found to work correctly using blotter r1457 6 | # 7 | # After Jaekle & Tamasini: A new approach to system development and portfolio optimisation (ISBN 978-1-905641-79-6) 8 | # 9 | # Paragraph 3.7 walk forward analysis 10 | 11 | require(quantstrat) 12 | 13 | source(paste0(path.package("quantstrat"),"/demo/luxor.include.R")) 14 | source(paste0(path.package("quantstrat"),"/demo/luxor.getSymbols.R")) 15 | source(paste0(path.package("quantstrat"),"/demo/luxor.5.strategy.ordersets.R")) 16 | 17 | ### foreach and doMC 18 | 19 | require(foreach) 20 | require(doMC) 21 | registerDoMC(cores=8) 22 | 23 | ### robustbase and PerformanceAnalytics 24 | 25 | if (!requireNamespace("robustbase", quietly=TRUE)) 26 | stop("package 'robustbase' required, but not installed") 27 | if (!requireNamespace("PerformanceAnalytics", quietly=TRUE)) 28 | stop("package 'PerformanceAnalytics' required, but not installed") 29 | 30 | ### blotter 31 | 32 | initPortf(portfolio.st, symbols='GBPUSD', currency='USD') 33 | initAcct(account.st, portfolios=portfolio.st, currency='USD', initEq=100000) 34 | 35 | ### quantstrat 36 | 37 | initOrders(portfolio.st) 38 | 39 | load.strategy(strategy.st) 40 | 41 | enable.rule(strategy.st, 'chain', 'StopLoss') 42 | #enable.rule(strategy.st, 'chain', 'StopTrailing') 43 | enable.rule(strategy.st, 'chain', 'TakeProfit') 44 | 45 | addPosLimit( 46 | portfolio=portfolio.st, 47 | symbol='GBPUSD', 48 | timestamp=startDate, 49 | maxpos=.orderqty) 50 | 51 | ### objective function 52 | 53 | ess <- function(account.st, portfolio.st) 54 | { 55 | require(robustbase, quietly=TRUE) 56 | require(PerformanceAnalytics, quietly=TRUE) 57 | 58 | portfolios.st <- ls(pos=.blotter, pattern=paste('portfolio', portfolio.st, '[0-9]*',sep='.')) 59 | pr <- PortfReturns(Account = account.st, Portfolios=portfolios.st) 60 | 61 | my.es <- ES(R=pr, clean='boudt') 62 | 63 | return(my.es) 64 | } 65 | 66 | my.obj.func <- function(x) 67 | { 68 | # pick one of the following objective functions (uncomment) 69 | 70 | #return(max(x$tradeStats$Max.Drawdown) == x$tradeStats$Max.Drawdown) 71 | 72 | #return(max(x$tradeStats$Net.Trading.PL) == x$tradeStats$Net.Trading.PL) 73 | 74 | return(max(x$user.func$GBPUSD.DailyEndEq) == x$user.func$GBPUSD.DailyEndEq) 75 | } 76 | 77 | ### walk.forward 78 | 79 | r <- walk.forward(strategy.st, 80 | paramset.label='WFA', 81 | portfolio.st=portfolio.st, 82 | account.st=account.st, 83 | period='days', 84 | k.training=3, 85 | k.testing=1, 86 | obj.func=my.obj.func, 87 | obj.args=list(x=quote(result$apply.paramset)), 88 | user.func=ess, 89 | user.args=list('account.st'=account.st, 'portfolio.st'=portfolio.st), 90 | audit.prefix='wfa', 91 | anchored=FALSE, 92 | verbose=TRUE) 93 | 94 | ### analyse 95 | 96 | pdf(paste('GBPUSD', .from, .to, 'pdf', sep='.')) 97 | chart.Posn(portfolio.st) 98 | dev.off() 99 | 100 | ts <- tradeStats(portfolio.st) 101 | save(ts, file=paste('GBPUSD', .from, .to, 'RData', sep='.')) 102 | 103 | -------------------------------------------------------------------------------- /R/utils.R: -------------------------------------------------------------------------------- 1 | 2 | must.have.args <- function(supplied.args, mandatory.args) 3 | { 4 | msg <- ': argument(s) missing in call to function ' 5 | 6 | missing.args <- NULL 7 | 8 | for(arg in mandatory.args) 9 | { 10 | if(length(grep(paste('^',arg,'$',sep=''), names(as.list(supplied.args)))) == 0) 11 | { 12 | if(is.null(missing.args)) 13 | missing.args <- arg 14 | else 15 | missing.args <- paste(missing.args, ', ', arg) 16 | } 17 | } 18 | if(length(missing.args) > 0) 19 | { 20 | funcname <- as.character(sys.call(-1)[[1]]) 21 | 22 | stop(paste(missing.args, msg, funcname, sep='')) 23 | } 24 | } 25 | 26 | must.be.environment <- function(e) 27 | { 28 | if(!is.environment(e)) 29 | stop(paste(e, ': not an environment', sep='')) 30 | } 31 | 32 | must.be.strategy <- function(strategy) 33 | { 34 | if(!is.strategy(strategy)) 35 | { 36 | strategy<-try(getStrategy(strategy)) 37 | 38 | if(inherits(strategy,"try-error")) 39 | stop(paste(strategy, ': not a strategy')) 40 | } 41 | return(strategy) 42 | } 43 | 44 | must.be.portfolio <- function(portfolio) 45 | { 46 | if(!is.portfolio(portfolio)) 47 | { 48 | portfolio<-try(.getPortfolio(portfolio)) 49 | 50 | if(inherits(portfolio,"try-error")) 51 | stop(paste(portfolio, ': not a portfolio')) 52 | } 53 | } 54 | 55 | modify.args <- function(formals, arglist, ..., dots=FALSE) 56 | { 57 | # avoid evaluating '...' to make things faster 58 | dots.names <- eval(substitute(alist(...))) 59 | 60 | if(missing(arglist)) 61 | arglist <- NULL 62 | arglist <- c(arglist, dots.names) 63 | 64 | # see 'S Programming' p. 67 for this matching 65 | 66 | # nothing to do if arglist is empty; return formals 67 | if(!length(arglist)) 68 | return(formals) 69 | 70 | argnames <- names(arglist) 71 | if(!is.list(arglist) && !is.null(argnames) && !any(argnames == "")) 72 | stop("'arglist' must be a *named* list, with no names == \"\"") 73 | 74 | .formals <- formals 75 | onames <- names(.formals) 76 | 77 | pm <- pmatch(argnames, onames, nomatch = 0L) 78 | #if(any(pm == 0L)) 79 | # message(paste("some arguments stored for", fun, "do not match")) 80 | names(arglist[pm > 0L]) <- onames[pm] 81 | .formals[pm] <- arglist[pm > 0L] 82 | 83 | # include all elements from arglist if function formals contain '...' 84 | if(dots && !is.null(.formals$...)) { 85 | dotnames <- names(arglist[pm == 0L]) 86 | .formals[dotnames] <- arglist[dotnames] 87 | #.formals$... <- NULL # should we assume we matched them all? 88 | } 89 | 90 | .formals 91 | } 92 | 93 | ############################################################################### 94 | # R (http://r-project.org/) Quantitative Strategy Model Framework 95 | # 96 | # Copyright (c) 2009-2015 97 | # Peter Carl, Dirk Eddelbuettel, Brian G. Peterson, 98 | # Jeffrey Ryan, Joshua Ulrich, and Garrett See 99 | # 100 | # This library is distributed under the terms of the GNU Public License (GPL) 101 | # for full details see the file COPYING 102 | # 103 | # $Id: rules.R 1452 2013-05-04 22:39:39Z opentrades $ 104 | # 105 | ############################################################################### 106 | -------------------------------------------------------------------------------- /man/Federov.paramset.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/Federov.design.R 3 | \name{Federov.paramset} 4 | \alias{Federov.paramset} 5 | \title{construct a full Federov design or a constrained Monte Carlo Federov design for a strategy parameter set} 6 | \usage{ 7 | Federov.paramset( 8 | strategy.st, 9 | paramset.label, 10 | ..., 11 | method = "Federov", 12 | printd = FALSE, 13 | returnlist = FALSE, 14 | approximate = TRUE, 15 | center = TRUE, 16 | constrain = FALSE 17 | ) 18 | } 19 | \arguments{ 20 | \item{strategy.st}{astring describing the name of an object of type `strategy` that contains a parameter set to construct a Federov design for} 21 | 22 | \item{paramset.label}{label describing the paramset to use in the strategy object} 23 | 24 | \item{...}{any other passthrough parameters} 25 | 26 | \item{method}{one of "Federov" or "MonteCarlo", see Details} 27 | 28 | \item{printd}{if TRUE, print the design summary} 29 | 30 | \item{returnlist}{if TRUE, return the list object describing the Federov design, else return just the `param.combos`} 31 | 32 | \item{approximate}{if FALSE, use an exact design, will be slower but more accurate than if TRUE} 33 | 34 | \item{center}{if TRUE, the default, center the parameters around a center value, see Details} 35 | 36 | \item{constrain}{if TRUE, `apply.constraints` for the full Federov design, see Details} 37 | } 38 | \value{ 39 | 40 | } 41 | \description{ 42 | This function provides a wrapper for constructing Federov designs for 43 | parameters by using the parameter set logic of quantstrat and the experiment 44 | design functions from the `AlgDesign` package. It will construct a full or 45 | approximate Federov design via `method="Federov"` (not case sensitive) using 46 | the `optFederov` function and will construct a constrained Monte Carlo 47 | Federov design via `method="MonteCarlo"` using the `optMonteCarlo` function. 48 | } 49 | \details{ 50 | It is important to note from the beginning that while `method="Federov"` is 51 | the default, that the closed form Federov design is not suitable when there 52 | are constraints. We will warn the user if there are constraints in the 53 | strategy specification and a full Federov design is chosen. The function 54 | also supports the option `constrain=TRUE` that will apply constraints to 55 | the full Federov design. For some strategies with many constraints, this 56 | may result in a significantly unbalanced set. This should still be OK as a 57 | starting point for optimization, but may hamper some statistical inference 58 | about parameter interactions and lower the overall power of the design if 59 | the unbalanced nature is severe. 60 | 61 | For now, for constrained Monte Carlo Federov designs, we are not supporting 62 | factor or mixture models, though these designs are supported by the `AlgDesign` 63 | package. Patches welcome, or even just discussion of solid use cases. 64 | 65 | The user may use \dots to pass through any additional parameters for use by 66 | `optFederov` or `optMonteCarlo`. For example, `nLevels`, `nCand`, `nRepeats` 67 | may be candidates for finer grained control. see `?AlgDesign::optMonteCarlo` 68 | for details. We have tried to make reasonable decisions based on the data 69 | contained in the strategy object. `nLevels` defaults to the minimum of 5 70 | (though 3 is a reasonable and smaller choice) or the number of levels 71 | contained in the paramset for that variable. 72 | } 73 | \seealso{ 74 | optFederov 75 | } 76 | -------------------------------------------------------------------------------- /man/setParameterDistribution.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/parameters.R 3 | \name{setParameterDistribution} 4 | \alias{setParameterDistribution} 5 | \title{Function used to create an object that contains the distribution of parameters to be generated from, before testing parameters of a strategy. (deprecated)} 6 | \usage{ 7 | setParameterDistribution( 8 | paramDist = NULL, 9 | strategy, 10 | component.type, 11 | component.label, 12 | distribution = NULL, 13 | weight, 14 | label, 15 | psindex = NULL 16 | ) 17 | } 18 | \arguments{ 19 | \item{paramDist}{The object in which the parameter list is stored; if this parameter is missing, or object does not exist, the function will return a new object.} 20 | 21 | \item{strategy}{The strategy object} 22 | 23 | \item{component.type}{A character string that specifies the type of the strategy component that contains the parameter, it takes the value in one of 'indicator', 'signal', 'enter', 'exit', 'order', 'chain'.} 24 | 25 | \item{component.label}{The label that uniquely identifies the strategy component that contains the parameter} 26 | 27 | \item{distribution}{Distribution of the parameter, can be any function that returns a vector of value. See detail. (A numerical example: 1:10 or sample(1:20,6)} 28 | 29 | \item{weight}{The weight of each value in the distribution, if missing, the default value of all equal weights will be taken.} 30 | 31 | \item{label}{A string label to apply to the parameter distribution} 32 | 33 | \item{psindex}{A number specify the index within the parameter distribution object, it is used to make change/ repalce a parameter distribution in the object.} 34 | } 35 | \value{ 36 | The returned object is a structure contains the distribution of parameters, if the input argument 'paramDist' is provided, the function update the input paramDist object and return the updated one. When specify the distribution of several parameters, usually the first returned object is passed to the next several call of the function as input argument 'paramDist'. See example. 37 | } 38 | \description{ 39 | Each call to the function will set/update the distribution of ONE parameter in the 'parameter distribution object' that is associated with a specific strategy. 40 | } 41 | \details{ 42 | Parameter distribution object for one strategy usually won't work for another strategy, because different strategies has different parameter structure. 43 | Type of the parameter and the sequence in that type is needed to specify the exact parameter in THAT STRATEGY. 44 | 45 | The parameter 'distribution' is a list contains vector of values NAMED WITH THE NAMES OF THE PARAMETERS, the values can be any type (integer, characters, etc) but must match with the legal value of that parameter. 46 | For example: distribution=list(nFast=(10:30)) or distribution=list(relationship=c('gt','gte')) 47 | } 48 | \examples{ 49 | \dontrun{ 50 | #(For complete demo see parameterTestMACD.R) 51 | tPD2<-setParameterDistribution(tPD2, strat, component.type='indicator', component.label='FastSMA', 52 | distribution=list(nFast=(10:30)), label='nFast') 53 | tPD2<-setParameterDistribution(tPD2, strat, component.type='indicator', component.label='SlowSMA', 54 | distribution=list(nSlow=(20:40)), label='nSlow') 55 | tPD2<-setParameterDistribution(tPD2, strat, component.type='signal', component.label='go.long', 56 | distribution=list(relationship=c('gt', 'gte')), label='sig1.gtgte') 57 | } 58 | 59 | } 60 | \author{ 61 | Yu Chen 62 | } 63 | -------------------------------------------------------------------------------- /R/tradeOrderStats.R: -------------------------------------------------------------------------------- 1 | #' get order information associated with closing positions 2 | #' 3 | #' Combine perTradeStats output with closed order information. 4 | #' 5 | #' TODO: decide which of these columns are actually important 6 | #' TODO: add option for opening order/trade pairing rather than closing 7 | #' 8 | #' @param portfolio text name of the portfolio the order book is associated with 9 | #' @param symbol text string defining the symbol to get trades and orders for 10 | #' @param ... any other passthrough parameters 11 | #' @return 12 | #' A \code{xts} object containing: 13 | #' 14 | #' \describe{ 15 | #' \item{Order.Qty}{} 16 | #' \item{Order.Price}{} 17 | #' \item{Order.Type}{} 18 | #' \item{Order.Side}{} 19 | #' \item{Order.Threshold}{} 20 | #' \item{Order.Status}{should be 'closed' only} 21 | #' \item{Order.StatusTime}{time of the closing trade, should match 'End' column} 22 | #' \item{Prefer}{prefer argument for \code{getPrice}} 23 | #' \item{Order.Set}{order set of the closing trade} 24 | #' \item{Txn.Fees}{and fees applied to the closing trade} 25 | #' \item{Rule}{the name of the rule that generated the order which closed the position} 26 | #' \item{Start}{the \code{POSIXct} timestamp of the start of the trade} 27 | #' \item{Init.Pos}{the initial position on opening the trade} 28 | #' \item{Max.Pos}{the maximum (largest) position held during the open trade} 29 | #' \item{Num.Txns}{ the number of transactions included in this trade} 30 | #' \item{Max.Notional.Cost}{ the largest notional investment cost of this trade} 31 | #' \item{Net.Trading.PL}{ net trading P&L in the currency of \code{Symbol}} 32 | #' \item{MAE}{ Maximum Adverse Excursion (MAE), in the currency of \code{Symbol}} 33 | #' \item{MFE}{ Maximum Favorable Excursion (MFE), in the currency of \code{Symbol}} 34 | #' \item{Pct.Net.Trading.PL}{ net trading P&L in percent of invested \code{Symbol} price gained or lost} 35 | #' \item{Pct.MAE}{ Maximum Adverse Excursion (MAE), in percent} 36 | #' \item{Pct.MFE}{ Maximum Favorable Excursion (MFE), in percent} 37 | #' \item{tick.Net.Trading.PL}{ net trading P&L in ticks} 38 | #' \item{tick.MAE}{ Maximum Adverse Excursion (MAE) in ticks} 39 | #' \item{tick.MFE}{ Maximum Favorable Excursion (MFE) in ticks} 40 | #' } 41 | #' @export 42 | tradeOrderStats <- function(portfolio, symbol, ...) { 43 | stats.table <- perTradeStats(Portfolio=portfolio,Symbol=symbol,...) 44 | stats.xts <- as.xts(stats.table, order.by=stats.table$End) 45 | orderbook <- getOrderBook(portfolio=portfolio)[[portfolio]][[symbol]] 46 | closed <- orderbook[which(orderbook$Order.Status=='closed'),] 47 | closed.xts <- xts(closed, as.POSIXct(as.character(closed$Order.StatusTime), tz=tzone(closed), format="%Y-%m-%d %H:%M:%OS")) 48 | merged.table <- merge(closed.xts,stats.xts) 49 | merged.closed <- merged.table[index(stats.xts)] 50 | return(merged.closed) 51 | } 52 | 53 | 54 | ############################################################################### 55 | # R (http://r-project.org/) Quantitative Strategy Model Framework 56 | # 57 | # Copyright (c) 2009-2015 58 | # Peter Carl, Dirk Eddelbuettel, Brian G. Peterson, 59 | # Jeffrey Ryan, Joshua Ulrich, and Garrett See 60 | # 61 | # This library is distributed under the terms of the GNU Public License (GPL) 62 | # for full details see the file COPYING 63 | # 64 | # $Id: ruleOrderProc.R 1435 2013-04-16 15:23:34Z bodanker $ 65 | # 66 | ############################################################################### 67 | -------------------------------------------------------------------------------- /man/profitHurdle.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/profit.hurdle.R 3 | \name{profitHurdle} 4 | \alias{profitHurdle} 5 | \alias{profit.hurdle} 6 | \title{Profit Hurdle function - A Minimum Profitability Method for Proposed Trading Strategies} 7 | \usage{ 8 | profitHurdle( 9 | portfolios, 10 | ..., 11 | strategy = NULL, 12 | trials = NULL, 13 | alpha_sig = 0.05, 14 | vol_annual = 0.1, 15 | RHO = 0.2, 16 | audit = NULL, 17 | env = .GlobalEnv 18 | ) 19 | } 20 | \arguments{ 21 | \item{portfolios}{string name of portfolio, or optionally a vector of portfolios, see DETAILS} 22 | 23 | \item{...}{any other passthrough parameters} 24 | 25 | \item{strategy}{optional strategy specification that would contain more information on the process, default NULL} 26 | 27 | \item{trials}{optional number of trials,default NULL} 28 | 29 | \item{alpha_sig}{Significance level e.g. 0.05 ie. 5\%, default 0.05} 30 | 31 | \item{vol_annual}{Annual return volatility e.g. 0.10 ie. 10\%, default 0.10} 32 | 33 | \item{RHO}{Assumed average correlation, default 0.2} 34 | 35 | \item{audit}{optional audit environment containing the results of parameter optimization or walk forward, default NULL} 36 | 37 | \item{env}{optional environment to find market data in, if required} 38 | } 39 | \value{ 40 | an object of type \code{profitHurdle} containing: 41 | 42 | \itemize{ 43 | \item{Significance Level: the significance level used to determine the minimum required average monthly return} 44 | \item{Number of Monthly Observations: the number of monthly observations in the strategy, converted from one of either daily, weekly, monthly, quarterly or yearly} 45 | \item{Annualized Return Volatility: the annualized volatility of the strategy returns} 46 | \item{Assumed Number of Tests: the number of tests assumed and needed to account for in multiple testing adjustment} 47 | \item{Assumed Average Correlation: assumed average level of correlation among strategy returns} 48 | \item{Independent: unadjusted return hurdle, implying single test significance} 49 | \item{Bonferroni: the Bonferroni adjusted return hurdle for the given level of significance} 50 | \item{Holm: the Holm adjusted return hurdle for the given level of significance} 51 | \item{BHY: the BHY adjusted return hurdle for the given level of significance} 52 | \item{Average for Multiple Tests: the average multiple testing return hurdle for the given level of significance} 53 | } 54 | } 55 | \description{ 56 | Based on their 2015 JPM paper "Backtesting", Campbell Harvey and Yan Liu (HL) propose 57 | and demonstrate three methods of adjusting for potential multiple testing bias. 58 | Using their model they propose haircuts for Sharpe ratios returned by trading strategies 59 | (see \code{\link{haircutSharpe}}). 60 | HL pose another way of viewing the problem is to ascertain a minimum average monthly 61 | return for a given significance level. This is replicated in \code{quantstrat} with the 62 | \code{profitHurdle} function. 63 | } 64 | \references{ 65 | Harvey, Campbell R. and Yan Liu. 2015. Backtesting The Journal of Portfolio Management. 41:1 pp. 13-28. 66 | 67 | Harvey, Campbell R., Yan Liu, and Heqing Zhu. 2016. "... and the cross-section of expected returns." The Review of Financial Studies 29, no. 1 (2016): 5-68. 68 | 69 | Mackie, Jasen. 2016. R-view: Backtesting - Harvey & Liu (2015). https://opensourcequant.wordpress.com/2016/11/17/r-view-backtesting-harvey-liu-2015/ 70 | } 71 | \seealso{ 72 | \code{\link{SharpeRatio.haircut}} 73 | } 74 | \author{ 75 | Jasen Mackie, Brian G. Peterson 76 | } 77 | -------------------------------------------------------------------------------- /demo/luxor.1.strategy.basic.R: -------------------------------------------------------------------------------- 1 | #!/usr/bin/Rscript --vanilla 2 | # 3 | # Jan Humme (@opentrades) - August 2012, revised April 2013 4 | # 5 | # Tested and found to work correctly using blotter r1457 6 | # 7 | # After Jaekle & Tamasini: A new approach to system development and portfolio optimisation (ISBN 978-1-905641-79-6) 8 | # 9 | # Paragraph 3.2: luxor with slippage and transaction costs 10 | 11 | require(quantstrat) 12 | 13 | source(paste0(path.package("quantstrat"),"/demo/luxor.include.R")) 14 | .fast = 10 15 | .slow = 30 16 | 17 | source(paste0(path.package("quantstrat"),"/demo/luxor.getSymbols.R")) 18 | 19 | ### blotter 20 | 21 | initPortf(portfolio.st, symbols='GBPUSD', currency='USD') 22 | initAcct(account.st, portfolios=portfolio.st, currency='USD') 23 | 24 | ### quantstrat 25 | 26 | initOrders(portfolio.st) 27 | 28 | ### define strategy 29 | 30 | strategy(strategy.st, store=TRUE) 31 | 32 | ### indicators 33 | 34 | add.indicator(strategy.st, name = "SMA", 35 | arguments = list( 36 | x = quote(Cl(mktdata)[,1]), 37 | n = .fast 38 | ), 39 | label="nFast" 40 | ) 41 | 42 | add.indicator(strategy.st, name="SMA", 43 | arguments = list( 44 | x = quote(Cl(mktdata)[,1]), 45 | n = .slow 46 | ), 47 | label="nSlow" 48 | ) 49 | 50 | ### signals 51 | 52 | add.signal(strategy.st, name='sigCrossover', 53 | arguments = list( 54 | columns=c("nFast","nSlow"), 55 | relationship="gte" 56 | ), 57 | label='long' 58 | ) 59 | 60 | add.signal(strategy.st, name='sigCrossover', 61 | arguments = list( 62 | columns=c("nFast","nSlow"), 63 | relationship="lt" 64 | ), 65 | label='short' 66 | ) 67 | 68 | ### rules 69 | 70 | add.rule(strategy.st, name='ruleSignal', 71 | arguments=list(sigcol='long' , sigval=TRUE, 72 | orderside='short', 73 | ordertype='market', 74 | orderqty='all', 75 | TxnFees=.txnfees, 76 | replace=TRUE 77 | ), 78 | type='exit', 79 | label='Exit2LONG' 80 | ) 81 | 82 | add.rule(strategy.st, name='ruleSignal', 83 | arguments=list(sigcol='short', sigval=TRUE, 84 | orderside='long' , 85 | ordertype='market', 86 | orderqty='all', 87 | TxnFees=.txnfees, 88 | replace=TRUE 89 | ), 90 | type='exit', 91 | label='Exit2SHORT' 92 | ) 93 | 94 | add.rule(strategy.st, name='ruleSignal', 95 | arguments=list(sigcol='long' , sigval=TRUE, 96 | orderside='long' , 97 | ordertype='stoplimit', prefer='High', threshold=.threshold, 98 | orderqty=+.orderqty, 99 | replace=FALSE 100 | ), 101 | type='enter', 102 | label='EnterLONG' 103 | ) 104 | 105 | add.rule(strategy.st, name='ruleSignal', 106 | arguments=list(sigcol='short', sigval=TRUE, 107 | orderside='short', 108 | ordertype='stoplimit', prefer='Low', threshold=-.threshold, 109 | orderqty=-.orderqty, 110 | replace=FALSE 111 | ), 112 | type='enter', 113 | label='EnterSHORT' 114 | ) 115 | 116 | ############################################################################### 117 | 118 | applyStrategy(strategy.st, portfolio.st) 119 | 120 | print(getOrderBook(portfolio.st)[[portfolio.st]]$GBPUSD) 121 | 122 | ############################################################################### 123 | 124 | updatePortf(portfolio.st, Symbols='GBPUSD', Dates=paste('::',as.Date(Sys.time()),sep='')) 125 | 126 | chart.Posn(portfolio.st, "GBPUSD") 127 | 128 | ############################################################################### 129 | 130 | print(t(tradeStats(portfolio.st, 'GBPUSD'))) 131 | 132 | ############################################################################### 133 | 134 | # save the strategy in an .RData object for later retrieval 135 | 136 | save.strategy(strategy.st) 137 | -------------------------------------------------------------------------------- /man/apply.paramset.signal.analysis.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/signals.R 3 | \name{apply.paramset.signal.analysis} 4 | \alias{apply.paramset.signal.analysis} 5 | \title{Signal Analysis With Parmeter Optimization} 6 | \usage{ 7 | apply.paramset.signal.analysis( 8 | strategy.st, 9 | paramset.label, 10 | portfolio.st, 11 | sigcol, 12 | sigval, 13 | on, 14 | forward.days, 15 | cum.sum = TRUE, 16 | include.day.of.signal, 17 | obj.fun, 18 | decreasing = TRUE, 19 | mktdata = NULL, 20 | verbose = TRUE 21 | ) 22 | } 23 | \arguments{ 24 | \item{strategy.st}{an object of type 'strategy' to add the indicator to} 25 | 26 | \item{paramset.label}{a label uniquely identifying the paramset within the strategy} 27 | 28 | \item{portfolio.st}{text name of the portfolio to associate the order book with} 29 | 30 | \item{sigcol}{column name to check for signal} 31 | 32 | \item{sigval}{signal value to match against} 33 | 34 | \item{on}{the periods endpoints to find as a character string} 35 | 36 | \item{forward.days}{days to exit post signal} 37 | 38 | \item{cum.sum}{whether to use cumsum on price changes} 39 | 40 | \item{include.day.of.signal}{whether to include the day of signal generation} 41 | 42 | \item{obj.fun}{objective function for determining goodness of each paramset} 43 | 44 | \item{decreasing}{if \code{TRUE} (the default), larger objective function values are better} 45 | 46 | \item{mktdata}{market data} 47 | 48 | \item{verbose}{whether to output processing messages} 49 | } 50 | \value{ 51 | A list of objects that contains the results 52 | \describe{ 53 | \item{signals}{List of signals named by parameter combination. Each object within the list is a XTS object with columns being assets and rows being signals.} 54 | \item{sigret.by.paramset}{List of list. Sorted by parameter combination and then by asset. Contains matrix of next day returns; columns are period (N day look ahead) and rows are signals} 55 | \item{sigret.by.asset}{List of list. Sorted by Asset and then by parameter combinations. Contains same matrix as sigret.by.paramset} 56 | \item{signal.stats}{List of signal statistics as calculated via custom user defined fitness function. Sorted by assets.} 57 | } 58 | } 59 | \description{ 60 | This function allows user to analyze signals independently from rules. 61 | } 62 | \details{ 63 | This function is similar to \code{applyParameter} but includes additionally \code{applySignal} wrapped within it. To use it, the user 64 | will need to initially define the distribution and constraints by using \code{add.distribution} and \code{add.distribution.constraint}. 65 | 66 | More generally, the function is designed to generate signals across various parameter combinations defined within the distribution and 67 | constraints. Afterwards it extract the next N day price changes for further anlaysis. 68 | 69 | The parameter \code{on} allows user to calculate post signal returns in different frequencies. Different signals have different timeframes effectiveness. 70 | \code{forward.days} lets the user select the number of post signal days to analyze results. 71 | 72 | To determine the goodness of a parameter set relative to all others, we let the user specify their own objective function (via parameter \code{obj.func}) 73 | that will be used to calculate an objective value representing each parameter. These will then be sorted from best to worst. The 74 | objective function will take in a single matrix \code{ret.mat} of price changes. Each row represents an individual signal 75 | while each column represents periods/post signal. 76 | } 77 | \seealso{ 78 | \code{\link{add.distribution}} 79 | \code{\link{add.distribution.constraint}} 80 | } 81 | \author{ 82 | Michael Guan 83 | } 84 | -------------------------------------------------------------------------------- /R/chart.forward.training.R: -------------------------------------------------------------------------------- 1 | #' Chart to analyse walk.forward() objective function 2 | #' 3 | #' The \code{\link{walk.forward}} function creates an audit environment, written 4 | #' out as a results file, which contains the out of sample results of the (chosen) 5 | #' parameter set. It also writes out in-sample audit environment files for each 6 | #' training period. 7 | #' 8 | #' This function reads one of those training files and will construct a performance 9 | #' chart of the in-sample performance of all the parameter sets during the training 10 | #' period, including the in-sample performance of the chosen parameter set. 11 | #' 12 | #' Note that parameter \code{audit filename} may also be an audit environment 13 | #' which is already loaded in \R, for ease of development and debugging. Little 14 | #' checking is done to ensure the correct structure of this environment, so passing 15 | #' an unsuitable environment (such as the .blotter environment) will result in 16 | #' errors. 17 | #' 18 | #' @param audit.filename name of .audit environment file as produced by walk.forward(). 19 | #' Filename will match pattern [audit.prefix].[symbol].[start timestamp].[end timestamp].RData. 20 | #' 21 | #' @seealso \code{\link{walk.forward}}, \code{\link{chart.forward}} 22 | #' @export 23 | chart.forward.training <- function(audit.filename) 24 | { 25 | if(is.environment(audit.filename)){ 26 | .audit <- audit.filename 27 | } else { 28 | .audit <- NULL # keep codetools happy 29 | # ensure correct training file written by walk.forward() is provided 30 | datePattern <- "[[:digit:]]{8}T[[:digit:]]{6}?" 31 | if (!grepl(paste0(datePattern, "\\.", datePattern, "\\.RData$"), audit.filename[1L])) { 32 | stop("'audit.filename' should match pattern:\n [audit.prefix].[symbol].[start timestamp].[end timestamp].RData for trainging file written by walk.forward.") 33 | } 34 | if (file.exists(audit.filename)) { 35 | load(audit.filename) 36 | } else { 37 | stop("'audit.filename', ", audit.filename, " not found.") 38 | } 39 | } 40 | 41 | # extract all portfolio names from the audit environment 42 | # NB: training data only has portfolios that end in digits 43 | portfolios.st = ls(name=.audit, pattern='portfolio.*') 44 | n <- length(portfolios.st) 45 | 46 | # calculate Net.Trading.PL for each portfolio, one xts col per portfolio 47 | PL.xts <- xts() 48 | for(portfolio.st in portfolios.st) 49 | { 50 | p <- getPortfolio(portfolio.st, envir=.audit) 51 | 52 | from <- index(p$summary[2]) 53 | 54 | #R <- cumsum(p$summary['2004-01-01/','Net.Trading.PL']) 55 | R <- cumsum(p$summary[paste(from, '/', sep=''),'Net.Trading.PL']) 56 | names(R) <- portfolio.st 57 | 58 | PL.xts <- cbind(PL.xts, R) 59 | } 60 | 61 | # .audit$param.combo.nr contains the rowname of the best portfolio 62 | chosen.one <- .audit$param.combo.nr[1L] 63 | chosen.portfolio.st = ls(name=.audit, pattern=glob2rx(paste('portfolio', '*', chosen.one, sep='.'))) 64 | # add a column for the chosen portfolio, doubling it and 65 | # making it plot last (first column, per PerfA convention) 66 | # so it's not over-plotted by other portfolios 67 | R <- PL.xts[,chosen.portfolio.st] 68 | PL.xts <- cbind(R, PL.xts) 69 | 70 | PL.xts <- na.locf(PL.xts) 71 | 72 | # add drawdown columns for all portfolio columns 73 | CumMax <- cummax(PL.xts) 74 | Drawdowns.xts <- -(CumMax - PL.xts) 75 | data.to.plot <- as.xts(cbind(PL.xts, Drawdowns.xts)) 76 | 77 | # based on the suggestion by Ross, note that the number of 78 | # lines is increased by 1 since the 'chosen' portfolio is added as the last one 79 | # and highlighted using the blue color 80 | p <- plot(PL.xts, col=c("blue", rep("grey", n )), main="Walk Forward Analysis") 81 | # set on=NA so it is drawn on a new panel 82 | p <- lines(Drawdowns.xts, col=c("blue", rep("grey", n )), on=NA, main="Drawdowns") 83 | print(p) 84 | } 85 | --------------------------------------------------------------------------------