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