Subversion Repositories Integrator Subversion

Rev

Rev 771 | Rev 776 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 771 Rev 775
Line 1... Line 1...
1
package br.com.sl.core;
1
package br.com.sl.core;
2
2
-
 
3
import java.io.BufferedReader;
3
import java.io.FileInputStream;
4
import java.io.FileInputStream;
4
import java.io.IOException;
5
import java.io.IOException;
5
import java.io.InputStream;
-
 
6
import java.math.BigDecimal;
6
import java.math.BigDecimal;
-
 
7
import java.nio.charset.StandardCharsets;
-
 
8
import java.nio.file.Files;
7
import java.nio.file.Path;
9
import java.nio.file.Path;
8
import java.text.SimpleDateFormat;
-
 
9
import java.time.LocalDate;
10
import java.time.LocalDate;
10
import java.time.LocalDateTime;
11
import java.time.LocalDateTime;
11
import java.time.LocalTime;
12
import java.time.LocalTime;
12
import java.time.ZoneId;
-
 
13
import java.time.format.DateTimeFormatter;
13
import java.time.format.DateTimeFormatter;
14
import java.util.ArrayList;
14
import java.util.ArrayList;
15
import java.util.Collections;
15
import java.util.Collections;
16
import java.util.Date;
-
 
17
import java.util.List;
16
import java.util.List;
18
import java.util.Locale;
17
import java.util.Locale;
19
import java.util.Map;
18
import java.util.Map;
-
 
19
import java.util.stream.Stream;
20
20
21
import org.apache.poi.EncryptedDocumentException;
21
import org.apache.poi.EncryptedDocumentException;
22
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
-
 
23
import org.apache.poi.ss.usermodel.Cell;
22
import org.apache.poi.ss.usermodel.Cell;
24
import org.apache.poi.ss.usermodel.CellType;
-
 
25
import org.apache.poi.ss.usermodel.DateUtil;
-
 
26
import org.apache.poi.ss.usermodel.Row;
23
import org.apache.poi.ss.usermodel.Row;
27
import org.apache.poi.ss.usermodel.Sheet;
24
import org.apache.poi.ss.usermodel.Sheet;
28
import org.apache.poi.ss.usermodel.Workbook;
25
import org.apache.poi.ss.usermodel.Workbook;
29
import org.apache.poi.ss.usermodel.WorkbookFactory;
-
 
30
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
26
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
31
27
32
import br.com.kronus.core.Timeframe;
28
import br.com.kronus.core.Timeframe;
33
import br.com.sl.domain.dto.robo.ProfitTick;
29
import br.com.sl.domain.dto.robo.ProfitTick;
34
import br.com.sl.domain.model.Candle;
30
import br.com.sl.domain.model.Candle;
35
import br.com.sl.domain.model.tipos.TipoPeriodo;
-
 
36
import br.com.sl.domain.model.tipos.TipoPeriodoCandle;
31
import br.com.sl.domain.model.tipos.TipoPeriodoCandle;
37
import br.com.sl.shared.ExcelDataUtils;
32
import br.com.sl.shared.ExcelDataUtils;
38
33
39
public class ExcelProfitHistoricoDataProvider implements ProfitDataProvider {
34
public class ExcelProfitHistoricoDataProvider implements ProfitDataProvider {
40
35
41
        private final Path excelFile;
-
 
-
 
36
    private final Path excelFile; // agora pode ser arquivo OU pasta
42
    private final String sheetName;
37
    private final String sheetName;
43
   
-
 
44
        private static final DateTimeFormatter STRING_DATA_FORMATTER = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss");
-
 
45
    private static final DateTimeFormatter STRING_DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss");
-
 
-
 
38
-
 
39
    private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("dd/MM/yyyy");
-
 
40
    private static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern("HH:mm:ss");
46
41
47
    public ExcelProfitHistoricoDataProvider(Path excelFile, String sheetName) {
42
    public ExcelProfitHistoricoDataProvider(Path excelFile, String sheetName) {
48
        this.excelFile = excelFile;
43
        this.excelFile = excelFile;
49
        this.sheetName = sheetName;
44
        this.sheetName = sheetName;
50
    }
45
    }
51
   
-
 
-
 
46
52
    @Override
47
    @Override
53
    public Map<String, ProfitTick> readCurrentTicks() {
48
    public Map<String, ProfitTick> readCurrentTicks() {
54
        // TODO Auto-generated method stub
-
 
55
        return null;
-
 
-
 
49
        // TODO Auto-generated method stub
-
 
50
        return null;
56
    }
51
    }
57
   
-
 
-
 
52
58
    /**
53
    /**
59
     * Lê o arquivo Excel dentro do resources.
-
 
60
     * Exemplo de uso:
-
 
61
     *    lerCandles("/dados/Dados Trade 20251117.xlsx");
-
 
62
     * @throws IOException
-
 
-
 
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.
63
     */
57
     */
64
    public List<Candle> lerCandles() throws IOException {
58
    public List<Candle> lerCandles() throws IOException {
65
        List<Candle> candles = new ArrayList<>();
59
        List<Candle> candles = new ArrayList<>();
66
60
67
        try (FileInputStream fis = new FileInputStream(excelFile.toFile()); Workbook workbook = new XSSFWorkbook(fis)) {
-
 
-
 
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(".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(inverterLista(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(".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
68
            int numberOfSheets = workbook.getNumberOfSheets();
110
            int numberOfSheets = workbook.getNumberOfSheets();
69
111
70
            for (int i = 0; i < numberOfSheets; i++) {
112
            for (int i = 0; i < numberOfSheets; i++) {
71
                Sheet sheet = workbook.getSheetAt(i);
113
                Sheet sheet = workbook.getSheetAt(i);
-
 
114
72
                for (Row row : sheet) {
115
                for (Row row : sheet) {
73
116
74
                    // 0 = Ativo
117
                    // 0 = Ativo
75
                    // 1 = Dia
118
                    // 1 = Dia
76
                    // 2 = Hora
119
                    // 2 = Hora
Line 88... Line 131...
88
                    Cell maximaCell     = row.getCell(4);
131
                    Cell maximaCell     = row.getCell(4);
89
                    Cell minimaCell     = row.getCell(5);
132
                    Cell minimaCell     = row.getCell(5);
90
                    Cell fechamentoCell = row.getCell(6);
133
                    Cell fechamentoCell = row.getCell(6);
91
134
92
                    if (!ExcelDataUtils.isNumeric(aberturaCell) || !ExcelDataUtils.isNumeric(maximaCell)
135
                    if (!ExcelDataUtils.isNumeric(aberturaCell) || !ExcelDataUtils.isNumeric(maximaCell)
93
                                || !ExcelDataUtils.isNumeric(minimaCell) || !ExcelDataUtils.isNumeric(fechamentoCell)) {
-
 
-
 
136
                            || !ExcelDataUtils.isNumeric(minimaCell) || !ExcelDataUtils.isNumeric(fechamentoCell)) {
94
                        continue;
137
                        continue;
95
                    }
138
                    }
96
                   
-
 
-
 
139
97
                    LocalDate data = ExcelDataUtils.lerData(dataCell);
140
                    LocalDate data = ExcelDataUtils.lerData(dataCell);
98
                    LocalTime hora = ExcelDataUtils.lerHora(horaCell);
141
                    LocalTime hora = ExcelDataUtils.lerHora(horaCell);
99
                    hora = hora.plusMinutes(6).plusSeconds(28);
142
                    hora = hora.plusMinutes(6).plusSeconds(28);
100
                    LocalDateTime dataHora = LocalDateTime.of(data, hora);
143
                    LocalDateTime dataHora = LocalDateTime.of(data, hora);
101
                   
-
 
-
 
144
102
                    String ativoDescricao = ativoCell.getStringCellValue();
145
                    String ativoDescricao = ativoCell.getStringCellValue();
103
                    BigDecimal abertura = BigDecimal.valueOf(aberturaCell.getNumericCellValue());
146
                    BigDecimal abertura = BigDecimal.valueOf(aberturaCell.getNumericCellValue());
104
                    BigDecimal topo = BigDecimal.valueOf(maximaCell.getNumericCellValue());
147
                    BigDecimal topo = BigDecimal.valueOf(maximaCell.getNumericCellValue());
105
                    BigDecimal fundo = BigDecimal.valueOf(minimaCell.getNumericCellValue());
148
                    BigDecimal fundo = BigDecimal.valueOf(minimaCell.getNumericCellValue());
106
                    BigDecimal fechamento = BigDecimal.valueOf(fechamentoCell.getNumericCellValue());
149
                    BigDecimal fechamento = BigDecimal.valueOf(fechamentoCell.getNumericCellValue());
107
150
108
                    Candle candle = new Candle(null, ativoDescricao, dataHora, abertura, topo, fundo, fechamento, TipoPeriodoCandle.M1.getValor());
-
 
109
                        candles.add(candle);
-
 
-
 
151
                    Candle candle = new Candle(
-
 
152
                            null,
-
 
153
                            ativoDescricao,
-
 
154
                            dataHora,
-
 
155
                            abertura,
-
 
156
                            topo,
-
 
157
                            fundo,
-
 
158
                            fechamento,
-
 
159
                            TipoPeriodoCandle.M1.getValor()
-
 
160
                    );
-
 
161
                    candles.add(candle);
110
                }
162
                }
111
            }
163
            }
112
        } catch (EncryptedDocumentException e) {
164
        } catch (EncryptedDocumentException e) {
113
                        // TODO Auto-generated catch block
-
 
114
                        e.printStackTrace();
-
 
-
 
165
            e.printStackTrace();
115
        }
166
        }
116
        return adicionarContadores(inverterLista(candles));
-
 
117
    }
167
    }
118
   
-
 
-
 
168
-
 
169
    /**
-
 
170
     * Lê os candles de UM arquivo CSV e adiciona na lista passada.
-
 
171
     * Espera layout:
-
 
172
     * 0 = Ativo
-
 
173
     * 1 = Dia  (dd/MM/yyyy)
-
 
174
     * 2 = Hora (HH:mm:ss)
-
 
175
     * 3 = Abertura
-
 
176
     * 4 = Máxima
-
 
177
     * 5 = Mínima
-
 
178
     * 6 = Fechamento
-
 
179
     */
-
 
180
    private void lerCandlesDeArquivoCsv(Path arquivoCsv, List<Candle> candles) throws IOException {
-
 
181
        try (BufferedReader br = Files.newBufferedReader(arquivoCsv, StandardCharsets.UTF_8)) {
-
 
182
            String line;
-
 
183
            while ((line = br.readLine()) != null) {
-
 
184
-
 
185
                // Substitui line.isBlank() por trim().isEmpty()
-
 
186
                String trimmed = line.trim();
-
 
187
                if (trimmed.isEmpty()) {
-
 
188
                    continue;
-
 
189
                }
-
 
190
-
 
191
                // Ajuste aqui se o separador do seu CSV for vírgula
-
 
192
                String[] parts = trimmed.split(";", -1);
-
 
193
                if (parts.length < 7) {
-
 
194
                    continue;
-
 
195
                }
-
 
196
-
 
197
                String ativoDescricao = parts[0].trim();
-
 
198
                String dataStr        = parts[1].trim();
-
 
199
                String horaStr        = parts[2].trim();
-
 
200
                String aberturaStr    = parts[3].trim();
-
 
201
                String maximaStr      = parts[4].trim();
-
 
202
                String minimaStr      = parts[5].trim();
-
 
203
                String fechamentoStr  = parts[6].trim();
-
 
204
-
 
205
                // Ignora header, caso exista
-
 
206
                if (ativoDescricao.equalsIgnoreCase("ativo")) {
-
 
207
                    continue;
-
 
208
                }
-
 
209
-
 
210
                if (!isNumericString(aberturaStr) ||
-
 
211
                    !isNumericString(maximaStr)   ||
-
 
212
                    !isNumericString(minimaStr)   ||
-
 
213
                    !isNumericString(fechamentoStr)) {
-
 
214
                    continue;
-
 
215
                }
-
 
216
-
 
217
                LocalDate data = LocalDate.parse(dataStr, DATE_FORMAT);
-
 
218
                LocalTime hora = LocalTime.parse(horaStr, TIME_FORMAT);
-
 
219
                LocalDateTime dataHora = LocalDateTime.of(data, hora);
-
 
220
-
 
221
                BigDecimal abertura   = parseBigDecimal(aberturaStr);
-
 
222
                BigDecimal topo       = parseBigDecimal(maximaStr);
-
 
223
                BigDecimal fundo      = parseBigDecimal(minimaStr);
-
 
224
                BigDecimal fechamento = parseBigDecimal(fechamentoStr);
-
 
225
-
 
226
                Candle candle = new Candle(
-
 
227
                        null,
-
 
228
                        ativoDescricao,
-
 
229
                        dataHora,
-
 
230
                        abertura,
-
 
231
                        topo,
-
 
232
                        fundo,
-
 
233
                        fechamento,
-
 
234
                        TipoPeriodoCandle.M1.getValor()
-
 
235
                );
-
 
236
                candles.add(candle);
-
 
237
            }
-
 
238
        }
-
 
239
    }
-
 
240
-
 
241
-
 
242
    private BigDecimal parseBigDecimal(String value) {
-
 
243
        if (value == null) return null;
-
 
244
        String normalized = value.trim().replace(".", "").replace(",", ".");
-
 
245
        // Se o Profit já exportar com ponto como separador decimal, remova o replace(".","")
-
 
246
        // e deixe apenas: value.trim().replace(",", ".")
-
 
247
        if (normalized.isEmpty()) return null;
-
 
248
        return new BigDecimal(normalized);
-
 
249
    }
-
 
250
-
 
251
    private boolean isNumericString(String value) {
-
 
252
        if (value == null) return false;
-
 
253
        String normalized = value.trim().replace(".", "").replace(",", ".");
-
 
254
        if (normalized.isEmpty()) return false;
-
 
255
        try {
-
 
256
            new BigDecimal(normalized);
-
 
257
            return true;
-
 
258
        } catch (NumberFormatException e) {
-
 
259
            return false;
-
 
260
        }
-
 
261
    }
-
 
262
119
    public static List<Candle> inverterLista(List<Candle> candles) {
263
    public static List<Candle> inverterLista(List<Candle> candles) {
120
        List<Candle> invertida = new ArrayList<>(candles);
264
        List<Candle> invertida = new ArrayList<>(candles);
121
        Collections.reverse(invertida);
265
        Collections.reverse(invertida);
122
        return invertida;
266
        return invertida;
123
    }
267
    }
124
268
125
    public static List<Candle> adicionarContadores(List<Candle> candles) {
269
    public static List<Candle> adicionarContadores(List<Candle> candles) {
126
        Integer contador = 1;
270
        Integer contador = 1;
127
        List<Candle> comContadores = new ArrayList<>();
-
 
-
 
271
        List<Candle> comContadores = new ArrayList<>();
128
        for (Candle candle : candles) {
272
        for (Candle candle : candles) {
129
                candle.setContadorCandle(contador);
-
 
130
                comContadores.add(candle);
-
 
131
                contador++;
-
 
-
 
273
            candle.setContadorCandle(contador);
-
 
274
            comContadores.add(candle);
-
 
275
            contador++;
132
        }
276
        }
133
        return comContadores;
277
        return comContadores;
134
    }
278
    }
135
   
-
 
-
 
279
136
    /**
280
    /**
137
     * 1 minuto = 1, 5 minutos = 2, 15 minutos = 3, 1 dia = 4
281
     * 1 minuto = 1, 5 minutos = 2, 15 minutos = 3, 1 dia = 4
138
     */
282
     */
139
    private Timeframe resolveTipoTemporizador(String sheetName) {
283
    private Timeframe resolveTipoTemporizador(String sheetName) {
140
        if (sheetName == null) return null;
284
        if (sheetName == null) return null;
Line 147... Line 291...
147
        if (name.startsWith("1 DIA"))  return Timeframe.D1;
291
        if (name.startsWith("1 DIA"))  return Timeframe.D1;
148
292
149
        return null;
293
        return null;
150
    }
294
    }
151
295
152
}
296
}