Subversion Repositories Integrator Subversion

Rev

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