Blogs

Some Useful Stock Analysis Functions & Stock Class

This is mostly visualization. 

Here's the imports:

import statsmodels.api as sm
import pandas_datareader.data as pdr
import numpy as np
import matplotlib.pyplot as plt

Get data, btc and eth in this case:

btc = pdr.DataReader('BTC-USD', 'yahoo', start='2018-06-30', end='2022-06-30')
btc = btc[['Close']]

eth = pdr.DataReader('ETH-USD', 'yahoo', start='2018-06-30', end='2022-06-30')
eth = eth[['Close']]

Function 1: Plot price with moving averages:

def plot_price_ma(df, ma1=14, ma2=50):
    fig, ax = plt.subplots(figsize=(10,6))
    plt.title('Price and Moving Averages')

    ax.plot(df.index,df['Close'],label='BTC', color='black', alpha=0.7)

    df.rolling(window=ma1).mean()['Close'].plot(label=str(ma1)+' Day MA',
                                                color='green', linewidth=2, alpha=0.7)

    df.rolling(window=ma2).mean()['Close'].plot(label=str(ma2)+' Day MA',
                                                color='red', linewidth=2, alpha=0.7)

    ax.set_xlabel('Date')
    ax.set_ylabel('Price')
    plt.legend()
    plt.grid()
    plt.show()

Function 2: Plot pct return histogram

def plot_returns_hist(returns):
    fig, ax = plt.subplots(figsize=(10,6))
    plt.title('Histagram of Returns ')
    ax.hist(returns, bins=100)
    ax.set_xlabel('Returns (%)')
    ax.set_ylabel('Frequency')
    plt.grid()
    plt.show()

Function 3:  Print basic performance metrics

def print_basic_perf(returns, days=252):
    ret = round(returns.mean()*days,2)
    std = round(returns.std()*np.sqrt(days),2)
    sharpe = round(ret / std,2)
    print('Annual avg return:', str(ret))
    print('Annual avg std:', str(std))
    print('Sharpe :', str(sharpe))

Annual avg return: 54.16
Annual avg std: 72.34
Sharpe : 0.75

Function 3: Plot rolling standard deviation

def plot_rolling_std(returns,window):
    ma_std = returns.rolling(window=window).std() * np.sqrt(window)
    ma_std.plot()
    plt.title(f'STD rolling {window} day')
    plt.ylabel('Std')
    plt.show()

Function 4: Plot rolling Min Max

def plot_rolling_minmax(Prices, window):
    ma_max = Prices.rolling(window=window).max()
    ma_min = Prices.rolling(window=window).min()
    ma_max.plot(label='max')
    ma_min.plot(label='min')
    plt.title(f'Rolling {window} Min-Max Prices')
    plt.show()

Function 5:  Plot Rolling Correlation

def plot_rolling_corr(Returns1, Returns2, window):
    Returns1.rolling(window=window).corr(Returns2).plot()
    plt.title(f'Rolling {window} Days Correlations')
    plt.ylabel('Corr')
    plt.show()

def plot_ols_returns(Returns1, Returns2, names):
    """
    names X first, y second
    coefs beta first, const second

    """
    X = sm.add_constant(Returns1.dropna())
    model = sm.OLS(Returns2.dropna(),X).fit()

    plt.scatter(Returns1, Returns2, alpha=0.6)
    plt.plot(Returns1,(Returns1*model.params[1])+model.params[0], c='r')
    plt.xlabel(names[0])
    plt.ylabel(names[1])
    plt.title(f'{names[0]} vs. {names[1]} Returns')
    plt.show()

It is meaningful to build a Stock class with these function. Here's the Stock class:

(There may be small differences between the functions below and above, I wrote them at different times without cross-checking)

import pandas_datareader.data as pdr
import numpy as np
import matplotlib.pyplot as plt


class Asset:
    def __init__(self, df, Name):
        self.df = df
        self.pctret = df['Close'].pct_change()
        self.cumret = (self.pctret+1).cumprod()
        self.Name = Name

    def print_basic_perf(self, Days=252):
        avgret = round(self.pctret.mean()*Days,4)
        std = round(self.pctret.std()*np.sqrt(Days),4)
        sharpe = round((avgret / std),4)
        print(f'Daily Mean Return: {avgret}, \n' +
                f'Daily Mean Std: {std} \n'+
                f'Yearly Sharpe: {sharpe}')

    def print_return_hist(self, bins=50, figsize=(8,6)):
        fig, ax = plt.subplots(figsize=figsize)
        ax.set_title(f"{self.Name} Daily % Return Frequency")
        ax.hist(self.pctret*100, bins=bins)
        ax.set_xlabel('Daily Returns')
        ax.set_ylabel('Frequency')
        ax.grid()
        plt.show()

    def print_price_ma(self, ma1=14, ma2=50, figsize=(8,6)):
        fig, ax = plt.subplots(figsize=figsize)
        ax.set_title(f'{self.Name} Daily Price and Moving Averages')
        ax.plot(self.df.index, self.df['Close'],label='Price', color='black', alpha=0.7)
        self.df.rolling(window=ma1).mean()['Close'].plot(label=str(ma1)+'_sma',
                                                         color='green', linewidth=2, alpha=0.7)
        self.df.rolling(window=ma2).mean()['Close'].plot(label=str(ma2)+'_sma',
                                                         color='red', linewidth=2, alpha=0.7)
        ax.set_xlabel('Date')
        ax.set_ylabel('Price')
        ax.legend()
        ax.grid()
        plt.show()

    def print_roll_std(self, window=50, figsize=(8,6)):
        rollstd = self.pctret.rolling(window=window).std() * np.sqrt(window)
        fig, ax = plt.subplots(figsize=figsize)
        ax.plot(rollstd.index, rollstd)
        ax.set_title(f"{self.Name} {window} day rolling std")
        ax.set_xlabel("Date")
        ax.set_ylabel("Std")



aapl_data = pdr.DataReader('AAPL', 'yahoo', start='2018-07-12', end='2022-06-30')
tsla_data = pdr.DataReader('TSLA', 'yahoo', start='2018-07-12', end='2022-06-30')

AAPL = Asset(aapl_data, 'APPLE')
TSLA = Asset(tsla_data, 'TESLA')