Skip to content

Commit 122d509

Browse files
authored
Refactor/rolling beta (#19)
* simplifica a implementação do beta móvel * atualiza versão para 0.1.3
1 parent 5b591e6 commit 122d509

File tree

2 files changed

+52
-14
lines changed

2 files changed

+52
-14
lines changed

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
setup(
77
name="turingquant",
8-
version="0.1.2",
8+
version="0.1.3",
99
packages=find_packages(),
1010
install_requires=["pandas", "pandas_datareader", "numpy", "matplotlib", "alpha_vantage", "bs4", "plotly"],
1111

turingquant/metrics.py

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -63,19 +63,11 @@ def rolling_beta(returns, benchmark, window, plot=True):
6363
A série não possui os `window` primeiros dias.
6464
6565
"""
66-
returns = pd.DataFrame(returns)
67-
benchmark = pd.DataFrame(benchmark)
68-
merged = returns.merge(benchmark, left_index=True, right_index=True)
69-
# one-liner meio ilegível mas: pega um array de NaN de numpy e junta com uma lista
70-
# que itera entre (window, len) e calcula o beta pros últimos `window` dias
71-
merged['rolling_beta'] = np.append(np.full(window, np.nan),
72-
[beta(merged.iloc[i - window:i, 0], merged.iloc[i - window:i, 1])
73-
for i in range(window, len(merged))]
74-
)
75-
merged = merged[window:]
66+
rolling_beta = pd.Series([beta(returns[i-window:i], benchmark[i-window:i])
67+
for i in range(window, len(returns))], index=returns[window:].index)
7668
if plot:
77-
fig = px.line(merged['rolling_beta'], title="Beta móvel")
78-
overall_beta = beta(merged.iloc[:, 0], merged.iloc[:, 1])
69+
fig = px.line(rolling_beta, title="Beta móvel")
70+
overall_beta = beta(returns, benchmark)
7971
fig.update_layout(shapes=[
8072
dict(
8173
type='line',
@@ -99,7 +91,53 @@ def rolling_beta(returns, benchmark, window, plot=True):
9991
fig.update_xaxes(title_text='Tempo')
10092
fig.update_yaxes(title_text='Beta móvel: ' + str(window) + ' períodos')
10193
fig.show()
102-
return merged['rolling_beta']
94+
return rolling_beta
95+
96+
97+
def rolling_sharpe(returns, window, risk_free=0, plot=True):
98+
"""
99+
Plota o beta móvel para um ativo e um benchmark de referência, na forma de séries de retornos.
100+
101+
Parâmetros:
102+
returns (array): série de retornos para o qual o Sharpe Ratio será calculado.
103+
window (int): janela móvel para calcular o Sharpe ao longo do tempo.
104+
risk_free (float): valor da taxa livre de risco para cálculo do Sharpe.
105+
plot (bool): se `True`, plota um gráfico de linha com o Sharpe ao longo do tempo.
106+
107+
Retorna:
108+
rolling_beta (pd.Series): uma série com os valores do Beta para os últimos `window` dias.
109+
A série não possui os `window` primeiros dias.
110+
111+
"""
112+
rolling_sharpe = pd.Series([sharpe_ratio(returns[i - window:i], risk_free)
113+
for i in range(window, len(returns))], returns[window:].index)
114+
if plot:
115+
fig = px.line(rolling_sharpe, title="Sharpe móvel")
116+
overall_sharpe = sharpe_ratio(returns, risk_free)
117+
fig.update_layout(shapes=[
118+
dict(
119+
type='line',
120+
xref='paper', x0=0, x1=1,
121+
yref='y', y0=overall_sharpe, y1=overall_sharpe,
122+
line=dict(
123+
color='grey',
124+
width=2,
125+
dash='dash'
126+
)
127+
)
128+
], annotations=[
129+
dict(
130+
text='sharpe total: %.3f' % overall_sharpe,
131+
xref='paper', x=0.05,
132+
yref='y', y=overall_sharpe,
133+
xanchor='left'
134+
)
135+
])
136+
fig.update_layout(showlegend=False)
137+
fig.update_xaxes(title_text='Tempo')
138+
fig.update_yaxes(title_text='Sharpe móvel: ' + str(window) + ' períodos')
139+
fig.show()
140+
return rolling_sharpe
103141

104142

105143
def rolling_sharpe(returns, window, risk_free=0, plot=True):

0 commit comments

Comments
 (0)