R 在 金 融 数 据 挖 掘 的 应 用 预 测 股 票 收 益 率 20 平 平 平 平 平 2
Why R? 1. 开 源, 免 费, 用 户 贡 献 自 己 的 包 2. 灵 活, 可 处 理 多 种 事 务 OOP 泛 型 函 数 3. 有 大 量 的 函 数 包, 不 用 再 重 新 发 明 轮 子 4. 先 用 R 实 现 算 法 原 型, 再 用 C++ C# 等 语 言 开 发 系 统
传 统 的 时 间 序 列 Box-Jenkins: AR MA ARMA ARIMA 异 方 差 模 型 :ARCH 类
以 交 易 为 目 的 的 预 测 预 测 是 为 决 策 提 供 支 持 的 预 测 模 型 与 交 易 系 统 整 合 评 价 标 准 是 交 易 系 统 的 收 益, 而 不 是 预 测 的 精 确 度
目 录 一 数 据 导 入 二 预 测 模 型 三 从 预 测 到 决 策 四 模 型 评 价 和 选 择
一 数 据 导 入 1. 数 据 的 结 构 : 交 易 的 日 期 开 盘 价 最 高 价 最 低 价 收 盘 价 交 易 量 调 整 的 收 盘 价 2. 为 简 单 起 见, 用 的 是 股 票 指 数 的 数 据 3. 处 理 时 间 序 列 的 包 zoo,xts, 后 者 是 前 者 的 拓 展 4. 表 示 的 处 理 时 间 的 类 : POSIXct/ POSIXlt,date Open High Low Close Volume AdjClose 1970-01-02 92.06 93.54 91.79 93.00 8050000 93.00 1970-01-05 93.00 94.25 92.53 93.46 11490000 93.46 1970-01-06 93.46 93.81 92.13 92.82 11460000 92.82 1970-01-07 92.82 93.38 91.93 92.63 10010000 92.63 1970-01-08 92.63 93.47 91.99 92.68 10670000 92.68 1970-01-09 92.68 93.25 91.82 92.40 9380000 92.40
5. 从 CSV 文 件 读 数 据 > GSPC <- as.xts(read.zoo("sp500.csv", header = T)) 6. 从 网 络 读 取 数 据 > library(tseries) > GSPC <- as.xts(get.hist.quote("^gspc",start="1970-01-02", quote=c("open", "High", "Low", "Close","Volume","AdjClose"))) 7. quantmod 包 里 的 getsymbols() > setsymbollookup(ibm=list(name='ibm',src='yahoo'), + USDEUR=list(name='USD/EUR',src='oanda)) > getsymbols(c('ibm','usdeur')) 8. 从 数 据 库 读 数 据 : 包 RODBC,RMySQL win myodbc RODBC linux RMySQL DBI
目 标 变 量 日 平 均 价 用 下 面 的 式 子 近 似 P i Ci + Hi + Li = 3 设 Vi 是 接 下 来 k 天 平 均 价 对 i 时 刻 的 变 动 百 分 比 ( 算 术 收 益 率 ) V i P C i + j i = 指 标 T 定 义 为 绝 对 值 大 于 p% 的 那 些 变 动 的 总 和 C i k j = 1 Ti = { v Vi : v > p% or v < p% } v T 为 正 且 较 大 说 明 未 来 有 若 干 天 股 价 高 于 今 天 的 收 盘 价, 买 入 信 号 T 为 负 且 绝 对 值 较 大 说 明 未 来 有 若 干 天 股 价 低 于 今 天 的 收 盘 价, 卖 出 信 号
T.ind <- function(quotes,tgt.margin=0.025,n.days=10) { v <- apply(hlc(quotes),1,mean) r <- matrix(na,ncol=n.days,nrow=nrow(quotes)) for(x in 1:n.days) r[,x] <- Next(Delt(v,k=x),x) x <- apply(r,1,function(x) sum(x[x > tgt.margin x < -tgt.margin])) if (is.xts(quotes)) xts(x,time(quotes)) else x }
用 什 么 变 量 预 测? 历 史 数 据 技 术 指 标 : 包 TTR 有 大 量 的 指 标, 如 何 选 择? 1. 特 征 过 滤 ( feature filters ), 不 依 赖 于 模 型 2. 特 征 封 装 ( feature wrappers ), 依 赖 于 模 型, 迭 代 的
候 选 特 征 R i h Ci C = C i h i h 变 动 h:1 10 TTR 的 技 术 指 标 : ATR(Average True Range), 衡 量 序 列 波 动 SMI(Stochastic Momentum Index), 动 量 指 标 Average Directional Movement Index(ADI) Aroon 指 标, 扑 捉 起 始 趋 势 的 ;Bollinger Bands, 比 较 一 段 时 期 的 波 动 率 Chaikin Volatility;EMV(Ease of Movement Value);MACD MFI(Money Flow Index ) 先 经 过 预 处 理, 产 生 单 指 标
myatr <- function(x) ATR(HLC(x))[,'atr'] mysmi <- function(x) SMI(HLC(x))[,'SMI'] myadx <- function(x) ADX(HLC(x))[,'ADX'] myaroon <- function(x) aroon(x[,c('high','low')])$oscillator mybb <- function(x) BBands(HLC(x))[,'pctB'] mychaikinvol <- function(x) Delt(chaikinVolatility(x[,c("High","Low")]))[,1] myclv <- function(x) EMA(CLV(HLC(x)))[,1] myemv <- function(x) EMV(x[,c('High','Low')],x[,'Volume'])[,2] mymacd <- function(x) MACD(Cl(x))[,2] mymfi <- function(x) MFI(x[,c("High","Low","Close")], x[,"volume"]) mysar <- function(x) SAR(x[,c('High','Close')]) [,1] myvolat <- function(x) volatility(ohlc(x),calc="garman")[,1]
特 征 选 择 随 机 森 林 library(randomforest) 把 数 据 分 两 部 分 (1) 构 建 交 易 系 统 (2) 测 试 library(randomforest) data.model <- specifymodel(t.ind(gspc) ~ Delt(Cl(GSPC),k=1:10) + myatr(gspc) + mysmi(gspc) + myadx(gspc) + myaroon(gspc) + mybb(gspc) + mychaikinvol(gspc) + myclv(gspc) + CMO(Cl(GSPC)) + EMA(Delt(Cl(GSPC))) + myemv(gspc) + myvolat(gspc) + mymacd(gspc) + mymfi(gspc) + RSI(Cl(GSPC)) + mysar(gspc) + runmean(cl(gspc)) + runsd(cl(gspc))) set.seed(1234) rf <- buildmodel(data.model,method='randomforest', training.per=c(start(gspc),index(gspc["1999-12-31"])), ntree=50, importance=t) ex.model <- specifymodel(t.ind(ibm) ~ Delt(Cl(IBM),k=1:3)) data <- modeldata(ex.model,data.window=c('2009-01-01','2009-08-10'))
预 测 问 题 1. 用 解 释 变 量 来 预 测 T( 回 归 问 题 ), 然 后 计 算 信 号 signal sell if T < 0.1 signal = hold if 0.1 T 0.1 buy if T > 0.1 2. 用 解 释 变 量 直 接 预 测 signal( 分 类 ) 问 题!!! sell 和 buy 是 少 数,hold 住 是 多 数 原 因 : 不 平 衡 数 据
评 估 准 则 N 1 error. rate = L ˆ 0/1( yi, yi ) N i = 1 Prec 和 Recall 通 常 合 并 到 一 起, 成 为 单 一 的 统 计 量,F- 测 度 ( Rijsbergen, 1979 )
负 责 的 金 融 时 间 序 列 通 常 会 出 现 区 域 转 移 (regime switch) 的 情 况 如 果 用 训 练 集 数 据 得 到 模 型 来 预 测 接 下 来 的 时 间 区 域, 可 能 会 发 现 区 域 转 移 用 较 近 的 数 据 来 扑 捉 最 近 区 域 (regime) 的 特 性
预 测 模 型 1. 人 工 神 经 网 络 set.seed(1234) library(nnet) norm.data <- scale(tdata.train) nn <- nnet(tform, norm.data[1:1000, ], size = 10, decay = 0.01, maxit = 1000, linout = T, trace = F) norm.preds <- predict(nn, norm.data[1001:2000, ]) preds <- unscale(norm.preds, norm.data)
2. 支 持 向 量 机 : 包 kernlab e1071 library(e1071) sv <- svm(tform, Tdata.train[1:1000, ], gamma = 0.001, cost = 100) s.preds <- predict(sv, Tdata.train[1001:2000, ]) library(kernlab) data <- cbind(signals = signals, Tdata.train[, -1]) ksv <- ksvm(signals ~., data[1:1000, ],C=10) ks.preds <- predict(ksv, data[1001:2000, ])
3. 多 变 量 自 适 应 回 归 样 条 Multivariate Adaptive Regression Splines 包 mda 的 mars(), 包 earth 里 的 earth() library(earth) e <- earth(tform, Tdata.train[1:1000, ]) e.preds <- predict(e, Tdata.train[1001:2000, ]) MARS 只 适 用 于 回 归 问 题, 不 可 用 于 分 类
三 从 预 测 到 决 策 策 略 1 (1)t 时 刻 卖 出 信 号 如 果 有 头 寸, 信 号 被 忽 略 如 果 没 有 头 寸, 开 一 个 空 头 头 寸 ( 价 格 pr), 然 后 两 个 限 价 指 令 一 个 买 入 指 令 pr-p%, 一 个 买 入 指 令 pr+l%, 用 来 止 损 (2) t 时 刻 买 入 信 号 一 个 卖 出 指 令 pr+p%, 一 个 卖 出 指 令 pr-l%, 用 来 止 损 策 略 2 只 开 一 个 头 寸, 等 待 收 益 达 到 预 期, 不 设 止 损
与 交 易 关 联 的 评 估 准 则 包 PerformanceAnalytics (1) 总 体 收 益 :Profit/Loss (2) 风 险 相 关 的 收 益 :Sharpe 比 率, 衡 量 单 位 风 险 的 收 益
四 模 型 评 估 和 选 择 1. Monte carlo 模 拟 2. 实 验 比 较 3. 原 因 分 析
参 考 文 献 1. DataMining with R: Learning with Case Studies 2. 邓 一 硕 整 理 的 关 于 quantmod 和 PerformanceAnalytics 的 手 册
Contact yanping.chen@cos.name http://ypchen.inwake.com
Thank you!