/* *
*  @ brief
*  This module implements Alpha158 factor formulas in DolphinDB,
*  and divides the functions into three categories according to their features:
*  K-bar factors, price factors, and rolling factors.
*  The development of this module is based on day level panel data.
*  @ FileName: alpha158.dos
*/

module alpha158

//1. kbar 因子
//The calculation process includes factors for time-series cross-sections or subject cross-sections (or both), without industry neutralization.
//These factors take panel data as parameters and return panel data.


//KLEN
//(high-low)/open
def klen(high, low, open) {
	return (high - low) \ open
}


//KMID
//(close-open)/open

def kmid(close, open){
    return (close - open) \ open
}

// KMID2
// (close - open) / (high - low)
def kmid2(close, high, low, open) {
    den = high - low
    return iif(
        den == 0,double(),(close - open) \ den
    )
}
//KUP
//(high-Greater(open, close))/open
def kup(close, high, open) {
    return (high - max(open, close)) \ open;
}

//KUP2
//(high-Greater(open, close))/(high-low)
def kup2(close, high, low, open) {
    den = high - low
    upper = iif(open > close, open, close)
    return iif(
        den == 0, double(), (high - upper) \ den
    )
}
//KLOW
//(Less(open, close)-low)/open
def klow(close, low, open) {
    return (min(open, close) - low) \ open
}

//KLOW2 
//(Less(open, close)-low)/(high-low)
def klow2(close, high, low, open) {
    den = high - low
    lower = iif(open < close, open, close)
    return iif(
        den == 0, double(), (lower - low) \ den
    )
}
//KSFT 
//(2*close-high-low)/open
def ksft(close, high, low, open) {
    return (2 * close - high - low) \ open
}

//KSFT2
//(2*close-high-low)/(high-low)
def ksft2(close, high, low, open) {
    den = high - low
    return iif(
        den == 0, double(), (2.0 * close - high - low) \ den
    )
}

//2.price因子
//OPEN0
//open/close
def open0(open, close) {
    return open \ close
}

//HIGH0
//high/close
def high0(high, close) {
    return high \ close
}

//LOW0
//low/close
def low0(low, close) {
    return low \ close
}

//VWAP0
//vwap/close
def vwap0(vwap, close) {
    return vwap \ close
}

//3.rolling因子

//3.1 趋势类因子
//ROC[N]
//Ref(close, N)/close
// In this study, N only takes values in {5, 10, 20, 30, 60}.
// Therefore, the actual factors are ROC5, ROC10, ROC20, ROC30, and ROC60.

def rocN(n, close) {
    return move(close, n) \ close
}

def roc5(close) {
    return rocN(5, close)
}

def roc10(close) {
    return rocN(10, close)
}

def roc20(close) {
    return rocN(20, close)
}

def roc30(close) {
    return rocN(30, close)
}

def roc60(close) {
    return rocN(60, close)
}

//MA[N]
//Mean(close, N)/close
def maN(n, close) {
    return mavg(close, n) \ close
}

def ma5(close) {
    return maN(5, close)
}

def ma10(close) {
    return maN(10, close)
}

def ma20(close) {
    return maN(20, close)
}

def ma30(close) {
    return maN(30, close)
}

def ma60(close) {
    return maN(60, close)
}

//BETA[N]
//Slope(close, N)/close
def betaN(n, close) {
    return linearTimeTrend(close, n)[1] \ close
}

def beta5(close) {
    return betaN(5, close)
}

def beta10(close) {
    return betaN(10, close)
}   

def beta20(close) {
    return betaN(20, close)
}

def beta30(close) {
    return betaN(30, close)
}   

def beta60(close) {
    return betaN(60, close)
}

//RSQR[N]
//Rsquare(close, N)
// Rsquare(close, N)
// close is a panel matrix: rows = dates, columns = symbols
// R² = rolling correlation(close, timeIndex)^2

def rsquareN(n, close) {
    s = shape(close)
    nr = s[0]
    nc = s[1]

    timeIndex = take(1..nr, nr * nc) $ nr:nc

    r = mcorr(close, timeIndex, n)

    return r * r
}

def rsquare5(close) {
    return rsquareN(5, close)
}

def rsquare10(close) {
    return rsquareN(10, close)
}

def rsquare20(close) {
    return rsquareN(20, close)
}

def rsquare30(close) {
    return rsquareN(30, close)
}

def rsquare60(close) {
    return rsquareN(60, close)
}

//RESI[N]
//Resi(close, N)/close
def resiN(n, close) {
    trend = linearTimeTrend(close, n)
    alpha = trend[0]
    beta = trend[1]

    fitted = alpha + beta * (n - 1)

    return (close - fitted) \ close
}

def resi5(close) {
    return resiN(5, close)
}

def resi10(close) {
    return resiN(10, close)
}

def resi20(close) {
    return resiN(20, close)
}


def resi30(close) {
    return resiN(30, close)
}

def resi60(close) {
    return resiN(60, close)
}


//3.2波动类因子
//STD[N]
//Std(close, N)/close
def stdN(n, close) {
    return mstd(close, n) \ close
}   

def std5(close) {
    return stdN(5, close)
}

def std10(close) {
    return stdN(10, close)
}

def std20(close) {
    return stdN(20, close)
}

def std30(close) {
    return stdN(30, close)
}

def std60(close) {
    return stdN(60, close)
}

//MAX[N]
//Max(high, N)/close
def maxN(n, high, close) {
    return mmax(high, n) \ close
}

def max5(high, close) {
    return maxN(5, high, close)
}

def max10(high, close) {
    return maxN(10, high, close)
}

def max20(high, close) {
    return maxN(20, high, close)
}

def max30(high, close) {
    return maxN(30, high, close)
}

def max60(high, close) {
    return maxN(60, high, close)
}

//MIN[N]
//Min(low, N)/close
def minN(n, low, close) {
    return mmin(low, n) \ close
}

def min5(low, close) {
    return minN(5, low, close)
}

def min10(low, close) {
    return minN(10, low, close)
}

def min20(low, close) {
    return minN(20, low, close)
}

def min30(low, close) {
    return minN(30, low, close)
}

def min60(low, close) {
    return minN(60, low, close)
}

//QTLU[N]
//Quantile(close, N, 0.8)/close

def quantile80N(n, close) {
    return mpercentile(close, 80, n) \ close
}
def quantile80_5(close) {
    return quantile80N(5, close)
}

def quantile80_10(close) {
    return quantile80N(10, close)
}

def quantile80_20(close) {
    return quantile80N(20, close)
}

def quantile80_30(close) {
    return quantile80N(30, close)
}

def quantile80_60(close) {
    return quantile80N(60, close)
}

//QTLD[N]
//Quantile(close, N, 0.2)/close
def quantile20N(n, close) {
    return mpercentile(close, 20, n) \ close
}   

def quantile20_5(close) {
    return quantile20N(5, close)
}

def quantile20_10(close) {
    return quantile20N(10, close)
}

def quantile20_20(close) {
    return quantile20N(20, close)
}

def quantile20_30(close) {
    return quantile20N(30, close)
}

def quantile20_60(close) {
    return quantile20N(60, close)
}


//RSV[N]
//(close - Min(low, N)) / (Max(high, N) - Min(low, N))
def rsvN(n, close, high, low) {
    den = mmax(high, n) - mmin(low, n)
    return iif(
        den == 0, double(), (close - mmin(low, n)) \ den
    )
}

def rsv5(close, high, low) {
    return rsvN(5, close, high, low)
}

def rsv10(close, high, low) {
    return rsvN(10, close, high, low)
}

def rsv20(close, high, low) {
    return rsvN(20, close, high, low)
}

def rsv30(close, high, low) {
    return rsvN(30, close, high, low)
}

def rsv60(close, high, low) {
    return rsvN(60, close, high, low)
}

//3.3 时间周期类因子

//IMAX[N]
//IdxMax(high, N)/N

def imaxN(n, high) {
    return mimax(high, n) \ n
}

def imax5(high) {
    return imaxN(5, high)
}

def imax10(high) {
    return imaxN(10, high)
}

def imax20(high) {
    return imaxN(20, high)
}

def imax30(high) {
    return imaxN(30, high)
}

def imax60(high) {
    return imaxN(60, high)
}

//IMIN[N]
//IdxMin(low, N)/N

def iminN(n, low) {
    return mimin(low, n) \ n
}

def imin5(low) {
    return iminN(5, low)
}

def imin10(low) {
    return iminN(10, low)
}

def imin20(low) {
    return iminN(20, low)
}

def imin30(low) {
    return iminN(30, low)
}   

def imin60(low) {
    return iminN(60, low)
}


//IMXD[N]
//(IdxMax(high, N) - IdxMin(low, N))/N

def imxdN(n, high, low) {
    return (mimax(high, n) - mimin(low, n)) \ n
}

def imxd5(high, low) {
    return imxdN(5, high, low)
}

def imxd10(high, low) {
    return imxdN(10, high, low)
}

def imxd20(high, low) {
    return imxdN(20, high, low)
}

def imxd30(high, low) {
    return imxdN(30, high, low)
}

def imxd60(high, low) {
    return imxdN(60, high, low)
}

//3.4 量价关系类因子
//CORR[N]
//Corr(close, Log(volume+1), N)
def corrN(n, close, vol) {
    tmp1 = log(vol + 1)
    return mcorr(close, tmp1, n)
}

def corr5(close, vol) {
    return corrN(5, close, vol)
}

def corr10(close, vol) {
    return corrN(10, close, vol)
}

def corr20(close, vol) {
    return corrN(20, close, vol)
}

def corr30(close, vol) {
    return corrN(30, close, vol)
}

def corr60(close, vol) {
    return corrN(60, close, vol)
}

//CORD[N]
//Corr(close/Ref(close,1), Log(volume/Ref(volume,1)+1), N)
def cordN(n, close, vol) {
    priceRatio = close \ move(close, 1)
    volumeRatioLog = log(vol \ move(vol, 1) + 1)

    return mcorr(priceRatio, volumeRatioLog, n)
}

def cord5(close, vol) {
    return cordN(5, close, vol)
}

def cord10(close, vol) {
    return cordN(10, close, vol)
}

def cord20(close, vol) {
    return cordN(20, close, vol)
}

def cord30(close, vol) {
    return cordN(30, close, vol)
}

def cord60(close, vol) {
    return cordN(60, close, vol)
}

//CNTP[N]
//Mean(close>Ref(close,1), N)
def cntpN(n, close) {
    prevClose = prev(close)
    up = iif(isNull(prevClose), NULL, iif(close > prevClose, 1.0, 0.0))
    return mavg(up, n)
}

def cntp5(close) {
    return cntpN(5, close)
}

def cntp10(close) {
    return cntpN(10, close)
}

def cntp20(close) {
    return cntpN(20, close)
}

def cntp30(close) {
    return cntpN(30, close)
}

def cntp60(close) {
    return cntpN(60, close)
}

//CNTN[N]
//Mean(close<Ref(close,1), N)
def cntnN(n, close) {
    prevClose = prev(close)
    down = iif(isNull(prevClose), NULL, iif(close < prevClose, 1.0, 0.0))
    return mavg(down, n)
}

def cntn5(close) {
    return cntnN(5, close)
}

def cntn10(close) {
    return cntnN(10, close)
}

def cntn20(close) {
    return cntnN(20, close)
}

def cntn30(close) {
    return cntnN(30, close)
}

def cntn60(close) {
    return cntnN(60, close)
}

//CNTD[N]
//Mean(close>Ref(close,1),N)-Mean(close<Ref(close,1),N)
def cntdN(n, close) {
    return cntpN(n, close) - cntnN(n, close)
}

def cntd5(close) {
    return cntdN(5, close)
}

def cntd10(close) {
    return cntdN(10, close)
}

def cntd20(close) {
    return cntdN(20, close)
}

def cntd30(close) {
    return cntdN(30, close)
}

def cntd60(close) {
    return cntdN(60, close)
}


//SUMP[N]
//Sum(Greater(close-Ref(close,1),0),N)/(Sum(Abs(close-Ref(close,1)),N))
def sumpN(n, close) {
    delta = close - prev(close)

    upMove = iif(delta > 0, delta, 0.0)

    numerator = msum(upMove, n)
    denominator = msum(abs(delta), n)

    return iif(denominator == 0, NULL, numerator \ denominator)
}


def sump5(close) {
    return sumpN(5, close)
}

def sump10(close) {
    return sumpN(10, close)
}

def sump20(close) {
    return sumpN(20, close)
}

def sump30(close) {
    return sumpN(30, close)
}

def sump60(close) {
    return sumpN(60, close)
}


//SUMN[N]
//Sum(Greater(Ref(close,1)-close,0),N)/(Sum(Abs(close-Ref(close,1)),N))
def sumnN(n, close) {
    delta = close - prev(close)

    downMove = iif(isNull(delta), NULL, iif(delta < 0, -delta, 0.0))
    totalMove = abs(delta)

    numerator = msum(downMove, n)
    denominator = msum(totalMove, n)

    return iif(denominator == 0, NULL, numerator \ denominator)
}

def sumn5(close) {
    return sumnN(5, close)
}

def sumn10(close) {
    return sumnN(10, close)
}

def sumn20(close) {
    return sumnN(20, close)
}

def sumn30(close) {
    return sumnN(30, close)
}

def sumn60(close) {
    return sumnN(60, close)
}

//SUMD[N]
//(Sum(Greater(close-Ref(close,1),0),N)-Sum(Greater(Ref(close,1)-close,0),N))/(Sum(Abs(close-Ref(close,1)),N))
def sumdN(n, close) {
    delta = close - prev(close)

    upMove = iif(isNull(delta), NULL, iif(delta > 0, delta, 0.0))
    downMove = iif(isNull(delta), NULL, iif(delta < 0, -delta, 0.0))
    totalMove = abs(delta)

    numerator = msum(upMove, n) - msum(downMove, n)
    denominator = msum(totalMove, n)

    return iif(denominator == 0, NULL, numerator \ denominator)
}

def sumd5(close) {
    return sumdN(5, close)
}

def sumd10(close) {
    return sumdN(10, close)
}

def sumd20(close) {
    return sumdN(20, close)
}

def sumd30(close) {
    return sumdN(30, close)
}

def sumd60(close) {
    return sumdN(60, close)
}


//3.5 成交量波动类因子

//VMA[N]
//Mean(volume, N)/(volume)
def vmaN(n, vol) {
    return mavg(vol, n) \ vol
}

def vma5(vol) {
    return vmaN(5, vol)
}

def vma10(vol) {
    return vmaN(10, vol)
}

def vma20(vol) {
    return vmaN(20, vol)
}

def vma30(vol) {
    return vmaN(30, vol)
}

def vma60(vol) {
    return vmaN(60, vol)
}

//VSTD[N]
//Std(volume, N)/(volume)
def vstdN(n, vol) {
    return mstd(vol, n) \ vol
}

def vstd5(vol) {
    return vstdN(5, vol)
}

def vstd10(vol) {
    return vstdN(10, vol)
}

def vstd20(vol) {
    return vstdN(20, vol)
}

def vstd30(vol) {
    return vstdN(30, vol)
}

def vstd60(vol) {
    return vstdN(60, vol)
}


//3.6 成交量加权类因子

//WVMA[N]
//Std(Abs(close/Ref(close,1)-1)*volume, N)/(Mean(Abs(close/Ref(close,1)-1)*volume, N))

def wvmaN(close, vol, N){
    x = abs(close / prev(close) - 1) * vol
    den = mavg(x, N)
    num = mstd(x, N)

    return iif(isNull(den) or den == 0, double(NULL), num / den)
}

def wvma5(close, vol) {
    return wvmaN(close, vol, 5)
}

def wvma10(close, vol) {
    return wvmaN(close, vol, 10)
}

def wvma20(close, vol) {
    return wvmaN(close, vol, 20)
}

def wvma30(close, vol) {
    return wvmaN(close, vol, 30)
}

def wvma60(close, vol) {
    return wvmaN(close, vol, 60)
}

//VSUMP[N]
//Sum(Greater(volume-Ref(volume,1),0),N)/(Sum(Abs(volume-Ref(volume,1)),N))
def vsumpN(n, vol) {
    delta = vol - prev(vol)
    upVolume = iif(isNull(delta), NULL, iif(delta > 0, delta, 0.0))
    totalVolume = abs(delta)

    numerator = msum(upVolume, n)
    denominator = msum(totalVolume, n)

    return iif(denominator == 0, NULL, numerator \ denominator)
}

def vsump5(vol) {
    return vsumpN(5, vol)
}

def vsump10(vol) {
    return vsumpN(10, vol)
}

def vsump20(vol) {
    return vsumpN(20, vol)
}

def vsump30(vol) {
    return vsumpN(30, vol)
}

def vsump60(vol) {
    return vsumpN(60, vol)
}


//VSUMN[N]
//Sum(Greater(Ref(volume,1)-volume,0),N)/(Sum(Abs(volume-Ref(volume,1)),N))

def vsumnN(n, vol) {
    delta = vol - prev(vol)

    downVolume = iif(isNull(delta), double(NULL), iif(delta < 0, -delta, 0.0))
    totalVolume = abs(delta)

    numerator = msum(downVolume, n)
    denominator = msum(totalVolume, n)

    return iif(isNull(denominator) or denominator == 0, double(NULL), numerator \ denominator)
}

def vsumn5(vol) {
    return vsumnN(5, vol)
}

def vsumn10(vol) {
    return vsumnN(10, vol)
}

def vsumn20(vol) {
    return vsumnN(20, vol)
}

def vsumn30(vol) {
    return vsumnN(30, vol)
}

def vsumn60(vol) {
    return vsumnN(60, vol)
}


//VSUMD[N]
//(Sum(Greater(volume-Ref(volume,1),0),N)-Sum(Greater(Ref(volume,1)-volume,0),N))/(Sum(Abs(volume-Ref(volume,1)),N))
def vsumdN(n, vol) {
    delta = vol - prev(vol)

    upVolume = iif(isNull(delta), double(NULL), iif(delta > 0, delta, 0.0))
    downVolume = iif(isNull(delta), double(NULL), iif(delta < 0, -delta, 0.0))
    totalVolume = abs(delta)

    numerator = msum(upVolume, n) - msum(downVolume, n)
    denominator = msum(totalVolume, n)

    return iif(isNull(denominator) or denominator == 0, double(NULL), numerator \ denominator)
}

def vsumd5(vol) {
    return vsumdN(5, vol)
}

def vsumd10(vol) {
    return vsumdN(10, vol)
} 

def vsumd20(vol) {
    return vsumdN(20, vol)
}

def vsumd30(vol) {
    return vsumdN(30, vol)
}

def vsumd60(vol) {
    return vsumdN(60, vol)
}

def rankN(n, close) {
    return mrank(close, true, n) \ n
}

def rank5(close) {
    return rankN(5, close)
}
def rank10(close) { 
    return rankN(10, close) 
}
def rank20(close) {
    return rankN(20, close) 
}
def rank30(close) { 
    return rankN(30, close) 
}
def rank60(close) { 
    return rankN(60, close) 
}
