Beispiel #1
0
def nav2ret(nav, method='log', window=1):
    '''
    将净值转换为收益率

    Parameter
    ---------
    nav: pandas.Series
        原始净值数据
    method: string, default 'log'
        计算收益率的方法,提供[plain, log]两种,分别表示单利和连续复利
    window: int, default 1
        计算收益的时间窗口长度

    Return
    ------
    ret: pandas.Series

    Notes
    -----
    第一期的收益被重置为0
    '''
    validation_checker(['log', 'plain'])(method)
    if method == 'log':
        return np.log(nav).diff(window).fillna(0)
    else:
        return nav.pct_change(window).fillna(0)
Beispiel #2
0
def ret2nav(ret, method='log'):
    '''
    将收益率转换为净值

    Parameter
    ---------
    ret: pandas.Series
        收益率数据
    method: string, default 'plain'
        转换方式,可选的有[plain, log]

    Return
    ------
    nav: pandas.Series
    '''
    validation_checker(['log', 'plain'])(method)
    if method == 'log':
        return np.exp(ret.cumsum())
    else:
        return ret.add(1).cumprod()
Beispiel #3
0
def transform_return_frequency(raw_ret, freq, method='plain'):
    '''
    转换收益的频率

    Parameter
    ---------
    raw_ret: float
        原始收益
    freq: float
        目标收益相对于源收益数据的倍数,例如源数据为月度收益,要转换为年度收益,则freq为12
    method: string, default 'plain'
        收益计算方式,可选为[plain, log]

    Return
    ------
    transed_ret: float
    '''
    validation_checker(['log', 'plain'])(method)
    if method == 'plain':
        return (1 + raw_ret)**freq - 1
    else:
        return raw_ret * freq
Beispiel #4
0
def cal_return(r0, r1, method):
    '''
    计算从r0到r1的收益

    Parameter
    ---------
    r0: float or np.array like
        前期净值数据
    r1: float
        后期净值数据
    method: string or np.array like
        收益计算方法,可选有[plain, log]

    Return
    ------
    r: float
    '''
    validation_checker(['plain', 'log'])(method)
    if method == 'plain':
        return r1 / r0 - 1
    else:
        return np.log(r1) - np.log(r0)
Beispiel #5
0
def total_return(nav, bnav, method='plain'):
    '''
    计算期间总收益

    Parameter
    ---------
    nav: pandas.Series
        策略净值
    bnav: pandas.Series
        基准净值,无用处
    method: string, default 'log'
        计算收益的方法,提供[plain, log]两种

    Return
    ------
    ret: float
    '''
    validation_checker(['log', 'plain'])(method)
    if method == 'log':
        nav = np.log(nav)
        return nav.iloc[-1] - nav.iloc[0]
    else:
        return nav.iloc[-1] / nav.iloc[0] - 1
Beispiel #6
0
def oneside_vol(nav,
                bnav,
                freq=250,
                method='plain',
                threshold=0.,
                direction=-1):
    '''
    单向波动率,即上行波动率或者下行波动率

    Parameter
    ---------
    nav: pandas.Series
        策略净值
    bnav: pandas.Series
        基准净值
    freq: int, default 250
        策略净值的频率,即低频数据相对于高频数据的时间倍数,例如一般一年约有250个交易日,则日频数据计算年化数据的频率为250
    method: string, default 'plain'
        计算收益率的方法,可选有[log, plain]
    threshold: double, default 0.
        识别上行或者下行收益的阈值,收益的频率与freq要匹配
    direction: int, default -1
        波动率方向,可选为[-1, 1],其中-1表示下行,1表示上行

    Return
    ------
    dv: float

    Notes
    -----
    dv = sqrt(freq / len(ret) * sum(min(ret - threshold, 0)**2))
    '''
    validation_checker([-1, 1])(direction)
    ret = nav2ret(nav, method)
    valid_ret = ret - threshold
    valid_ret.loc[direction * valid_ret <= 0] = 0
    return np.sqrt(valid_ret.dot(valid_ret) * freq / len(nav))
Beispiel #7
0
def rolling_comparable_return(nav,
                              bnav,
                              freq=250,
                              method='plain',
                              cut_tail=30):
    '''
    滚动起始时间的可比收益,即以每一个交易日作为起始日期计算最终的可比收益

    Parameter
    ---------
    nav: pandas.Series
        策略净值
    bnav: pandas.Series
        基准净值
    method: string, default 'plain'
        收益计算方式,可选为[plain, log]
    freq: int, default 250
        策略净值的频率,即低频数据相对于高频数据的时间倍数,例如一般一年约有250个交易日,则日频数据计算年化数据的频率为250
    cut_tail: int, default 10
        尾部数据因为时间间隔比较短,容易受极端值的影响,因此需要扣除。该参数表示扣除的尾部的长度

    Return
    ------
    out: pandas.Series
    '''
    validation_checker(['plain', 'log'])(method)
    if freq <= 0 or not isinstance(freq, int):
        raise ValueError('freq parameter must be positive integer!')
    if cut_tail <= 0 or not isinstance(freq, int):
        raise ValueError('cut_tail parameter must be positive integer!')
    valid_nav = nav.iloc[:-cut_tail]
    period_time = freq / (len(nav) - np.arange(1, len(valid_nav) + 1))
    if method == 'plain':
        ret = (nav.iloc[-1] / valid_nav)**period_time - 1
    else:
        ret = (np.log(nav.iloc[-1]) - np.log(valid_nav)) * period_time
    return ret
Beispiel #8
0
def max_gl(nav,
           bnav,
           method='plain',
           window=20,
           gl_flag=1,
           excess_ret_flag=False):
    '''
    滚动窗口的最大收益或损失

    Parameter
    ---------
    nav: pandas.Series
        策略净值
    bnav: pandas.Series
        基准净值
    method: string, default 'plain'
        收益计算方式,可选有[log, plain]
    window: pandas.Series
        收益或损失的计算窗口长度
    gl_flag: int, default 1
        标记计算收益还是损失,1表示收益,- 1表示损失
    er_flag: boolean, default False
        是否以超额数据为基础计算

    Return
    ------
    gl: (gl, gl_start, gl_end)
    '''
    validation_checker([1, -1])(gl_flag)
    ret = nav2ret(nav, method, window)
    if excess_ret_flag:
        ret = ret - nav2ret(bnav, method, window)
    mgl = gl_flag * np.max(ret * gl_flag)
    mgl_end = (ret * gl_flag).argmax()
    mgl_start = ret.index[ret.index.get_loc(mgl_end) - window]
    return (mgl, mgl_start, mgl_end)