Subversion Repositories Integrator Subversion

Rev

Rev 782 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
760 blopes 1
package br.com.sl.core;
2
 
3
import java.io.FileInputStream;
4
import java.io.IOException;
5
import java.math.BigDecimal;
779 blopes 6
import java.nio.file.Files;
760 blopes 7
import java.nio.file.Path;
8
import java.time.LocalDate;
9
import java.time.LocalDateTime;
10
import java.time.LocalTime;
11
import java.time.format.DateTimeFormatter;
764 blopes 12
import java.util.ArrayList;
13
import java.util.Collections;
782 blopes 14
import java.util.HashMap;
761 blopes 15
import java.util.List;
764 blopes 16
import java.util.Locale;
760 blopes 17
import java.util.Map;
779 blopes 18
import java.util.stream.Stream;
760 blopes 19
 
764 blopes 20
import org.apache.poi.EncryptedDocumentException;
760 blopes 21
import org.apache.poi.ss.usermodel.Cell;
22
import org.apache.poi.ss.usermodel.Row;
23
import org.apache.poi.ss.usermodel.Sheet;
24
import org.apache.poi.ss.usermodel.Workbook;
25
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
26
 
782 blopes 27
import br.com.ec.core.util.VerificadorUtil;
764 blopes 28
import br.com.kronus.core.Timeframe;
760 blopes 29
import br.com.sl.domain.dto.robo.ProfitTick;
761 blopes 30
import br.com.sl.domain.model.Candle;
764 blopes 31
import br.com.sl.domain.model.tipos.TipoPeriodoCandle;
767 blopes 32
import br.com.sl.shared.ExcelDataUtils;
760 blopes 33
 
34
public class ExcelProfitDataProvider implements ProfitDataProvider {
35
 
764 blopes 36
        private final Path excelFile;
760 blopes 37
    private final String sheetName;
38
 
39
    // índices de coluna (0 = A, 1 = B, etc.)
40
    private final int colAsset = 0;
41
    private final int colDate  = 1;
42
    private final int colTime  = 2;
43
    private final int colLast  = 3;
44
 
779 blopes 45
    private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss");
46
    private static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss");
760 blopes 47
 
48
    public ExcelProfitDataProvider(Path excelFile, String sheetName) {
49
        this.excelFile = excelFile;
50
        this.sheetName = sheetName;
51
    }
764 blopes 52
 
53
    /**
779 blopes 54
     * Lê um ou vários arquivos:
55
     * - Se excelFile for um arquivo: lê apenas esse arquivo (.xlsx, .xls ou .csv)
56
     * - Se excelFile for uma pasta: lê todos os .xlsx, .xls e .csv da pasta.
764 blopes 57
     */
58
    public List<Candle> lerCandles() throws IOException {
59
        List<Candle> candles = new ArrayList<>();
760 blopes 60
 
779 blopes 61
        if (Files.isDirectory(excelFile)) {
62
            // Percorre todos os arquivos da pasta
63
            try (Stream<Path> stream = Files.list(excelFile)) {
64
                stream
65
                    .filter(Files::isRegularFile)
66
                    .filter(p -> {
67
                        String name = p.getFileName().toString().toLowerCase(Locale.ROOT);
68
                        return name.endsWith(".xlsm") || name.endsWith(".xlsx") || name.endsWith(".xls") || name.endsWith(".csv");
69
                    })
70
                    .forEach(path -> {
71
                        try {
72
                            lerCandlesDeArquivo(path, candles);
73
                        } catch (IOException e) {
74
                            // aqui você pode trocar por log
75
                            e.printStackTrace();
76
                        }
77
                    });
78
            }
79
        } else {
80
            // Apenas um arquivo
81
            lerCandlesDeArquivo(excelFile, candles);
82
        }
83
 
84
        return adicionarContadores(candles);
85
    }
86
 
87
    /**
88
     * Decide se o arquivo é Excel ou CSV e delega para o método correto.
89
     */
90
    private void lerCandlesDeArquivo(Path arquivo, List<Candle> candles) throws IOException {
91
        String name = arquivo.getFileName().toString().toLowerCase(Locale.ROOT);
92
 
93
        if (name.endsWith(".xlsm") || name.endsWith(".xlsx") || name.endsWith(".xls")) {
94
            lerCandlesDeArquivoExcel(arquivo, candles);
95
        } else if (name.endsWith(".csv")) {
96
//            lerCandlesDeArquivoCsv(arquivo, candles);
97
        } else {
98
            // Tipo não suportado, ignora ou loga
99
        }
100
    }
101
 
102
    /**
103
     * Lê os candles de UM arquivo Excel e adiciona na lista passada.
104
     * (É basicamente o seu código original, só movido para cá)
105
     */
106
    private void lerCandlesDeArquivoExcel(Path arquivoExcel, List<Candle> candles) throws IOException {
107
        try (FileInputStream fis = new FileInputStream(arquivoExcel.toFile());
108
             Workbook workbook = new XSSFWorkbook(fis)) {
109
 
764 blopes 110
            int numberOfSheets = workbook.getNumberOfSheets();
779 blopes 111
 
112
            // LER APENAS OS ATIVOS
113
            List<String> ativos = new ArrayList<String>();
764 blopes 114
            for (int i = 0; i < numberOfSheets; i++) {
115
                Sheet sheet = workbook.getSheetAt(i);
116
                if (sheet.getSheetName().equals(sheetName)) {
117
                        boolean firstRow = true;
118
 
119
                        for (Row row : sheet) {
120
                            if (firstRow) {
121
                                firstRow = false; // pula o cabeçalho
122
                                continue;
123
                            }
124
 
782 blopes 125
                            Cell ativoCell = row.getCell(1);
126
                            if (VerificadorUtil.naoEstaNulo(ativoCell)) {
127
                                String ativoString = ativoCell.getStringCellValue();
128
                                if (VerificadorUtil.naoEstaNuloOuVazio(ativoString)) {
129
                                        if (!ativos.contains(ativoString)) {
130
                                                ativos.add(ativoString);
131
                                        }
132
                                }
764 blopes 133
                            }
134
                        }
760 blopes 135
                }
136
            }
779 blopes 137
 
138
            for (String ativo : ativos) {
139
                    for (int i = 0; i < numberOfSheets; i++) {
140
                        Sheet sheet = workbook.getSheetAt(i);
141
                        if (sheet.getSheetName().equals(sheetName)) {
142
                                boolean firstRow = true;
143
 
144
                                for (Row row : sheet) {
145
                                    if (firstRow) {
146
                                        firstRow = false; // pula o cabeçalho
147
                                        continue;
148
                                    }
149
 
150
                                    // 0 = Contador
151
                                    // 1 = Ativo
152
                                    // 2 = Dia
153
                                    // 3 = Hora
154
                                    // 4 = Abertura
155
                                    // 5 = Máxima
156
                                    // 6 = Mínima
157
                                    // 7 = Fechamento
158
 
159
                                    Cell contadorCell   = row.getCell(0);
160
                                    Cell ativoCell      = row.getCell(1);
161
                                    Cell dataCell       = row.getCell(2);
162
                                    Cell horaCell       = row.getCell(3);
163
                                    Cell aberturaCell   = row.getCell(4);
164
                                    Cell maximaCell     = row.getCell(5);
165
                                    Cell minimaCell     = row.getCell(6);
166
                                    Cell fechamentoCell = row.getCell(7);
167
                                    Cell finalizadoCell = row.getCell(8);
168
 
169
                                    if (!ExcelDataUtils.isNumeric(aberturaCell) || !ExcelDataUtils.isNumeric(maximaCell)
782 blopes 170
                                                || !ExcelDataUtils.isNumeric(minimaCell) || !ExcelDataUtils.isNumeric(fechamentoCell)) {
779 blopes 171
                                        continue;
172
                                    }
173
 
782 blopes 174
                                    String ativoDescricao = ativoCell.getStringCellValue();
175
                                    if (!ativo.equals(ativoDescricao)) {
176
                                        continue;
177
                                    }
178
 
779 blopes 179
                                    Integer contador = BigDecimal.valueOf(contadorCell.getNumericCellValue()).intValue();
180
 
181
                                    LocalDate data = ExcelDataUtils.lerData(dataCell);
182
                                    LocalTime hora = ExcelDataUtils.lerHora(horaCell);
183
                                    LocalDateTime dataHora = LocalDateTime.of(data, hora);
184
 
185
                                    BigDecimal abertura = BigDecimal.valueOf(aberturaCell.getNumericCellValue());
186
                                    BigDecimal topo = BigDecimal.valueOf(maximaCell.getNumericCellValue());
187
                                    BigDecimal fundo = BigDecimal.valueOf(minimaCell.getNumericCellValue());
188
                                    BigDecimal fechamento = BigDecimal.valueOf(fechamentoCell.getNumericCellValue());
189
 
190
                                    String finalizado = finalizadoCell.getStringCellValue();
191
                                    if (finalizado.equals("S")) {
192
                                        Candle candle = new Candle(contador, ativoDescricao, dataHora, abertura, topo, fundo, fechamento, TipoPeriodoCandle.M1.getValor());
193
                                        candles.add(candle);
194
                                    }
195
                                }
196
                        }
197
                    }
198
            }
764 blopes 199
        } catch (EncryptedDocumentException e) {
779 blopes 200
            e.printStackTrace();
201
        }
764 blopes 202
    }
203
 
779 blopes 204
    /**
205
     * Lê os candles de UM arquivo CSV e adiciona na lista passada.
206
     * Espera layout:
207
     * 0 = Ativo
208
     * 1 = Dia  (dd/MM/yyyy)
209
     * 2 = Hora (HH:mm:ss)
210
     * 3 = Abertura
211
     * 4 = Máxima
212
     * 5 = Mínima
213
     * 6 = Fechamento
214
     */
215
    private void lerCandlesDeArquivoCsv(Path arquivoCsv, List<Candle> candles) throws IOException {}
216
 
217
    private boolean isNumericString(String value) {
218
        if (value == null) return false;
219
        String normalized = value.trim().replace(".", "").replace(",", ".");
220
        if (normalized.isEmpty()) return false;
221
        try {
222
            new BigDecimal(normalized);
223
            return true;
224
        } catch (NumberFormatException e) {
225
            return false;
226
        }
227
    }
228
 
764 blopes 229
    public static List<Candle> inverterLista(List<Candle> candles) {
230
        List<Candle> invertida = new ArrayList<>(candles);
231
        Collections.reverse(invertida);
232
        return invertida;
233
    }
760 blopes 234
 
782 blopes 235
    // Contador separado para cada ativo iniciando pelo primeiro contador encontrado
764 blopes 236
    public static List<Candle> adicionarContadores(List<Candle> candles) {
782 blopes 237
        Map<String, Integer> contadorPorAtivo = new HashMap<>();
779 blopes 238
        List<Candle> comContadores = new ArrayList<>();
239
 
764 blopes 240
        for (Candle candle : candles) {
779 blopes 241
            String ativo = candle.getNomeAtivo();
242
 
782 blopes 243
            // Se for o primeiro candle do ativo, usar o contador original dele como ponto de partida
244
            if (!contadorPorAtivo.containsKey(ativo)) {
245
                int contadorInicial = candle.getContadorCandle() != null
246
                        ? candle.getContadorCandle()
247
                        : 1;  // fallback, se vier nulo
248
                contadorPorAtivo.put(ativo, contadorInicial);
249
                candle.setContadorCandle(contadorInicial);
250
                comContadores.add(candle);
251
                continue;
779 blopes 252
            }
253
 
782 blopes 254
            // Se não é o primeiro candle do ativo, incrementar baseado no último
255
            int proximoContador = contadorPorAtivo.get(ativo) + 1;
256
            contadorPorAtivo.put(ativo, proximoContador);
257
            candle.setContadorCandle(proximoContador);
258
 
779 blopes 259
            comContadores.add(candle);
760 blopes 260
        }
782 blopes 261
 
764 blopes 262
        return comContadores;
760 blopes 263
    }
782 blopes 264
 
764 blopes 265
 
266
    /**
267
     * 1 minuto = 1, 5 minutos = 2, 15 minutos = 3, 1 dia = 4
268
     */
269
    private Timeframe resolveTipoTemporizador(String sheetName) {
270
        if (sheetName == null) return null;
271
 
272
        String name = sheetName.toUpperCase(Locale.ROOT);
273
 
274
        if (name.startsWith("1 MIN"))  return Timeframe.M1;
275
        if (name.startsWith("5 MIN"))  return Timeframe.M5;
276
        if (name.startsWith("15 MIN")) return Timeframe.M15;
277
        if (name.startsWith("1 DIA"))  return Timeframe.D1;
278
 
279
        return null;
280
    }
281
 
760 blopes 282
}