Skip to content

Commit

Permalink
Merge pull request #24 from GrupoTuring/feature/intraday_volatilities
Browse files Browse the repository at this point in the history
Adiciona estimadores de volatilidade (garman klass e parkinson)
  • Loading branch information
lucas-leme committed Oct 20, 2020
2 parents 4a51eee + d4d9e6e commit f75755b
Showing 1 changed file with 148 additions and 10 deletions.
158 changes: 148 additions & 10 deletions turingquant/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,18 +72,20 @@ def drawdown(return_series, plot=True):

wealth_index = 1000 * (1 + return_series).cumprod()
previous_peaks = wealth_index.cummax()
drawdowns = pd.Series((wealth_index - previous_peaks)/previous_peaks, name='Drawdown')
drawdowns = pd.Series((wealth_index - previous_peaks) /
previous_peaks, name='Drawdown')

if plot:
fig = px.line(drawdowns, x=drawdowns.index, y='Drawdown', title='Drawdown')
fig = px.line(drawdowns, x=drawdowns.index,
y='Drawdown', title='Drawdown')
fig.update_xaxes(title_text='Tempo')
fig.update_yaxes(title_text='Drawdown (%)')
fig.show()

return drawdowns


def rolling_beta(returns, benchmark, window, plot=True):
def rolling_beta(returns, benchmark, window=60, plot=True):
"""
Plota o beta móvel para um ativo e um benchmark de referência, na forma de séries de retornos.
Expand All @@ -99,7 +101,7 @@ def rolling_beta(returns, benchmark, window, plot=True):
"""
rolling_beta = pd.Series([beta(returns[i-window:i], benchmark[i-window:i])
for i in range(window, len(returns))], index=returns[window:].index)
for i in range(window, len(returns))], index=returns[window:].index)
if plot:
fig = px.line(rolling_beta, title="Beta móvel")
overall_beta = beta(returns, benchmark)
Expand Down Expand Up @@ -170,12 +172,13 @@ def rolling_sharpe(returns, window, risk_free=0, plot=True):
])
fig.update_layout(showlegend=False)
fig.update_xaxes(title_text='Tempo')
fig.update_yaxes(title_text='Sharpe móvel: ' + str(window) + ' períodos')
fig.update_yaxes(title_text='Sharpe móvel: ' +
str(window) + ' períodos')
fig.show()
return rolling_sharpe


def ewma_volatility(close_prices,return_type,window,plot=True):
def ewma_volatility(close_prices, return_type, window, plot=True):
"""
Essa função possibilita a visualização da volatilidade a partir do cálculo da EWMA e da plotagem do gráfico
dessa métrica ao longo de um período.
Expand All @@ -198,15 +201,149 @@ def ewma_volatility(close_prices,return_type,window,plot=True):
ewma_volatility = returns.ewm(span=window).std()
ewma_volatility = pd.Series.to_frame(ewma_volatility)
if plot:
fig = px.line(ewma_volatility,x=ewma_volatility.index,y='Close',title='EWMA')
fig = px.line(ewma_volatility, x=ewma_volatility.index,
y='Close', title='EWMA')
fig.update_xaxes(title_text='Tempo')
fig.update_yaxes(title_text='EWMA')
fig.show()
fig.show()
return ewma_volatility
if plot == False:
return ewma_volatility

def rolling_std(close_prices,return_type,window,plot=True):

def garman_klass_volatility(high_prices, low_prices, close_prices, open_prices, window=60, time_scale=1, plot=True):
"""
Estima a volatilidade a partir dos seguintes preços: alta, baixa, abertura e fechamento
Parâmetros:
high_prices (pd.DataFrame): série de preços de alta de uma ação
low_prices (pd.DataFrame): série de preços de baixa de uma ação
close_prices (pd.DataFrame): série de preços de fechamento de uma ação
open_prices (pd.DataFrame): série de preços de abertura de uma ação
window (int): janela das estimativa de volatilidade
time_scale (int): fator de escala da volatilidade, por padrão é 1 (diária)
plot (bool): se 'True', plota um gráfico da volatilidade móvel
Retorna:
garman_klass_vol (pd.Series): série das estimativas de volatildade
"""
# Calculando parcelas internas da somatoria
high_low_ratio = (1 / 2) * \
(np.log(np.divide(high_prices, low_prices))) ** 2

close_open_ratio = -(2 * np.log(2) - 1) * (
np.log(np.divide(close_prices, open_prices)) ** 2
)

# Somando parcelas calculadas
log_ratio = high_low_ratio + close_open_ratio.values

# Criando dataframe para atribuir as volatilidades
garman_klass_vol = pd.Series(log_ratio, name='Garman Klass', copy=True)

# Termo constante fora da somatoria (Considerando vol diaria)
Period_const = time_scale / window

# Atribuindo not a number, para os valores iniciais
garman_klass_vol.iloc[:window] = np.nan

# iteração do centro de massa da vol
for date in range(window, len(high_prices)):
garman_klass_vol.iloc[date] = np.sqrt(
Period_const * np.sum(log_ratio.iloc[date - window: date])
)

if plot:
fig = px.line(garman_klass_vol, title='Garman Klass')
fig.update_xaxes(title_text='Tempo')
fig.update_yaxes(title_text='Volatilidade')

mean_garman_klass = garman_klass_vol.mean()
fig.update_layout(shapes=[
dict(
type='line',
xref='paper', x0=0, x1=1,
yref='y', y0=mean_garman_klass, y1=mean_garman_klass,
line=dict(
color='grey',
width=2,
dash='dash'
)
)
], annotations=[
dict(
text='Volatilidade média: %.3f' % mean_garman_klass,
xref='paper', x=0.95,
yref='y', y=1.1 * mean_garman_klass,
xanchor='left'
)
])

fig.show()

return garman_klass_vol


def parkinson_volatility(high_prices, low_prices, window=60, time_scale=1, plot=True):
"""
Estimando a volatilidade a partir dos preços de Alta e de Baixa
Parâmetros:
high (pd.DataFrame): série de preços de alta de uma ação
low (pd.DataFrame): série de preços de baixa de uma ação
window (int): janela das estimativa de volatilidade
time_scale (int): fator de escala da volatilidade, por padrão é 1 (diária)
plot (bool): se 'True', plota um gráfico da volatilidade móvel
Retorna:
garman_klass_vol (pd.Series): série das estimativas de volatildade
"""

log_ratio = np.log(np.divide(high_prices, low_prices)) ** 2

parkinson_vol = pd.Series(log_ratio, name='Parkinson', copy=True)

Period_const = time_scale / (4 * window * np.log(2))

parkinson_vol.iloc[:window] = np.nan

for date in range(window, len(high_prices)):
parkinson_vol.iloc[date] = np.sqrt(
Period_const * np.sum(log_ratio.iloc[date - window: date])
)

if plot:
fig = px.line(parkinson_vol, title='Número de Parkinson')
fig.update_xaxes(title_text='Tempo')
fig.update_yaxes(title_text='Volatilidade')

mean_parkinson = parkinson_vol.mean()
fig.update_layout(shapes=[
dict(
type='line',
xref='paper', x0=0, x1=1,
yref='y', y0=mean_parkinson, y1=mean_parkinson,
line=dict(
color='grey',
width=2,
dash='dash'
)
)
], annotations=[
dict(
text='Volatilidade média: %.3f' % mean_parkinson,
xref='paper', x=0.95,
yref='y', y=1.1 * mean_parkinson,
xanchor='left'
)
])
fig.show()

return parkinson_vol


def rolling_std(close_prices, return_type, window, plot=True):
"""
Essa função possibilita a visualização da volatilidade a partir do cálculo da desvio padrão móvel e da plotagem do gráfico dessa
métrica ao longo de um período.
Expand All @@ -229,7 +366,8 @@ def rolling_std(close_prices,return_type,window,plot=True):
rolling_std = returns.rolling(window).std()
rolling_std = pd.Series.to_frame(rolling_std)
if plot:
fig = px.line(rolling_std, x=rolling_std.index, y='Close',title='Desvio Padrão Móvel')
fig = px.line(rolling_std, x=rolling_std.index,
y='Close', title='Desvio Padrão Móvel')
fig.update_xaxes(title_text='Tempo')
fig.update_yaxes(title_text='Desvio padrão móvel')
fig.show()
Expand Down

0 comments on commit f75755b

Please sign in to comment.