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
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
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))
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
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
def generate(tickers, features): """ input: tickers a list of tickers of stocks/ETFs features a list of feature names to be calculated Return a pandas DataFrame """ from invest.get_data import read_ETF from time_series.functions import resample from invest.calculation import get_returns data = pd.DataFrame() for t in tickers: etf = read_ETF(t) weekly = resample(etf, style='week', method='close') ret = get_returns(weekly, style='simple') rv = get_return_vol(ret, scale=52, ret=True, plotit=False)
def set_benchmark(self): ticker = self.benchmark.get().upper() if ticker == "": self._logger_.info("Remove benchmark") self._data_['benchmark'] = 0 else: self._logger_.info("Set benchmark as {}".format(ticker)) try: data = read_ETF(ticker, file_dir=path + "\\data_temp") except: self._logger_.error("Cannot load benchmark {}".format(ticker)) else: self._data_['benchmark'] = get_returns(resample( data.Close, column=None, style="week", method='close'), style='simple', fillna=False) self.update_plot()
def main_frame(self): holdings = pd.read_csv(file_dir + '\\data\\holdings.csv', index_col=None, parse_dates=[0]).dropna() data = {} for t in holdings.Ticker.unique(): data[t] = read_ETF(t) if (data[t].index[-1].date() != date.today()) and (date.today().weekday() < 5): self._logger_.debug("Latest date is {}. Update local data for ticker {}"\ .format(data[t].index[-1].date(), t)) update_ETF_data([t], dt="2000-01-01", file_dir=file_dir + '\\data\\') add_dividend(data[t], price='Close', adj='Adj Close', out='Dividend') def pop_up(): self._logger_.info("Popup window") frame = tk.Tk() self.transactions(frame) frame.mainloop() tk.Button(self, text='Add Transactions', command=pop_up).pack(anchor=tk.E) fig = plot_embed(self) fig.pack() table = tk.Frame(self) table.pack() for i, text in enumerate([ "Ticker", "Buy Date", "Buy Price", "Current Price", "Buy Shares", "Reinvested Shares", "Capital Gain", "Dividend Gain", "Total Gain" ]): tk.Label(table, text=text).grid(row=0, column=i, padx=5, pady=5) total_gain = 0 for loc, i in enumerate(holdings.index): t = holdings.Ticker[i] d = holdings.Date[i] p = holdings.Price[i] s = holdings.Shares[i] r = (date.today() - d.date()).days / 365 print(r) vals = [ t, "{}".format(d.date()), "{:.2f}".format(p), "{:.2f}".format(data[t].iloc[-1, :].Close), "{:.0f}".format(s) ] current_share = data[t].loc[d, 'Close'] / data[t].loc[d, 'Adj Close'] * s vals.append("{:.4f}".format(current_share - s)) vals.append("{:.2f} ({:.2%})".format( (data[t].iloc[-1, :].Close - p) * s, (data[t].iloc[-1, :].Close / p - 1) / r)) vals.append("{:.2f} ({:.2%})".format( data[t].loc[d:, 'Dividend'].sum() * s, data[t].loc[d:, 'Dividend'].sum() / p / r)) gain = data[t].iloc[-1, :].Close * current_share - p * s total_gain += gain vals.append("{:.2f} ({:.2%})".format(gain, gain / p / s / r)) for j, text in enumerate(vals): tk.Label(table, text=text).grid(row=loc + 1, column=j, padx=5, pady=5) tk.Label(table, text="Total gain is: {:.2f}".format(total_gain))\ .grid(row=holdings.shape[0]+1, column=0, columnspan=3)
def show_performance(ticker, current=None): """ Calculate total return and effective annual return for different starting point. Simple return is calculated input: ticker ticker of the stock/ETF current the date to be calculated Return a DataFrame with two rows: Total Return, Annual Return """ from datetime import date, timedelta from invest.get_data import read_ETF from time_series.functions import change_month data = read_ETF(ticker)[['Close', 'Adj Close']] if current is None: current = data.index[-1] else: current = data[:current].index[-1] mns = np.array([1, 3, 6, 12, 24, 36, 48, 60, 72, 84, 96, 108, 120]) dates = [change_month(current, -x) for x in mns] df = pd.DataFrame(columns=['Close', 'Adj Close']) dates = np.array(dates) dates = dates[np.where(dates >= data.index[0].date())] for d in dates: vals = data[:d] if vals.empty: break df.loc[vals.index[-1].date(), :] = 100 * ( data.loc[current, :] / vals.iloc[-1, :] - 1) df['label'] = [ '1M', '3M', '6M', '1Y', '2Y', '3Y', '4Y', '5Y', '6Y', '7Y', '8Y', '9Y', '10Y' ][:df.shape[0]] df['years'] = mns[:df.shape[0]] / 12 result = pd.DataFrame(index=df.index) result['Total Return'] = df.Close result['Annual Return'] = df.Close / df.years result['Adjusted Total Return'] = df['Adj Close'] result['Adjusted Annual Return'] = df['Adj Close'] / df.years plt.figure(figsize=(14, 8)) plt.subplot(2, 1, 1) plt.title("Performance for close price (not adjusted)") plt.bar(df.index.map(lambda x: x - timedelta(days=12)), df.Close, width=24, label='Total Return') plt.bar(df.index.map(lambda x: x + timedelta(days=12)), df.Close / df.years, width=24, label='Annual Return') plt.hlines(xmin=df.index[-1] - timedelta(days=24), xmax=current, y=0) plt.xticks(df.index, df.label) plt.xlim(df.index[-1] - timedelta(days=24), current) plt.ylim(max(-10, np.min(result.values) - 1), min(20, np.max(result.values) + 1)) plt.legend(loc='best') plt.grid() plt.subplot(2, 1, 2) plt.title("Performance for close price (adjusted)") plt.bar(df.index.map(lambda x: x - timedelta(days=12)), df['Adj Close'], width=24, label='Total Return') plt.bar(df.index.map(lambda x: x + timedelta(days=12)), df['Adj Close'] / df.years, width=24, label='Annual Return') plt.hlines(xmin=df.index[-1] - timedelta(days=24), xmax=current, y=0) plt.xticks(df.index, df.label) plt.xlim(df.index[-1] - timedelta(days=24), current) plt.ylim(max(-10, np.min(result.values) - 1), min(20, np.max(result.values) + 1)) plt.legend(loc='best') plt.grid() print(np.round(result[::-1].astype(float), 2)) plt.show() return np.round(result[::-1].astype(float), 2).T