Subversion Repositories Integrator Subversion

Rev

Rev 783 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

package br.com.sl.core;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Stream;

import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import br.com.ec.core.util.VerificadorUtil;
import br.com.kronus.core.Timeframe;
import br.com.sl.domain.dto.robo.ProfitTick;
import br.com.sl.domain.model.Candle;
import br.com.sl.domain.model.tipos.TipoPeriodoCandle;
import br.com.sl.domain.util.BigDecimalUtils;
import br.com.sl.shared.ExcelDataUtils;

public class ExcelProfitDataProvider implements ProfitDataProvider {

        private final Path excelFile;
    private final String sheetName;

    // índices de coluna (0 = A, 1 = B, etc.)
    private final int colAsset = 0;
    private final int colDate  = 1;
    private final int colTime  = 2;
    private final int colLast  = 3;

    private static final DateTimeFormatter DATE_FORMAT_CSV = DateTimeFormatter.ofPattern("dd/MM/yyyy");
    private static final DateTimeFormatter TIME_FORMAT_CSV = DateTimeFormatter.ofPattern("HH:mm:ss");
   
    private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss");
    private static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss");

    public ExcelProfitDataProvider(Path excelFile, String sheetName) {
        this.excelFile = excelFile;
        this.sheetName = sheetName;
    }
   
    /**
     * Lê um ou vários arquivos:
     * - Se excelFile for um arquivo: lê apenas esse arquivo (.xlsx, .xls ou .csv)
     * - Se excelFile for uma pasta: lê todos os .xlsx, .xls e .csv da pasta.
     */

    public List<Candle> lerCandles() throws IOException {
        List<Candle> candles = new ArrayList<>();

        if (Files.isDirectory(excelFile)) {
            // Percorre todos os arquivos da pasta
            try (Stream<Path> stream = Files.list(excelFile)) {
                stream
                    .filter(Files::isRegularFile)
                    .filter(p -> {
                        String name = p.getFileName().toString().toLowerCase(Locale.ROOT);
                        return name.endsWith(".xlsm") || name.endsWith(".xlsx") || name.endsWith(".xls") || name.endsWith(".csv");
                    })
                    .forEach(path -> {
                        try {
                            lerCandlesDeArquivo(path, candles);
                        } catch (IOException e) {
                            // aqui você pode trocar por log
                            e.printStackTrace();
                        }
                    });
            }
        } else {
            // Apenas um arquivo
            lerCandlesDeArquivo(excelFile, candles);
        }

        return adicionarContadores(candles);
    }
   
    /**
     * Decide se o arquivo é Excel ou CSV e delega para o método correto.
     */

    private void lerCandlesDeArquivo(Path arquivo, List<Candle> candles) throws IOException {
        String name = arquivo.getFileName().toString().toLowerCase(Locale.ROOT);

        if (name.endsWith(".xlsm") || name.endsWith(".xlsx") || name.endsWith(".xls")) {
            lerCandlesDeArquivoExcel(arquivo, candles);
        } else if (name.endsWith(".csv")) {
            lerCandlesDeArquivoCsv(arquivo, candles);
        } else {
            // Tipo não suportado, ignora ou loga
        }
    }

    /**
     * Lê os candles de UM arquivo Excel e adiciona na lista passada.
     * (É basicamente o seu código original, só movido para cá)
     */

    private void lerCandlesDeArquivoExcel(Path arquivoExcel, List<Candle> candles) throws IOException {
        try (FileInputStream fis = new FileInputStream(arquivoExcel.toFile());
             Workbook workbook = new XSSFWorkbook(fis)) {

            int numberOfSheets = workbook.getNumberOfSheets();
           
            // LER APENAS OS ATIVOS
            List<String> ativos = new ArrayList<String>();
            for (int i = 0; i < numberOfSheets; i++) {
                Sheet sheet = workbook.getSheetAt(i);
                if (sheet.getSheetName().equals(sheetName)) {
                        boolean firstRow = true;
       
                        for (Row row : sheet) {
                            if (firstRow) {
                                firstRow = false; // pula o cabeçalho
                                continue;
                            }
                           
                            Cell ativoCell = row.getCell(1);
                            if (VerificadorUtil.naoEstaNulo(ativoCell)) {
                                String ativoString = ativoCell.getStringCellValue();
                                if (VerificadorUtil.naoEstaNuloOuVazio(ativoString)) {
                                        if (!ativos.contains(ativoString)) {
                                                ativos.add(ativoString);
                                        }
                                }
                            }
                        }
                }
            }
           
            for (String ativo : ativos) {
                    for (int i = 0; i < numberOfSheets; i++) {
                        Sheet sheet = workbook.getSheetAt(i);
                        if (sheet.getSheetName().equals(sheetName)) {
                                boolean firstRow = true;
               
                                for (Row row : sheet) {
                                    if (firstRow) {
                                        firstRow = false; // pula o cabeçalho
                                        continue;
                                    }
                                   
                                    // 0 = Contador
                                    // 1 = Ativo
                                    // 2 = Dia
                                    // 3 = Hora
                                    // 4 = Abertura
                                    // 5 = Máxima
                                    // 6 = Mínima
                                    // 7 = Fechamento
               
                                    Cell contadorCell   = row.getCell(0);
                                    Cell ativoCell      = row.getCell(1);
                                    Cell dataCell       = row.getCell(2);
                                    Cell horaCell       = row.getCell(3);
                                    Cell aberturaCell   = row.getCell(4);
                                    Cell maximaCell     = row.getCell(5);
                                    Cell minimaCell     = row.getCell(6);
                                    Cell fechamentoCell = row.getCell(7);
                                    Cell finalizadoCell = row.getCell(8);
               
                                    if (!ExcelDataUtils.isNumeric(aberturaCell) || !ExcelDataUtils.isNumeric(maximaCell)
                                                || !ExcelDataUtils.isNumeric(minimaCell) || !ExcelDataUtils.isNumeric(fechamentoCell)) {
                                        continue;
                                    }
                                   
                                    String ativoDescricao = ativoCell.getStringCellValue();
                                    if (!ativo.equals(ativoDescricao)) {
                                        continue;
                                    }
                                   
                                    Integer contador = BigDecimal.valueOf(contadorCell.getNumericCellValue()).intValue();
                                   
                                    LocalDate data = ExcelDataUtils.lerData(dataCell);
                                    LocalTime hora = ExcelDataUtils.lerHora(horaCell);
                                    LocalDateTime dataHora = LocalDateTime.of(data, hora);
               
                                    BigDecimal abertura = BigDecimal.valueOf(aberturaCell.getNumericCellValue());
                                    BigDecimal topo = BigDecimal.valueOf(maximaCell.getNumericCellValue());
                                    BigDecimal fundo = BigDecimal.valueOf(minimaCell.getNumericCellValue());
                                    BigDecimal fechamento = BigDecimal.valueOf(fechamentoCell.getNumericCellValue());
                                   
                                    String finalizado = finalizadoCell.getStringCellValue();
                                    if (finalizado.equals("S")) {
                                        Candle candle = new Candle(contador, ativoDescricao, dataHora, abertura, topo, fundo, fechamento, TipoPeriodoCandle.M1.getValor());
                                        candles.add(candle);
                                    }
                                }
                        }
                    }
            }
        } catch (EncryptedDocumentException e) {
            e.printStackTrace();
        }
    }
   
    /**
     * Lê os candles de UM arquivo CSV e adiciona na lista passada.
     * Espera layout:
     * 0 = Ativo
     * 1 = Dia  (dd/MM/yyyy)
     * 2 = Hora (HH:mm:ss)
     * 3 = Abertura
     * 4 = Máxima
     * 5 = Mínima
     * 6 = Fechamento
     */

    private void lerCandlesDeArquivoCsv(Path arquivoCsv, List<Candle> candles) throws IOException {
        try (BufferedReader br = Files.newBufferedReader(arquivoCsv, StandardCharsets.UTF_8)) {
            String line;
            while ((line = br.readLine()) != null) {

                // Substitui line.isBlank() por trim().isEmpty()
                String trimmed = line.trim();
                if (trimmed.isEmpty()) {
                    continue;
                }

                // Ajuste aqui se o separador do seu CSV for vírgula
                String[] parts = trimmed.split(";", -1);
                if (parts.length < 7) {
                    continue;
                }
               
                String ativoDescricao = "";
                String dataStr        = "";
                String horaStr        = "";
                String aberturaStr    = "";
                String maximaStr      = "";
                String minimaStr      = "";
                String fechamentoStr  = "";
               
                ativoDescricao = parts[0].trim();
                dataStr        = parts[1].trim();
                if (parts.length >= 9) {
                        horaStr        = parts[2].trim();
                        aberturaStr    = parts[3].trim();
                        maximaStr      = parts[4].trim();
                        minimaStr      = parts[5].trim();
                        fechamentoStr  = parts[6].trim();
                } else {
                        horaStr        = "18:00:00";
                        aberturaStr    = parts[2].trim();
                        maximaStr      = parts[3].trim();
                        minimaStr      = parts[4].trim();
                        fechamentoStr  = parts[5].trim();
                }

                // Ignora header, caso exista
                if (ativoDescricao.equalsIgnoreCase("ativo")) {
                    continue;
                }

                if (!isNumericString(aberturaStr) ||
                    !isNumericString(maximaStr)   ||
                    !isNumericString(minimaStr)   ||
                    !isNumericString(fechamentoStr)) {
                    continue;
                }

                LocalDate data = LocalDate.parse(dataStr, DATE_FORMAT_CSV);
                LocalTime hora = LocalTime.parse(horaStr, TIME_FORMAT_CSV);
                LocalDateTime dataHora = LocalDateTime.of(data, hora);

                BigDecimal abertura   = BigDecimalUtils.converterStringEmBigDecimal(aberturaStr);
                BigDecimal topo       = BigDecimalUtils.converterStringEmBigDecimal(maximaStr);
                BigDecimal fundo      = BigDecimalUtils.converterStringEmBigDecimal(minimaStr);
                BigDecimal fechamento = BigDecimalUtils.converterStringEmBigDecimal(fechamentoStr);

                Candle candle = new Candle(
                        null,
                        ativoDescricao,
                        dataHora,
                        abertura,
                        topo,
                        fundo,
                        fechamento,
                        TipoPeriodoCandle.M1.getValor()
                );
                candles.add(candle);
            }
        }
   
       
    }
   
    private boolean isNumericString(String value) {
        if (value == null) return false;
        String normalized = value.trim().replace(".", "").replace(",", ".");
        if (normalized.isEmpty()) return false;
        try {
            new BigDecimal(normalized);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    public static List<Candle> inverterLista(List<Candle> candles) {
        List<Candle> invertida = new ArrayList<>(candles);
        Collections.reverse(invertida);
        return invertida;
    }

    // Contador separado para cada ativo iniciando pelo primeiro contador encontrado
    public static List<Candle> adicionarContadores(List<Candle> candles) {
        Map<String, Integer> contadorPorAtivo = new HashMap<>();
        List<Candle> comContadores = new ArrayList<>();

        for (Candle candle : candles) {
            String ativo = candle.getNomeAtivo();

            // Se for o primeiro candle do ativo, usar o contador original dele como ponto de partida
            if (!contadorPorAtivo.containsKey(ativo)) {
                int contadorInicial = candle.getContadorCandle() != null
                        ? candle.getContadorCandle()
                        : 1;  // fallback, se vier nulo
                contadorPorAtivo.put(ativo, contadorInicial);
                candle.setContadorCandle(contadorInicial);
                comContadores.add(candle);
                continue;
            }

            // Se não é o primeiro candle do ativo, incrementar baseado no último
            int proximoContador = contadorPorAtivo.get(ativo) + 1;
            contadorPorAtivo.put(ativo, proximoContador);
            candle.setContadorCandle(proximoContador);

            comContadores.add(candle);
        }

        return comContadores;
    }

   
    /**
     * 1 minuto = 1, 5 minutos = 2, 15 minutos = 3, 1 dia = 4
     */

    private Timeframe resolveTipoTemporizador(String sheetName) {
        if (sheetName == null) return null;

        String name = sheetName.toUpperCase(Locale.ROOT);

        if (name.startsWith("1 MIN"))  return Timeframe.M1;
        if (name.startsWith("5 MIN"))  return Timeframe.M5;
        if (name.startsWith("15 MIN")) return Timeframe.M15;
        if (name.startsWith("1 DIA"))  return Timeframe.D1;

        return null;
    }

}