Subversion Repositories Integrator Subversion

Rev

Rev 762 | Go to most recent revision | Details | 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;
5
import java.time.LocalDateTime;
6
import java.time.temporal.ChronoUnit;
7
import java.util.Map;
8
import java.util.concurrent.ConcurrentHashMap;
9
import java.util.concurrent.TimeUnit;
10
import java.util.concurrent.atomic.AtomicBoolean;
11
 
12
import javax.inject.Singleton;
13
 
14
import org.springframework.beans.factory.annotation.Autowired;
15
import org.springframework.stereotype.Service;
16
 
17
import br.com.ec.core.generic.AbstractService;
18
import br.com.ec.core.generic.GenericRepository;
19
import br.com.ec.core.validador.Validador;
20
import br.com.sl.core.ExcelProfitDataProvider;
21
import br.com.sl.core.ProfitDataProvider;
22
import br.com.sl.domain.dto.RoboDTO;
23
import br.com.sl.domain.dto.robo.CandleState;
24
import br.com.sl.domain.dto.robo.ProfitTick;
25
import br.com.sl.domain.service.CandleService;
26
import br.com.sl.domain.service.RoboColetorService;
27
 
28
@Singleton
29
@Service
30
public class RoboColetorServiceImpl extends AbstractService<RoboDTO> implements RoboColetorService {
31
 
32
        private final AtomicBoolean rodando = new AtomicBoolean(false);
33
 
34
        private RoboDTO roboDTO;
35
 
36
        private CandleService candleService;
37
 
38
        private ProfitDataProvider profitDataProvider;
39
 
40
        // estado de candle por ativo
41
    private final Map<String, CandleState> estados = new ConcurrentHashMap<>();
42
 
43
    // config básica (pode ser lido de properties)
44
    private static final String EXCEL_PATH = "C:/trade/temporeal.xlsx";
45
    private static final String EXCEL_SHEET = "Asset";
46
 
47
        @Autowired
48
        public RoboColetorServiceImpl(CandleService candleService, Validador validador) {
49
                super(validador);
50
                this.candleService = candleService;
51
        }
52
 
53
        @Override
54
        protected GenericRepository<RoboDTO> getRepository() {
55
                return null;
56
        }
57
 
58
        public RoboDTO getRoboDTO() {
59
                return roboDTO;
60
        }
61
        public void setRoboDTO(RoboDTO roboDTO) {
62
                this.roboDTO = roboDTO;
63
        }
64
 
65
        @Override
66
        public void iniciarColetor1Minuto() {
67
                RoboDTO roboDTO = new RoboDTO();
68
                roboDTO.setRodando(true);
69
                setRoboDTO(roboDTO);
70
 
71
                this.profitDataProvider = new ExcelProfitDataProvider(Paths.get(EXCEL_PATH), EXCEL_SHEET);
72
        if (!rodando.compareAndSet(false, true)) {
73
            // já está rodando
74
            return;
75
        }
76
 
77
        Thread t = new Thread(this::loopColetor, "CandleCollector-1M");
78
        t.setDaemon(true);
79
        t.start();
80
    }
81
 
82
        private void loopColetor() {
83
        while (rodando.get()) {
84
            try {
85
                // Lê ticks atuais de TODOS os ativos (snapshot)
86
                Map<String, ProfitTick> ticks = profitDataProvider.readCurrentTicks();
87
 
88
                // Atualiza estado de cada ativo
89
                for (Map.Entry<String, ProfitTick> entry : ticks.entrySet()) {
90
                    String symbol = entry.getKey();
91
                    ProfitTick tick = entry.getValue();
92
 
93
                    processarTick(symbol, tick);
94
                }
95
 
96
                // Espera 1 segundo antes da próxima leitura
97
//                TimeUnit.SECONDS.sleep(1);
98
 
99
            } catch (Exception e) {
100
                e.printStackTrace();
101
                try {
102
                    TimeUnit.SECONDS.sleep(1);
103
                } catch (InterruptedException ex) {
104
                    Thread.currentThread().interrupt();
105
                }
106
            }
107
        }
108
    }
109
 
110
        private void processarTick(String ativo, ProfitTick tick) {
111
        CandleState situacaoCandle = estados.get(ativo);
112
        LocalDateTime tickTime = tick.getDateTime();
113
 
114
        // Evita processar o mesmo tick de novo (mesma data/hora)
115
        if (situacaoCandle != null && situacaoCandle.getLastTickTime() != null
116
                && tickTime.equals(situacaoCandle.getLastTickTime())) {
117
            return;
118
        }
119
 
120
        LocalDateTime minutoTick = tickTime.truncatedTo(ChronoUnit.MINUTES);
121
        BigDecimal preco = tick.getPrice();
122
 
123
        if (situacaoCandle == null) {
124
            // Primeiro tick desse ativo
125
                situacaoCandle = new CandleState(minutoTick, preco, tickTime);
126
            estados.put(ativo, situacaoCandle);
127
            return;
128
        }
129
 
130
        // Se o minuto mudou → fecha candle anterior e salva no banco
131
        if (!minutoTick.equals(situacaoCandle.getMinutoAtual())) {
132
 
133
 
134
            LocalDateTime inicioCandle = situacaoCandle.getMinutoAtual();
135
            LocalDateTime fimCandle = inicioCandle.plusMinutes(1);
136
 
137
            candleService.cadastrar(ativo, inicioCandle, fimCandle, situacaoCandle);
138
 
139
            // Inicia o próximo candle (novo minuto) com o tick atual
140
            situacaoCandle = new CandleState(minutoTick, preco, tickTime);
141
        } else {
142
            // Ainda dentro do mesmo minuto → atualiza OHLC
143
            if (preco.compareTo(situacaoCandle.getMaxima()) > 0) {
144
                situacaoCandle.setMaxima(preco);
145
            }
146
            if (preco.compareTo(situacaoCandle.getMinima()) < 0) {
147
                situacaoCandle.setMinima(preco);
148
            }
149
            situacaoCandle.setFechamento(preco);
150
            situacaoCandle.setLastTickTime(tickTime);
151
            // volume se tiver → state.volume += ...
152
        }
153
    }
154
 
155
        @Override
156
        public void pararColetor() {
157
        rodando.set(false);
158
    }
159
 
160
        @Override
161
        public Boolean isRodando() {
162
                return rodando.get();
163
        }
164
 
165
        @Override
166
        public RoboDTO statusRobo() {
167
                getRoboDTO().setRodando(isRodando());
168
                return getRoboDTO();
169
        }
170
 
171
}