Capítulo 0 - Introdução a Python#
1 - Abrir conta no Deepnote#
Abrir conta em Deepnote e depois de fazer o log in, clicar em:
# !pip install -r requirements.txt
2 - Iniciação a Python#
Penso que o primeiro passo para nos habituarmos será usar python como uma calculadora.
Podemos fazer as contas que quiserermos.
Calculadora#
2+2
4
3*3
9
3**3
27
Comentários#
Se colocarmos um # antes do código ele não corre
# 2+2
Como podemos ver o # fez com o cálculo não tivesse sido feito
Assignação de uma valor a uma variável#
a = 3
a
3
a = 3
b = 5
a + b
8
a = 3
b = 5
a = 5
a + b
10
Isto pode parecer trivial mas em notebooks maiores, com muitas variáveis, se estas não tiverem bons nomes acaba por ser uma mistura de variáveis e uma confusão (falo por experiência própria). A correcta nomenclatura de variáveis é essencial em boa programação. Diferentes nomes mas também explicitos. Mesmo que trabalhem sozinhos daqui a 6/9 meses quando voltarem a pegar no notebook será importante será importante perceberem o que fizeram e/ou estão a calcular).
Equality operators#
Em python (como noutras linguagens de programação) podem ver se duas variáveis são iguais. Mas como ver se duas variáveis são iguais se = é o simbolo de assignação?
== (ver se duas variáveis são iguais)
!= (ver se duas variáveis são diferentes)
< (ver se variável esquerda é mais pequena)
<= (ver se variável esquerda é mais pequena ou igual)
> (ver se variável à esquerda é maior)
>= (ver se variável à esquerda é maior ou igual)
A resposta do programa será TRUE ou FALSE (conhecidos por booleans)
a = 3
b = 3
a == b
True
a > b
False
a >= b
True
Não tem de ser necessariamente só variáveis. Podem comparar números directamente:
3 > 4
False
Funções#
Como vimos nas aulas as funções em python são de grande importância e que vamos usar bastante. Como criar uma função?
Temos de usar o termo “def”, para que python saiba que pretendemos criar uma função, podemos usar variáveis que depois são passadas para a função e por último um return para que o computador saiba o output que pretendemos que seja devolvido. Vamos criar uma função simples chamada soma que faz a soma de dois números.
def soma():
return 2+2
soma()
4
Neste caso ao corrermos a função soma() o computador devolve-nos 4, que é a soma de 2+2. Mas e se quisermos fazer a soma de quaisquer dois números em vez de apenas 2+2? Nesse caso, que é a maioria das vezes uma vez que uma função deverá ser genérica, temos de passar duas variáveis na função. Exemplo:
def soma(a, b):
return a + b
soma(2, 5)
7
Atenção que se dizemos que a função tem variáveis e não as fornecermos dá erro:
def soma(a, b):
return a + b
soma()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[15], line 4
1 def soma(a, b):
2 return a + b
----> 4 soma()
TypeError: soma() missing 2 required positional arguments: 'a' and 'b'
É importante também darmos as variáveis por ordem ou dizermos explicitamente o valor das variáveis. Vamos testar isso com uma função chamada divisão e ver o que acontece quando damos as variáveis em ordem errada ou as damos explicitamente. Nos desejamos uma divisão de 10 por 2, com resultado de 5.
def divisão(a, b):
return a / b
divisão(10, 2)
5.0
divisão(2, 10)
0.2
Aqui o que aconteceu foi que dividimos 2 por 10 mas:
divisão(b=2, a=10)
5.0
Este tipo de informação explicita é bom quando temos muitas variáveis na função e se torna complicado saber a ordem em que se encontram na função.
Tipos de dados#
Float#
São números que podem tomar qualquer valor, como 3.3 ou 5.545236
Integers#
São os números inteiros como 0,1,2,3,50, -10 etc etc
Strings#
Texto. Tem de ser entre aspas
"Hello World"
'Hello World'
Uma das características do texto é que se pode juntar e eventualmente escrever texto “dinâmico”
a = 3
b = 5
"a mais b é " + str(a+b)
'a mais b é 8'
Neste caso str(a+b) está a transformar o 8, que é o resultado de a + b em texto “8” que pode ser somado ao texto “a mais b”
Booleans#
Verdadeiro ou Falso
# É 2 maior que 4?
2 > 4
False
If else clause#
Uma if clause é uma cláusula se. Do estilo. Se algo acontecer então faz isto, senão acontecer faz aquilo. É um tipo de ordem muito comum em programação e útil em termos lógicos.
Vamos testar construindo em cima do que já aprendemos até aqui:
if 2 == 2:
print("É o mesmo número")
É o mesmo número
Aqui estamos simplesmente a dizer ao computador para escrever “É o mesmo número” caso a igualdade seja verdade. Naturalmente se colocarmos 3 == 2, como é falso ele não vai escrever nada, pois oignora o que é para fazer caso os números fossem o mesmo. Vamos evoluir a if clause para que o computador escreva “Os números são diferentes”, caso eles não sejam iguais.
if 2 == 3:
print("É o mesmo número")
else:
print("São números diferentes")
São números diferentes
Aqui o que dissemos ao computador para dizer é “Se a igualdade for verdadeira escreve “É o mesmo número”, senão escreve “São números diferentes”.
Vamos criar uma função com esta funcionalidade, com o nome “igualdade” para vermos se duas variáveis são iguais ou não.
def igualdade(a, b):
if a == b:
return "É o mesmo número"
else:
return "São números diferentes"
igualdade(5, 4)
'São números diferentes'
igualdade(4, 4)
'É o mesmo número'
Reparem que os print passaram a return. Porquê? A verdade é que se eu tivesse mantido os print iria funcionar de forma aparentemente igual. A diferença é que o “print” apenas diz ao computador para escrever algo, ou seja não dá para assignar a uma variável. Um return vai fazer com que possamos assignar o resultado a uma variável, que é normalmente desejado numa função.
Listas#
numeros = igualdade(4, 4)
numeros
'É o mesmo número'
Listas são variáveis onde conseguimos colocar mais que um valor. Nas aulas usamos listas onde temos vários cash-flows. Uma lista tem parentises rectos e os valores são separados por vírgulas.
cfs = [1000, 2000, 3000, 4000, 5000]
cfs
[1000, 2000, 3000, 4000, 5000]
Se quisermos somar valores temos de as transformar em numpy arrays
import numpy as np
np.array(cfs) + np.array(cfs)
array([ 2000, 4000, 6000, 8000, 10000])
Neste caso importamos numpy (a biblioteca de python usada para matemática) e ao transformar as listas em numpy arrays se somarmos já conseguimos que os valores individuais sejam somados.
Podemos seleccionar qualquer valor na lista pelo seu índice (posição na lista)
# Seleccionar o primeiro valor da lista
cfs[0]
1000
# Seleccionar o último valor da lista
cfs[-1]
5000
For loops#
Em algumas funções usamos for loops. Com For loops estamos a dizer ao computador para fazer o algo um número determinado de vezes.
Vamos experimentar, com a lista acima de cash flows.
for value in cfs:
print(value * 5)
5000
10000
15000
20000
25000
Aqui o que estamos a dizer é por cada valor na lista cfs imprime o valor vezes 5. O que python está a fazer é pegar no 1000, 2000, …, 5000 e por cada valor está a imprimir a multiplicação desse valor por 5.
Um for loop faz isso mesmo. Dizemos o número de vezes que queremos que python faça algo e depois temos de dizer o que é esse algo que queremos que o computador faça.
Ler ficheiros excel e criar uma dataframe#
import pandas as pd
url = "https://s3.us-east-2.amazonaws.com/cbs.pg.repository/data/example_4.xlsx"
df = pd.read_excel(url)[['Mercado', 'Retorno (%)']].dropna()
df
Mercado | Retorno (%) | |
---|---|---|
0 | País A | 7.7 |
1 | País B | 8.5 |
2 | País C | 9.1 |
3 | País D | 5.5 |
4 | País E | 7.1 |
5 | País F | 9.9 |
6 | País G | 6.2 |
7 | País H | 6.8 |
8 | País I | 7.5 |
9 | País J | 8.9 |
10 | País K | 7.4 |
11 | País L | 8.6 |
12 | País M | 9.6 |
13 | País N | 7.7 |
14 | País O | 6.8 |
15 | País P | 6.1 |
16 | País R | 8.8 |
17 | País Q | 7.9 |
Tirando directamente do exercício 2.4.
Seleccionar uma coluna da dataframe#
df[['Mercado']]
Mercado | |
---|---|
0 | País A |
1 | País B |
2 | País C |
3 | País D |
4 | País E |
5 | País F |
6 | País G |
7 | País H |
8 | País I |
9 | País J |
10 | País K |
11 | País L |
12 | País M |
13 | País N |
14 | País O |
15 | País P |
16 | País R |
17 | País Q |
Haver dois parênteses rectos é importante e podem aumentar com os nomes das colunas que quiserem seleccionar
df[['Mercado', 'Retorno (%)']]
Mercado | Retorno (%) | |
---|---|---|
0 | País A | 7.7 |
1 | País B | 8.5 |
2 | País C | 9.1 |
3 | País D | 5.5 |
4 | País E | 7.1 |
5 | País F | 9.9 |
6 | País G | 6.2 |
7 | País H | 6.8 |
8 | País I | 7.5 |
9 | País J | 8.9 |
10 | País K | 7.4 |
11 | País L | 8.6 |
12 | País M | 9.6 |
13 | País N | 7.7 |
14 | País O | 6.8 |
15 | País P | 6.1 |
16 | País R | 8.8 |
17 | País Q | 7.9 |
Instalar bibliotecas#
Ocasionalmente é necessário instalar certas bibliotecas que não estão no sistema.
Um exemplo é o numpy_financial no exercício 1.20.
Ao tentarmos fazer o exercício dá um erro ModuleNotFoundError: No module named ‘numpy_financial’
O código que temos de executar para install a biblioteca é:
!pip install numpy-financial
Outra biblioteca que será necessária instalar para fazer download de cotações da yahoo finance é o yfinance:
!pip install yfinance
Download das cotações do Yahoo Finance#
#!pip install yfinance
import yfinance as yf
def merge_time_series(df_1, df_2, how='outer'):
df = df_1.merge(df_2, how=how, left_index=True, right_index=True)
return df
def normalize(df):
df = df.dropna()
return (df / df.iloc[0]) * 100
def download_yahoo_data(tickers, normalize_quotes=True,
start='1970-01-01', end='2030-12-31'):
quotes=pd.DataFrame()
for ticker in tickers:
df = yf.download(ticker, start=start, end=end, progress=False)
df = df[['Adj Close']]
df.columns=[ticker]
quotes = merge_time_series(quotes, df)
quotes = quotes.ffill()
if normalize_quotes:
quotes = normalize(quotes)
return quotes
quotes = download_yahoo_data(tickers=['SPY', 'DIA'], start='1999-12-31', end='2021-12-31')
quotes
SPY | DIA | |
---|---|---|
Date | ||
1999-12-31 | 100.000000 | 100.000000 |
2000-01-03 | 99.021284 | 98.535103 |
2000-01-04 | 95.148921 | 95.293043 |
2000-01-05 | 95.319128 | 96.527464 |
2000-01-06 | 93.787217 | 97.015782 |
... | ... | ... |
2021-12-23 | 481.125435 | 507.513185 |
2021-12-27 | 487.934336 | 512.540751 |
2021-12-28 | 487.535598 | 514.051979 |
2021-12-29 | 488.159276 | 515.252418 |
2021-12-30 | 486.809765 | 514.165043 |
5536 rows × 2 columns
Como transformar cotações diárias em mensais ou anuais#
# Mensais
# Uma vez que o que queremos é o último dia do mês vamos fazer resample com last()
quotes = quotes.resample('M').last()
quotes
/tmp/ipykernel_155916/2832114247.py:3: FutureWarning: 'M' is deprecated and will be removed in a future version, please use 'ME' instead.
quotes = quotes.resample('M').last()
SPY | DIA | |
---|---|---|
Date | ||
1999-12-31 | 100.000000 | 100.000000 |
2000-01-31 | 95.021285 | 95.125122 |
2000-02-29 | 93.574445 | 88.338419 |
2000-03-31 | 102.643177 | 95.329122 |
2000-04-30 | 99.038310 | 93.735335 |
... | ... | ... |
2021-08-31 | 458.574197 | 496.717439 |
2021-09-30 | 437.202147 | 475.787006 |
2021-10-31 | 467.877779 | 504.000404 |
2021-11-30 | 464.118454 | 486.194551 |
2021-12-31 | 486.809765 | 514.165043 |
265 rows × 2 columns
# Anuais
# Uma vez que o que queremos é o último dia do ano vamos fazer resample com last()
quotes = quotes.resample('A').last()
quotes
/tmp/ipykernel_155916/4151832949.py:3: FutureWarning: 'A' is deprecated and will be removed in a future version, please use 'YE' instead.
quotes = quotes.resample('A').last()
SPY | DIA | |
---|---|---|
Date | ||
1999-12-31 | 100.000000 | 100.000000 |
2000-12-31 | 90.258494 | 93.952767 |
2001-12-31 | 79.645421 | 89.280914 |
2002-12-31 | 62.454236 | 76.160818 |
2003-12-31 | 80.054792 | 97.411996 |
2004-12-31 | 88.619042 | 102.304649 |
2005-12-31 | 92.897796 | 103.950323 |
2006-12-31 | 107.617701 | 123.611817 |
2007-12-31 | 113.155932 | 134.484531 |
2008-12-31 | 71.520240 | 91.266971 |
2009-12-31 | 90.367040 | 112.023517 |
2010-12-31 | 103.972869 | 127.719723 |
2011-12-31 | 105.943134 | 138.012756 |
2012-12-31 | 122.883808 | 151.727127 |
2013-12-31 | 162.584837 | 196.701060 |
2014-12-31 | 184.474902 | 215.825683 |
2015-12-31 | 186.751840 | 216.019920 |
2016-12-31 | 209.158134 | 251.387080 |
2017-12-31 | 254.556741 | 321.987274 |
2018-12-31 | 242.926101 | 309.936494 |
2019-12-31 | 318.777024 | 387.503187 |
2020-12-31 | 377.213976 | 424.665786 |
2021-12-31 | 486.809765 | 514.165043 |
O .last() que usamos no resample é muitas vezes também .sum() para somar os valores no intervalo ou o .mean() para fazer a média aritmética dos valores no intervalo.
Usamos “M” para mensal e “A” para anual e neste caso vai buscar o último dia do mês ou do ano mas podemos também usar o “BM” (Business month) ou o “BA” (business annum) que vai buscar o último dia útil.
Podem ver aqui uma tabela com a frequências aceites:
A verdade é que não se limitam apenas a estes. É possível fazer combinações e fazer por exemplo um semanal às quartas.
Onde aprender mais python?#
Recomendo muito os cursos do Portilla na udemy mas podem começar por Python for Data Science and Machine Learning Bootcamp.
Ele tem muitos outros cursos de python seja aplicado a finanças, estatística ou à criação de sites. Podem ver aqui: https://www.udemy.com/user/joseportilla/
O curso de python para finanças do 365 Careers também é bastante bom e um bom sítio para começarem se assim preferirem: Python for Finance: Investment Fundamentals & Data Analytics
Os cursos da udemy encontram-se muitas vezes com descontos altos a valores entre os 12 e os 18 euros, o que torna um curso de 10 ou 20 euros bastante acessível.
Outro local para começarem a aprender pode ser o datacamp que tem muitos cursos. Sendo que 99% deles são a pagar podem encontrar os mais básicos de graça: Datacamp: Introduction to Python
Outro local com renome e grátis onde podem aprender python é o freecodecamp, embora eu não seja fã da forma de ensino deles é provavelmente a melhor opção grátis: Data Analysis with Python
Uma das melhores formas de aprenderem python é também pensarem num projecto e à medida que o vão fazendo pesquisem como resolver os passos no google (nomeadamente resultado do stackoverflow são bastante bons)
Incluo aqui este capítulo em versão Notebook para se ambientarem ao mesmo tempo que podem ver as potencialidades do uso dos mesmos: https://deepnote.com/@luisilva/Capitulo-0-Introducao-a-Python-a879b2f5-d1d1-47b3-b14a-259bd67392f6