├── images ├── .DS_Store └── markowitz_NN.png ├── requirements.txt ├── README.md ├── LICENSE └── quant-basics.ipynb /images/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turing-usp/Quant-basics/HEAD/images/.DS_Store -------------------------------------------------------------------------------- /images/markowitz_NN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turing-usp/Quant-basics/HEAD/images/markowitz_NN.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | attrs==19.3.0 2 | backcall==0.1.0 3 | certifi==2020.4.5.1 4 | chardet==3.0.4 5 | cycler==0.10.0 6 | decorator==4.4.2 7 | idna==2.9 8 | importlib-metadata==1.6.0 9 | ipykernel==5.2.1 10 | ipython==7.14.0 11 | ipython-genutils==0.2.0 12 | jedi==0.17.0 13 | joblib==0.14.1 14 | jsonschema==3.2.0 15 | jupyter-client==6.1.3 16 | jupyter-core==4.6.3 17 | kiwisolver==1.2.0 18 | lxml==4.5.0 19 | matplotlib==3.2.1 20 | nbformat==5.0.6 21 | numpy==1.18.4 22 | pandas==1.0.3 23 | pandas-datareader==0.8.1 24 | parso==0.7.0 25 | patsy==0.5.1 26 | pexpect==4.8.0 27 | pickleshare==0.7.5 28 | plotly==4.7.1 29 | prompt-toolkit==3.0.5 30 | ptyprocess==0.6.0 31 | Pygments==2.6.1 32 | pyparsing==2.4.7 33 | pyrsistent==0.16.0 34 | python-dateutil==2.8.1 35 | pytz==2020.1 36 | pyzmq==19.0.1 37 | requests==2.23.0 38 | retrying==1.3.3 39 | scikit-learn==0.22.2.post1 40 | scipy==1.4.1 41 | six==1.14.0 42 | sklearn==0.0 43 | statsmodels==0.11.1 44 | tornado==6.0.4 45 | traitlets==4.3.3 46 | urllib3==1.25.9 47 | wcwidth==0.1.9 48 | zipp==3.1.0 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Quant basics 2 | 3 | Notebook com estudo guiado de finanças quantitativas, contendo os seguinte tópicos 4 | 5 | - Importação de dataset de preço históricos 6 | - Retornos e Risco (Volatilidade) 7 | - Lidando com portfolios 8 | - Predição de Series Temporais 9 | 10 | ## Instalação 11 | 12 | Crie um ambiente virtual 13 | ``` 14 | $ virtualenv .quantenv 15 | ``` 16 | 17 | Instale os requirements 18 | 19 | ``` 20 | $ pip install -r requirements.txt 21 | ``` 22 | 23 | Adicione o ambiente virtual a sua base de kernels do jupyter notebook 24 | 25 | ``` 26 | $ python -m ipykernel install --user --name=.quantenv 27 | ``` 28 | 29 | Após executar esse comando espera-se um resultado como o seguinte: 30 | 31 | ``` 32 | Installed kernelspec .quantenv in /home/user/.local/share/jupyter/kernels/.quantenv 33 | ``` 34 | 35 | Ative o ambiente virtual 36 | 37 | ``` 38 | $ source .quantenv/bin/activate 39 | ``` 40 | 41 | Inicie o Jupyter Notebook 42 | 43 | ``` 44 | $ jupyter notebook 45 | ``` 46 | 47 | **Obs:** Não esqueça de alterar o kernel para .quan 48 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Grupo Turing 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /quant-basics.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Quant basics\n", 8 | "\n", 9 | "Bem vindo ao projetinho do Turing Quant!\n", 10 | "\n", 11 | "Neste notebook você aprenderá os seguinte assuntos:\n", 12 | "\n", 13 | "- Importação e visualização de dados financeiros\n", 14 | "- Retornos e Risco de um ativo\n", 15 | "- Análise de portfólios\n", 16 | "- Previsão de Series Temporais" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "## 1. Importação de dataset de preço histórico\n", 24 | "\n", 25 | "Para a importação de dados existem diversas bibliotecas em python que fornem preços históricos de ativos\n", 26 | "\n", 27 | "Dentre elas podemos citar as seguinte plataformas:\n", 28 | "\n", 29 | "- Google Finance (Via panda_datareader)\n", 30 | "- Yahoo Finace (Via panda_datareader ou yfinance)\n", 31 | "- Quandl\n", 32 | "- Investing.com (investpy)\n", 33 | "\n", 34 | "Pesquise sobre como importar dados nessas bibliotecas. Os datasets que conseguimos com essas bibliotecas são denominados OHLCV (open-high-low-close-volume).\n", 35 | "\n", 36 | "- 1.1) Plote os preços de fechamento\n", 37 | "- 1.2) Faça uma simples análise qualitativa do ativo escolhido (Ex: porque ele teve grande variação em algum momento)" 38 | ] 39 | }, 40 | { 41 | "cell_type": "code", 42 | "execution_count": null, 43 | "metadata": {}, 44 | "outputs": [], 45 | "source": [ 46 | "# Escreva seu código aqui!" 47 | ] 48 | }, 49 | { 50 | "cell_type": "markdown", 51 | "metadata": {}, 52 | "source": [ 53 | "## Análise qualitativa\n", 54 | "\n", 55 | "Responda aqui no markdown..." 56 | ] 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "metadata": {}, 61 | "source": [ 62 | "# 2. Retorno e Risco\n", 63 | "\n", 64 | "Essencialmente, a natureza do Mercado Financeiro é baseada em um certo nível de retorno (a variação do seu investimento) para um dado nível de risco (o quão provável é esse retorno). Há uma série de maneiras para mensurar o risco, mas geralmente elas estão ligadas à volatilidade do ativo, que, em sua forma mais simples, é o desvio padrão dos preços em um dado período.\n", 65 | "\n", 66 | "Com o mesmo ativo que você importou anteriormente, iremos iniciar os calculos de risco e retorno. Porém inicialmente iremos analisar retorno e risco com o preço de fechamento." 67 | ] 68 | }, 69 | { 70 | "cell_type": "markdown", 71 | "metadata": {}, 72 | "source": [ 73 | "## Retorno\n", 74 | "\n", 75 | "Existem algumas maneiras de se calcular o retorno de uma série temporal, aqui podemos citar duas:\n", 76 | "\n", 77 | "- 2.1) Retorno Percentual: $R_t = \\frac{P_t - P_{t-1}}{P_{t-1}} = \\frac{P_t}{P_{t-1}} - 1$\n", 78 | "- 2.2) Retorno Logaritmo: $r_t = \\ln(\\frac{P_t}{P{t-1}}) = \\ln(P_t) - \\ln(P_{t-1})$\n", 79 | "\n", 80 | "Sendo $P_t$ o preço no tempo t, e $P_{t-1}$ preço no tempo $t-1$ (Dia anterior).\n", 81 | "\n", 82 | "Manipulando o dataframe implemente esse dois tipos de retonos e compare-os. \n", 83 | "\n", 84 | "Calcule os retornos cumulativos ao longo do tempo:\n", 85 | "\n", 86 | "- 2.3) Retorno Cumulativo Percentual: \n", 87 | "\n", 88 | "$R_{cum} = \\prod_{t=0}^{t = \\text{max dias}}{(1 + R_{t})} = (1+R_{t-\\text{max dias}}) * \\dots * (1+R_{t-1}) * (1+R_t)$\n", 89 | "- 2.4) Retorno Cumulativo Logaritmo: \n", 90 | "\n", 91 | "$r_{cum} = \\sum_{t = 0}^{t = \\text{max dias}}{(1 + r_t)} = (1+r_{t-\\text{max dias}}) + \\dots + (1+r_{t-1}) + (1+r_t)$" 92 | ] 93 | }, 94 | { 95 | "cell_type": "code", 96 | "execution_count": null, 97 | "metadata": {}, 98 | "outputs": [], 99 | "source": [ 100 | "# Escreva seu código aqui" 101 | ] 102 | }, 103 | { 104 | "cell_type": "markdown", 105 | "metadata": {}, 106 | "source": [ 107 | "## Risco\n", 108 | "\n", 109 | "Há diversos tipo de definições de risco, em finança quantitativas uma maneira bem fácil de calcular o risco é a partir da variação do ativo. Basicamente, você não quer investir num ativo que varia muito, ou seja, muito imprevisível. Uma maneira estátistica de cálcular essa volatilidade é a partir do desvio padrão.\n", 110 | "\n", 111 | "- 2.5) Calcule o desvio padrão do ativo\n", 112 | "\n", 113 | "Apenas o valor do desvio padrão não apresenta muita informação, então iremos calcular o rolling std. Básicamente iremos calcular o desvio padrão a cada t intervalo de tempo.\n", 114 | "\n", 115 | "- 2.6) Calcule o rolling std\n", 116 | "\n", 117 | "Dica: utilize o método ```pandas.rolling(window).std()``` do pandas, window é o intervalo em que você irá calcular o desvio padrão\n", 118 | "\n", 119 | "- 2.7) Calcule o desvio padrão exponencial móvel (EWMA)\n", 120 | "\n", 121 | "## Desafio\n", 122 | "\n", 123 | "- 2.8) Calcule o desvio padrão estimado pelo High e Low ([Parkinson Number](https://www.ivolatility.com/help/3.html))\n", 124 | "\n", 125 | "\n", 126 | "- 2.9) Calcule o desvio padrão estimado por High, Low, Close e Open ([Garman-Klass](https://portfolioslab.com/garman-klass))\n", 127 | "\n", 128 | "\n", 129 | "\n", 130 | "Temos uma breve explicação desses estimadores de volatilidade em nosso Turing Talks: [Construindo uma Estratégia de Investimentos Quantitativa — Time Series Momentum](https://medium.com/turing-talks/construindo-uma-estrat%C3%A9gia-de-investimentos-quantitativa-time-series-momentum-7e60a40636bd)" 131 | ] 132 | }, 133 | { 134 | "cell_type": "code", 135 | "execution_count": null, 136 | "metadata": {}, 137 | "outputs": [], 138 | "source": [ 139 | "# Escreva seu código aqui" 140 | ] 141 | }, 142 | { 143 | "cell_type": "markdown", 144 | "metadata": {}, 145 | "source": [ 146 | "# 3. Lidando com portfolios\n", 147 | " \n", 148 | "[Notebook de auxilio](https://github.com/quantopian/research_public/blob/master/notebooks/lectures/Introduction_to_NumPy/notebook.ipynb)\n", 149 | "\n", 150 | "Agora que você já aprendeu como importar preços históricos e como calcular o risco e retorno de ativos, podemos usar esse conhecimento para começar a montar o nosso portfolio!\n", 151 | "\n", 152 | "Nessa etapa, você irá montar uma carteira com 4 ações diferentes. \n", 153 | " - Use o que você aprendeu nas etapas anteriores para construir um dataframe com 4 ativos diferentes junto com os seus respectivos **dados históricos de fechamento**.\n", 154 | " \n", 155 | "Em seguida, você precisa distribuir a porcentagem que cada ativo da sua carteira receberá dos seus investimentos. Em finanças, chamamos isso de [pesos de um portfolio](https://www.investopedia.com/terms/p/portfolio-weight.asp)\n", 156 | " - Atribua pesos ($w$) para cada um dos ativos que estão na sua carteira (Ele devem somar 1) . Ex: w = [0.3, 0.3, 0.2, 0.2]\n", 157 | "\n", 158 | "## Retorno\n", 159 | "\n", 160 | "Agora, você pode calcular o **retorno** do seu portfolio. \n", 161 | "\n", 162 | "O retorno para um período é dado pela seguinte fórmula: $R = \\vec{r} \\times \\vec{w}$\n", 163 | "\n", 164 | "Onde $\\vec{r}$ é o vetor de retornos de cada ativo da carteira, e $\\vec{w}$ os seus respectivos pesos.\n", 165 | "\n", 166 | "- 3.1) Calcule o **retorno** para cada dia da série temporal\n", 167 | "\n", 168 | "- 3.2) Faça um gráfico para visualizar os **retornos cumulativos** do seu portfolio e compare com algum benchmark (EX: IBOV). " 169 | ] 170 | }, 171 | { 172 | "cell_type": "code", 173 | "execution_count": null, 174 | "metadata": { 175 | "scrolled": true 176 | }, 177 | "outputs": [], 178 | "source": [ 179 | "# Escreva seu código aqui" 180 | ] 181 | }, 182 | { 183 | "cell_type": "markdown", 184 | "metadata": {}, 185 | "source": [ 186 | "## Risco\n", 187 | "\n", 188 | "Para calcular um **risco** de um portfolio precisamos levar em conta as correlações entre todos os ativos. Para isso calcularemos a matriz de covariaças $C$ (```pandas.cov()``` ou ```np.cov()```).\n", 189 | "\n", 190 | "A equação do risco de uma portfólio é dada pela seguinte fórmula: $\\sigma = \\sqrt{\\vec{w}C\\vec{w}^\\mathsf{T}}$, sendo $T$ a tranposição de um array \n", 191 | "\n", 192 | "- 3.3) Calcule o risco de 3 portfólios (varie o vetor de pesos)." 193 | ] 194 | }, 195 | { 196 | "cell_type": "code", 197 | "execution_count": null, 198 | "metadata": {}, 199 | "outputs": [], 200 | "source": [ 201 | "# Escreva seu código aqui" 202 | ] 203 | }, 204 | { 205 | "cell_type": "markdown", 206 | "metadata": {}, 207 | "source": [ 208 | "## Teoria Moderna de Portifolio - Markowitz \n", 209 | "\n", 210 | "Markowitz também conhecido como efficient frontier, é uma maneira de otimizar uma carteira de investimentos. A maneira mais simples de encontrar a melhor solução é via simulação. Portanto simula-se diversos pesos, e para cada peso é calculado seu retorno esperado e risco. \n", 211 | "\n", 212 | "- 3.4) Otimize a carteira e obtenha o portfolio com o melhor retorno ajustado ao risco (Sharpe Ratio)\n", 213 | "\n", 214 | "" 215 | ] 216 | }, 217 | { 218 | "cell_type": "code", 219 | "execution_count": null, 220 | "metadata": {}, 221 | "outputs": [], 222 | "source": [ 223 | "# Escreva seu código aqui" 224 | ] 225 | }, 226 | { 227 | "cell_type": "markdown", 228 | "metadata": {}, 229 | "source": [ 230 | "## Backtesting\n", 231 | "\n", 232 | "Estratégia de investimento: Rebalanceamento mensal de uma carteira de investimentos.\n", 233 | "\n", 234 | "- 3.5.1) Maneira simplificada: Calcular retornos mensais ao longo do tempo. Obtenha os pesos otimizado para o mês e calcule o rendimento do proxímo mês.\n", 235 | "- 3.5.2) Maneira completa: Realize o rebalanceamento mensal e calcule os retornos diários. Fique atento que ao longo do mês os pesos do ativos variam.\n", 236 | "- 3.6) Faça uma análise quantitativa e qualitativa da performace do backtesting." 237 | ] 238 | }, 239 | { 240 | "cell_type": "code", 241 | "execution_count": 1, 242 | "metadata": {}, 243 | "outputs": [], 244 | "source": [ 245 | "# Escreva seu código aqui" 246 | ] 247 | }, 248 | { 249 | "cell_type": "markdown", 250 | "metadata": {}, 251 | "source": [ 252 | "# 4. Previsão de Time Series\n", 253 | "\n", 254 | "## Cross validation em Séries Temporais\n", 255 | "\n", 256 | "Sempre que lidamos com algoritmos de machine learning, para treiná-los temos que separar os datasets em treino e em teste. Em séries temporais não podemos separar os dados aleatoriamente, pois a ordem no tempo importa! Portanto, seguimos a seguinte separação ao longo do tempo:\n", 257 | "\n", 258 | "\n", 259 | "\n", 260 | "## Feature Engineering em Série Temporal\n", 261 | "\n", 262 | "Para inserir machine learning em séries temporais, precisamos efetuar o processo conhecido como feature engineering, que é básicamente construir as entradas de nosso modelo.\n", 263 | "\n", 264 | "### Lags\n", 265 | "Os dados mais simples que podemos inserir no nosso modelo são os valores passados.\n", 266 | "Se deslocarmos (com a função `.shift(i)`) a série temporal em $i$ vezes, conseguimos estabelecer uma feature onde o valor atual no tempo $t$ é alinhado com um valor no tempo $t-i$. Chamamos isso de _lag_, ou atraso na série temporal. Isso é bastante útil, por exemplo, para estratégias baseadas em um valor histórico de uma feature.\n", 267 | "\n", 268 | "### Demais features\n", 269 | "Além dos pontos passados outras features podem ser inseridas no modelo: Volume de negociações, momentum, volatilidade, dados do mercado (ex: ibov) e etc.\n", 270 | "\n", 271 | "- 4.1) Realize o feature engineering e teste alguns modelos de ML (Ex: Regressão linear, ARIMA, Decision Tree, Random Forest, Redes Neurais, etc...)\n", 272 | "- 4.2) Faça um gráfico comparando os valores reais e preditos pelo modelo, durante um determinado período.\n", 273 | "
\n", 274 | "Exemplo:\n", 275 | "
\n", 276 | "" 277 | ] 278 | }, 279 | { 280 | "cell_type": "code", 281 | "execution_count": null, 282 | "metadata": {}, 283 | "outputs": [], 284 | "source": [ 285 | "# Escreva seu código aqui" 286 | ] 287 | }, 288 | { 289 | "cell_type": "markdown", 290 | "metadata": {}, 291 | "source": [ 292 | "## LSTM\n", 293 | "\n", 294 | "E por fim te desafiamos a implementar uma arquitetura de redes neurais para dados sequências: LSTM. Podem tomar como referência esse notebook, podem copiar o código, o intuito dessa etapa é que vocês tenham um contato com Deep Learning. (https://drive.google.com/file/d/1uagMXYRMJTdMJwoQbQD5LVfrYj4aUuSF/view?usp=sharing)" 295 | ] 296 | }, 297 | { 298 | "cell_type": "code", 299 | "execution_count": null, 300 | "metadata": {}, 301 | "outputs": [], 302 | "source": [ 303 | "# Escreva seu código aqui" 304 | ] 305 | } 306 | ], 307 | "metadata": { 308 | "kernelspec": { 309 | "display_name": "Python 3", 310 | "language": "python", 311 | "name": "python3" 312 | }, 313 | "language_info": { 314 | "codemirror_mode": { 315 | "name": "ipython", 316 | "version": 3 317 | }, 318 | "file_extension": ".py", 319 | "mimetype": "text/x-python", 320 | "name": "python", 321 | "nbconvert_exporter": "python", 322 | "pygments_lexer": "ipython3", 323 | "version": "3.9.5" 324 | } 325 | }, 326 | "nbformat": 4, 327 | "nbformat_minor": 4 328 | } 329 | --------------------------------------------------------------------------------