How to realize momentum trading strategy with database

Time:2021-8-3

How to realize momentum trading strategy with database

Momentum strategy is one of the most popular quantitative strategies. Most CTA strategies of commodity futures are based on momentum strategy. In the stock market, momentum strategy is also one of the commonly used quantitative factors. Generally speaking, momentum strategy is “chasing up and killing down”. Next, we will introduce how to test the momentum trading strategy in dolphin dB and calculate the cumulative return of the momentum trading strategy.

Dolphin DB database is a high-performance distributed temporal database. Different from other common databases, dolphin DB can not only store and retrieve data, but also has powerful programming and analysis functions. It can directly complete complex tasks such as policy backtesting in the database, which is convenient and efficient.

The most commonly used stock momentum factor is based on the return of the past year minus the most recent month. Momentum strategy is usually adjusted once a month and the holding period is also one month. In this example,Adjust 1 / 21 of the portfolio every day and hold a new portfolio for 21 days。 For the sake of simplicity, the back test in this paper does not consider the transaction cost.

Suppose the original data is a CSV file. It contains the following columns:

Permno: stock code

Date: Date

PRC: price per share

Shrout: number of outstanding shares

RET: daily stock return

Vol: daily trading volume

Step 1Load the stock trading data, clean and filter the data, and then construct the momentum signal of the past year minus the yield of the last month for each stock.

US = loadText("C:/DolphinDB/Data/US.csv")
def loadPriceData(inData){
    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 
}
priceData = loadPriceData(US)

Step 2. generate portfolio for momentum strategy

First, select the tradable shares that meet the following conditions: no missing momentum signal value, positive trading volume on the day, market value of more than US $100 million and price of more than US $5 per share.

def genTradables(indata){
    return select date, PERMNO, MV, signal from indata where PRC>5, MV>100000, VOL>0, isValid(signal) order by date
}
tradables = genTradables(priceData)

Then, according to the momentum signal every day, 10 groups of circulating stocks are generated. Only the two most extreme groups (winners and losers) are retained. Suppose that in 21 days, we always have a long $1 and a short $1 every day, so we have a long $1 / 21 in the winner group and a short $1 / 21 in the loser group every day. In each group, we can use equal weight or market value weight to calculate the weight of each stock on the portfolio formation date.

//Wtscheme = 1 means equal weight; Wtscheme = 2 indicates value weight
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.0count(PERMNO)holdingDays where rank=0 context by date
        update ports set wt = 1.0count(PERMNO)holdingDays where rank=groups-1 context by date
    }
    else if (WtScheme==2){
        update ports set wt = -MVsum(MV)holdingDays where rank=0 context by date
        update ports set wt = MVsum(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

Step 3. calculate the profit or loss of each stock in the portfolio for the next 21 days. Close the portfolio 21 days after the formation of the portfolio.

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]), dictIndexDate[dictDateIndex[tranche]+age]<=min(lastDays[PERMNO], endDate)

    update pos set ret = dailyRet from ej(pos, dailyRtn,`date`PERMNO)
    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)

Step 4. calculate the profit or loss of the portfolio and plot the cumulative return of the momentum strategy over time.

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")

The following is the 20-year back test results of the U.S. stock market from 1996 to 2016. During the back test, a new tranche is generated every day, including about 1500 stocks (an average of about 7500 stocks per day, 20%) and held for 21 days. With such a huge amount of data and computation, using single thread computing, dolphin DB takes only 3 minutes.

How to realize momentum trading strategy with database

The implementation of momentum trading strategy needs to understand the principle of obtaining excess return, certain trading skills and possible investment risks. Interested friends can go toOfficial websiteDownload dolphin DB database and design your own momentum trading strategy.

Recommended Today

Detailed steps for installing Perl and Komodo IDE for windows

Perl official website: https://www.perl.org/Perl document: https://perldoc.perl.org/Download address: https://www.perl.org/get.html The installation package of Perl Windows version is divided into activestate Perl and strawberry Perl. For the difference between the two, see: http://www.zzvips.com/article/202134.htm Note: the download speed of activestate Perl is slow. You may need KX to surf the Internet I have uploaded all the versions of […]