Gráficos Dinâmicos com Vraptor, JqPlot e Yahoo Finances

3485637956_9713c5ffc1

Motivação

A maioria das aplicações web precisam apresentar dados ou valores numéricos para os usuários. O uso de tabelas pode resolver este problema, porém, utilizando gráficos podemos evidenciar as informações de forma mais rápida e objetiva. Os gráficos são auto-explicativos e de fácil compreensão e por isso sempre devemos levar em conta sua utilização.

Objetivo

Você aprenderá neste post a criar gráficos dinâmicos para aplicações web Java através do framework Vraptor e do plugin para Jquery JqPlot. Utilizaremos informações de preços dos papéis no mercado de ações fornecidos pelo Yahoo Finances para exibir gráficos candlestick(Aprenda Mais).

Por quê essas Tecnologias?

Vraptor

boxVraptor-trans

Nas últimas semanas comecei a brincar com este framework Java para Web que foi criado por brasileiros e é mantido pela Caelum. As primeiras impressões foram muito boas. A Documentação disponível no site facilita bastante o processo de aprendizado. Além disso, deu pra notar que ele é uma ferramenta bem completa capaz de permitir a criação de web services REST (Aprenda Mais) e a utilização da Inversão de Controle (Aprenda Mais) de forma fácil e rápida.

Pretendo utilizá-lo mais em meus projetos e as novidades e dificuldades que eu for encontrando foi postando.

Outro ponto que merece atenção de quem está conhecendo a ferramenta é que não é intenção do Vraptor fornecer componentes visuais para as páginas. Ele se baseia no fato de que existem muitas bibliotecas javascript que podem resolver esse problema muito bem. Com isso, as páginas podem ser mantidas por designers ou qualquer outra pessoa que não precisa necessariamente conheça o Vraptor. Achei isso muito interessante.

JqPlot

graficosjqplot

O JqPlot é um dos plugins para Jquery capazes de criar e exibir gráficos dinâmicos. Existem muitas opções de plugins que resolvem este problema, mas o JqPlot me chamou a atenção por ser free, não usar flash, ser fácil de utilizar e por possuir muitas opções de gráficos e configurações (Confira os Exemplos).

Construindo Gráficos Dinâmicos

 

Vamos conhecer agora os passos necessários para construirmos gráficos dinâmicos com os dados do Yahoo Finances. O resultado final pode ser visto nas duas Figuras abaixo, o usuário poderá escolher o papel (nacionais e internacionais) das cotações. Apresentaremos informações dos últimos 2 anos, nas quais poderemos dar zoom para visualizar períodos específicos do gráfico.

resultado1

Gráfico com os valores diários das ações da Petrobrás

resultado2

Gráfico anterior com zoom nos últimos dias

1º Passo – Preparando o ambiente

– IDE de Desenvolvimento: Eclipse: Download

– Vraptor 3 Blank Project: Download

– JqPlot: Download

Depois de realizar os downloads, abra o Vraptor Blank Project no Eclipse e dentro da pasta Web Content crie duas pastas: js e css. Agora inclua os arquivos do JqPlot apresentados na figura abaixo:

Obs.: O arquivo customCandlestick.js será construído por nós mais a frente.

image

2º Passo – Criar classes para extrair dados do Yahoo Finances

O Yahoo Finances nos fornece para cada dia várias informações sobre um determinado papel, chamaremos essas informações de Resumo Diario. Fazem parte deste resumo: data, valor máximo, valor mínimo, valor de fechamento, volume e valor de fechamento ajustado. A primeira coisa a se fazer então é criar uma classe chamada ResumoDiario a partir da qual poderemos instanciar objetos com essas informações.

ResumoDiario.java

package Model;

public class ResumoDiario {

    private String data;
    private double abertura;
    private double maxima;
    private double minima;
    private double fechamento;
    private double volume;
    private double fechamentoAjustado;

    public ResumoDiario() {
    }

    public void setData(String data) {
        String[] dataPartes = data.split("-");
        this.data = dataPartes[1]+"/"+dataPartes[2]+"/"+(dataPartes[0].substring(2));
    }

    //getters and setters

}

Agora vamos criar uma classe chamada ColecaoResumosDiarios que terá o método getResumosDiarios, reposnável por buscar as informações de um papel no site do Yahoo Finances. Os dados são devolvidos do site em uma planilha csv, por isso vamos tratá-los para depois colocá-los em uma lista de Resumos Diários.

ColecaoResumosDiarios.java

package Utils;

import Model.ResumoDiario;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

public class ColecaoResumosDiarios {

    public static List<ResumoDiario> getResumosDiarios(String codPapel) {

        List<ResumoDiario> resumos = new ArrayList<ResumoDiario>();

        DateFormat dfDia = new SimpleDateFormat("dd");
        DateFormat dfMes = new SimpleDateFormat("MM");
        DateFormat dfAno = new SimpleDateFormat("yyyy");
        Date date = new Date();

        int diaAtual = Integer.parseInt(dfDia.format(date));
        int mesAtual = Integer.parseInt(dfMes.format(date));
        int anoAtual = Integer.parseInt(dfAno.format(date));

        try {

            String strUrl = "http://au.rd.yahoo.com/finance/quotes/internal/historical/download/*http://ichart.finance.yahoo.com/table.csv?s=" + codPapel + "&a=00&b=1&c=2010&d=" + (mesAtual - 1) + "&e=" + diaAtual + "&f=" + anoAtual + "&g=d&ignore=.csv";
            URL url = new URL(strUrl);
            BufferedReader arq = new BufferedReader(new InputStreamReader(url.openStream()));
            String[] nums = null;
            String linha = arq.readLine();
            linha = arq.readLine();
            ResumoDiario resumo = new ResumoDiario();

            while (linha != null) {
                nums = linha.split(",");
                resumo.setData(nums[0]);
                resumo.setAbertura(Double.parseDouble(nums[1]));
                resumo.setMaxima(Double.parseDouble(nums[2]));
                resumo.setMinima(Double.parseDouble(nums[3]));
                resumo.setFechamento(Double.parseDouble(nums[4]));
                resumo.setVolume(Double.parseDouble(nums[5]));
                resumo.setFechamentoAjustado(Double.parseDouble(nums[6]));
                resumos.add(resumo);
                resumo = new ResumoDiario();
                linha = arq.readLine();
            }
            arq.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        Collections.reverse(resumos);
        return resumos;
    }
}

Agora você já pode obter os dados que vamos utilizar!

3º Passo – Construir classe Controller para os gráficos

Vamos conhecer agora a classe IndexController, esta disponibilizará a lista de Resumos Diários para a página de visualização. Note que utilizamos 2 annotations específicos do Vraptor: @Resource e @Path.

@Resource

No caso de uma aplicação Web baseada no VRaptor, um recurso deve ser anotado com a anotação @Resource. Assim que o programador insere tal anotação em seu código, todos os métodos públicos desse recurso se tornam acessíveis através de chamadas do tipo GET a URIs específicas.

@Path

A anotação @Path permite que você customize as URIs de acesso a seus métodos. O uso básico dessa anotação é feito através de uma URI fixa.

http://vraptor.caelum.com.br/documentacao/resources-rest/

O método resumo() funcionará como um serviço e ao ser chamado disponibilizará, no formato JSON, a lista de Resumos Diários de um determinado papel. Fazendo isso podemos consumir este serviço utilizando ajax com Jquery.

 

IndexController.java

package Controller;

import Utils.ColecaoResumosDiarios;
import br.com.caelum.vraptor.Path;
import br.com.caelum.vraptor.Resource;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.view.Results;

@Resource
public class IndexController {

    private final Result result;

    public IndexController(Result result) {
        this.result = result;
    }

    @Path("/")
    public void index() {

    }

    @Path("/resumo/{papel}")
    public void resumo(String papel) {
        result.use(Results.json()).withoutRoot().from(ColecaoResumosDiarios.getResumosDiarios(papel)).serialize();
    }

}

4º Passo – Criar e configurar javascript do JqPlot

Agora chegou a hora de brincarmos com o plugin JqPlot. Para isso vamos criar um arquivo chamado customCandlestick.js. Este arquivo terá o método gerarGrafico() que será usado toda vez que o usuário desejar visualizar os dados de um papel. Dentro deste método a primeira coisa a se fazer é buscar os dados chamando o serviço que criamos com ajax. Em seguida, agrupamos estes dados no formato esperado pelo plugin. Aí então iniciamos as configurações, passando iniciamente o id da tag <div> onde o gráfico será plotado e o array com os dados. As demais configurações definem: título,formato(candlestick), zoom, highlighter(exibido ao passar sobre um ponto do gráfico), entre outras.

O arquivo deverá ser escrito assim:

customCandlestick.js

$.jqplot.config.enablePlugins = true;

            function gerarGrafico(papel){
                $.ajax({
                    url: 'http://localhost:8080/vraptor-jqplot-project/resumo/'+papel,
                    method: 'GET',
                    dataType: 'json',
                    success: function(json){
                        if(json.length == 0){
                            alert('Pesquisa invalida, tente outro Papel!');
                            return;
                        }
                        arraySaida = [];
                        for (var i = 0; i < json.length; i++) {
                            arrayTemp = [json[i].data, json[i].abertura, json[i].maxima, json[i].minima, json[i].fechamento];
                            arraySaida.push(arrayTemp);
                        }
                        $("#grafico").html('');
                        plot2 = $.jqplot('grafico', [arraySaida], {
                            title: 'Stock Market - '+papel,
                            axesDefaults: {},
                            axes: {
                                xaxis: {
                                    renderer: $.jqplot.DateAxisRenderer,
                                    tickOptions: {
                                        formatString: '%m.%y'
                                    }
                                },
                                yaxis: {
                                    tickOptions: {
                                        formatString: '%.2f'
                                    }
                                }
                            },
                            series: [{
                                renderer: $.jqplot.OHLCRenderer,
                                rendererOptions: {
                                    candleStick: true
                                }
                            }],
                            cursor: {
                                zoom: true,
                                tooltipOffset: 10,
                                tooltipLocation: 'nw'
                            },
                            highlighter: {
                                showMarker: false,
                                tooltipAxes: 'xy',
                                yvalues: 4,
                                formatString: '<table class="jqplot-highlighter"> \
                                  <tr><td>data:</td><td>%s</td></tr> \
                                  <tr><td>abertura:</td><td>%s</td></tr> \
                                  <tr><td>max:</td><td>%s</td></tr> \
                                  <tr><td>min:</td><td>%s</td></tr> \
                                  <tr><td>fechamento:</td><td>%s</td></tr></table>'
                            }
                        });
                    },
                    error: function(xhr, status){
                        alert('Desculpe, ocorreu um problema inesperado! Voltamos logo mais com a programação normal...');
                    }
                });
            }

            function alterarPapel(){
                gerarGrafico($("#nomePapel").val());
            }

5º Passo – Criar a página de visualização dos gráficos

A página que irá exibir os gráficos será bem simples tendo na tag <head> as referências dos arquivos javascript e css necessários e na tag <body> Uma caixa de texto e um botão para a troca de papeis e uma tag <div> onde o gráfico será exibido.

O código deverá ficar assim:

index.jsp

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <title>Graficos da Bovespa com jqPlot e Vraptor</title>
        <link rel="stylesheet" type="text/css" href="css/jquery.jqplot.css" />
        <script language="javascript" type="text/javascript" src="js/jquery-1.4.2.min.js">
        </script>
        <script language="javascript" type="text/javascript" src="js/jquery.jqplot.js">
        </script>
        <script language="javascript" type="text/javascript" src="js/jqplot.dateAxisRenderer.js">
        </script>
        <script language="javascript" type="text/javascript" src="js/jqplot.categoryAxisRenderer.js">
        </script>
        <script language="javascript" type="text/javascript" src="js/jqplot.ohlcRenderer.js">
        </script>
        <script language="javascript" type="text/javascript" src="js/jqplot.highlighter.js">
        </script>
        <script language="javascript" type="text/javascript" src="js/jqplot.cursor.js">
        </script>
        <script language="javascript" type="text/javascript" src="js/customCandlestick.js">
        </script>
        <script type="text/javascript">
            $(document).ready(function(){
                gerarGrafico("VALE5.SA");
            });
        </script>
    </head>
    <body>
        <center>
               Escolha um papel:<input type="text" id="nomePapel"/><input type="button" value="Gerar Grafico" onclick="alterarPapel()"/> <a href="http://finance.yahoo.com/q/cp?s=^BVSP" target="_blank">Lista de Papeis da Bovespa</a>
            <div id="grafico" style="margin:20px;height:440px; width:740px;"/>
        </center>
    </body>
</html>

Conclusão

Neste artigo mostramos uma opção para a construção de gráficos dinâmicos em aplicações Java para web. As informações apresentadas aqui podem ser utilizadas como base para a construção de outros tipos de gráficos através do plugin JqPlot e do framework Vraptor. Lembrando um ponto importante é que não precisamos de NADA em flash nos gráficos com este plugin!

 

Download

Clique aqui para baixar este projeto.

Aprenda Mais!

Gráficos Candlestick: http://www.grafbolsa.com/help/candle.html

jQPlot Documentação: http://www.jqplot.com/docs/files/usage-txt.html

Vraptor Documentação: http://vraptor.caelum.com.br/documentacao/

Web Services REST: http://brunopereira.org/webservicesrest-introducao/

Inversão de controle (Capítulo do Livro Arquitetura de Software Java): Inversão de Controle: Cadê a minha chave de fenda?

10 comments for “Gráficos Dinâmicos com Vraptor, JqPlot e Yahoo Finances

  1. 10 de Fevereiro de 2011 at 10:34

    Muito bacana o post.
    Não conheço o JqPlot, parece ser bem legal.
    []’s

    • 10 de Fevereiro de 2011 at 10:42

      Oii Loiane!!
      Que bom que gostou :)!
      Então, pesquisei vários plugins até achei alguns melhores que eram pagos! Esse bate de frente com os pagos e não fica devendo em nada! Muito fácil de usar também…
      Abraços!

  2. 11 de Fevereiro de 2011 at 21:46

    pow bem bacana mesmo! parabens pelo post, objetivo, claro e com boa abordagem.

  3. 1 de Janeiro de 2012 at 11:16

    Excelente post. Parabéns.

  4. 5 de Setembro de 2012 at 17:14

    Quando abro a aplicação diz que o site está fora do ar e volta em instantes e já tem dias que está assim.

  5. 27 de Junho de 2014 at 11:55

    O site esta caindo, fora isso ok

  6. Rafael
    23 de Dezembro de 2014 at 19:36

    E diferente a validacao no brasil o meu e assim e comecou a dar erro

    “URL;http://ichart.finance.yahoo.com/table.csv?s=” + stockTicker + “&a=” + StartMonth + “&b=” + StartDay + “&c=” + StartYear + “&d=” + EndMonth + “&e=” + EndDay + “&f=” + EndYear + “&g=” + freq + “&ignore=.csv”