R_Language 板


LINE

1. 套件名称: quantstrat 0.9.1739 Depends: R(>= 2.10), quantmod, xts(>= 0.8-2), blotter(>= 0.9), FinancialInstrument(>= 0.12.5), foreach(>= 1.4.0) Repos: https://github.com/braverock/quantstrat https://R-Forge.R-project.org 2. 套件主要用途: 提供股票和各国货币等资产组合模拟交易的框架 能够产生商品k线图、进出场flag、留仓部位等 也支援使用者定义的技术指标、买卖手续费设定 http://imgur.com/a/BJ5Zo 提供交易次数、Annual Sharpe Ratio、MAE、MFE、年化算术平均/几何报酬率等统计资料 http://imgur.com/a/RsTO1 还有基於平行运算的Walk Forward Analysis http://imgur.com/a/vsm9l 但因为OS的问题 注册cluster的方式不一样 需要不同的package Windows: doParallel、doRedis、snow等 Ubuntu: doMC 由於多数Finance相关的package都是基於quantmod的框架再延伸 所以有蛮多相依的套件,但我觉得主要功能是在quantstrat 所以标题就用quantstrat了XD 3. 套件主要函数列表: quantstrat: add.indicator add.signal add.rule applyStrategy apply.paramset add.distribution add.distribution.constraint walk.forward blotter: tradeStats chart.Posn FinancialInstrument: currency stock 4. 分享内容: 其实网路上资料蛮多的,但都是英文 所以我很纳闷怎麽都没有人写中文的教学文 台湾看到的回测程式大多是用Python、VBA或现成套装软体居多 想说可以推广一下R这个还蛮方便的package Analysis、Visualization和用平行运算处理参数最佳化和WFA是他的特色 不过觉得他的documentation不是很完整 由於我今年GSoC的project是整合Josh新的xts_0.10-0和quantmod、quantstrat等套件 和加入dynamic graphs feature 顺利的话在计画结束前应该能把他补得更完整 如果想要自动交易 台湾券商的话 可以将R作为computing server 将结果pass到C++进行下单 国外券商的话 可以用IBroker直接用R跟国外券商API串接 就可以下单了 如果跟shiny结合 就可以做出一个简单的线上应用 https://naturalsmen.shinyapps.io/Backtest 这是小弟有段时间之前写来自用的 已经内建策略了 所以请忽略首页设定参数的tab 直接到Backtest 选择股号就可以run了 run完请选择Backtest result highchart是我之前加上去的 不在本文介绍的范围内 日後有时间应该会把他完善 这边就先用来做个简单的范例 ------以下正题------ 以Windows为例 library(doParallel) # for apply.paramset() and walk.forward() library(quantstrat) # main package library(IKTrading) # quantstrat extensions, mainly for asset allocation # and order-sizing functions library(quantmod) # retrieve symbols from yahoo finance, google finance, etc getSymbols("^GSPC") # 由於之前可能有策略存在.blotter environment里,我们要先把他清空 rm(list = ls(.blotter), envir = .blotter) # 设定货币是TWD、USD或EUR等 currency("TWD") # 设定时区,一般是Universal Time(UTC)或GreenWich Mean Time(GMT) # 也可以用xts::indexTZ(GSPC)来确认时区 Sys.setenv(TZ = "UTC") # 可以有多个symbols,多个symbols会形成投资组合 # 如symbols = c("GSPC", "GDAXI") # 为了方便说明,这边只用一个指数商品 symbols = "GSPC" # multiplier为杠杆乘数,比如90元买入中华电(2412)一张,100卖出 # 当multiplier=m,不计手续费下赚m*10000元 stock(symbols, currency = "TWD", multiplier = 1) # 设定日期、策略名称和初始权益(本金) initDate = "1999-01-01" strategy.st <- portfolio.st <- account.st <- "myStrat" tradeSize <- 1000000 initEq <- tradeSize*length(symbols) # 避免策略重复,先将投组、策略、帐号等初始化 # 并从initDate开始执行策略 rm.strat(portfolio.st) rm.strat(strategy.st) initPortf(portfolio.st, symbols = symbols, initDate = initDate, currency = "TWD") initAcct(account.st, portfolios = portfolio.st, initDate = initDate, currency = "TWD", initEq = initEq) initOrders(portfolio.st, initDate = initDate) strategy(strategy.st, store = TRUE) # 设定会使用到的参数 nRSI = 2 thresh1 = 10 thresh2 = 6 nSMAexit = 10 nSMAfilter = 200 period = 10 pctATR = .02 # 2% ATR, size the position based on risk maxPct = .04 # 设定indicator # name是这个indicator的名称,会由名称呼叫该函数 # 所以你也可以自己定义技术指标或加入ML函数 # mktdata在function内会被替换成你的symbols所以不用更动 # label会让你指标的栏位名称变成<column1>.label add.indicator(strategy.st, name = "lagATR", arguments = list(HLC=quote(HLC(mktdata)), n=period), label = "atrX") add.indicator(strategy.st, name = "RSI", arguments = list(price=quote(Cl(mktdata)), n=nRSI), label = "rsi") # 举例来说,这里coloumn name 会变成 SMA.quickMA add.indicator(strategy.st, name = "SMA", arguments = list(x=quote(Cl(mktdata)), n=nSMAexit), label = "quickMA") add.indicator(strategy.st, name = "SMA", arguments = list(x=quote(Cl(mktdata)), n=nSMAfilter), label = "filterMA") # 设定signals # 主要有sigComparison、sigThreshold、sigCrossover和sigAND # sigComparison:比较两个设定好的indicator # sigThreshold:比较设定好的indicator和一个定值 # sigCrossover:也是比较两个indicator,但default是t-1时和t时的交叉 # 若要其他lag期间需要使用者自行定义函数 # 效果等同於sigComparison(..., cross=TRUE) # sigAND:两个signal需要同时成立 # relationship有gt(greater than)、lt(lower than)、 # gte(greater than or equal to)、lte(lower than or equal to) # 这边设定close price > 200日MA时产生讯号,并设定label为upTrend add.signal(strategy.st, name = "sigComparison", arguments = list(columns = c("Close", "filterMA"), relationship = "gt"), label = "upTrend") # cross = FALSE, for current signal # cross = TRUE, for both previous day and current signal # rsi < 10 add.signal(strategy.st, name = "sigThreshold", arguments = list(column = "rsi", threshold = thresh1, relationship = "lt", cross = FALSE), label = "rsiThresh1") # rsi < 6 add.signal(strategy.st, name = "sigThreshold", arguments = list(column = "rsi", threshold = thresh2, relationship = "lt", cross = FALSE), label = "rsiThresh2") # 进场讯号1:今天的rsi<10 且 close price > 200日MA,昨天则否(任一不成立) # long add.signal(strategy.st, name = "sigAND", arguments = list(columns = c("rsiThresh1", "upTrend"), cross = TRUE), label = "longEntry1") # 进场讯号2:今天的rsi<6 且 close price > 200日MA,昨天则否(任一不成立) # 可以看出这是反向加码策略 add.signal(strategy.st, name = "sigAND", arguments = list(columns = c("rsiThresh2", "upTrend"), cross = TRUE), label = "longEntry2") # 出场讯号1:今天的close price > 10日MA,昨天则否 add.signal(strategy.st, name = "sigCrossover", arguments = list(columns = c("Close", "quickMA"), relationship = "gt"), label = "exitLongNormal") # 出场讯号2:今天的close price < 200日MA,昨天则否 add.signal(strategy.st, name = "sigCrossover", arguments = list(columns = c("Close", "filterMA"), relationship = "lt"), label = "exitLongFilter") # 这边设定台湾的手续费和交易税,买入0.001425,卖出0.004425 # function args必须有TxnQty, TxnPrice和Symbol buyCost <- 0.001425 # custom transaction fee function based on value of transaction buyFee <- function(TxnQty, TxnPrice, Symbol, ...) { abs(TxnQty) * TxnPrice * -buyCost } sellCost <- 0.004425 sellFee <- function(TxnQty, TxnPrice, Symbol, ...) { abs(TxnQty) * TxnPrice * -sellCost } # 设定规则,为了方便讲解,这边都以做多为例 # name: rule的名称,用来呼叫ruleSignal(),所以也可以自己定义 # sigcol: 上面讯号的label # sigval: 当讯号产生,是否给讯号赋值,TRUE为1、FALSE为0 # ordertype: 下单类型,有市价单、限价单、停损单等 # 这边以市价单为例 # orderside: 做多或放空 # replace: 如果两个讯号同时成立,这个讯号是否取代另一个 # prefer: 因为是回测,所以我们需要假定买入和卖出的价格 # 这边假设是开盘价,若要考虑滑价的话需要自行定义function # osFUN: 下单的数量,default为osDollarATR和osMaxDollar # osDollarATR: 依照现有部位产品的波动度和风险承受度加权 # osMaxDollar: 每次都依现有资金买满,ex.一股160的2330,本金50w,会买满3张 # 零股需另外定义function # tradeSize: 用多少本金交易 # pctATR, maxPctATR: 风险承受度的百分比 # atrMod: 搭配ATR,最早的indicator,lastATR的label必须要是atrX # TxnFees: 额外交易费用,如上所定义之函数 # type: 进场或出场 # path.dep: 当这个rule未close掉,其他的rule不会执行 # call ruleSignal时需要设为TRUE add.rule(strategy.st, name = "ruleSignal", arguments = list(sigcol = "longEntry1", sigval = TRUE, ordertype = "market", orderside = "long", replace = FALSE, # replace = TRUE may choose just one rule prefer = "Open", # tomorrow because today has closed osFUN = osDollarATR, # order size function tradeSize = tradeSize, pctATR = pctATR, maxPctATR = pctATR, # set an upper limit of orders atrMod = "X", TxnFees = "buyFee"), # atrx above type = "enter", path.dep = TRUE, label = "enterLong1") add.rule(strategy.st, name = "ruleSignal", arguments = list(sigcol = "longEntry2", sigval = TRUE, ordertype = "market", orderside = "long", replace = FALSE, # replace = TRUE may choose just one rule prefer = "Open", # tomorrow because today has closed osFUN = osDollarATR, # order size function tradeSize = tradeSize, pctATR = pctATR, maxPctATR = maxPct, # set an upper limit of orders atrMod = "X", TxnFees = "buyFee"), # atrx above type = "enter", path.dep = TRUE, label = "enterLong2") # 出场规则 # orderqty: 'all'为卖出所有部位,可以是数字或自定义function # ordertype是停损单(stoplimit)时,需额外设定停损点 # 如果tmult=TRUE,threshold需为百分比,如0.2(=20%),买入价*threshold=停损价 # 如果tmult=FALSE,threshold为绝对数字,如158,停损价就是跌破158时平仓 # 这边都以市价单出场 add.rule(strategy.st, name = "ruleSignal", arguments = list(sigcol = "exitLongNormal", sigval = TRUE, orderqty = "all", # order quantity, in all and out all ordertype = "market", orderside = "long", replace = FALSE, prefer = "Open", TxnFees = "sellFee"), type = "exit", path.dep = TRUE, label = "normalExitLong") add.rule(strategy.st, name = "ruleSignal", arguments = list(sigcol = "exitLongFilter", sigval = TRUE, orderqty = "all", ordertype = "market", orderside = "long", replace = FALSE, prefer = "Open", TxnFees = "sellFee"), type = "exit", path.dep = TRUE, label = "filterExitLong") # 开始进行回测 out <- applyStrategy(strategy = strategy.st, portfolios = portfolio.st) # 更新投组资料 updatePortf(portfolio.st) tradeDetails <- getPortfolio(portfolio.st) posPL <- tradeDetails$symbols$tsmc$posPL # 更新帐户资料和期末权益金额 dateRange <- time(tradeDetails$summary)[-1] updateAcct(portfolio.st, dateRange) updateEndEq(account.st) # 统计资料 tStats <- tradeStats(Portfolios = portfolio.st, use = "trades", inclZeroDays = FALSE) tStats[, 4:ncol(tStats)] <- round(tStats[, 4:ncol(tStats)], 2) (aggPF <- sum(tStats$Gross.Profits)/-sum(tStats$Gross.Losses)) (aggCorrect <- mean(tStats$Percent.Positive)) (numTrades <- sum(tStats$Num.Trades)) (meanAvgwLR <- mean(tStats$Avg.WinLoss.Ratio[tStats$Avg.WinLoss.Ratio < Inf], na.rm = TRUE)) # 画k线图、进出场flag、持有部位和累积报酬 myTheme<-chart_theme() myTheme$col$dn.col<-'lightgray' myTheme$col$dn.border <- 'lightgray' myTheme$col$up.border <- 'lightgray' chart.Posn(Portfolio = portfolio.st, Symbol=symbols, theme= myTheme) # 自由加入技术指标 sma <- SMA(x = Cl(tsmc), n = 200) sma2 <- SMA(x = Cl(tsmc), n = 10) rsi <- RSI(price = Cl(tsmc), n = 2) atr <- lagATR(HLC = HLC(tsmc), n = 10) add_TA(sma2, on = 1, col = "red") add_TA(sma, on = 1, col = "green") add_TA(rsi, col = "green", lwd = 1.5) ### 参数最佳化 # 设定参数范围 # add distribution and distribution contraints # rsi # paramset.label: 参数组合名称 # label: 这个参数的范围 add.distribution(strategy.st, paramset.label = 'allParam', component.type = 'signal', component.label = 'rsiThresh1', variable = list(threshold = 5:10), label = 'up.rsi' ) add.distribution(strategy.st, paramset.label = 'allParam', component.type = 'signal', component.label = 'rsiThresh2', variable = list(threshold = 5:10), label = 'dn.rsi' ) # 加入参数范围限制 add.distribution.constraint(strategy.st, paramset.label = 'allParam', distribution.label.1 = 'up.rsi', distribution.label.2 = 'dn.rsi', operator = '>', label = 'RSI' ) # MA add.distribution(strategy.st, paramset.label = 'allParam', component.type = 'indicator', component.label = 'quickMA', variable = list(threshold = 5:15), label = 'quickMA' ) add.distribution(strategy.st, paramset.label = 'allParam', component.type = 'indicator', component.label = 'filterMA', variable = list(threshold = 220:260), label = 'filterMA' ) # Walk Forward Analysis # paramset.label: 设定的参数范围 # k.training: 样本期间 # k.testing: 测试期间 # nsamples: 等於0代表所有组合 # obj.func: objective function,目标函数,由於default的最佳化是以 # 报酬率最大为指标,若要改成Max drawdown或其他条件则要自定义函数 # anchored: 是否是moving time window # verbose: 是否印出交易明细 registerDoParallel(cores=detectCores()) resultsWFA <- walk.forward( strategy.st=strategy.st, paramset.label='allParam', portfolio.st=portfolio.st, account.st=account.st, period='years', k.training=4, k.testing=2, nsamples=0, audit.prefix='wfa', #obj.func=my.obj, #obj.args=my.args, anchored=TRUE, verbose=TRUE, include.insamples=TRUE ) 结果会自动输出样本内和样本外的.RData档到使用者的预设路径,可以 用ls(.audit)看到training和testing的名称 举例来说: chart.forward.training("wfa.GSPC.2007-01-03.2010-12-31.RData") http://imgur.com/a/Scgc3 如果是testing的部分: chart.forward("wfa.results.RData") 如果不清楚Out of sample和In sample的关系 可以参考我网页上WFA的tab https://naturalsmen.shinyapps.io/Backtest 因为quantstrat的help page真的不太友善,所以打了很多arguments的定义和用法说明 code不知不觉也打了一长串@@ 虽然看起来有点长 但我觉得这是用quantstrat搭配其他package建立自己的交易系统蛮完整的code了 如果排版或内容有哪里需要改进再请板友指教 之後会再慢慢修改与完善这篇 或者可能直接搬到我的部落格了@@ 下一个打算分享IBrokers 如果没有被其他板友抢先的话XD 还有Josh新版的xts_0.10-0、quantmod、PerformanceAnalytics等 或者是等到正式release之後再写了 5. 备注: 因为自己埋头研究quantstrat和IBrokers这两个package非常非常久 一直希望找个时间把自己经验分享出去 一方面是让大家知道有这个很好用的package来写交易程式 另一方面是让大家少走些弯路 因为可能碰到的bug我大概都遇过 也open issue过了@@: 但是自己一直懒懒的 又在忙GSoC的计画 以至於一拖再拖 感谢c大提供这个机会让我上来骗骗p币 也给我个动机写了第一篇弱弱的分享文 感觉板上大大多是讨论技术为主 所以就想说来个比较应用的范例好了 之後会慢慢把这篇补完、弄得更通顺更好阅读一点 感谢耐心看完或直接End的大家XD 参考资料: Guy Yollin, Computational Finance & Risk Management, University of Washington, Department of Applied Mathematics: http://www.r-programming.org/papers QuantStrat TradeR: https://quantstrattrader.wordpress.com/ --



※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 61.228.18.39
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/R_Language/M.1469300017.A.7D0.html
1F:推 cywhale: 传这个给同事他应该就有动力学R了 详细推~~ 07/24 08:13
2F:推 ofspring: impressive, 想问MAC需要的套件组要到哪个网站查询呢? 07/24 10:10
3F:推 LinNine: 推~ 07/24 10:24
4F:推 snoopyleo: 谢谢分享! 07/24 21:07
5F:推 roqe: 好长,慢慢看~ 07/24 23:35
6F:推 kevin0401: GOOD 07/25 08:00
7F:推 psinqoo: 拍手~~ 07/25 08:29
8F:推 howard40116: 推广一下~~会有一堆人想来学 07/25 20:31
9F:推 celestialgod: 推,谢谢大大分享 07/25 20:36
※ 编辑: naturalsmen (140.113.136.217), 07/26/2016 19:18:52
10F:推 h310713: 跪下来了 07/28 09:44
※ 编辑: naturalsmen (36.229.209.213), 09/28/2016 21:05:15
11F:推 poker0531: 不断更新欸 给推 08/10 17:53







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:Gossiping站内搜寻

TOP