def simple(x, fc, alpha=None):
    '''
        单参数简单指数平滑预测模型
        parameters:
            --------
            x:时间序列数据列表
            fc:预测期数
            alpha:alpha参数,初始值默认为空

        return:
            --------
            pred:预测值
            alpha:最优alpha值
            rmse
            aic
            ds
            prestd:残差标准差
    '''

    Y = x[:]
    if alpha is None:
        initial_values = array([0.1])
        boundaries = [(0, 1)]
        type = 'simple'

        parameters = fmin_l_bfgs_b(RMSE,
                                   x0=initial_values,
                                   args=(Y, type),
                                   bounds=boundaries,
                                   approx_grad=True)
        alpha = parameters[0][0]

    a = [Y[0]]  # 求和
    y = [a[0]]  # 预测列
    rmse = 0

    for i in range(len(Y) + fc):
        if i == len(Y):
            Y.append(a[-1])

        a.append(alpha * Y[i] + (1 - alpha) * a[i])
        y.append(a[i + 1])

    # rmse = sqrt(sum([(m - n) ** 2 for m,n in zip(Y[:-fc],y[:-fc-1])]) / len(Y[:-fc]))
    rmse = Rmse(Y[:-fc], y[:-fc - 1])
    aic = Aic(Y[:-fc], y[:-fc - 1], 1)
    ds = Ds(Y[:-fc], y[:-fc - 1])
    prestd = Stde([(m - n) for m, n in zip(Y[:-fc], y[:-fc - 1])])

    return {
        'pred': Y[-fc:],
        'alpha': alpha,
        'rmse': rmse,
        'aic': aic,
        'ds': ds,
        'prestd': prestd,
        'fittedvalues': y[1:-fc]
    }
def multiplicative_seasonal(x, m, fc, alpha=None, beta=None, gamma=None):
    """
    同multiplicative,返回数据作调整
    """
    Y = x[:]

    if (alpha == None or beta == None or gamma == None):

        initial_values = array([0.0, 1.0, 0.0])
        boundaries = [(0, 1), (0, 1), (0, 1)]
        type = 'multiplicative'

        parameters = fmin_l_bfgs_b(RMSE,
                                   x0=initial_values,
                                   args=(Y, type, m),
                                   bounds=boundaries,
                                   approx_grad=True)
        alpha, beta, gamma = parameters[0]

    a = [sum(Y[0:m]) / float(m)]
    b = [(sum(Y[m:2 * m]) - sum(Y[0:m])) / m**2]
    s = [Y[i] / a[0] for i in range(m)]
    y = [(a[0] + b[0]) * s[0]]
    rmse = 0

    for i in range(len(Y) + fc):

        if i == len(Y):
            Y.append((a[-1] + b[-1]) * s[-m])

        a.append(alpha * (Y[i] / s[i]) + (1 - alpha) * (a[i] + b[i]))
        b.append(beta * (a[i + 1] - a[i]) + (1 - beta) * b[i])
        s.append(gamma * (Y[i] / (a[i] + b[i])) + (1 - gamma) * s[i])
        y.append((a[i + 1] + b[i + 1]) * s[i + 1])

    # rmse = sqrt(sum([(m - n) ** 2 for m, n in zip(Y[:-fc], y[:-fc - 1])]) / len(Y[:-fc]))
    rmse = Rmse(Y[:-fc], y[:-fc - 1])

    return {
        'pred': Y[-fc:],
        'alpha': alpha,
        'beta': beta,
        'gamma': gamma,
        'rmse': rmse,
        'seasonal': s,
        'fittedvalues': y[1:-fc]
    }
def rolling(seq, wind, fc):
    '''
        含有rmse和预测值的移动平均
        parameters:
            --------
            seq:计算移动平均的时间序列
            wind:移动期数
            fc:预测期数

        return:
            --------
            pred:预测值
            rmse
            aic
            ds
            prestd:残差标准差
    '''

    mavg = seq.rolling(window=wind, center=False).mean()  # 移动平均,wind表示移动期数
    mavg.dropna(inplace=True)  # 原地删除空值
    man_value = list(mavg.values)  # 移动平均序列值
    old_value = list(seq.values)[wind - 1:]  # 排除移动期原始序列值
    # rmse = sqrt(sum((m-n)**2 for m,n in zip(man_value,old_value)) / len(man_value))
    rmse = Rmse(old_value, man_value)
    aic = Aic(old_value, man_value, 0)
    ds = Ds(old_value, man_value)
    prestd = Stde([(m - n) for m, n in zip(old_value, man_value)])
    predata = [man_value[-1]] * fc * 7  # 预测值

    return {
        'pred': predata,
        'rmse': rmse,
        'aic': aic,
        'ds': ds,
        'prestd': prestd
    }
def RMSE(params, *args):
    '''
        计算均方根误差
        parameters:
            --------
            params:包含alpha,beta,gamma三者或其中之一的初始值元组
            args:包含原始计算序列与type的元组

        return:
            --------
            rmse:均方根误差
    '''

    Y = args[0]
    type = args[1]
    rmse = 0

    if type == 'simple':
        alpha = params[0]
        a = [Y[0]]
        y = [a[0]]

        for i in range(len(Y)):
            a.append(alpha * Y[i] + (1 - alpha) * a[i])
            y.append(a[i + 1])

    elif type == 'linear':

        alpha, beta = params
        a = [Y[0]]
        b = [Y[1] - Y[0]]
        y = [a[0] + b[0]]

        for i in range(len(Y)):

            a.append(alpha * Y[i] + (1 - alpha) * (a[i] + b[i]))
            b.append(beta * (a[i + 1] - a[i]) + (1 - beta) * b[i])
            y.append(a[i + 1] + b[i + 1])

    else:

        alpha, beta, gamma = params
        m = args[2]
        a = [sum(Y[0:m]) / float(m)]
        b = [(sum(Y[m:2 * m]) - sum(Y[0:m])) / m**2]

        if type == 'additive':

            s = [Y[i] - a[0] for i in range(m)]
            y = [a[0] + b[0] + s[0]]

            for i in range(len(Y)):

                a.append(alpha * (Y[i] - s[i]) + (1 - alpha) * (a[i] + b[i]))
                b.append(beta * (a[i + 1] - a[i]) + (1 - beta) * b[i])
                s.append(gamma * (Y[i] - a[i] - b[i]) + (1 - gamma) * s[i])
                y.append(a[i + 1] + b[i + 1] + s[i + 1])

        elif type == 'multiplicative':

            s = [Y[i] / a[0] for i in range(m)]
            y = [(a[0] + b[0]) * s[0]]

            for i in range(len(Y)):

                a.append(alpha * (Y[i] / s[i]) + (1 - alpha) * (a[i] + b[i]))
                b.append(beta * (a[i + 1] - a[i]) + (1 - beta) * b[i])
                s.append(gamma * (Y[i] / (a[i] + b[i])) + (1 - gamma) * s[i])
                y.append((a[i + 1] + b[i + 1]) * s[i + 1])

        else:

            exit('Type must be either linear, additive or multiplicative')

    # rmse = sqrt(sum([(m - n) ** 2 for m, n in zip(Y, y[:-1])]) / len(Y))
    rmse = Rmse(Y, y[:-1])

    return rmse
def multiplicative(x, m, fc, alpha=None, beta=None, gamma=None):
    '''
        HW指数平滑乘法预测模型
        parameters:
            --------
            x:时间序列数据列表
            m:序列周期数(eg.序列为月份数据,m=12)
            fc:预测期数
            alpha:alpha参数,初始值默认为空
            beta:beta参数,初始值默认为空
            gamma:gamma参数,初始值默认为空

        return:
            --------
            pred:预测值
            alpha:最优alpha值
            beta:最优beta值
            gamma:最优gamma值
            rmse
            aic
            ds
            prestd:残差标准差
    '''

    Y = x[:]

    if (alpha is None or beta is None or gamma is None):

        initial_values = array([0.0, 1.0, 0.0])
        boundaries = [(0, 1), (0, 1), (0, 1)]
        type = 'multiplicative'

        parameters = fmin_l_bfgs_b(RMSE,
                                   x0=initial_values,
                                   args=(Y, type, m),
                                   bounds=boundaries,
                                   approx_grad=True)
        alpha, beta, gamma = parameters[0]

    a = [sum(Y[0:m]) / float(m)]
    b = [(sum(Y[m:2 * m]) - sum(Y[0:m])) / m**2]
    s = [Y[i] / a[0] for i in range(m)]
    y = [(a[0] + b[0]) * s[0]]
    rmse = 0

    for i in range(len(Y) + fc):

        if i == len(Y):
            Y.append((a[-1] + b[-1]) * s[-m])

        a.append(alpha * (Y[i] / s[i]) + (1 - alpha) * (a[i] + b[i]))
        b.append(beta * (a[i + 1] - a[i]) + (1 - beta) * b[i])
        s.append(gamma * (Y[i] / (a[i] + b[i])) + (1 - gamma) * s[i])
        y.append((a[i + 1] + b[i + 1]) * s[i + 1])

    # rmse = sqrt(sum([(m - n) ** 2 for m, n in zip(Y[:-fc], y[:-fc - 1])]) / len(Y[:-fc]))
    rmse = Rmse(Y[:-fc], y[:-fc - 1])
    aic = Aic(Y[:-fc], y[:-fc - 1], 3)
    ds = Ds(Y[:-fc], y[:-fc - 1])
    prestd = Stde([(m - n) for m, n in zip(Y[:-fc], y[:-fc - 1])])

    return {
        'pred': Y[-fc:],
        'alpha': alpha,
        'beta': beta,
        'gamma': gamma,
        'rmse': rmse,
        'aic': aic,
        'ds': ds,
        'prestd': prestd,
        'fittedvalues': y[1:-fc]
    }
def linear(x, fc, alpha=None, beta=None):
    '''
        双参数简单指数平滑预测模型
        parameters:
            --------
            x:时间序列数据列表
            fc:预测期数
            alpha:alpha参数,初始值默认为空
            beta:beta参数,初始默认值为空

        return:
            --------
            pred:预测值
            alpha:最优alpha值
            beta:最优beta值
            rmse
            aic
            ds
            prestd:残差标准差
    '''

    Y = x[:]

    if (alpha is None or beta is None):

        initial_values = array([0.3, 0.1])
        boundaries = [(0, 1), (0, 1)]
        type = 'linear'

        # fmin_l_bfgs_b为迭代函数,接受一个函数参数,返回使得该函数的结果最优的数据
        parameters = fmin_l_bfgs_b(RMSE,
                                   x0=initial_values,
                                   args=(Y, type),
                                   bounds=boundaries,
                                   approx_grad=True)
        alpha, beta = parameters[0]

    a = [Y[0]]
    b = [Y[1] - Y[0]]
    y = [a[0] + b[0]]
    rmse = 0

    for i in range(len(Y) + fc):

        if i == len(Y):
            Y.append(a[-1] + b[-1])

        a.append(alpha * Y[i] + (1 - alpha) * (a[i] + b[i]))
        b.append(beta * (a[i + 1] - a[i]) + (1 - beta) * b[i])
        y.append(a[i + 1] + b[i + 1])

    # rmse = sqrt(sum([(m - n) ** 2 for m, n in zip(Y[:-fc], y[:-fc - 1])]) / len(Y[:-fc]))
    rmse = Rmse(Y[:-fc], y[:-fc - 1])
    aic = Aic(Y[:-fc], y[:-fc - 1], 2)
    ds = Ds(Y[:-fc], y[:-fc - 1])
    prestd = Stde([(m - n) for m, n in zip(Y[:-fc], y[:-fc - 1])])

    return {
        'pred': Y[-fc:],
        'alpha': alpha,
        'beta': beta,
        'rmse': rmse,
        'aic': aic,
        'ds': ds,
        'prestd': prestd,
        'fittedvalues': y[1:-fc]
    }