Следующие показатели можно использовать для измерения эффективности вашего портфеля или торговой прибыли.
1. Коэффициент Шарпа
Коэффициент Шарпа (также известный как индекс Шарпа, мера Шарпа и отношение вознаграждения к изменчивости) измеряет эффективность инвестиций, таких как ценные бумаги или портфели, по сравнению с безрисковым активом после поправки на его риск. Он был назван в честь Уильяма Ф. Шарпа, который разработал его в 1966 году.
def annualized_sharpe_ratio(self): return round( ( (self.returns.mean() - self.risk_free_rate) / (self.returns.std()) )\ * ( np.sqrt(self.frequency) ), 2 )
2. Коэффициент Кальмара
Коэффициент Calmar (или коэффициент просадки) — это показатель эффективности, используемый для оценки советников по торговле товарами и хедж-фондов. Он был создан Терри У. Янгом и впервые опубликован в 1991 году в отраслевом журнале Futures.
def calmar_ratio(self): return round(self.annualized_returns()/abs(self.max_draw_down()), 2)
3. Коэффициент Сортино
Коэффициент Сортино измеряет доходность инвестиционного актива, портфеля или стратегии с поправкой на риск. Это модификация коэффициента Шарпа, но наказывается только та доходность, которая падает ниже указанной пользователем цели или требуемой нормы прибыли, в то время как коэффициент Шарпа в равной степени наказывает как восходящую, так и нисходящую волатильность.
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 )
4. Максимальная просадка
Максимальная просадка (MDD) — это максимальная наблюдаемая потеря от пика до минимума портфеля до достижения нового пика. Максимальная просадка — это показатель риска снижения за определенный период времени.
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 )
5. Волатильность
Волатильность часто относится к степени неопределенности или риска, связанного с размером изменений стоимости ценной бумаги. Более высокая волатильность означает, что стоимость ценной бумаги потенциально может быть распределена по более широкому диапазону значений.
def annualized_volatility(self): return round( self.returns.std()*np.sqrt(self.frequency)*100, 2 )
6. Бета
Коэффициент бета может измерять волатильность отдельной акции по сравнению с систематическим риском всего рынка.
def beta(self,index): return round(self.returns.cov(index)/index.var(), 2)
Примеры показателей для Lockheed Martin ( LMT ) между 01.01.2022 и 01.01.2023
Весь код для запуска метрик приведен ниже, и его можно запустить для любой акции, указав тикер.
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))
Код также можно найти здесь.
Вывод выглядит следующим образом
Sharpe Ratio 1.35 Calmar Ratio 2.4 Sortino Ratio 2.21 Max Draw Down -16.94 Volatility 26.43 Beta 0.41