Subversion Repositories Integrator Subversion

Rev

Rev 764 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
761 blopes 1
package br.com.sl.domain.service.impl;
2
 
3
import java.math.BigDecimal;
4
import java.nio.file.Paths;
764 blopes 5
import java.time.Duration;
761 blopes 6
import java.time.LocalDateTime;
7
import java.time.temporal.ChronoUnit;
8
import java.util.Map;
9
import java.util.concurrent.ConcurrentHashMap;
10
import java.util.concurrent.TimeUnit;
11
import java.util.concurrent.atomic.AtomicBoolean;
12
 
13
import javax.inject.Singleton;
14
 
15
import org.springframework.beans.factory.annotation.Autowired;
16
import org.springframework.stereotype.Service;
17
 
764 blopes 18
import com.itextpdf.text.log.SysoLogger;
19
 
761 blopes 20
import br.com.ec.core.generic.AbstractService;
21
import br.com.ec.core.generic.GenericRepository;
22
import br.com.ec.core.validador.Validador;
23
import br.com.sl.core.ExcelProfitDataProvider;
764 blopes 24
import br.com.sl.core.ExcelProfitTempoRealPorSegundoProvider;
761 blopes 25
import br.com.sl.core.ProfitDataProvider;
26
import br.com.sl.domain.dto.RoboDTO;
27
import br.com.sl.domain.dto.robo.CandleState;
28
import br.com.sl.domain.dto.robo.ProfitTick;
29
import br.com.sl.domain.service.CandleService;
30
import br.com.sl.domain.service.RoboColetorService;
31
 
32
@Singleton
33
@Service
34
public class RoboColetorServiceImpl extends AbstractService<RoboDTO> implements RoboColetorService {
35
 
36
        private final AtomicBoolean rodando = new AtomicBoolean(false);
37
 
762 blopes 38
        private RoboDTO roboDTO = new RoboDTO();
761 blopes 39
 
40
        private CandleService candleService;
41
 
42
        private ProfitDataProvider profitDataProvider;
43
 
44
        // estado de candle por ativo
45
    private final Map<String, CandleState> estados = new ConcurrentHashMap<>();
46
 
47
    // config básica (pode ser lido de properties)
48
    private static final String EXCEL_PATH = "C:/trade/temporeal.xlsx";
49
    private static final String EXCEL_SHEET = "Asset";
50
 
51
        @Autowired
52
        public RoboColetorServiceImpl(CandleService candleService, Validador validador) {
53
                super(validador);
54
                this.candleService = candleService;
55
        }
56
 
57
        @Override
58
        protected GenericRepository<RoboDTO> getRepository() {
59
                return null;
60
        }
61
 
62
        public RoboDTO getRoboDTO() {
63
                return roboDTO;
64
        }
65
        public void setRoboDTO(RoboDTO roboDTO) {
66
                this.roboDTO = roboDTO;
67
        }
68
 
69
        @Override
70
        public void iniciarColetor1Minuto() {
71
                RoboDTO roboDTO = new RoboDTO();
72
                roboDTO.setRodando(true);
73
                setRoboDTO(roboDTO);
74
 
783 blopes 75
                /*
764 blopes 76
                this.profitDataProvider = new ExcelProfitTempoRealPorSegundoProvider(Paths.get(EXCEL_PATH), EXCEL_SHEET);
761 blopes 77
        if (!rodando.compareAndSet(false, true)) {
78
            // já está rodando
79
            return;
80
        }
783 blopes 81
        */
761 blopes 82
 
83
        Thread t = new Thread(this::loopColetor, "CandleCollector-1M");
84
        t.setDaemon(true);
85
        t.start();
86
    }
87
 
88
        private void loopColetor() {
764 blopes 89
                System.out.println("INICIANDO COLETOR DE DADOS...");
90
                getRoboDTO().setObservacaoRobo("INICIANDO COLETOR DE DADOS...");
91
 
92
                /*
93
                try {
94
                        // INICIA NO PRIMEIRO SEGUNDO DO PRÓXIMO MINUTO HH:mm:01
95
                        LocalDateTime agora = LocalDateTime.now();
96
                        LocalDateTime proximoMinuto = agora
97
                                        .truncatedTo(ChronoUnit.MINUTES)
98
                                        .plusMinutes(1)
99
                                        .plusSeconds(1);
100
 
101
                        long millisAteProximaExecucao = Duration.between(agora, proximoMinuto).toMillis();
102
                        if (millisAteProximaExecucao > 0) {
103
                                System.out.println("AGUARDANDO PARA INICIAR NO PRÓXIMO MINUTO");
104
                                getRoboDTO().setObservacaoRobo("AGUARDANDO PARA INICIAR NO PRÓXIMO MINUTO");
105
                                Thread.sleep(millisAteProximaExecucao);
106
                        }
107
 
108
                } catch (InterruptedException e) {
109
                        // TODO Auto-generated catch block
110
                        e.printStackTrace();
111
                }
112
                */
113
 
114
                System.out.println("INICIANDO CAPTURA!");
115
                getRoboDTO().setObservacaoRobo("INICIANDO CAPTURA!");
116
 
761 blopes 117
        while (rodando.get()) {
118
            try {
783 blopes 119
                /*
761 blopes 120
                // Lê ticks atuais de TODOS os ativos (snapshot)
121
                Map<String, ProfitTick> ticks = profitDataProvider.readCurrentTicks();
122
 
123
                // Atualiza estado de cada ativo
124
                for (Map.Entry<String, ProfitTick> entry : ticks.entrySet()) {
125
                    String symbol = entry.getKey();
126
                    ProfitTick tick = entry.getValue();
127
                    processarTick(symbol, tick);
128
                }
783 blopes 129
        */
761 blopes 130
                // Espera 1 segundo antes da próxima leitura
764 blopes 131
                TimeUnit.SECONDS.sleep(1);
761 blopes 132
            } catch (Exception e) {
133
                e.printStackTrace();
134
                try {
135
                    TimeUnit.SECONDS.sleep(1);
136
                } catch (InterruptedException ex) {
137
                    Thread.currentThread().interrupt();
138
                }
139
            }
140
        }
764 blopes 141
        System.out.println("CAPTURA FINALIZADA!");
142
        getRoboDTO().setObservacaoRobo("CAPTURA FINALIZADA!");
761 blopes 143
    }
144
 
145
        private void processarTick(String ativo, ProfitTick tick) {
146
        CandleState situacaoCandle = estados.get(ativo);
147
        LocalDateTime tickTime = tick.getDateTime();
148
 
149
        // Evita processar o mesmo tick de novo (mesma data/hora)
150
        if (situacaoCandle != null && situacaoCandle.getLastTickTime() != null
151
                && tickTime.equals(situacaoCandle.getLastTickTime())) {
152
            return;
153
        }
154
 
155
        LocalDateTime minutoTick = tickTime.truncatedTo(ChronoUnit.MINUTES);
156
        BigDecimal preco = tick.getPrice();
764 blopes 157
 
158
        System.out.println("CAPTURANDO: " + preco + " [" + tickTime + "]");
761 blopes 159
 
160
        if (situacaoCandle == null) {
161
            // Primeiro tick desse ativo
162
                situacaoCandle = new CandleState(minutoTick, preco, tickTime);
163
            estados.put(ativo, situacaoCandle);
164
            return;
165
        }
166
 
167
        // Se o minuto mudou → fecha candle anterior e salva no banco
168
        if (!minutoTick.equals(situacaoCandle.getMinutoAtual())) {
169
            LocalDateTime inicioCandle = situacaoCandle.getMinutoAtual();
170
            LocalDateTime fimCandle = inicioCandle.plusMinutes(1);
171
 
172
            candleService.cadastrar(ativo, inicioCandle, fimCandle, situacaoCandle);
173
 
174
            // Inicia o próximo candle (novo minuto) com o tick atual
175
            situacaoCandle = new CandleState(minutoTick, preco, tickTime);
176
        } else {
764 blopes 177
                System.out.println("PREÇO: " + preco + " [" + tickTime + "]");
178
 
761 blopes 179
            // Ainda dentro do mesmo minuto → atualiza OHLC
180
            if (preco.compareTo(situacaoCandle.getMaxima()) > 0) {
181
                situacaoCandle.setMaxima(preco);
182
            }
183
            if (preco.compareTo(situacaoCandle.getMinima()) < 0) {
184
                situacaoCandle.setMinima(preco);
185
            }
186
            situacaoCandle.setFechamento(preco);
187
            situacaoCandle.setLastTickTime(tickTime);
188
            // volume se tiver → state.volume += ...
189
        }
190
    }
191
 
192
        @Override
193
        public void pararColetor() {
194
        rodando.set(false);
195
    }
196
 
197
        @Override
198
        public Boolean isRodando() {
199
                return rodando.get();
200
        }
201
 
202
        @Override
203
        public RoboDTO statusRobo() {
204
                getRoboDTO().setRodando(isRodando());
205
                return getRoboDTO();
206
        }
207
 
208
}