Introdução
Em um mundo onde a análise de dados e a automação de processos são cada vez mais essenciais, entender como integrar ferramentas tecnológicas pode ser um grande diferencial. Este projeto foi desenvolvido como uma iniciativa didática para treinar a utilização de APIs e inteligência artificial (IA), explorando ferramentas tecnológicas que podem simplificar processos complexos.
Objetivo do Projeto
- Coletar dados financeiros de ações em tempo real;
- Gerar gráficos e análises técnicas;
- Automatizar a criação de um relatório em PDF;
- Enviar o relatório por e-mail para stakeholders.
Ferramentas Utilizadas
- Python: Para a lógica de programação e automação.
- Alpha Vantage API: Para coleta de dados financeiros.
- Pandas e Matplotlib: Para análise e visualização de dados.
- FPDF: Para geração de PDFs.
- OpenAI API: Para gerar insights automatizados com IA.
- SMTP: Para envio de e-mails automatizados.
Passo a Passo do Projeto
1. Coleta de Dados com a Alpha Vantage API
A primeira etapa foi coletar dados financeiros em tempo real. Para isso, utilizei a API da Alpha Vantage, que fornece dados históricos e em tempo real de ações. A biblioteca requests foi utilizada para fazer as chamadas à API.
2. Análise e Visualização de Dados
Com os dados em mãos, utilizei o Pandas para manipulação e o Matplotlib para criar gráficos de preços de fechamento e médias móveis.
3. Geração de Relatórios em PDF
Para criar o relatório em PDF, utilizei a biblioteca FPDF. O relatório inclui o gráfico gerado e insights obtidos com a OpenAI API.
4. Automação de E-mails
Por fim, utilizei a biblioteca smtplib para enviar o relatório por e-mail automaticamente.
Conclusão
Este projeto foi uma excelente oportunidade para aprofundar meus conhecimentos em Python e APIs. Ao longo do desenvolvimento, pude explorar conceitos importantes, como o protocolo HTTP, status codes, estrutura de requisições HTTP, tipos de autenticação de APIs e muito mais.
Vale ressaltar que o objetivo principal deste projeto foi didático. As recomendações de compra ou venda geradas no relatório são baseadas em análises técnicas automatizadas e não devem ser utilizadas como única fonte para decisões de investimento. A análise de mercado exige uma abordagem mais abrangente, considerando fatores fundamentais, macroeconômicos e contextuais.
Aqui está um exemplo do relatório gerado para as ações da Apple no dia 30/01/2025, juntamente com o código utilizado:
import osfrom dotenv import load_dotenvimport requestsimport pandas as pdimport matplotlib.pyplot as pltfrom fpdf import FPDF, enumsimport openaiimport timeimport smtplibfrom email.mime.multipart import MIMEMultipartfrom email.mime.text import MIMETextfrom email.mime.base import MIMEBasefrom email import encodersimport re# Carregar variáveis de ambiente do arquivo .envload_dotenv()# Obter as chaves da API e senha do e-mailapi_key = os.getenv('ALPHA_VANTAGE_API_KEY')openai_api_key = os.getenv('OPENAI_API_KEY')email_app_password = os.getenv('EMAIL_APP_PASSWORD')# Verificar se as chaves foram carregadas corretamenteif not api_key:raise ValueError("Chave da API Alpha Vantage não encontrada. Verifique o arquivo .env.")if not openai_api_key:raise ValueError("Chave da API OpenAI não encontrada. Verifique o arquivo .env.")if not email_app_password:raise ValueError("Senha do aplicativo de e-mail não encontrada. Verifique o arquivo .env.")# Inicializa o cliente OpenAI corretamenteclient = openai.OpenAI(api_key=openai_api_key)# Função para remover emojis e caracteres especiaisdef remover_emoji(texto):return re.sub(r'[^\x00-\x7F]+', '', texto)# Função para obter insights da IAdef obter_insights(dados):prompt = f"""A seguir estão os dados financeiros recentes para as ações monitoradas:{dados}Com base nesses dados e utilizando exclusivamente análise grafista, sem considerar fatores externos, você recomendaria a compra ou venda dessas ações?Explique brevemente utilizando apenas uma análise grafista, e sendo puramente técnico. Pode utilizar conceitos avançados da análise grafista, como linhas de tendência, suporte e resistência, fibonacci, etc.Somado a isso, gere um texto sem caracteres especiais, exemplo: Ao invés de escrever Relatório, escreva Relatorio. Por fim, elabore um texto de, no mínimo, 200 palavras com uma análise completa."""try:response = client.chat.completions.create(model="gpt-3.5-turbo",messages=[{"role": "system", "content": "Você é um analista financeiro."},{"role": "user", "content": prompt}])insights = response.choices[0].message.content.strip()insights = remover_emoji(insights) # Remove emojisprint("\n **Insights Gerados pela IA:**\n")print(insights) # Exibir insights na telareturn insightsexcept Exception as e:return f"Erro ao obter insights: {str(e)}"# Lista de símbolos das ações monitoradassymbols = ['AAPL']# Dicionário para armazenar os DataFrames de cada açãodataframes = {}# Coletar dados das açõesfor symbol in symbols:url = f'https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol={symbol}&apikey={api_key}'response = requests.get(url)data = response.json()if "Time Series (Daily)" in data:print(f"Dados coletados com sucesso para {symbol}")time_series = data['Time Series (Daily)']df = pd.DataFrame.from_dict(time_series, orient='index')df.index = pd.to_datetime(df.index)df.columns = ['Open', 'High', 'Low', 'Close', 'Volume']df = df.astype(float)df['SMA_20'] = df['Close'].rolling(window=20).mean()dataframes[symbol] = dfelif "Error Message" in data or "Note" in data:print(f"Erro na API para {symbol}: {data}")breaktime.sleep(15) # Respeitar limite da API# Criar o PDFpdf = FPDF()pdf.set_auto_page_break(auto=True, margin=15)# Adicionar cabeçalho ao PDFpdf.add_page()pdf.set_font("Arial", 'B', 16)pdf.cell(200, 10, "Relatório Diário: Desempenho das Ações", new_x=enums.XPos.LMARGIN, new_y=enums.YPos.NEXT, align='C')pdf.ln(10) # Aumentar o espaçamento após o cabeçalho# Gerar gráficos e adicionar ao PDFfor symbol, df in dataframes.items():plt.figure(figsize=(10, 5))plt.plot(df.index, df['Close'], label='Preço de Fechamento', color='#1f77b4')plt.plot(df.index, df['SMA_20'], label='Média Móvel 20 dias', color='orange')plt.title(f'Preço de Fechamento da Ação {symbol}', fontsize=14, fontweight='bold')plt.xlabel('Data', fontsize=12)plt.ylabel('Preço de Fechamento (USD ou BRL)', fontsize=12)plt.legend(loc='upper left')plt.grid(True, linestyle='--', alpha=0.7)image_path = f"{symbol}.png"plt.savefig(image_path)plt.close()# Adicionar título do gráficopdf.set_font("Arial", 'B', 14)pdf.cell(200, 10, f'Desempenho da Ação: {symbol}', new_x=enums.XPos.LMARGIN, new_y=enums.YPos.NEXT, align='C')pdf.ln(5) # Ajuste o espaçamento após o título do gráfico# Adicionar gráfico ao PDFpdf.image(image_path, x=10, y=pdf.get_y(), w=190)pdf.ln(100) # Aumentar o espaçamento após o gráficoos.remove(image_path)# Obter e adicionar insights da IAdados_para_ia = f"{symbol}: Preço de Fechamento: {df['Close'].iloc[-1]:.2f}, Média Móvel 20 dias: {df['SMA_20'].iloc[-1]:.2f}"insights = obter_insights(dados_para_ia)# Adicionar os insights abaixo do gráficopdf.set_font("Arial", 'B', 12)pdf.set_xy(10, pdf.get_y()) # Definir a posição x e y para o textopdf.multi_cell(w=190, h=8, text=f"Insights da IA para {symbol}:")pdf.set_font("Arial", size=11)pdf.set_xy(10, pdf.get_y()) # Definir a posição x e y para o textopdf.multi_cell(w=190, h=6, text=insights)# Salvar o PDFpdf_output_path = "desempenho_acoes_corrigido.pdf"pdf.output(pdf_output_path)print(f" PDF gerado com sucesso: {pdf_output_path}")# **Envio de E-mail**from_address = "matheusronelle1@gmail.com"to_address = "matheusronelle@hotmail.com"subject = "Relatório Diário: Desempenho das Ações"body = """<html><body><h2>Relatório Diário: Desempenho das Ações</h2><p>Por favor, encontre em anexo o relatório diário com o desempenho das ações monitoradas.</p><p>Atenciosamente,<br>Matheus</p></body></html>"""msg = MIMEMultipart()msg['From'] = from_addressmsg['To'] = to_addressmsg['Subject'] = subjectmsg.attach(MIMEText(body, 'html'))with open(pdf_output_path, "rb") as attachment:part = MIMEBase('application', 'octet-stream')part.set_payload(attachment.read())encoders.encode_base64(part)part.add_header('Content-Disposition', f'attachment; filename= {os.path.basename(pdf_output_path)}')msg.attach(part)server = smtplib.SMTP('smtp.gmail.com', 587)server.starttls()server.login(from_address, email_app_password)server.sendmail(from_address, to_address, msg.as_string())server.quit()print(" E-mail enviado com sucesso!")import os from dotenv import load_dotenv import requests import pandas as pd import matplotlib.pyplot as plt from fpdf import FPDF, enums import openai import time import smtplib from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.mime.base import MIMEBase from email import encoders import re # Carregar variáveis de ambiente do arquivo .env load_dotenv() # Obter as chaves da API e senha do e-mail api_key = os.getenv('ALPHA_VANTAGE_API_KEY') openai_api_key = os.getenv('OPENAI_API_KEY') email_app_password = os.getenv('EMAIL_APP_PASSWORD') # Verificar se as chaves foram carregadas corretamente if not api_key: raise ValueError("Chave da API Alpha Vantage não encontrada. Verifique o arquivo .env.") if not openai_api_key: raise ValueError("Chave da API OpenAI não encontrada. Verifique o arquivo .env.") if not email_app_password: raise ValueError("Senha do aplicativo de e-mail não encontrada. Verifique o arquivo .env.") # Inicializa o cliente OpenAI corretamente client = openai.OpenAI(api_key=openai_api_key) # Função para remover emojis e caracteres especiais def remover_emoji(texto): return re.sub(r'[^\x00-\x7F]+', '', texto) # Função para obter insights da IA def obter_insights(dados): prompt = f""" A seguir estão os dados financeiros recentes para as ações monitoradas: {dados} Com base nesses dados e utilizando exclusivamente análise grafista, sem considerar fatores externos, você recomendaria a compra ou venda dessas ações? Explique brevemente utilizando apenas uma análise grafista, e sendo puramente técnico. Pode utilizar conceitos avançados da análise grafista, como linhas de tendência, suporte e resistência, fibonacci, etc. Somado a isso, gere um texto sem caracteres especiais, exemplo: Ao invés de escrever Relatório, escreva Relatorio. Por fim, elabore um texto de, no mínimo, 200 palavras com uma análise completa. """ try: response = client.chat.completions.create( model="gpt-3.5-turbo", messages=[ {"role": "system", "content": "Você é um analista financeiro."}, {"role": "user", "content": prompt} ] ) insights = response.choices[0].message.content.strip() insights = remover_emoji(insights) # Remove emojis print("\n **Insights Gerados pela IA:**\n") print(insights) # Exibir insights na tela return insights except Exception as e: return f"Erro ao obter insights: {str(e)}" # Lista de símbolos das ações monitoradas symbols = ['AAPL'] # Dicionário para armazenar os DataFrames de cada ação dataframes = {} # Coletar dados das ações for symbol in symbols: url = f'https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol={symbol}&apikey={api_key}' response = requests.get(url) data = response.json() if "Time Series (Daily)" in data: print(f"Dados coletados com sucesso para {symbol}") time_series = data['Time Series (Daily)'] df = pd.DataFrame.from_dict(time_series, orient='index') df.index = pd.to_datetime(df.index) df.columns = ['Open', 'High', 'Low', 'Close', 'Volume'] df = df.astype(float) df['SMA_20'] = df['Close'].rolling(window=20).mean() dataframes[symbol] = df elif "Error Message" in data or "Note" in data: print(f"Erro na API para {symbol}: {data}") break time.sleep(15) # Respeitar limite da API # Criar o PDF pdf = FPDF() pdf.set_auto_page_break(auto=True, margin=15) # Adicionar cabeçalho ao PDF pdf.add_page() pdf.set_font("Arial", 'B', 16) pdf.cell(200, 10, "Relatório Diário: Desempenho das Ações", new_x=enums.XPos.LMARGIN, new_y=enums.YPos.NEXT, align='C') pdf.ln(10) # Aumentar o espaçamento após o cabeçalho # Gerar gráficos e adicionar ao PDF for symbol, df in dataframes.items(): plt.figure(figsize=(10, 5)) plt.plot(df.index, df['Close'], label='Preço de Fechamento', color='#1f77b4') plt.plot(df.index, df['SMA_20'], label='Média Móvel 20 dias', color='orange') plt.title(f'Preço de Fechamento da Ação {symbol}', fontsize=14, fontweight='bold') plt.xlabel('Data', fontsize=12) plt.ylabel('Preço de Fechamento (USD ou BRL)', fontsize=12) plt.legend(loc='upper left') plt.grid(True, linestyle='--', alpha=0.7) image_path = f"{symbol}.png" plt.savefig(image_path) plt.close() # Adicionar título do gráfico pdf.set_font("Arial", 'B', 14) pdf.cell(200, 10, f'Desempenho da Ação: {symbol}', new_x=enums.XPos.LMARGIN, new_y=enums.YPos.NEXT, align='C') pdf.ln(5) # Ajuste o espaçamento após o título do gráfico # Adicionar gráfico ao PDF pdf.image(image_path, x=10, y=pdf.get_y(), w=190) pdf.ln(100) # Aumentar o espaçamento após o gráfico os.remove(image_path) # Obter e adicionar insights da IA dados_para_ia = f"{symbol}: Preço de Fechamento: {df['Close'].iloc[-1]:.2f}, Média Móvel 20 dias: {df['SMA_20'].iloc[-1]:.2f}" insights = obter_insights(dados_para_ia) # Adicionar os insights abaixo do gráfico pdf.set_font("Arial", 'B', 12) pdf.set_xy(10, pdf.get_y()) # Definir a posição x e y para o texto pdf.multi_cell(w=190, h=8, text=f"Insights da IA para {symbol}:") pdf.set_font("Arial", size=11) pdf.set_xy(10, pdf.get_y()) # Definir a posição x e y para o texto pdf.multi_cell(w=190, h=6, text=insights) # Salvar o PDF pdf_output_path = "desempenho_acoes_corrigido.pdf" pdf.output(pdf_output_path) print(f" PDF gerado com sucesso: {pdf_output_path}") # **Envio de E-mail** from_address = "matheusronelle1@gmail.com" to_address = "matheusronelle@hotmail.com" subject = "Relatório Diário: Desempenho das Ações" body = """ <html> <body> <h2>Relatório Diário: Desempenho das Ações</h2> <p>Por favor, encontre em anexo o relatório diário com o desempenho das ações monitoradas.</p> <p>Atenciosamente,<br>Matheus</p> </body> </html> """ msg = MIMEMultipart() msg['From'] = from_address msg['To'] = to_address msg['Subject'] = subject msg.attach(MIMEText(body, 'html')) with open(pdf_output_path, "rb") as attachment: part = MIMEBase('application', 'octet-stream') part.set_payload(attachment.read()) encoders.encode_base64(part) part.add_header('Content-Disposition', f'attachment; filename= {os.path.basename(pdf_output_path)}') msg.attach(part) server = smtplib.SMTP('smtp.gmail.com', 587) server.starttls() server.login(from_address, email_app_password) server.sendmail(from_address, to_address, msg.as_string()) server.quit() print(" E-mail enviado com sucesso!")import os from dotenv import load_dotenv import requests import pandas as pd import matplotlib.pyplot as plt from fpdf import FPDF, enums import openai import time import smtplib from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.mime.base import MIMEBase from email import encoders import re # Carregar variáveis de ambiente do arquivo .env load_dotenv() # Obter as chaves da API e senha do e-mail api_key = os.getenv('ALPHA_VANTAGE_API_KEY') openai_api_key = os.getenv('OPENAI_API_KEY') email_app_password = os.getenv('EMAIL_APP_PASSWORD') # Verificar se as chaves foram carregadas corretamente if not api_key: raise ValueError("Chave da API Alpha Vantage não encontrada. Verifique o arquivo .env.") if not openai_api_key: raise ValueError("Chave da API OpenAI não encontrada. Verifique o arquivo .env.") if not email_app_password: raise ValueError("Senha do aplicativo de e-mail não encontrada. Verifique o arquivo .env.") # Inicializa o cliente OpenAI corretamente client = openai.OpenAI(api_key=openai_api_key) # Função para remover emojis e caracteres especiais def remover_emoji(texto): return re.sub(r'[^\x00-\x7F]+', '', texto) # Função para obter insights da IA def obter_insights(dados): prompt = f""" A seguir estão os dados financeiros recentes para as ações monitoradas: {dados} Com base nesses dados e utilizando exclusivamente análise grafista, sem considerar fatores externos, você recomendaria a compra ou venda dessas ações? Explique brevemente utilizando apenas uma análise grafista, e sendo puramente técnico. Pode utilizar conceitos avançados da análise grafista, como linhas de tendência, suporte e resistência, fibonacci, etc. Somado a isso, gere um texto sem caracteres especiais, exemplo: Ao invés de escrever Relatório, escreva Relatorio. Por fim, elabore um texto de, no mínimo, 200 palavras com uma análise completa. """ try: response = client.chat.completions.create( model="gpt-3.5-turbo", messages=[ {"role": "system", "content": "Você é um analista financeiro."}, {"role": "user", "content": prompt} ] ) insights = response.choices[0].message.content.strip() insights = remover_emoji(insights) # Remove emojis print("\n **Insights Gerados pela IA:**\n") print(insights) # Exibir insights na tela return insights except Exception as e: return f"Erro ao obter insights: {str(e)}" # Lista de símbolos das ações monitoradas symbols = ['AAPL'] # Dicionário para armazenar os DataFrames de cada ação dataframes = {} # Coletar dados das ações for symbol in symbols: url = f'https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol={symbol}&apikey={api_key}' response = requests.get(url) data = response.json() if "Time Series (Daily)" in data: print(f"Dados coletados com sucesso para {symbol}") time_series = data['Time Series (Daily)'] df = pd.DataFrame.from_dict(time_series, orient='index') df.index = pd.to_datetime(df.index) df.columns = ['Open', 'High', 'Low', 'Close', 'Volume'] df = df.astype(float) df['SMA_20'] = df['Close'].rolling(window=20).mean() dataframes[symbol] = df elif "Error Message" in data or "Note" in data: print(f"Erro na API para {symbol}: {data}") break time.sleep(15) # Respeitar limite da API # Criar o PDF pdf = FPDF() pdf.set_auto_page_break(auto=True, margin=15) # Adicionar cabeçalho ao PDF pdf.add_page() pdf.set_font("Arial", 'B', 16) pdf.cell(200, 10, "Relatório Diário: Desempenho das Ações", new_x=enums.XPos.LMARGIN, new_y=enums.YPos.NEXT, align='C') pdf.ln(10) # Aumentar o espaçamento após o cabeçalho # Gerar gráficos e adicionar ao PDF for symbol, df in dataframes.items(): plt.figure(figsize=(10, 5)) plt.plot(df.index, df['Close'], label='Preço de Fechamento', color='#1f77b4') plt.plot(df.index, df['SMA_20'], label='Média Móvel 20 dias', color='orange') plt.title(f'Preço de Fechamento da Ação {symbol}', fontsize=14, fontweight='bold') plt.xlabel('Data', fontsize=12) plt.ylabel('Preço de Fechamento (USD ou BRL)', fontsize=12) plt.legend(loc='upper left') plt.grid(True, linestyle='--', alpha=0.7) image_path = f"{symbol}.png" plt.savefig(image_path) plt.close() # Adicionar título do gráfico pdf.set_font("Arial", 'B', 14) pdf.cell(200, 10, f'Desempenho da Ação: {symbol}', new_x=enums.XPos.LMARGIN, new_y=enums.YPos.NEXT, align='C') pdf.ln(5) # Ajuste o espaçamento após o título do gráfico # Adicionar gráfico ao PDF pdf.image(image_path, x=10, y=pdf.get_y(), w=190) pdf.ln(100) # Aumentar o espaçamento após o gráfico os.remove(image_path) # Obter e adicionar insights da IA dados_para_ia = f"{symbol}: Preço de Fechamento: {df['Close'].iloc[-1]:.2f}, Média Móvel 20 dias: {df['SMA_20'].iloc[-1]:.2f}" insights = obter_insights(dados_para_ia) # Adicionar os insights abaixo do gráfico pdf.set_font("Arial", 'B', 12) pdf.set_xy(10, pdf.get_y()) # Definir a posição x e y para o texto pdf.multi_cell(w=190, h=8, text=f"Insights da IA para {symbol}:") pdf.set_font("Arial", size=11) pdf.set_xy(10, pdf.get_y()) # Definir a posição x e y para o texto pdf.multi_cell(w=190, h=6, text=insights) # Salvar o PDF pdf_output_path = "desempenho_acoes_corrigido.pdf" pdf.output(pdf_output_path) print(f" PDF gerado com sucesso: {pdf_output_path}") # **Envio de E-mail** from_address = "matheusronelle1@gmail.com" to_address = "matheusronelle@hotmail.com" subject = "Relatório Diário: Desempenho das Ações" body = """ <html> <body> <h2>Relatório Diário: Desempenho das Ações</h2> <p>Por favor, encontre em anexo o relatório diário com o desempenho das ações monitoradas.</p> <p>Atenciosamente,<br>Matheus</p> </body> </html> """ msg = MIMEMultipart() msg['From'] = from_address msg['To'] = to_address msg['Subject'] = subject msg.attach(MIMEText(body, 'html')) with open(pdf_output_path, "rb") as attachment: part = MIMEBase('application', 'octet-stream') part.set_payload(attachment.read()) encoders.encode_base64(part) part.add_header('Content-Disposition', f'attachment; filename= {os.path.basename(pdf_output_path)}') msg.attach(part) server = smtplib.SMTP('smtp.gmail.com', 587) server.starttls() server.login(from_address, email_app_password) server.sendmail(from_address, to_address, msg.as_string()) server.quit() print(" E-mail enviado com sucesso!")
Enter fullscreen mode Exit fullscreen mode
原文链接:Automatizando Análises de Ações da Bolsa com Python e Inteligência Artificial
暂无评论内容