Created
January 21, 2023 11:18
-
-
Save mlblogger/fb9552b434e9e2217caf961d01f61321 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import pandas as pd | |
import pandas_datareader.data as web | |
import numpy as np | |
class Metrics(): | |
def __init__(self, returns, risk_free_rate=2, period='daily'): | |
self.returns = returns | |
self.period = { | |
'monthly' : 12, | |
'weekly' : 52, | |
'daily' : 252 | |
} | |
self.frequency = self.period[period] | |
self.risk_free_rate = np.power(1+risk_free_rate*0.01,1/self.frequency) - 1 | |
def annualized_sharpe_ratio(self): | |
return round( | |
( (self.returns.mean() - self.risk_free_rate) / (self.returns.std()) )\ | |
* ( np.sqrt(self.frequency) ), 2 | |
) | |
def annualized_volatility(self): | |
return round( | |
self.returns.std()*np.sqrt(self.frequency)*100, 2 | |
) | |
def max_draw_down(self): | |
cum_returns = self.returns.add(1).cumprod() | |
draw_down = cum_returns.div(cum_returns.cummax()).sub(1) | |
max_draw_down = draw_down.min()*100 | |
return round( max_draw_down, 2 ) | |
def cumulative_rets(self): | |
return (self.returns+1).prod() | |
def annualized_returns(self): | |
num_years = len(self.returns) / self.frequency | |
ending_value = self.cumulative_rets() | |
return (ending_value **(1 / num_years) - 1)*100 | |
def calmar_ratio(self): | |
return round(self.annualized_returns()/abs(self.max_draw_down()), 2) | |
def downside_risk(self): | |
df = pd.DataFrame() | |
df['Returns'] = self.returns | |
df['downside_returns'] = 0 | |
df.loc[df['Returns'] < 0, 'downside_returns'] = df['Returns']**2 | |
down_risk = np.sqrt(df['downside_returns'].mean())*np.sqrt(self.frequency) | |
return down_risk | |
def sortino_ratio(self): | |
average_annual_return = np.nanmean(self.returns, axis=0) * self.frequency | |
return round( | |
(average_annual_return - self.risk_free_rate)/self.downside_risk(), 2 | |
) | |
def beta(self,index): | |
return round(self.returns.cov(index)/index.var(), 2) | |
if __name__ == '__main__': | |
stock = 'LMT.US' | |
index = '^DJI' | |
start = '2022-01-01' | |
end = '2023-01-01' | |
lmt = web.DataReader(stock, 'stooq') | |
lmt = lmt.sort_values(by='Date') | |
lmt = lmt['Close'].pct_change() | |
mask = ( start <= lmt.index ) & ( lmt.index <= end ) | |
lmt = lmt[mask] | |
dji = web.DataReader(index, 'stooq') | |
dji = dji.sort_values(by='Date') | |
dji = dji['Close'].pct_change() | |
mask = ( start <= dji.index ) & ( dji.index <= end ) | |
dji = dji[mask] | |
metrics = Metrics(lmt) | |
print('Sharpe Ratio ', metrics.annualized_sharpe_ratio()) | |
print('Calmar Ratio ', metrics.calmar_ratio()) | |
print('Sortino Ratio ', metrics.sortino_ratio()) | |
print('Max Draw Down ', metrics.max_draw_down()) | |
print('Volatility ', metrics.annualized_volatility()) | |
print('Beta ', metrics.beta(dji)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment