Primeira vez aqui? Seja bem vindo e cheque o FAQ!
x

Considere que você deseja implementar um programa para lidar com alocação de carteiras.

+1 voto
64 visitas
perguntada Mar 31 em Finanças por MarcioGama (66 pontos)  

Considere que você deseja implementar um programa para lidar com alocação de carteiras. Nesse contexto vocˆe precisa desenvolver cuidadosamente duas classes. Um classe que você chamará de ativo e deve ser capaz de apresentar/calcular características/propriedades básicas do ativo como nome, empresa associada, vetor de preços, vetor de retornos, retorno médio e variância. Uma outra classe que você chamará de carteira que é uma coleção de ativos e deve também considerar propriedades específicas. Pense cuidadosamente na implementação dessas classes e implemente em Python.

Compartilhe

4 Respostas

0 votos
respondida Mar 31 por MarcioGama (66 pontos)  
editado Mar 31 por MarcioGama

Segue a implementação.

Utilizei as seguinte bibliotecas:

import numpy as np
import pandas_datareader.data as web
import pandas as pd
import datetime as dt

A classe de Ativos:

class Ativo(object):

    def __init__(self, nome, empresa, price):
        self.nome = nome;
        self.empresa = empresa;
        self.price = price;

    def calcRetorno(self):
        #calcula o retorno diário do ativo usando a fórmula R = log(Rt/Rt-1)
        return np.log(self.price/self.price.shift(1))
    def calcRetornoMedio(self):
        #calcula o retorno médio anualizado
        return self.calcRetorno().mean()*250;

    def calcVariancia(self):
        #calcula a variância anualizada
        return self.calcRetorno().var()*250;

    def ultFechamento(self):

        return self.price[-1];

    def __str__(self):
        #método mágico para redefinir como a função print trata o objeto
        return "%s: %s - último fechamento: %d" % (self.empresa, self.nome, self.ultFechamento());

    def __eq__(self, outro):
        #método mágico que define como os objetos da classe se comparam entre si
        if self.nome == outro.nome:
            return True;
        else:
            return False;

Essa classe recebe como parâmetros o nome da empresa, o nome do ativo e um vetor de preços.

0 votos
respondida Mar 31 por MarcioGama (66 pontos)  

Usei o pandas_datareader para extrair informações de ações na internet.

Usei como fonte o Quandl pois, aparentemente, o google e o yahoo não estão funcionando direito. Se alguém souber uma fonte melhor para esses dados, por favor, me informe.

if __name__ == '__main__':
    start = dt.datetime(2015,2,11);
    end = dt.datetime(2017,6,16);
    a = web.DataReader('WIKI/GOOGL', 'quandl', start, end)['AdjClose'];
    b = web.DataReader('WIKI/YHOO', 'quandl', start, end)['AdjClose'];
    c = web.DataReader('WIKI/FB', 'quandl', start, end)['AdjClose'];
    d = web.DataReader('WIKI/AMZN', 'quandl', start, end)['AdjClose'];
    a.sort_index(inplace = True);
    b.sort_index(inplace = True);
    c.sort_index(inplace = True);
    d.sort_index(inplace = True);

A função DataReader do pandas_datareader recebe como parâmetros o nome da ação, a fonte dos dados, uma data início e uma fim. Selecionei apenas a coluna contendo os preços de fechamento do dia. Depois fiz um sort em cada uma delas para deixar em ordem crescente de data.

Com essas informações, criei os objetos do tipo Ativo.

  yahoo = Ativo('YHOO', 'Yahoo', a);
    google = Ativo('GOOGL', 'Google', b);
    facebook = Ativo('FB', 'Facebook', c);
    amazon = Ativo('AMZN', 'Amazon', d);

Testando algumas funções:

print(yahoo);

Yahoo: YHOO - último fechamento: 958

print(google.calcRetornoMedio());
0.0855504760014569

print(facebook.calcVariancia());
0.062243159274610056
0 votos
respondida Mar 31 por MarcioGama (66 pontos)  
editado Abr 1 por MarcioGama

Classe Carteira:

class Carteira(object):

    def __init__(self):
        self.carteira = [];
        self.quantidade = [];
        self.pesos = [];

    def inserirAtivo(self, ativo, quantidade):
        count = 0;
        for i in range(0, len(self.carteira)):
            if self.carteira[i] == ativo:
                self.quantidade[i] += quantidade;
                total = self.calcValorCarteira();
                self.atualizarPesos(total);
            else:
                count += 1;

        if count == len(self.carteira):

            self.carteira.append(ativo);
            self.quantidade.append(quantidade);
            total = self.calcValorCarteira();
            self.atualizarPesos(total)

    def atualizarPesos(self, total):
        self.pesos = [];
        for i in range(0,len(self.quantidade)):
            self.pesos.append(self.carteira[i].ultFechamento()*self.quantidade[i]/total);

    def calcValorCarteira(self):
        valor = 0;
        for i in range(0, len(self.carteira)):
            valor += self.quantidade[i] * self.carteira[i].ultFechamento();

        return valor;

    def matrizRetornos(self):
        matriz = [];
        for i in self.carteira:
            matriz.append(i.price);

        matriz2 = pd.concat(matriz, axis = 1);
        matrizret = np.log(matriz2/matriz2.shift(1));
        return matrizret;

    def calcRetornoMedio(self):
        retorno = 0;
        for i in range(0,len(self.carteira)):
            retorno += self.pesos[i]*self.carteira[i].calcRetornoMedio();
        return retorno


    def calcMatrizCov(self):
        return self.matrizRetornos().cov()*250;


    def calcVolatilidade(self):
        return np.sqrt(self.calcMatrizCov());


    def calcVariancia(self):
        peso = np.array(self.pesos);
        return np.dot(peso.T, np.dot(self.calcMatrizCov(),peso));

    def printCarteira(self):
        print("Essa carteira contém: ")
        for i in range(0, len(self.carteira)):
            print(self.carteira[i])
            print("valor na carteira: %f" % (self.carteira[i].ultFechamento()*self.quantidade[i]));
            print("peso na carteira: %f" % (self.pesos[i]));

Essa classe recebe como parâmetros um ativo e a quantidade do ativo. Toda vez que um ativo é inserido na carteira, o programa verifica se o ativo já existe na carteira. Se sim, ele incrementa sua quantidade e atualiza o valor da carteira e pesos dos ativos na carteira. Caso contrário, o ativo é inserido e o valor e os pesos são atualizados.
Em algumas funções a array de pesos foi transformada numa numpy array para poder ser transposta.

Nessa classe fiquei com dificuldade de implementar o método mágico str , já que o método espera return e não um print e fiquei na dúvida de como implementar o return dentro do loop.

0 votos
respondida Mar 31 por MarcioGama (66 pontos)  
editado Abr 1 por MarcioGama

Teste da classe:

carteira = Carteira();
carteira.inserirAtivo(yahoo,200);
carteira.inserirAtivo(google,1000);
carteira.inserirAtivo(facebook,500);
carteira.inserirAtivo(amazon,300);

print(carteira.calcVariancia());
print(carteira.calcRetornoMedio());
print(carteira.calcMatrizCov());

0.04791689280154537

0.31540978528050556

AdjClose  AdjClose  AdjClose  AdjClose
AdjClose  0.051408  0.026315  0.035510  0.037150
AdjClose  0.026315  0.081923  0.027280  0.033412
AdjClose  0.035510  0.027280  0.062243  0.041839
AdjClose  0.037150  0.033412  0.041839  0.077534
...