﻿ Example 11.定量交易策略测试

# Example 11. 动量交易策略

USstocks = select PERMNO, date, abs(PRC) as PRC, VOL, RET, SHROUT*abs(PRC) as MV from inData where weekday(date) between 1:5, isValid(PRC), isValid(VOL) order by PERMNO, date

USstocks = select PERMNO, date, PRC, VOL, RET, MV, cumprod(1+RET) as cumretIndex from USstocks context by PERMNO

return select PERMNO, date, PRC, VOL, RET, MV, move(cumretIndex,21)\move(cumretIndex,252)-1 as signal from USstocks context by PERMNO

}

return select date, PERMNO, MV, signal from indata where PRC>5, MV>100000, VOL>0, isValid(signal) order by date

}

// WtScheme=1表示等权重 ，WtScheme=2表示值权重

def formPortfolio(startDate, endDate, tradables, holdingDays, groups, WtScheme){

ports = select date, PERMNO, MV, rank(signal,,groups) as rank, count(PERMNO) as symCount, 0.0 as wt from tradables where date between startDate:endDate context by date having count(PERMNO)>=100

if (WtScheme==1){

update ports set wt = -1.0\count(PERMNO)\holdingDays where rank=0 context by date

update ports set wt = 1.0\count(PERMNO)\holdingDays where rank=groups-1 context by date

}

else if (WtScheme==2){

update ports set wt = -MV\sum(MV)\holdingDays where rank=0 context by date

update ports set wt = MV\sum(MV)\holdingDays where rank=groups-1 context by date

}

return select PERMNO, date as tranche, wt from ports where wt != 0 order by PERMNO, date

}

startDate=1996.01.01

endDate=2017.01.01

holdingDays=21

groups=10

ports = formPortfolio(startDate, endDate, tradables, holdingDays, groups, 2)

dailyRtn = select date, PERMNO, RET as dailyRet from priceData where date between startDate:endDate

def calcStockPnL(ports, dailyRtn, holdingDays, endDate, lastDays){

ages = table(1..holdingDays as age)

dates = sort distinct ports.tranche

dictDateIndex = dict(dates, 1..dates.size())

dictIndexDate = dict(1..dates.size(), dates)

pos = select dictIndexDate[dictDateIndex[tranche]+age] as date, PERMNO, 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[PERMNO], endDate)

update pos set ret = RET from ej(pos, dailyRtn,datePERMNO)

update pos set expr = expr*cumprod(1+ret) from pos context by PERMNO, tranche

update pos set pnl = expr*ret/(1+ret)

return pos

}

lastDaysTable = select max(date) as date from priceData group by PERMNO

lastDays = dict(lastDaysTable.PERMNO, lastDaysTable.date)

undef(`priceData, VAR)

stockPnL = calcStockPnL(ports, dailyRtn, holdingDays, endDate, lastDays)

portPnL = select sum(pnl) as pnl from stockPnL group by date

portPnL = select * from portPnL order by date;

plot(cumsum(portPnL.pnl) as cumulativeReturn,portPnL.date, "Cumulative Returns of the Momentum Strategy")