Subversion Repositories Integrator Subversion

Rev

Rev 779 | Rev 783 | 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
 
760 blopes 53
    @Override
54
    public Map<String, ProfitTick> readCurrentTicks() {
764 blopes 55
        // TODO Auto-generated method stub
56
        return null;
57
    }
58
 
59
    /**
779 blopes 60
     * Lê um ou vários arquivos:
61
     * - Se excelFile for um arquivo: lê apenas esse arquivo (.xlsx, .xls ou .csv)
62
     * - Se excelFile for uma pasta: lê todos os .xlsx, .xls e .csv da pasta.
764 blopes 63
     */
64
    public List<Candle> lerCandles() throws IOException {
65
        List<Candle> candles = new ArrayList<>();
760 blopes 66
 
779 blopes 67
        if (Files.isDirectory(excelFile)) {
68
            // Percorre todos os arquivos da pasta
69
            try (Stream<Path> stream = Files.list(excelFile)) {
70
                stream
71
                    .filter(Files::isRegularFile)
72
                    .filter(p -> {
73
                        String name = p.getFileName().toString().toLowerCase(Locale.ROOT);
74
                        return name.endsWith(".xlsm") || name.endsWith(".xlsx") || name.endsWith(".xls") || name.endsWith(".csv");
75
                    })
76
                    .forEach(path -> {
77
                        try {
78
                            lerCandlesDeArquivo(path, candles);
79
                        } catch (IOException e) {
80
                            // aqui você pode trocar por log
81
                            e.printStackTrace();
82
                        }
83
                    });
84
            }
85
        } else {
86
            // Apenas um arquivo
87
            lerCandlesDeArquivo(excelFile, candles);
88
        }
89
 
90
        return adicionarContadores(candles);
91
    }
92
 
93
    /**
94
     * Decide se o arquivo é Excel ou CSV e delega para o método correto.
95
     */
96
    private void lerCandlesDeArquivo(Path arquivo, List<Candle> candles) throws IOException {
97
        String name = arquivo.getFileName().toString().toLowerCase(Locale.ROOT);
98
 
99
        if (name.endsWith(".xlsm") || name.endsWith(".xlsx") || name.endsWith(".xls")) {
100
            lerCandlesDeArquivoExcel(arquivo, candles);
101
        } else if (name.endsWith(".csv")) {
102
//            lerCandlesDeArquivoCsv(arquivo, candles);
103
        } else {
104
            // Tipo não suportado, ignora ou loga
105
        }
106
    }
107
 
108
    /**
109
     * Lê os candles de UM arquivo Excel e adiciona na lista passada.
110
     * (É basicamente o seu código original, só movido para cá)
111
     */
112
    private void lerCandlesDeArquivoExcel(Path arquivoExcel, List<Candle> candles) throws IOException {
113
        try (FileInputStream fis = new FileInputStream(arquivoExcel.toFile());
114
             Workbook workbook = new XSSFWorkbook(fis)) {
115
 
764 blopes 116
            int numberOfSheets = workbook.getNumberOfSheets();
779 blopes 117
 
118
            // LER APENAS OS ATIVOS
119
            List<String> ativos = new ArrayList<String>();
764 blopes 120
            for (int i = 0; i < numberOfSheets; i++) {
121
                Sheet sheet = workbook.getSheetAt(i);
122
                if (sheet.getSheetName().equals(sheetName)) {
123
                        boolean firstRow = true;
124
 
125
                        for (Row row : sheet) {
126
                            if (firstRow) {
127
                                firstRow = false; // pula o cabeçalho
128
                                continue;
129
                            }
130
 
782 blopes 131
                            Cell ativoCell = row.getCell(1);
132
                            if (VerificadorUtil.naoEstaNulo(ativoCell)) {
133
                                String ativoString = ativoCell.getStringCellValue();
134
                                if (VerificadorUtil.naoEstaNuloOuVazio(ativoString)) {
135
                                        if (!ativos.contains(ativoString)) {
136
                                                ativos.add(ativoString);
137
                                        }
138
                                }
764 blopes 139
                            }
140
                        }
760 blopes 141
                }
142
            }
779 blopes 143
 
144
            for (String ativo : ativos) {
145
                    for (int i = 0; i < numberOfSheets; i++) {
146
                        Sheet sheet = workbook.getSheetAt(i);
147
                        if (sheet.getSheetName().equals(sheetName)) {
148
                                boolean firstRow = true;
149
 
150
                                for (Row row : sheet) {
151
                                    if (firstRow) {
152
                                        firstRow = false; // pula o cabeçalho
153
                                        continue;
154
                                    }
155
 
156
                                    // 0 = Contador
157
                                    // 1 = Ativo
158
                                    // 2 = Dia
159
                                    // 3 = Hora
160
                                    // 4 = Abertura
161
                                    // 5 = Máxima
162
                                    // 6 = Mínima
163
                                    // 7 = Fechamento
164
 
165
                                    Cell contadorCell   = row.getCell(0);
166
                                    Cell ativoCell      = row.getCell(1);
167
                                    Cell dataCell       = row.getCell(2);
168
                                    Cell horaCell       = row.getCell(3);
169
                                    Cell aberturaCell   = row.getCell(4);
170
                                    Cell maximaCell     = row.getCell(5);
171
                                    Cell minimaCell     = row.getCell(6);
172
                                    Cell fechamentoCell = row.getCell(7);
173
                                    Cell finalizadoCell = row.getCell(8);
174
 
175
                                    if (!ExcelDataUtils.isNumeric(aberturaCell) || !ExcelDataUtils.isNumeric(maximaCell)
782 blopes 176
                                                || !ExcelDataUtils.isNumeric(minimaCell) || !ExcelDataUtils.isNumeric(fechamentoCell)) {
779 blopes 177
                                        continue;
178
                                    }
179
 
782 blopes 180
                                    String ativoDescricao = ativoCell.getStringCellValue();
181
                                    if (!ativo.equals(ativoDescricao)) {
182
                                        continue;
183
                                    }
184
 
779 blopes 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
 
782 blopes 241
    // Contador separado para cada ativo iniciando pelo primeiro contador encontrado
764 blopes 242
    public static List<Candle> adicionarContadores(List<Candle> candles) {
782 blopes 243
        Map<String, Integer> contadorPorAtivo = new HashMap<>();
779 blopes 244
        List<Candle> comContadores = new ArrayList<>();
245
 
764 blopes 246
        for (Candle candle : candles) {
779 blopes 247
            String ativo = candle.getNomeAtivo();
248
 
782 blopes 249
            // Se for o primeiro candle do ativo, usar o contador original dele como ponto de partida
250
            if (!contadorPorAtivo.containsKey(ativo)) {
251
                int contadorInicial = candle.getContadorCandle() != null
252
                        ? candle.getContadorCandle()
253
                        : 1;  // fallback, se vier nulo
254
                contadorPorAtivo.put(ativo, contadorInicial);
255
                candle.setContadorCandle(contadorInicial);
256
                comContadores.add(candle);
257
                continue;
779 blopes 258
            }
259
 
782 blopes 260
            // Se não é o primeiro candle do ativo, incrementar baseado no último
261
            int proximoContador = contadorPorAtivo.get(ativo) + 1;
262
            contadorPorAtivo.put(ativo, proximoContador);
263
            candle.setContadorCandle(proximoContador);
264
 
779 blopes 265
            comContadores.add(candle);
760 blopes 266
        }
782 blopes 267
 
764 blopes 268
        return comContadores;
760 blopes 269
    }
782 blopes 270
 
764 blopes 271
 
272
    /**
273
     * 1 minuto = 1, 5 minutos = 2, 15 minutos = 3, 1 dia = 4
274
     */
275
    private Timeframe resolveTipoTemporizador(String sheetName) {
276
        if (sheetName == null) return null;
277
 
278
        String name = sheetName.toUpperCase(Locale.ROOT);
279
 
280
        if (name.startsWith("1 MIN"))  return Timeframe.M1;
281
        if (name.startsWith("5 MIN"))  return Timeframe.M5;
282
        if (name.startsWith("15 MIN")) return Timeframe.M15;
283
        if (name.startsWith("1 DIA"))  return Timeframe.D1;
284
 
285
        return null;
286
    }
287
 
760 blopes 288
}