动量策略是最著名的长短期股票策略之一。
自从Jegadeesh和Titman(1993)首次提出这个概念以来,它广泛出现在学术研究和销售方面的著作中。
投资者在动量策略中相信,个股中,过去的赢家将超越过去的输家。
最常用的动量因素是股票出去最近一个月,在过去12个月的收益。
在学术出版物中,动量策略通常是一个月调整一次且持有期也是一个月。
在本例中, 我们每天重新平衡我们的投资组合的1/21,并持有新份额21天。为简单起见,我们不考虑交易成本。
# 载入股票数据
CH = ploadText("D:/DolphinDB/Data/CHstock1990_2018.csv")
# 计算动量信号
def loadPriceData(inData){CHstocks = select TS_CODE, TRADE_date, abs(open) as PRC, vol as VOL,close/open-1 as RET from inData where weekday(trade_date) between 1:5, isValid(open), isValid(VOL) order by ts_code, trade_dateCHstocks = select ts_code, trade_date, PRC, VOL, RET, cumprod(1+RET) as cumretIndex from CHstocks context by ts_codereturn select ts_code, trade_date, PRC, VOL, RET, move(cumretIndex,21)move(cumretIndex,252)-1 as signal from CHstocks context by ts_code
}priceData = loadPriceData(CH)
从SQL
语句中可以看到,数据库字段不区分大小写。
一般的数据库SQL
语言是不区分大小写的,但是DolphinDB
区分大小写,sql关键字只能用小写。这里区分大小写指的是sql
关键字。
# 释放内存
undef(`CH, VAR)
# undef函数释放对象需要是字符串标量或向量,所以在CH前加上`
# 筛选个股
def genTradables(indata){return select trade_date, ts_code, signal from indata where PRC>5, VOL>0, isValid(signal) order by trade_date
}
tradables = genTradables(priceData)
筛选条件是,动量信号值无缺失、当日是正交易量、动量信号无缺失、股价大于5元。
# WtScheme=1表示等权重 ,WtScheme=2表示值权重
def formPortfolio(startDate, endDate, tradables, holdingDays, groups, WtScheme){ports = select trade_date, ts_code, rank(signal,,groups) as rank, count(ts_code) as symCount, 0.0 as wt from tradables where trade_date between startDate:endDate context by trade_date having count(ts_code) >= 100if (WtScheme == 1){update ports set wt = -1.0count(ts_code)holdingDays where rank=0 context by trade_dateupdate ports set wt = 1.0count(ts_code)holdingDays where rank=groups-1 context by trade_date}else if (WtScheme == 2){# 缺数据未计算}return select ts_code, trade_date as tranche, wt from ports where wt != 0 order by ts_code, trade_date
}
startDate = 1996.01.01
endDate = 2018.01.01
holdingDays = 21
groups =10
ports = formPortfolio(startDate, endDate, tradables, holdingDays, groups, 1)
dailyRtn = select trade_date, ts_code, RET as dailyRet from priceData where trade_date between startDate:endDate
根据动量信号,制定10组可交易股票。只保留2个最极端的群体(赢家和输家)。假设我们总是想在21天内,每天多头1美元和空头$1,所以我们每天在赢家组多头$1/21,在输家组每天空头$1/21。在每组中,我们可以使用等权重或值权重, 来计算投资组合形成日期上每个股票的权重。
# 计算每支个股21天损益
def calcStockPnL(ports, dailyRtn, holdingDays, endDate, lastDays){ages = table(1..holdingDays as age)dates = sort anchedictDateIndex = dict(dates, 1..dates.size())dictIndexDate = dict(1..dates.size(), dates)pos = select dictIndexDate[dictDateIndex[tranche]+age] as trade_date, ts_code, tranche, age, take(0.0,size age) as ret, wt as expr, take(0.0,size age) as pnl from cj(ports,ages) where isValid(dictIndexDate[dictDateIndex[tranche]+age]) and dictIndexDate[dictDateIndex[tranche]+age]<=min(lastDays[ts_code], endDate)update pos set ret = RET from ej(pos, dailyRtn,`trade_date`ts_code)update pos set expr = expr*cumprod(1+ret) from pos context by ts_code, trancheupdate pos set pnl = expr*ret/(1+ret)return pos
}
lastDaysTable = select max(trade_date) as date from priceData group by ts_code
lastDays = dict(lastDaysTable.ts_code, lastDaysTable.date)
undef(`priceData, VAR)
stockPnL = calcStockPnL(ports, dailyRtn, holdingDays, endDate, lastDays)
# 计算总体收益并绘图
portPnL = select sum(pnl) as pnl from stockPnL group by trade_date
portPnL = select * from portPnL order by trade_date
plot(cumsum(portPnL.pnl) as ade_date, "Cumulative Returns of the Momentum Strategy")
最后两部分还没完全搞懂,主要是示例中所用美股数据字段与A股数据不同,后续重新构建一个数据集再把这块补上
本文发布于:2024-02-02 23:37:02,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170688822047204.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |