Subversion Repositories Integrator Subversion

Rev

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