Subversion Repositories Integrator Subversion

Rev

Rev 761 | Rev 767 | 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;
6
import java.nio.file.Path;
7
import java.time.LocalDate;
8
import java.time.LocalDateTime;
9
import java.time.LocalTime;
764 blopes 10
import java.time.ZoneId;
760 blopes 11
import java.time.format.DateTimeFormatter;
764 blopes 12
import java.util.ArrayList;
13
import java.util.Collections;
14
import java.util.Date;
760 blopes 15
import java.util.HashMap;
761 blopes 16
import java.util.List;
764 blopes 17
import java.util.Locale;
760 blopes 18
import java.util.Map;
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.CellType;
23
import org.apache.poi.ss.usermodel.DateUtil;
24
import org.apache.poi.ss.usermodel.Row;
25
import org.apache.poi.ss.usermodel.Sheet;
26
import org.apache.poi.ss.usermodel.Workbook;
27
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
28
 
764 blopes 29
import br.com.kronus.core.Timeframe;
760 blopes 30
import br.com.sl.domain.dto.robo.ProfitTick;
761 blopes 31
import br.com.sl.domain.model.Candle;
764 blopes 32
import br.com.sl.domain.model.tipos.TipoPeriodoCandle;
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
 
45
    // formatos da data e hora, conforme Excel
46
    private final DateTimeFormatter fmtData = DateTimeFormatter.ofPattern("dd/MM/yyyy");
47
    private final DateTimeFormatter fmtHora = DateTimeFormatter.ofPattern("HH:mm:ss");
764 blopes 48
 
49
    private static final DateTimeFormatter STRING_DATA_FORMATTER = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss");
50
    private static final DateTimeFormatter STRING_DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss");
760 blopes 51
 
52
    public ExcelProfitDataProvider(Path excelFile, String sheetName) {
53
        this.excelFile = excelFile;
54
        this.sheetName = sheetName;
55
    }
764 blopes 56
 
760 blopes 57
    @Override
58
    public Map<String, ProfitTick> readCurrentTicks() {
764 blopes 59
        // TODO Auto-generated method stub
60
        return null;
61
    }
62
 
63
    /**
64
     * Lê o arquivo Excel dentro do resources.
65
     * Exemplo de uso:
66
     *    lerCandles("/dados/Dados Trade 20251117.xlsx");
67
     * @throws IOException
68
     */
69
    public List<Candle> lerCandles() throws IOException {
70
        List<Candle> candles = new ArrayList<>();
760 blopes 71
 
72
        try (FileInputStream fis = new FileInputStream(excelFile.toFile()); Workbook workbook = new XSSFWorkbook(fis)) {
764 blopes 73
            int numberOfSheets = workbook.getNumberOfSheets();
760 blopes 74
 
764 blopes 75
            for (int i = 0; i < numberOfSheets; i++) {
76
                Sheet sheet = workbook.getSheetAt(i);
77
                if (sheet.getSheetName().equals(sheetName)) {
78
                        boolean firstRow = true;
79
 
80
                        for (Row row : sheet) {
81
                            if (firstRow) {
82
                                firstRow = false; // pula o cabeçalho
83
                                continue;
84
                            }
85
 
86
                            // 0 = Contador
87
                            // 0 = Ativo
88
                            // 1 = Dia
89
                            // 2 = Hora
90
                            // 3 = Abertura
91
                            // 4 = Máxima
92
                            // 5 = Mínima
93
                            // 6 = Fechamento
94
                            // 7 = Volume
95
                            // 8 = ...
96
 
97
                            Cell contadorCell   = row.getCell(0);
98
                            Cell ativoCell      = row.getCell(1);
99
                            Cell dataCell       = row.getCell(2);
100
                            Cell horaCell       = row.getCell(3);
101
                            Cell aberturaCell   = row.getCell(4);
102
                            Cell maximaCell     = row.getCell(5);
103
                            Cell minimaCell     = row.getCell(6);
104
                            Cell fechamentoCell = row.getCell(7);
105
                            Cell finalizadoCell = row.getCell(8);
106
 
107
                            if (!isNumeric(aberturaCell) || !isNumeric(maximaCell)
108
                                        || !isNumeric(minimaCell) || !isNumeric(fechamentoCell)) {
109
                                continue;
110
                            }
111
 
112
                            Integer contador = BigDecimal.valueOf(contadorCell.getNumericCellValue()).intValue();
113
                            String ativoDescricao = ativoCell.getStringCellValue();
114
 
115
        //                    String data = dataCell.getStringCellValue();
116
        //                    String hora = horaCell.getStringCellValue();
117
 
118
                            LocalDate data = lerData(dataCell);
119
                            LocalTime hora = lerHora(horaCell);
120
                            LocalDateTime dataHora = LocalDateTime.of(data, hora);
121
 
122
        //                    Date data = diaCell.getDateCellValue();
123
        //                    String dia = new SimpleDateFormat("dd/MM/yyyy").format(data);
124
        //                    String hora = horaCell.getStringCellValue();
125
        //                    LocalDateTime time = getLocalDateTime(dia + " " + hora, STRING_DATA_FORMATTER);
126
                            BigDecimal abertura = BigDecimal.valueOf(aberturaCell.getNumericCellValue());
127
                            BigDecimal topo = BigDecimal.valueOf(maximaCell.getNumericCellValue());
128
                            BigDecimal fundo = BigDecimal.valueOf(minimaCell.getNumericCellValue());
129
                            BigDecimal fechamento = BigDecimal.valueOf(fechamentoCell.getNumericCellValue());
130
 
131
                            String finalizado = finalizadoCell.getStringCellValue();
132
                            if (finalizado.equals("S")) {
133
                                Candle candle = new Candle(contador, ativoDescricao, dataHora, abertura, topo, fundo, fechamento, TipoPeriodoCandle.M1.getValor());
134
                                candles.add(candle);
135
                            }
136
                        }
760 blopes 137
                }
138
            }
764 blopes 139
        } catch (EncryptedDocumentException e) {
140
                        // TODO Auto-generated catch block
141
                        e.printStackTrace();
142
                }
143
//        return adicionarContadores(inverterLista(candles));
144
        return candles;
145
    }
146
 
147
    public static List<Candle> inverterLista(List<Candle> candles) {
148
        List<Candle> invertida = new ArrayList<>(candles);
149
        Collections.reverse(invertida);
150
        return invertida;
151
    }
760 blopes 152
 
764 blopes 153
    public static List<Candle> adicionarContadores(List<Candle> candles) {
154
        Integer contador = 1;
155
        List<Candle> comContadores = new ArrayList<>();
156
        for (Candle candle : candles) {
157
                candle.setContadorCandle(contador);
158
                comContadores.add(candle);
159
                contador++;
760 blopes 160
        }
764 blopes 161
        return comContadores;
760 blopes 162
    }
764 blopes 163
 
760 blopes 164
    private LocalDate lerData(Cell cell) {
165
        if (cell == null) return null;
166
 
167
        try {
168
            int t = cell.getCellType();
169
 
170
            // 1) Se for fórmula RTD
171
            if (t == CellType.FORMULA.getCode()) {
172
                int ct = cell.getCachedFormulaResultType();
173
 
174
                if (ct == CellType.NUMERIC.getCode()) {
175
                    double dv = cell.getNumericCellValue();
176
                    java.util.Date d = DateUtil.getJavaDate(dv);
177
                    return d.toInstant()
178
                            .atZone(java.time.ZoneId.systemDefault())
179
                            .toLocalDate();
180
                }
181
 
182
                if (ct == CellType.STRING.getCode()) {
183
                    String text = cell.getStringCellValue().trim();
184
                    if (text.isEmpty()) return null;
185
 
186
                    DateTimeFormatter[] patterns = {
187
                            DateTimeFormatter.ofPattern("dd/MM/yyyy"),
188
                            DateTimeFormatter.ofPattern("dd-MM-yyyy"),
189
                            DateTimeFormatter.ofPattern("yyyy-MM-dd"),
190
                            DateTimeFormatter.ofPattern("yyyy/MM/dd")
191
                    };
192
 
193
                    for (DateTimeFormatter p : patterns) {
194
                        try {
195
                            return LocalDate.parse(text, p);
196
                        } catch (Exception ignored) {}
197
                    }
198
                }
199
            }
200
 
201
            // 2) Se for numérico formatado como data
202
            if (t == CellType.NUMERIC.getCode() && DateUtil.isCellDateFormatted(cell)) {
203
                java.util.Date d = cell.getDateCellValue();
204
                return d.toInstant()
205
                        .atZone(java.time.ZoneId.systemDefault())
206
                        .toLocalDate();
207
            }
208
 
209
            // 3) Se vier como texto
210
            String text = cell.toString().trim();
211
            if (text.isEmpty()) return null;
212
 
213
            DateTimeFormatter[] patterns = {
214
                    DateTimeFormatter.ofPattern("dd/MM/yyyy"),
215
                    DateTimeFormatter.ofPattern("dd-MM-yyyy"),
216
                    DateTimeFormatter.ofPattern("yyyy-MM-dd"),
217
                    DateTimeFormatter.ofPattern("yyyy/MM/dd")
218
            };
219
 
220
            for (DateTimeFormatter p : patterns) {
221
                try {
222
                    return LocalDate.parse(text, p);
223
                } catch (Exception ignored) {}
224
            }
225
 
226
        } catch (Exception e) {
227
            System.out.println("[lerData] erro: " + e.getMessage());
228
        }
229
 
230
        return null;
231
    }
232
 
233
 
234
    private LocalTime lerHora(Cell cell) {
235
        if (cell == null) return null;
236
 
237
        try {
238
            // 1) Fórmula RTD
239
            if (cell.getCellType() == CellType.FORMULA.getCode()) {
240
 
241
                if (cell.getCachedFormulaResultType() == CellType.NUMERIC.getCode()) {
242
                    java.util.Date d = DateUtil.getJavaDate(cell.getNumericCellValue());
243
                    return d.toInstant()
244
                            .atZone(java.time.ZoneId.systemDefault())
245
                            .toLocalTime();
246
                }
247
 
248
                if (cell.getCachedFormulaResultType() == CellType.STRING.getCode()) {
249
                    String text = cell.getStringCellValue().trim();
250
                    if (text.isEmpty()) return null;
251
 
252
                    DateTimeFormatter[] patterns = {
253
                            DateTimeFormatter.ofPattern("HH:mm:ss"),
254
                            DateTimeFormatter.ofPattern("H:mm:ss"),
255
                            DateTimeFormatter.ofPattern("HH:mm"),
256
                            DateTimeFormatter.ofPattern("H:mm")
257
                    };
258
 
259
                    for (DateTimeFormatter p : patterns) {
260
                        try { return LocalTime.parse(text, p); }
261
                        catch (Exception ignored) {}
262
                    }
263
                }
264
            }
265
 
266
            // 2) Numérico com formato de data/hora
267
            if (cell.getCellType() == CellType.NUMERIC.getCode() && DateUtil.isCellDateFormatted(cell)) {
268
                java.util.Date d = cell.getDateCellValue();
269
                return d.toInstant()
270
                        .atZone(java.time.ZoneId.systemDefault())
271
                        .toLocalTime();
272
            }
273
 
274
            // 3) Texto simples
275
            String text = cell.toString().trim();
276
            if (text.isEmpty()) return null;
277
 
278
            DateTimeFormatter[] patterns = {
279
                    DateTimeFormatter.ofPattern("HH:mm:ss"),
280
                    DateTimeFormatter.ofPattern("H:mm:ss"),
281
                    DateTimeFormatter.ofPattern("HH:mm"),
282
                    DateTimeFormatter.ofPattern("H:mm")
283
            };
284
 
285
            for (DateTimeFormatter p : patterns) {
286
                try { return LocalTime.parse(text, p); }
287
                catch (Exception ignored) {}
288
            }
289
 
290
        } catch (Exception e) {
291
            System.out.println("[lerHora] erro: " + e.getMessage());
292
        }
293
 
294
        return null;
295
    }
296
 
297
 
298
    private BigDecimal lerPreco(Cell cell) {
299
        if (cell == null) return null;
300
 
301
        try {
302
            // 1) Fórmula RTD
303
            if (cell.getCellType() == CellType.FORMULA.getCode()) {
304
 
305
                if (cell.getCachedFormulaResultType() == CellType.NUMERIC.getCode()) {
306
                    return BigDecimal.valueOf(cell.getNumericCellValue());
307
                }
308
 
309
                if (cell.getCachedFormulaResultType() == CellType.STRING.getCode()) {
310
                    String text = cell.getStringCellValue().trim();
311
                    if (text.isEmpty()) return null;
312
                    text = text.replace(".", "").replace(",", ".");
313
                    return new BigDecimal(text);
314
                }
315
            }
316
 
317
            // 2) Numérico simples
318
            if (cell.getCellType() == CellType.NUMERIC.getCode()) {
319
                return BigDecimal.valueOf(cell.getNumericCellValue());
320
            }
321
 
322
            // 3) Texto
323
            String text = cell.toString().trim();
324
            if (text.isEmpty()) return null;
325
 
326
            text = text.replace(".", "").replace(",", ".");
327
            return new BigDecimal(text);
328
 
329
        } catch (Exception e) {
330
            System.out.println("[lerPreco] erro: " + e.getMessage());
331
        }
332
 
333
        return null;
334
    }
764 blopes 335
 
336
    /*
337
    public List<Candle> lerCandles(String resourcePath, Timeframe selecionarTipoTemporizador) throws IOException {
338
        List<Candle> candles = new ArrayList<>();
760 blopes 339
 
764 blopes 340
        // Arquivo dentro de src/main/resources
341
        InputStream is = getClass().getResourceAsStream(resourcePath);
342
        if (is == null) {
343
            throw new IOException("Arquivo não encontrado no resources: " + resourcePath);
344
        }
345
 
346
        try (Workbook workbook = WorkbookFactory.create(is)) {
347
 
348
            int numberOfSheets = workbook.getNumberOfSheets();
349
 
350
            for (int i = 0; i < numberOfSheets; i++) {
351
 
352
                Sheet sheet = workbook.getSheetAt(i);
353
                String sheetName = sheet.getSheetName();
354
 
355
                Timeframe tipoTemporizador = resolveTipoTemporizador(sheetName);
356
                if (tipoTemporizador == selecionarTipoTemporizador) {
357
                        boolean firstRow = true;
358
 
359
                        for (Row row : sheet) {
360
                            if (firstRow) {
361
                                firstRow = false; // pula o cabeçalho
362
                                continue;
363
                            }
364
 
365
                            // 0 = Data (data+hora)
366
                            // 1 = Abertura
367
                            // 2 = Máxima
368
                            // 3 = Mínima
369
                            // 4 = Fechamento
370
 
371
                            Cell dataCell       = row.getCell(0);
372
                            Cell aberturaCell   = row.getCell(1);
373
                            Cell maximaCell     = row.getCell(2);
374
                            Cell minimaCell     = row.getCell(3);
375
                            Cell fechamentoCell = row.getCell(4);
376
 
377
                            if (!isNumeric(aberturaCell) || !isNumeric(maximaCell)
378
                                    || !isNumeric(minimaCell) || !isNumeric(fechamentoCell)) {
379
                                // linha vazia ou inválida
380
                                continue;
381
                            }
382
 
383
                            LocalDateTime time = getLocalDateTime(dataCell, STRING_DATE_TIME_FORMATTER);
384
                            if (time == null) {
385
                                // se não conseguir converter a data/hora, pode pular ou manter null
386
                                // aqui vou pular para evitar candle "incompleto"
387
                                continue;
388
                            }
389
 
390
                            BigDecimal abertura = BigDecimal.valueOf(aberturaCell.getNumericCellValue());
391
                            BigDecimal topo = BigDecimal.valueOf(maximaCell.getNumericCellValue());
392
                            BigDecimal fundo = BigDecimal.valueOf(minimaCell.getNumericCellValue());
393
                            BigDecimal fechamento = BigDecimal.valueOf(fechamentoCell.getNumericCellValue());
394
 
395
                            Candle candle = new Candle(time, abertura, topo, fundo, fechamento, TipoPeriodoCandle.M1.getValor());
396
                            candles.add(candle);
397
                        }
398
                }
399
            }
400
        } catch (EncryptedDocumentException e) {
401
                        // TODO Auto-generated catch block
402
                        e.printStackTrace();
403
                } catch (InvalidFormatException e) {
404
                        // TODO Auto-generated catch block
405
                        e.printStackTrace();
406
                }
407
 
408
        return candles;
761 blopes 409
    }
764 blopes 410
    */
760 blopes 411
 
764 blopes 412
    /**
413
     * 1 minuto = 1, 5 minutos = 2, 15 minutos = 3, 1 dia = 4
414
     */
415
    private Timeframe resolveTipoTemporizador(String sheetName) {
416
        if (sheetName == null) return null;
417
 
418
        String name = sheetName.toUpperCase(Locale.ROOT);
419
 
420
        if (name.startsWith("1 MIN"))  return Timeframe.M1;
421
        if (name.startsWith("5 MIN"))  return Timeframe.M5;
422
        if (name.startsWith("15 MIN")) return Timeframe.M15;
423
        if (name.startsWith("1 DIA"))  return Timeframe.D1;
424
 
425
        return null;
426
    }
427
 
428
    private boolean isNumeric(Cell cell) {
429
        if (cell == null) return false;
430
 
431
        if (cell.getCellType() == CellType.NUMERIC.getCode()) {
432
            return true;
433
        }
434
 
435
        if (cell.getCellType() == CellType.STRING.getCode()) {
436
            try {
437
                Double.parseDouble(cell.getStringCellValue().replace(",", "."));
438
                return true;
439
            } catch (NumberFormatException e) {
440
                return false;
441
            }
442
        }
443
 
444
        return false;
445
    }
446
 
447
    /**
448
     * Converte a célula de data/hora do Excel para LocalDateTime.
449
     */
450
    private LocalDateTime getLocalDateTime(Cell cell, DateTimeFormatter formatacaoDataTime) {
451
        if (cell == null) {
452
            return null;
453
        }
454
 
455
        // Caso seja data/hora numérica do Excel
456
        if (cell.getCellType() == CellType.NUMERIC.getCode() && DateUtil.isCellDateFormatted(cell)) {
457
            Date date = cell.getDateCellValue(); // disponível em todas as versões
458
            if (date == null) {
459
                return null;
460
            }
461
            return date.toInstant()
462
                       .atZone(ZoneId.systemDefault())
463
                       .toLocalDateTime();
464
        }
465
 
466
        // Caso venha como TEXT (por exemplo num CSV importado)
467
        if (cell.getCellType() == CellType.STRING.getCode()) {
468
            String text = cell.getStringCellValue();
469
            if (text == null || text.trim().isEmpty()) {
470
                return null;
471
            }
472
            text = text.trim();
473
            try {
474
                // Ajuste o pattern se seu Excel estiver em outro formato
475
                return LocalDateTime.parse(text, formatacaoDataTime);
476
            } catch (Exception e) {
477
                return null;
478
            }
479
        }
480
        return null;
481
    }
482
 
483
    /**
484
     * Converte a célula de data/hora do Excel para LocalDateTime.
485
     */
486
    private LocalDateTime getLocalDateTime(String cell, DateTimeFormatter formatacaoDataTime) {
487
        if (cell == null || cell.trim().isEmpty()) {
488
            return null;
489
        }
490
        cell = cell.trim();
491
        try {
492
            return LocalDateTime.parse(cell, formatacaoDataTime);
493
        } catch (Exception e) {
494
            return null;
495
        }
496
    }
497
 
760 blopes 498
}