Пример #1
0
def show_dividend(ticker, start=None, end=None):
    """
    Show annual dividend yield
    input:  ticker  ticker of the stock/ETF
            start   start date, default '2000-01-01'
            end     end date, default current
    Return a DataFrame
    """
    from invest.useful import convert_time
    from invest.get_data import read_ETF
    from invest.calculation import add_dividend, get_dividend_yield
    start, end = convert_time(start, end)
    data = read_ETF(ticker)[start:end]
    add_dividend(data, price='Close', adj='Adj Close', out='Div')
    div = get_dividend_yield(data, price='Close', div='Div', style='simple')

    plt.figure(figsize=(14, 4))
    plt.bar(div.index, div * 100)

    ret = data.Div[data.Div > 0].tail(6).to_frame()
    ret.index = ret.index.date

    print(ret)
    plt.show()
    return ret.T
Пример #2
0
def investment_performance(ticker, price, quantity, start, end=None):
    """
    Calculate performance of given stock/ETF.
    input:  ticker  ticker of the stock/ETF
            start   start date
            end     end date, default current
    """
    from invest.useful import convert_time
    from invest.get_data import read_ETF
    from invest.plot import plot_day_price
    from invest.calculation import add_dividend, get_return_vol
    from time_series.functions import resample
    start, end = convert_time(start, end)
    data = read_ETF(ticker)[start:end]
    plot_day_price(data)
    plt.plot([start], [price], 'ro')
    plt.show()
    add_dividend(data, price='Close', adj='Adj Close', out='Dividend')
    temp = data[['Dividend']][data.Dividend != 0].copy()
    temp.index = temp.index.date
    display(temp.T)
    weekly = resample(data, style='week', method='close')
    rv = get_return_vol(weekly[['Close', 'Adj Close']],
                        scale=52,
                        ret=False,
                        plotit=False)
    rv['Total Return'] = data[['Close', 'Adj Close']].iloc[-1, :] / data[
        ['Close', 'Adj Close']].iloc[0, :] - 1
    rv = rv * 100
    rv['Gain'] = np.round(price * quantity * rv['Total Return'] / 100, 2)
    display(rv)
    print("Actual gain without reinvest: {:.2f}".format(
        (data.Close[-1] - price) * quantity))
    print("Dividend gain: {:.2f}".format(data.Dividend.sum() * quantity))
Пример #3
0
def show_yield(ticker, start=None, end=None, weeks=52):
    """
    Calculate annualized return. Simple return is calculated
    input:  ticker  ticker of the stock/ETF
            start   start date, default '2000-01-01'
            end     end date, default current
            weeks   number of weeks for each calculation, default 52
    Return a DataFrame with three rows: Adj Close, Dividend, Close
    """
    from invest.useful import convert_time
    from invest.get_data import read_ETF
    from invest.calculation import add_dividend, get_returns
    from time_series.functions import resample
    start, end = convert_time(start, end)
    data = read_ETF(ticker)[start:end]
    add_dividend(data, price='Close', adj='Adj Close', out='Dividend')
    data['Dividend'] = np.cumsum(data.Dividend)
    weekly = resample(data, style='week', method='close')
    weekly = weekly[(weekly.shape[0] - 1) % weeks::weeks]
    df = get_returns(weekly[['Adj Close', 'Dividend', 'Close']], 'simple')
    df['Dividend'] = (weekly.Dividend.diff() / weekly.Close.shift(1))
    df = df * 100 * 52 / weeks
    from datetime import timedelta
    ds = df.index
    xlim = [
        ds[0] - timedelta(days=3 * weeks), ds[-1] + timedelta(days=3 * weeks)
    ]
    plt.figure(figsize=(14, 3))
    plt.title("Annualized Return")
    plt.hlines(xmin=xlim[0], xmax=xlim[1], y=0)
    plt.hlines(xmin=xlim[0],
               xmax=xlim[1],
               y=df['Adj Close'].mean(),
               linestyle='--',
               color='#1f77b4')
    plt.hlines(xmin=xlim[0],
               xmax=xlim[1],
               y=df.Dividend.mean(),
               linestyle='--',
               color='#ff7f0e')
    plt.bar(ds, df.Close, width=5 * weeks, label='Yield')
    plt.bar(ds,
            df.Dividend,
            bottom=df.Close,
            width=5 * weeks,
            label='Div_Yield')
    plt.plot(ds, df['Adj Close'], 'o-', label='Adj_Yield')
    plt.xlabel("Date to sell")
    plt.xlim(xlim)
    plt.ylim([np.min(df.values) - 0.2, np.max(df.values) + 0.2])
    plt.legend(bbox_to_anchor=(1.01, 0.9), loc='upper left')
    plt.grid()
    df.index = df.index.date

    print(np.round(df, 2))
    plt.show()
    return np.round(df, 2).T
Пример #4
0
def show_trend(ticker, start=None, end=None):
    """
    Plot price change, return and volatility
    input:  ticker  ticker of the stock/ETF
            start   start date, default '2000-01-01'
            end     end date, default current
    Return correlation between return and volatility
    """
    from invest.useful import convert_time
    from invest.get_data import read_ETF
    from invest.calculation import get_returns
    from time_series.functions import moving_agg, resample
    from basic.mathe import covariance, correlation
    start, end = convert_time(start, end)
    data = read_ETF(ticker)[start:end]

    fig = plt.figure(figsize=(14,6))
    fig.add_axes([0.05,0.68,0.94,0.3])
    for c in ['Close','Adj Close']:
        plt.plot(data.index, data[c], label=c)
    plt.xlim(data.index[0],data.index[-1])
    plt.xticks([])
    plt.ylabel("Price ($)")
    plt.legend(loc='best')

    weekly = resample(data, style='week', method='close')
    df = get_returns(weekly.Close, 'simple')

    fig.add_axes([0.05,0.38,0.94,0.3])
    m = moving_agg(df, window=52, step=1, func=np.sum)
    plt.plot(df.index[51:], m*100)
    plt.hlines(xmin=data.index[0], xmax=data.index[-1], y=0, linestyle='--')
    plt.xlim(data.index[0],data.index[-1])
    plt.xticks([])
    plt.ylabel("Annual Return (%)")
    plt.legend(loc='best')

    fig.add_axes([0.05,0.08,0.94,0.3])
    v = moving_agg(df, window=52, step=1, func=covariance)
    v = np.sqrt(v*52)
    plt.plot(df.index[51:], v*100)
    plt.xlim(data.index[0],data.index[-1])
    plt.ylabel("Volatility (%)")
    plt.gca().set_ylim(bottom=0)
    plt.legend(loc='best')

    corr = correlation(m, v)
    print("Correlation between return and volatility:", corr)
    plt.show()
    return corr
Пример #5
0
def load_data_from_yahoo(tickers, start=None, end=None):
    """
    Get historical data from Yahoo Finance
    input:  tickers     one ticker or a list of tickers
            start       start date, default "2000-1-1"(defined in invest.useful)
            end         end date, default current date(defined in invest.useful)
    return whatever the website returns
    """
    from pandas_datareader import data as pdr
    import sys
    if not root in sys.path:
        sys.path.append(root)
    from invest.useful import convert_time
    logger = logging.getLogger(__name__)
    start, end = convert_time(start, end)
    logger.info("Download {} from Yahoo Finance for date range {} to {}".format(
        tickers, start.date(), end.date()))
    try:
        return pdr.get_data_yahoo(tickers, start=start, end=end)
    except:
        logger.error("Failed to download {} from Yahoo Finance. Return empty DataFrame"\
            .format(tickers))
        return pd.DataFrame()
Пример #6
0
def portfolio_analysis(tickers, alloc=None, start='2010-01-01', end=None):
    """
    Given a series of tickers, return a summery of each ETF in a DataFrame
    input:  tickers tickers of stocks/ETFs
            alloc   allocation for given stocks/TEFs, default None
            start   start date, default "2010-01-01"
            end     end date, default today
    """
    from invest.get_data import read_ETF, read_portfolio
    from invest.calculation import get_return_vol, get_alpha_beta, minimize_risk
    from invest.useful import convert_time
    from time_series.functions import resample
    from basic.useful import progress_bar
    from basic.plot import plot_correlation, plot_stacked_bar
    start, end = convert_time(start, end)
    if not (alloc is None):
        if len(tickers) != len(alloc):
            raise ValueError(
                "Length of shares and tickers should be the same if shares is given."
            )
        alloc = np.array(alloc) / np.sum(alloc)

    plt.figure(figsize=(15, 3))
    plt.subplot(131)
    plt.title("Calculated by Close Price")
    close = read_portfolio(tickers, 'Close', start, end)
    close = close / close.iloc[0, :]
    weekly = resample(close, style="week", method='close')
    al_clo = minimize_risk(weekly,
                           returns=None,
                           strict=True,
                           riskfree=None,
                           max_alloc=1,
                           scale=52,
                           ret=False,
                           verbose=False,
                           plotit=True)
    if not (alloc is None):
        weekly = weekly.dot(alloc)
        rv = get_return_vol(weekly, scale=52) * 100
        plt.plot(rv.Volatility, rv.Return, 'bo')

    plt.subplot(132)
    plt.title("Calculated by Adjusted Close Price")
    adj = read_portfolio(tickers, 'Adj Close', start, end)
    adj = adj / adj.iloc[0, :]
    weekly = resample(adj, style="week", method='close')
    al_adj = minimize_risk(weekly,
                           returns=None,
                           strict=True,
                           riskfree=None,
                           max_alloc=1,
                           scale=52,
                           ret=False,
                           verbose=False,
                           plotit=True)
    if not (alloc is None):
        weekly = weekly.dot(alloc)
        rv = get_return_vol(weekly, scale=52) * 100
        plt.plot(rv.Volatility, rv.Return, 'bo')

    plt.subplot(133)
    df = pd.DataFrame()

    def func(t):
        data = read_ETF(t)
        if data.index[0] < start:
            data = data[start:end]
            a, b = get_alpha_beta(data.Close, ret_type='simple', dspl=False)
            df.at[t, 'alpha'] = a
            df.at[t, 'beta'] = b

    progress_bar(tickers, func, disable=True)
    plt.plot(df.beta, df.alpha, 'o')
    if not (alloc is None):
        total = close.dot(alloc)
        alpha, beta = get_alpha_beta(total, ret_type='simple', dspl=False)
        plt.plot(beta, alpha, 'bo')
    plt.xlabel('Beta')
    plt.ylabel("Alpha")
    plt.hlines(xmin=-0.1, xmax=1.2, y=0, linestyles='--')
    plt.xlim(-0.1, 1.2)
    for t in df.index:
        plt.text(df.beta[t], df.alpha[t], t)

    plt.figure(figsize=(14, 3))
    plt.title("Allocation calculated from close price")
    plot_stacked_bar(al_clo[al_clo.columns[-3::-1]].T.values,
                     names=al_clo.columns[-3::-1],
                     ticks=np.round(al_clo.Return * 100, 2))
    plt.xlabel("Return in %")

    plt.figure(figsize=(14, 3))
    plt.title("Allocation calculated from adjusted close price")
    plot_stacked_bar(al_adj[al_adj.columns[-3::-1]].T.values,
                     names=al_adj.columns[-3::-1],
                     ticks=np.round(al_adj.Return * 100, 2))
    plt.xlabel("Return in %")

    plt.figure(figsize=(14, 3))
    plt.title("Price change (not adjusted)")
    for c in close.columns:
        plt.plot(close.index, close[c], '-', label=c)
    plt.hlines(xmin=close.index[0], xmax=close.index[-1], y=1, linestyles='--')
    plt.xlim(close.index[0], close.index[-1])
    plt.legend(bbox_to_anchor=(1.01, 0.99), loc='upper left')
    if not (alloc is None):
        plt.plot(close.index, total, 'k-')

    plt.figure(figsize=(6, 5))
    plot_correlation(close)
    plt.show()