常有人问我能用几分钟时间写一段代码进行一个简易的量化投资策略的开发和回测吗,答案是当然可以。对于量化投资而言,门槛永远不是编程和代码,而是投资思路和模型解读。下面我们用五分钟左右的时间来开发一个基于 SMA 指标的量化投资策略并进行回测。
引言
本文的代码基于R软件和 Rstuido 软件运行,如果未安装上述软件,请自行安装。
策略开发还需要基于以下 R 包来实现,可以运行如下代码安装并加载相关 R 包。
# 安装依赖包,如果未安装
install.packages(c("quantstrat", "Tushare", "xts", "dplyr", "showtext", "zoo","PerformanceAnalytics","tidyverse"))
# 加载软件包
suppressMessages({
library(quantmod)
library(quantstrat)
library(PerformanceAnalytics)
library(Tushare)
library(xts)
library(dplyr)
library(zoo)
library(tidyverse)
})
清理环境
第一步,先清理历史环境,避免历史环境的干扰。
# 清理历史环境
rm(list=ls(.blotter), envir=.blotter)
rm(list=ls(.strategy), envir=.strategy)
策略开发
下面进入正式开发流程。
初始化设置
# 参数设置
initDate <- "2009-12-31"
fromDate <- "2010-01-01"
endDate <- Sys.Date()
symbol <- "600519.SS"
initEq <- 100000
fastMA <- 5
slowMA <- 20
获取数据
使用quantmod获取贵州茅台数据
# 获取数据
getSymbols(symbol, from=fromDate, to=endDate, src="yahoo")
## [1] "600519.SS"
maotai <- `600519.SS`
colnames(maotai) <- c("Open","High","Low","Close","Volume","Adjusted")
初始化策略
currency("RMB")
## [1] "RMB"
stock(symbol, currency="RMB", multiplier=1)
## [1] "X600519.SS"
strategy.st <- "maotai_sma"
portfolio.st <- "maotai_portfolio"
account.st <- "maotai_account"
# 清除旧策略(如果存在)
if(exists("strategy.st", where=.strategy)) {
rm.strat(strategy.st)
}
# 创建组合/账户/策略
initPortf(portfolio.st, symbols=symbol, initDate=initDate)
## [1] "maotai_portfolio"
initAcct(account.st, portfolios=portfolio.st, initDate=initDate, initEq=initEq)
## [1] "maotai_account"
initOrders(portfolio.st, initDate=initDate)
strategy(strategy.st, store=TRUE)
添加指标
这里添加的简单移动平均线(SMA):
# 添加指标
add.indicator(
strategy.st,
name="SMA",
arguments=list(x=quote(Cl(mktdata)), n=fastMA),
label="fastMA"
)
## [1] "maotai_sma"
add.indicator(
strategy.st,
name="SMA",
arguments=list(x=quote(Cl(mktdata)), n=slowMA),
label="slowMA"
)
## [1] "maotai_sma"
添加信号 - 金叉死叉
# 添加信号
add.signal(
strategy.st,
name="sigCrossover",
arguments=list(columns=c("fastMA","slowMA"), relationship="gt"),
label="fast.gt.slow"
)
## [1] "maotai_sma"
add.signal(
strategy.st,
name="sigCrossover",
arguments=list(columns=c("fastMA","slowMA"), relationship="lt"),
label="fast.lt.slow"
)
## [1] "maotai_sma"
添加交易规则
add.rule(
strategy.st,
name="ruleSignal",
arguments=list(
sigcol="fast.gt.slow",
sigval=TRUE,
orderqty=100,
ordertype="market",
orderside="long",
replace=FALSE
),
type="enter",
label="EnterLONG"
)
## [1] "maotai_sma"
add.rule(
strategy.st,
name="ruleSignal",
arguments=list(
sigcol="fast.lt.slow",
sigval=TRUE,
orderqty="all",
ordertype="market",
orderside="long",
replace=FALSE
),
type="exit",
label="ExitLONG"
)
## [1] "maotai_sma"
策略回测
applyStrategy(strategy.st,
portfolios=portfolio.st)
## [1] "2010-05-25 00:00:00 600519.SS 100 @ 98.6100692749023"
## [1] "2010-06-01 00:00:00 600519.SS -100 @ 99.6468811035156"
## [1] "2010-06-03 00:00:00 600519.SS 100 @ 101.450035095215"
## [1] "2010-06-23 00:00:00 600519.SS -100 @ 98.9481582641602"
## [1] "2010-07-15 00:00:00 600519.SS 100 @ 99.0458297729492"
## [1] "2010-10-15 00:00:00 600519.SS -100 @ 120.195343017578"
## [1] "2010-10-25 00:00:00 600519.SS 100 @ 129.977462768555"
## [1] "2010-11-02 00:00:00 600519.SS -100 @ 122.216377258301"
## [1] "2010-11-11 00:00:00 600519.SS 100 @ 132.171295166016"
## [1] "2010-12-23 00:00:00 600519.SS -100 @ 143.283248901367"
## [1] "2011-02-11 00:00:00 600519.SS 100 @ 138.940643310547"
## [1] "2011-03-02 00:00:00 600519.SS -100 @ 133.140487670898"
## [1] "2011-03-16 00:00:00 600519.SS 100 @ 136.619079589844"
## [1] "2011-03-31 00:00:00 600519.SS -100 @ 135.123962402344"
## [1] "2011-04-27 00:00:00 600519.SS 100 @ 136.100677490234"
## [1] "2011-08-25 00:00:00 600519.SS -100 @ 171.421493530273"
## [1] "2011-08-29 00:00:00 600519.SS 100 @ 177.909088134766"
## [1] "2011-09-07 00:00:00 600519.SS -100 @ 171.561981201172"
## [1] "2011-10-20 00:00:00 600519.SS 100 @ 157.933883666992"
## [1] "2011-11-18 00:00:00 600519.SS -100 @ 165.760330200195"
## [1] "2011-11-28 00:00:00 600519.SS 100 @ 176.752059936523"
## [1] "2011-12-09 00:00:00 600519.SS -100 @ 165.140487670898"
## [1] "2012-02-07 00:00:00 600519.SS 100 @ 153.603302001953"
## [1] "2012-04-06 00:00:00 600519.SS -100 @ 171.876037597656"
## [1] "2012-04-10 00:00:00 600519.SS 100 @ 171.991729736328"
## [1] "2012-05-21 00:00:00 600519.SS -100 @ 184.454544067383"
## [1] "2012-06-01 00:00:00 600519.SS 100 @ 198.652893066406"
## [1] "2012-06-29 00:00:00 600519.SS -100 @ 197.644622802734"
## [1] "2012-07-04 00:00:00 600519.SS 100 @ 213.768600463867"
## [1] "2012-07-24 00:00:00 600519.SS -100 @ 206.099166870117"
## [1] "2012-08-10 00:00:00 600519.SS 100 @ 205.132232666016"
## [1] "2012-08-17 00:00:00 600519.SS -100 @ 189.768600463867"
## [1] "2012-09-10 00:00:00 600519.SS 100 @ 199.735534667969"
## [1] "2012-09-26 00:00:00 600519.SS -100 @ 194.933883666992"
## [1] "2012-09-28 00:00:00 600519.SS 100 @ 203.140487670898"
## [1] "2012-10-30 00:00:00 600519.SS -100 @ 202.132232666016"
## [1] "2012-11-05 00:00:00 600519.SS 100 @ 200.760330200195"
## [1] "2012-11-07 00:00:00 600519.SS -100 @ 196.256195068359"
## [1] "2012-12-19 00:00:00 600519.SS 100 @ 181.363632202148"
## [1] "2013-01-17 00:00:00 600519.SS -100 @ 169.528930664062"
## [1] "2013-03-12 00:00:00 600519.SS 100 @ 150.561981201172"
## [1] "2013-03-19 00:00:00 600519.SS -100 @ 136.512390136719"
## [1] "2013-04-16 00:00:00 600519.SS 100 @ 143.107437133789"
## [1] "2013-06-17 00:00:00 600519.SS -100 @ 156.59504699707"
## [1] "2013-07-04 00:00:00 600519.SS 100 @ 162.495864868164"
## [1] "2013-07-16 00:00:00 600519.SS -100 @ 157.809921264648"
## [1] "2013-08-14 00:00:00 600519.SS 100 @ 147.677688598633"
## [1] "2013-08-23 00:00:00 600519.SS -100 @ 142.966949462891"
## [1] "2013-10-18 00:00:00 600519.SS 100 @ 118.16529083252"
## [1] "2013-10-30 00:00:00 600519.SS -100 @ 109.578514099121"
## [1] "2013-11-13 00:00:00 600519.SS 100 @ 119.603302001953"
## [1] "2013-11-28 00:00:00 600519.SS -100 @ 117.214874267578"
## [1] "2013-12-02 00:00:00 600519.SS 100 @ 113.041320800781"
## [1] "2013-12-03 00:00:00 600519.SS -100 @ 113.702476501465"
## [1] "2014-01-23 00:00:00 600519.SS 100 @ 110.818183898926"
## [1] "2014-03-31 00:00:00 600519.SS -100 @ 127.85124206543"
## [1] "2014-04-09 00:00:00 600519.SS 100 @ 135"
## [1] "2014-04-30 00:00:00 600519.SS -100 @ 135.438018798828"
## [1] "2014-06-11 00:00:00 600519.SS 100 @ 127.223136901855"
## [1] "2014-08-14 00:00:00 600519.SS -100 @ 146.781814575195"
## [1] "2014-09-05 00:00:00 600519.SS 100 @ 152.281814575195"
## [1] "2014-09-18 00:00:00 600519.SS -100 @ 144.772720336914"
## [1] "2014-10-08 00:00:00 600519.SS 100 @ 146.118179321289"
## [1] "2014-10-13 00:00:00 600519.SS -100 @ 141.909088134766"
## [1] "2014-11-18 00:00:00 600519.SS 100 @ 141.5"
## [1] "2014-11-25 00:00:00 600519.SS -100 @ 140.581817626953"
## [1] "2014-11-27 00:00:00 600519.SS 100 @ 142.43635559082"
## [1] "2015-01-16 00:00:00 600519.SS -100 @ 169.190902709961"
## [1] "2015-02-12 00:00:00 600519.SS 100 @ 166.881820678711"
## [1] "2015-05-19 00:00:00 600519.SS -100 @ 227.309097290039"
## [1] "2015-05-25 00:00:00 600519.SS 100 @ 260.754547119141"
## [1] "2015-06-09 00:00:00 600519.SS -100 @ 235.481811523438"
## [1] "2015-07-07 00:00:00 600519.SS 100 @ 221.981811523438"
## [1] "2015-07-08 00:00:00 600519.SS -100 @ 215.327270507812"
## [1] "2015-07-14 00:00:00 600519.SS 100 @ 226.409088134766"
## [1] "2015-07-21 00:00:00 600519.SS -100 @ 221.660003662109"
## [1] "2015-09-15 00:00:00 600519.SS 100 @ 202"
## [1] "2015-09-29 00:00:00 600519.SS -100 @ 190.169998168945"
## [1] "2015-10-15 00:00:00 600519.SS 100 @ 199.990005493164"
## [1] "2015-11-20 00:00:00 600519.SS -100 @ 213.720001220703"
## [1] "2015-12-07 00:00:00 600519.SS 100 @ 214.509994506836"
## [1] "2015-12-11 00:00:00 600519.SS -100 @ 211.410003662109"
## [1] "2015-12-21 00:00:00 600519.SS 100 @ 227.029998779297"
## [1] "2016-01-05 00:00:00 600519.SS -100 @ 212.820007324219"
## [1] "2016-02-05 00:00:00 600519.SS 100 @ 203.869995117188"
## [1] "2016-04-18 00:00:00 600519.SS -100 @ 243.679992675781"
## [1] "2016-05-03 00:00:00 600519.SS 100 @ 260"
## [1] "2016-05-20 00:00:00 600519.SS -100 @ 251.259994506836"
## [1] "2016-05-27 00:00:00 600519.SS 100 @ 252.440002441406"
## [1] "2016-08-03 00:00:00 600519.SS -100 @ 306.820007324219"
## [1] "2016-08-12 00:00:00 600519.SS 100 @ 316.970001220703"
## [1] "2016-08-22 00:00:00 600519.SS -100 @ 307.320007324219"
## [1] "2016-10-13 00:00:00 600519.SS 100 @ 303.890014648438"
## [1] "2016-11-18 00:00:00 600519.SS -100 @ 310"
## [1] "2016-11-29 00:00:00 600519.SS 100 @ 323.959991455078"
## [1] "2016-12-26 00:00:00 600519.SS -100 @ 324.480010986328"
## [1] "2017-01-04 00:00:00 600519.SS 100 @ 351.910003662109"
## [1] "2017-02-07 00:00:00 600519.SS -100 @ 343.579986572266"
## [1] "2017-02-16 00:00:00 600519.SS 100 @ 348.089996337891"
## [1] "2017-07-05 00:00:00 600519.SS -100 @ 460.130004882812"
## [1] "2017-07-25 00:00:00 600519.SS 100 @ 477.959991455078"
## [1] "2017-09-07 00:00:00 600519.SS -100 @ 481.269989013672"
## [1] "2017-09-19 00:00:00 600519.SS 100 @ 496.950012207031"
## [1] "2017-11-27 00:00:00 600519.SS -100 @ 621.289978027344"
## [1] "2017-12-15 00:00:00 600519.SS 100 @ 653.789978027344"
## [1] "2018-01-31 00:00:00 600519.SS -100 @ 764.539978027344"
## [1] "2018-02-28 00:00:00 600519.SS 100 @ 725.619995117188"
## [1] "2018-03-14 00:00:00 600519.SS -100 @ 726.880004882812"
## [1] "2018-03-15 00:00:00 600519.SS 100 @ 746.469970703125"
## [1] "2018-03-27 00:00:00 600519.SS -100 @ 714.739990234375"
## [1] "2018-05-10 00:00:00 600519.SS 100 @ 714.190002441406"
## [1] "2018-06-25 00:00:00 600519.SS -100 @ 765.559997558594"
## [1] "2018-07-17 00:00:00 600519.SS 100 @ 742.429992675781"
## [1] "2018-08-02 00:00:00 600519.SS -100 @ 695.840026855469"
## [1] "2018-08-30 00:00:00 600519.SS 100 @ 680.400024414062"
## [1] "2018-09-06 00:00:00 600519.SS -100 @ 644"
## [1] "2018-09-21 00:00:00 600519.SS 100 @ 700.010009765625"
## [1] "2018-10-16 00:00:00 600519.SS -100 @ 667.140014648438"
## [1] "2018-12-04 00:00:00 600519.SS 100 @ 602.22998046875"
## [1] "2018-12-24 00:00:00 600519.SS -100 @ 568"
## [1] "2019-01-07 00:00:00 600519.SS 100 @ 605.489990234375"
## [1] "2019-05-09 00:00:00 600519.SS -100 @ 858.809997558594"
## [1] "2019-06-03 00:00:00 600519.SS 100 @ 892"
## [1] "2019-06-06 00:00:00 600519.SS -100 @ 862.130004882812"
## [1] "2019-06-14 00:00:00 600519.SS 100 @ 913"
## [1] "2019-07-16 00:00:00 600519.SS -100 @ 968"
## [1] "2019-08-01 00:00:00 600519.SS 100 @ 959.299987792969"
## [1] "2019-08-06 00:00:00 600519.SS -100 @ 946.299987792969"
## [1] "2019-08-13 00:00:00 600519.SS 100 @ 1017.95001220703"
## [1] "2019-09-17 00:00:00 600519.SS -100 @ 1094.01000976562"
## [1] "2019-09-23 00:00:00 600519.SS 100 @ 1149"
## [1] "2019-10-25 00:00:00 600519.SS -100 @ 1171.34997558594"
## [1] "2019-10-31 00:00:00 600519.SS 100 @ 1180.01000976562"
## [1] "2019-11-27 00:00:00 600519.SS -100 @ 1189.94995117188"
## [1] "2019-12-20 00:00:00 600519.SS 100 @ 1146.30004882812"
## [1] "2019-12-26 00:00:00 600519.SS -100 @ 1135.09997558594"
## [1] "2019-12-31 00:00:00 600519.SS 100 @ 1183"
## [1] "2020-01-06 00:00:00 600519.SS -100 @ 1077.98999023438"
## [1] "2020-02-14 00:00:00 600519.SS 100 @ 1088"
## [1] "2020-03-02 00:00:00 600519.SS -100 @ 1086.01000976562"
## [1] "2020-03-05 00:00:00 600519.SS 100 @ 1171"
## [1] "2020-03-18 00:00:00 600519.SS -100 @ 1007.98999023438"
## [1] "2020-04-03 00:00:00 600519.SS 100 @ 1139.7900390625"
## [1] "2020-07-29 00:00:00 600519.SS -100 @ 1672"
## [1] "2020-08-19 00:00:00 600519.SS 100 @ 1687"
## [1] "2020-09-11 00:00:00 600519.SS -100 @ 1733"
## [1] "2020-09-17 00:00:00 600519.SS 100 @ 1670.52001953125"
## [1] "2020-09-18 00:00:00 600519.SS -100 @ 1695"
## [1] "2020-10-14 00:00:00 600519.SS 100 @ 1729"
## [1] "2020-10-29 00:00:00 600519.SS -100 @ 1676"
## [1] "2020-11-10 00:00:00 600519.SS 100 @ 1745"
## [1] "2021-03-01 00:00:00 600519.SS -100 @ 2158"
## [1] "2021-04-01 00:00:00 600519.SS 100 @ 2044.5"
## [1] "2021-04-15 00:00:00 600519.SS -100 @ 2015.59997558594"
## [1] "2021-04-20 00:00:00 600519.SS 100 @ 2094.80004882812"
## [1] "2021-05-06 00:00:00 600519.SS -100 @ 1959"
## [1] "2021-05-20 00:00:00 600519.SS 100 @ 2058.8798828125"
## [1] "2021-06-18 00:00:00 600519.SS -100 @ 2090.93994140625"
## [1] "2021-09-08 00:00:00 600519.SS 100 @ 1633.09997558594"
## [1] "2021-11-01 00:00:00 600519.SS -100 @ 1803"
## [1] "2021-11-23 00:00:00 600519.SS 100 @ 1896.43005371094"
## [1] "2022-01-05 00:00:00 600519.SS -100 @ 2024"
## [1] "2022-01-28 00:00:00 600519.SS 100 @ 1887"
## [1] "2022-02-07 00:00:00 600519.SS -100 @ 1867.9599609375"
## [1] "2022-04-07 00:00:00 600519.SS 100 @ 1765"
## [1] "2022-04-28 00:00:00 600519.SS -100 @ 1835"
## [1] "2022-05-05 00:00:00 600519.SS 100 @ 1837"
## [1] "2022-05-13 00:00:00 600519.SS -100 @ 1778.23999023438"
## [1] "2022-06-02 00:00:00 600519.SS 100 @ 1786"
## [1] "2022-07-14 00:00:00 600519.SS -100 @ 1953"
## [1] "2022-08-18 00:00:00 600519.SS 100 @ 1895.5"
## [1] "2022-08-23 00:00:00 600519.SS -100 @ 1870.01000976562"
## [1] "2022-09-20 00:00:00 600519.SS 100 @ 1878"
## [1] "2022-09-23 00:00:00 600519.SS -100 @ 1834.43005371094"
## [1] "2022-09-30 00:00:00 600519.SS 100 @ 1872.5"
## [1] "2022-10-12 00:00:00 600519.SS -100 @ 1760"
## [1] "2022-11-16 00:00:00 600519.SS 100 @ 1585.25"
## [1] "2023-01-03 00:00:00 600519.SS -100 @ 1730.01000976562"
## [1] "2023-01-09 00:00:00 600519.SS 100 @ 1841.19995117188"
## [1] "2023-02-07 00:00:00 600519.SS -100 @ 1797"
## [1] "2023-02-21 00:00:00 600519.SS 100 @ 1867"
## [1] "2023-02-28 00:00:00 600519.SS -100 @ 1813.73999023438"
## [1] "2023-03-30 00:00:00 600519.SS 100 @ 1800"
## [1] "2023-04-13 00:00:00 600519.SS -100 @ 1723"
## [1] "2023-05-08 00:00:00 600519.SS 100 @ 1720.52001953125"
## [1] "2023-05-10 00:00:00 600519.SS -100 @ 1725"
## [1] "2023-06-15 00:00:00 600519.SS 100 @ 1755"
## [1] "2023-07-07 00:00:00 600519.SS -100 @ 1690.03002929688"
## [1] "2023-07-18 00:00:00 600519.SS 100 @ 1722.80004882812"
## [1] "2023-08-17 00:00:00 600519.SS -100 @ 1828.05004882812"
## [1] "2023-09-01 00:00:00 600519.SS 100 @ 1851.05004882812"
## [1] "2023-09-14 00:00:00 600519.SS -100 @ 1818.68994140625"
## [1] "2023-11-03 00:00:00 600519.SS 100 @ 1811.23999023438"
## [1] "2023-11-29 00:00:00 600519.SS -100 @ 1774.7099609375"
## [1] "2024-01-02 00:00:00 600519.SS 100 @ 1685.01000976562"
## [1] "2024-01-09 00:00:00 600519.SS -100 @ 1641"
## [1] "2024-02-08 00:00:00 600519.SS 100 @ 1706"
## [1] "2024-03-11 00:00:00 600519.SS -100 @ 1694.48999023438"
## [1] "2024-03-14 00:00:00 600519.SS 100 @ 1716.63000488281"
## [1] "2024-03-29 00:00:00 600519.SS -100 @ 1702.90002441406"
## [1] "2024-04-02 00:00:00 600519.SS 100 @ 1713.98999023438"
## [1] "2024-04-09 00:00:00 600519.SS -100 @ 1662.21997070312"
## [1] "2024-04-26 00:00:00 600519.SS 100 @ 1709.43005371094"
## [1] "2024-05-20 00:00:00 600519.SS -100 @ 1709"
## [1] "2024-07-18 00:00:00 600519.SS 100 @ 1497.51000976562"
## [1] "2024-07-26 00:00:00 600519.SS -100 @ 1422.18994140625"
## [1] "2024-08-16 00:00:00 600519.SS 100 @ 1431.19995117188"
## [1] "2024-08-28 00:00:00 600519.SS -100 @ 1389"
## [1] "2024-09-30 00:00:00 600519.SS 100 @ 1748"
## [1] "2024-10-29 00:00:00 600519.SS -100 @ 1531.61999511719"
## [1] "2024-11-08 00:00:00 600519.SS 100 @ 1609.96997070312"
## [1] "2024-11-20 00:00:00 600519.SS -100 @ 1544.81005859375"
## [1] "2024-12-13 00:00:00 600519.SS 100 @ 1519"
## [1] "2024-12-27 00:00:00 600519.SS -100 @ 1528.96997070312"
## [1] "2025-02-17 00:00:00 600519.SS 100 @ 1471.61999511719"
## [1] "2025-04-03 00:00:00 600519.SS -100 @ 1568.88000488281"
## [1] "2025-04-22 00:00:00 600519.SS 100 @ 1548.80004882812"
## [1] "2025-04-25 00:00:00 600519.SS -100 @ 1550"
## [1] "2025-05-09 00:00:00 600519.SS 100 @ 1591.18005371094"
更新组合和账户
updatePortf(portfolio.st)
## [1] "maotai_portfolio"
updateAcct(account.st)
## [1] "maotai_account"
updateEndEq(account.st)
## [1] "maotai_account"
分析结果
# 获取交易数据
trades <- getTxns(Portfolio = portfolio.st, Symbol = symbol)
print(trades)
## Txn.Qty Txn.Price Txn.Fees Txn.Value Txn.Avg.Cost
## 2009-12-31 0 0.00000 0 0.000 0.00000
## 2010-05-25 100 98.61007 0 9861.007 98.61007
## 2010-06-01 -100 99.64688 0 -9964.688 99.64688
## 2010-06-03 100 101.45004 0 10145.004 101.45004
## 2010-06-23 -100 98.94816 0 -9894.816 98.94816
## 2010-07-15 100 99.04583 0 9904.583 99.04583
## 2010-10-15 -100 120.19534 0 -12019.534 120.19534
## 2010-10-25 100 129.97746 0 12997.746 129.97746
## 2010-11-02 -100 122.21638 0 -12221.638 122.21638
## 2010-11-11 100 132.17130 0 13217.130 132.17130
## ...
## 2024-10-29 -100 1531.62000 0 -153162.000 1531.62000
## 2024-11-08 100 1609.96997 0 160996.997 1609.96997
## 2024-11-20 -100 1544.81006 0 -154481.006 1544.81006
## 2024-12-13 100 1519.00000 0 151900.000 1519.00000
## 2024-12-27 -100 1528.96997 0 -152896.997 1528.96997
## 2025-02-17 100 1471.62000 0 147162.000 1471.62000
## 2025-04-03 -100 1568.88000 0 -156888.000 1568.88000
## 2025-04-22 100 1548.80005 0 154880.005 1548.80005
## 2025-04-25 -100 1550.00000 0 -155000.000 1550.00000
## 2025-05-09 100 1591.18005 0 159118.005 1591.18005
## Net.Txn.Realized.PL
## 2009-12-31 0.0000
## 2010-05-25 0.0000
## 2010-06-01 103.6812
## 2010-06-03 0.0000
## 2010-06-23 -250.1877
## 2010-07-15 0.0000
## 2010-10-15 2114.9513
## 2010-10-25 0.0000
## 2010-11-02 -776.1086
## 2010-11-11 0.0000
## ...
## 2024-10-29 -21638.0005
## 2024-11-08 0.0000
## 2024-11-20 -6515.9912
## 2024-12-13 0.0000
## 2024-12-27 996.9971
## 2025-02-17 0.0000
## 2025-04-03 9726.0010
## 2025-04-22 0.0000
## 2025-04-25 119.9951
## 2025-05-09 0.0000
# 获取交易统计数据
tstats <- tradeStats(portfolio.st)
print(tstats)
## Portfolio Symbol Num.Txns Num.Trades Net.Trading.PL
## 600519.SS maotai_portfolio 600519.SS 219 109 107330
## Avg.Trade.PL Med.Trade.PL Largest.Winner Largest.Loser Gross.Profits
## 600519.SS 1001.725 -420.9091 53221 -21638 312497.1
## Gross.Losses Std.Dev.Trade.PL Std.Err.Trade.PL Percent.Positive
## 600519.SS -203309.1 8949.005 857.1592 41.2844
## Percent.Negative Profit.Factor Avg.Win.Trade Med.Win.Trade
## 600519.SS 58.7156 1.537054 6944.381 2675.455
## Avg.Losing.Trade Med.Losing.Trade Avg.Daily.PL Med.Daily.PL
## 600519.SS -3176.705 -1388.979 1001.725 -420.9091
## Std.Dev.Daily.PL Std.Err.Daily.PL Ann.Sharpe Max.Drawdown
## 600519.SS 8949.005 857.1592 1.776945 -88252.01
## Profit.To.Max.Draw Avg.WinLoss.Ratio Med.WinLoss.Ratio Max.Equity
## 600519.SS 1.216176 2.186032 1.926203 185832
## Min.Equity End.Equity
## 600519.SS -146.5065 107330
# 查看持仓情况
positions <- getPos(Portfolio = portfolio.st, Symbol = symbol, Date = "2020-12-31")
print(positions)
## Pos.Qty Pos.Avg.Cost
## 2020-11-10 100 1745
# 获取投资组合的收益率
returns <- PortfReturns(Account = account.st)
# 计算夏普比率,假设无风险利率为0.02
sharpe_ratio <- SharpeRatio(returns, Rf = 0.02)
# 计算最大回撤
max_drawdown <- maxDrawdown(returns)
print(paste0("夏普比率: ", sharpe_ratio))
## [1] "夏普比率: -1.36579368456422" "夏普比率: -1.44224144013023"
## [3] "夏普比率: -1.44224144013023" "夏普比率: -1.40746513390874"
print(paste0("最大回撤: ", max_drawdown))
## [1] "最大回撤: 0.66676665654044"
# 获取策略对象
strategyObj <- getStrategy(strategy.st)
str(strategyObj)
## List of 10
## $ name : chr "maotai_sma"
## $ assets : NULL
## $ indicators :List of 2
## ..$ fastMA:List of 5
## .. ..$ name : chr "SMA"
## .. ..$ label : chr "fastMA"
## .. ..$ enabled : logi TRUE
## .. ..$ arguments:List of 2
## .. .. ..$ x: language Cl(mktdata)
## .. .. ..$ n: num 5
## .. ..$ call : language add.indicator(strategy = strategy.st, name = "SMA", arguments = list(x = quote(Cl(mktdata)), n = fastMA), label = "fastMA")
## .. ..- attr(*, "class")= chr "strat_indicator"
## ..$ slowMA:List of 5
## .. ..$ name : chr "SMA"
## .. ..$ label : chr "slowMA"
## .. ..$ enabled : logi TRUE
## .. ..$ arguments:List of 2
## .. .. ..$ x: language Cl(mktdata)
## .. .. ..$ n: num 20
## .. ..$ call : language add.indicator(strategy = strategy.st, name = "SMA", arguments = list(x = quote(Cl(mktdata)), n = slowMA), label = "slowMA")
## .. ..- attr(*, "class")= chr "strat_indicator"
## $ signals :List of 2
## ..$ :List of 5
## .. ..$ name : chr "sigCrossover"
## .. ..$ label : chr "fast.gt.slow"
## .. ..$ enabled : logi TRUE
## .. ..$ arguments:List of 3
## .. .. ..$ columns : chr [1:2] "fastMA" "slowMA"
## .. .. ..$ relationship: chr "gt"
## .. .. ..$ label : chr "fast.gt.slow"
## .. ..$ call : language add.signal(strategy = strategy.st, name = "sigCrossover", arguments = list(columns = c("fastMA", "slowMA"), | __truncated__
## .. ..- attr(*, "class")= chr "strat_signal"
## ..$ :List of 5
## .. ..$ name : chr "sigCrossover"
## .. ..$ label : chr "fast.lt.slow"
## .. ..$ enabled : logi TRUE
## .. ..$ arguments:List of 3
## .. .. ..$ columns : chr [1:2] "fastMA" "slowMA"
## .. .. ..$ relationship: chr "lt"
## .. .. ..$ label : chr "fast.lt.slow"
## .. ..$ call : language add.signal(strategy = strategy.st, name = "sigCrossover", arguments = list(columns = c("fastMA", "slowMA"), | __truncated__
## .. ..- attr(*, "class")= chr "strat_signal"
## $ rules :List of 3
## ..$ order: list()
## ..$ enter:List of 1
## .. ..$ :List of 7
## .. .. ..$ name :function (mktdata = mktdata, timestamp, sigcol, sigval, orderqty = 0, ordertype,
## orderside = NULL, orderset = NULL, threshold = NULL, tmult = FALSE,
## replace = TRUE, delay = 1e-04, osFUN = "osNoOp", pricemethod = c("market",
## "opside", "active"), portfolio, symbol, ..., ruletype, TxnFees = 0,
## prefer = NULL, sethold = FALSE, label = "", order.price = NULL, chain.price = NULL,
## time.in.force = "")
## .. .. ..$ type : chr "enter"
## .. .. ..$ enabled : logi TRUE
## .. .. ..$ label : chr "EnterLONG"
## .. .. ..$ arguments:List of 6
## .. .. .. ..$ sigcol : chr "fast.gt.slow"
## .. .. .. ..$ sigval : logi TRUE
## .. .. .. ..$ orderqty : num 100
## .. .. .. ..$ ordertype: chr "market"
## .. .. .. ..$ orderside: chr "long"
## .. .. .. ..$ replace : logi FALSE
## .. .. ..$ path.dep : logi TRUE
## .. .. ..$ call : language add.rule(strategy = strategy.st, name = "ruleSignal", arguments = list(sigcol = "fast.gt.slow", sigval = TRU| __truncated__ ...
## .. .. ..- attr(*, "class")= chr "trade_rule"
## ..$ exit :List of 1
## .. ..$ :List of 7
## .. .. ..$ name :function (mktdata = mktdata, timestamp, sigcol, sigval, orderqty = 0, ordertype,
## orderside = NULL, orderset = NULL, threshold = NULL, tmult = FALSE,
## replace = TRUE, delay = 1e-04, osFUN = "osNoOp", pricemethod = c("market",
## "opside", "active"), portfolio, symbol, ..., ruletype, TxnFees = 0,
## prefer = NULL, sethold = FALSE, label = "", order.price = NULL, chain.price = NULL,
## time.in.force = "")
## .. .. ..$ type : chr "exit"
## .. .. ..$ enabled : logi TRUE
## .. .. ..$ label : chr "ExitLONG"
## .. .. ..$ arguments:List of 6
## .. .. .. ..$ sigcol : chr "fast.lt.slow"
## .. .. .. ..$ sigval : logi TRUE
## .. .. .. ..$ orderqty : chr "all"
## .. .. .. ..$ ordertype: chr "market"
## .. .. .. ..$ orderside: chr "long"
## .. .. .. ..$ replace : logi FALSE
## .. .. ..$ path.dep : logi TRUE
## .. .. ..$ call : language add.rule(strategy = strategy.st, name = "ruleSignal", arguments = list(sigcol = "fast.lt.slow", sigval = TRU| __truncated__ ...
## .. .. ..- attr(*, "class")= chr "trade_rule"
## $ constraints: NULL
## $ init : list()
## $ wrapup : list()
## $ trials : num 6
## $ call : language strategy(name = strategy.st, store = TRUE)
## - attr(*, "class")= chr "strategy"
# 查看指标数据
indicator_data <- strategyObj$indicators
print(indicator_data)
## $fastMA
## $name
## [1] "SMA"
##
## $label
## [1] "fastMA"
##
## $enabled
## [1] TRUE
##
## $arguments
## $arguments$x
## Cl(mktdata)
##
## $arguments$n
## [1] 5
##
##
## $call
## add.indicator(strategy = strategy.st, name = "SMA", arguments = list(x = quote(Cl(mktdata)),
## n = fastMA), label = "fastMA")
##
## attr(,"class")
## [1] "strat_indicator"
##
## $slowMA
## $name
## [1] "SMA"
##
## $label
## [1] "slowMA"
##
## $enabled
## [1] TRUE
##
## $arguments
## $arguments$x
## Cl(mktdata)
##
## $arguments$n
## [1] 20
##
##
## $call
## add.indicator(strategy = strategy.st, name = "SMA", arguments = list(x = quote(Cl(mktdata)),
## n = slowMA), label = "slowMA")
##
## attr(,"class")
## [1] "strat_indicator"
# 查看信号数据
signal_data <- strategyObj$signals
print(signal_data)
## [[1]]
## $name
## [1] "sigCrossover"
##
## $label
## [1] "fast.gt.slow"
##
## $enabled
## [1] TRUE
##
## $arguments
## $arguments$columns
## [1] "fastMA" "slowMA"
##
## $arguments$relationship
## [1] "gt"
##
## $arguments$label
## [1] "fast.gt.slow"
##
##
## $call
## add.signal(strategy = strategy.st, name = "sigCrossover", arguments = list(columns = c("fastMA",
## "slowMA"), relationship = "gt"), label = "fast.gt.slow")
##
## attr(,"class")
## [1] "strat_signal"
##
## [[2]]
## $name
## [1] "sigCrossover"
##
## $label
## [1] "fast.lt.slow"
##
## $enabled
## [1] TRUE
##
## $arguments
## $arguments$columns
## [1] "fastMA" "slowMA"
##
## $arguments$relationship
## [1] "lt"
##
## $arguments$label
## [1] "fast.lt.slow"
##
##
## $call
## add.signal(strategy = strategy.st, name = "sigCrossover", arguments = list(columns = c("fastMA",
## "slowMA"), relationship = "lt"), label = "fast.lt.slow")
##
## attr(,"class")
## [1] "strat_signal"
# 绘制权益曲线
equity <- getAccount(account.st)$summary$End.Eq
plot(equity, main="Strategy Equity Curve")
# 绘制持仓和交易图表
chart.Posn(portfolio.st, Symbol=symbol, TA="add_SMA(n=fastMA,col='blue');add_SMA(n=slowMA,col='red')")
结语
基于 R 软件进行量化回测一件极度舒适的事情。但由于本文未对回测指标(即 SMA )的参数做优化,因此,本文仅供技术探讨,不构成策略或投资建议。