Esempio n. 1
0
def comput_idicators(df,
                     trading_days,
                     required,
                     save_file,
                     save_address,
                     whole=1):
    # TODO:net_value has some problem.
    # columns needed
    col = ['index_price', 'Interest_rate', 'nav', 'rebalancing', 'stoploss']
    df_valid = df.ix[:, col]
    start_balance = df.index[df['rebalancing'] == 1][0]
    df_valid = df_valid[df_valid.index >= start_balance]

    # daily return
    df_valid['return'] = np.log(df['nav']) - np.log(df['nav'].shift(1))
    # benchmark_net_value
    df_valid[
        'benchmark'] = df_valid['index_price'] / df_valid['index_price'].ix[0]
    # benchmark_return
    df_valid['benchmark_return'] = (df_valid['benchmark']-
                                           df_valid['benchmark'].shift(1))/\
                                   df_valid['benchmark'].shift(1)
    # Annualized return
    df_valid['Annu_return'] = pd.expanding_mean(
        df_valid['return']) * trading_days
    # Volatility
    df_valid.loc[:, 'algo_volatility'] = pd.expanding_std(
        df_valid['return']) * np.sqrt(trading_days)
    df_valid.loc[:, 'xret'] = df_valid[
        'return'] - df_valid['Interest_rate'] / trading_days / 100
    df_valid.loc[:, 'ex_return'] = df_valid['return'] - df_valid[
        'benchmark_return']

    def ratio(x):
        return np.nanmean(x) / np.nanstd(x)

    # sharpe ratio
    df_valid.loc[:, 'sharpe'] = pd.expanding_apply(df_valid['xret'], ratio)\
                                * np.sqrt(trading_days)
    # information ratio
    df_valid.loc[:, 'IR'] = pd.expanding_apply(df_valid['ex_return'], ratio)\
                                * np.sqrt(trading_days)

    # Sortino ratio
    def modify_ratio(x, re):
        re /= trading_days
        ret = np.nanmean(x) - re
        st_d = np.nansum(np.square(x[x < re] - re)) / x[x < re].size
        return ret / np.sqrt(st_d)

    df_valid.loc[:, 'sortino'] = pd.expanding_apply(
        df_valid['return'], modify_ratio,
        args=(required, )) * np.sqrt(trading_days)
    # Transfer infs to NA
    df_valid.loc[np.isinf(df_valid.loc[:, 'sharpe']), 'sharpe'] = np.nan
    df_valid.loc[np.isinf(df_valid.loc[:, 'IR']), 'IR'] = np.nan
    # hit_rate
    wins = np.where(df_valid['return'] >= df_valid['benchmark_return'], 1.0,
                    0.0)
    df_valid.loc[:, 'hit_rate'] = wins.cumsum() / pd.expanding_apply(wins, len)
    # 95% VaR
    df_valid['VaR'] = -pd.expanding_quantile(df_valid['return'], 0.05)*\
                      np.sqrt(trading_days)
    # 95% CVaR
    df_valid['CVaR'] = -pd.expanding_apply(df_valid['return'],
                                          lambda x: x[x < np.nanpercentile(x, 5)].mean())\
                       * np.sqrt(trading_days)

    if whole == 1:
        # max_drawdown
        def exp_diff(x, type):
            if type == 'dollar':
                xret = pd.expanding_apply(x, lambda xx: (xx[-1] - xx.max()))
            else:
                xret = pd.expanding_apply(
                    x, lambda xx: (xx[-1] - xx.max()) / xx.max())
            return xret
    # dollar
    #     xret = exp_diff(df_valid['cum_profit'],'dollar')
    #     df_valid['max_drawdown_profit'] = abs(pd.expanding_min(xret))
    # percentage

        xret = exp_diff(df_valid['nav'], 'percentage')
        df_valid['max_drawdown_ret'] = abs(pd.expanding_min(xret))

        # max_drawdown_duration:
        # drawdown_enddate is the first time for restoring the max
        def drawdown_end(x, type):
            xret = exp_diff(x, type)
            minloc = xret[xret == xret.min()].index[0]
            x_sub = xret[xret.index > minloc]
            # if never recovering,then return nan
            try:
                return x_sub[x_sub == 0].index[0]
            except:
                return np.nan

        def drawdown_start(x, type):
            xret = exp_diff(x, type)
            minloc = xret[xret == xret.min()].index[0]
            x_sub = xret[xret.index < minloc]
            try:
                return x_sub[x_sub == 0].index[-1]
            except:
                return np.nan

        df_valid['max_drawdown_start'] = pd.Series()
        df_valid['max_drawdown_end'] = pd.Series()
        df_valid['max_drawdown_start'].ix[-1] = drawdown_start(
            df_valid['nav'], 'percentage')
        df_valid['max_drawdown_end'].ix[-1] = drawdown_end(
            df_valid['nav'], 'percentage')
    df_valid.to_csv(save_address)
    # =====result visualization=====
    plt.figure(1)
    if whole == 1:
        plt.subplot(224)
        plt.plot(df_valid['nav'], label='strategy')
        plt.plot(df_valid['benchmark'], label='S&P500')
    plt.xlabel('Date')
    plt.legend(loc=0, shadow=True)
    plt.ylabel('Nav')
    plt.title('Nav of ' + save_file + ' & SP500')

    # plt.subplot(223)
    # plt.plot(df_valid['cum_profit'],label = 'strategy')
    # plt.xlabel('Date')
    # plt.ylabel('Cum_profit')
    # plt.title('Cum_profit of ' + save_file)

    plt.subplot(221)
    plt.plot(df_valid['return'], label='strategy')
    plt.xlabel('Date')
    plt.ylabel('Daily_return')
    plt.title('Daily Return of ' + save_file)

    plt.subplot(222)
    x_return = df_valid[df_valid['return'].notna()].loc[:, 'return']
    y_return = df_valid[
        df_valid['benchmark_return'].notna()].loc[:, 'benchmark_return']
    mu = x_return.mean()
    sigma = x_return.std()
    mybins = np.linspace(mu - 3 * sigma, mu + 3 * sigma, 100)
    count_x, _, _ = plt.hist(x_return,
                             mybins,
                             normed=1,
                             alpha=0.5,
                             label='strategy')
    count_y, _, _ = plt.hist(y_return,
                             mybins,
                             normed=1,
                             alpha=0.5,
                             label='S&P500')
    plt.ylabel('density')
    plt.xlabel('daily_return')
    plt.title('Histogram of Daily Return for ' + save_file + ' & SP500')
    plt.grid(True)
    # add normal distribution line
    y = mlab.normpdf(mybins, mu, sigma)
    plt.plot(mybins, y, 'r--', linewidth=1, label='Normal of strategy')
    plt.legend(loc=0, shadow=True)
    # plt.tight_layout()
    plt.show()
    return df_valid
Esempio n. 2
0
def VaR(symbol='AAPL',
        notl=None,
        conf=0.95,
        dist=None,
        _d1=None,
        _d2=None,
        volwindow=50,
        varwindow=250):
    # Retrieve the data from Internet
    # Choose a time period
    d1 = _d1 if _d1 else datetime.datetime(2001, 1, 1)
    d2 = _d2 if _d2 else datetime.datetime(2012, 1, 1)
    #get the tickers
    price = DataReader(symbol, "yahoo", d1, d2)['Adj Close']
    price = price.asfreq('B').fillna(method='pad')
    ret = price.pct_change()

    #choose the quantile
    quantile = 1 - conf

    import pdb
    pdb.set_trace()
    #simple VaR using all the data
    # VaR on average accross all the data
    unnormedquantile = pd.expanding_quantile(ret, quantile)

    # similar one using a rolling window
    # VaR only calculated over the varwindow, rolling
    unnormedquantileR = pd.rolling_quantile(ret, varwindow, quantile)

    #we can also normalize the returns by the vol
    vol = pd.rolling_std(ret, volwindow) * np.sqrt(256)
    unitvol = ret / vol

    #and get the expanding or rolling quantiles
    # Same calcs as above except normalized so show VaR in
    # standard deviations instead of expected returns
    Var = pd.expanding_quantile(unitvol, quantile)
    VarR = pd.rolling_quantile(unitvol, varwindow, quantile)

    normedquantile = Var * vol
    normedquantileR = VarR * vol

    ret2 = ret.shift(-1)
    courbe = pd.DataFrame({
        'returns': ret2,
        'quantiles': unnormedquantile,
        'Rolling quantiles': unnormedquantileR,
        'Normed quantiles': normedquantile,
        'Rolling Normed quantiles': normedquantileR,
    })

    courbe['nqBreak'] = np.sign(ret2 - normedquantile) / (-2) + 0.5
    courbe['nqBreakR'] = np.sign(ret2 - normedquantileR) / (-2) + 0.5
    courbe['UnqBreak'] = np.sign(ret2 - unnormedquantile) / (-2) + 0.5
    courbe['UnqBreakR'] = np.sign(ret2 - unnormedquantileR) / (-2) + 0.5

    nbdays = price.count()
    print('Number of returns worse than the VaR')
    print('Ideal Var                : ', (quantile) * nbdays)
    print('Simple VaR               : ', np.sum(courbe['UnqBreak']))
    print('Normalized VaR           : ', np.sum(courbe['nqBreak']))
    print('---------------------------')
    print('Ideal Rolling Var        : ', (quantile) * (nbdays - varwindow))
    print('Rolling VaR              : ', np.sum(courbe['UnqBreakR']))
    print('Rolling Normalized VaR   : ', np.sum(courbe['nqBreakR']))
Esempio n. 3
0
#get the tickers
stock = "PETR4.SA"
price = DataReader(stock, "yahoo", d1, d2)['Adj Close']
price = price.asfreq('B').fillna(method='pad')

ret = price.pct_change()

#choose the quantile
quantile = 0.05
#the vol window
volwindow = 50
#and the Var window for rolling
varwindow = 250

#simple VaR using all the data
unnormedquantile = pd.expanding_quantile(ret, quantile)

#similar one using a rolling window
unnormedquantileR = pd.rolling_quantile(ret, varwindow, quantile)

#we can also normalize the returns by the vol
vol = pd.rolling_std(ret, volwindow) * np.sqrt(256)
unitvol = ret / vol

#and get the expanding or rolling quantiles
Var = pd.expanding_quantile(unitvol, quantile)
VarR = pd.rolling_quantile(unitvol, varwindow, quantile)

normedquantile = Var * vol
normedquantileR = VarR * vol