package br.com.ec.controller;
import java.io.IOException;
import java.io.Serializable;
import java.util.List;
import javax.inject.Named;
import org.primefaces.model.chart.Axis;
import org.primefaces.model.chart.AxisType;
import org.primefaces.model.chart.LineChartModel;
import org.primefaces.model.chart.LineChartSeries;
import org.primefaces.model.chart.OhlcChartModel;
import org.primefaces.model.chart.OhlcChartSeries;
import org.springframework.context.annotation.Scope;
import br.com.ec.core.generic.GenericService;
import br.com.ec.domain.dto.TradeDTO;
import br.com.ec.web.generic.AbstractBean;
import br.com.robo.backtest.Backtester;
import br.com.robo.model.BacktestResult;
import br.com.robo.model.Candle;
import br.com.robo.model.SwingLevelDetector;
import br.com.robo.model.SwingLevelDetector.Level;
import br.com.robo.model.SwingLevelDetector.LevelType;
import br.com.robo.model.Trade;
import br.com.robo.model.TriggerFinder;
import br.com.robo.sim.CandleExcelReader;
import br.com.robo.strategy.FibTriggerStrategy;
import br.com.robo.strategy.Strategy;
@Named
@Scope
("view")
public class BacktestBean
extends AbstractBean
<TradeDTO
> implements Serializable {
private static final long serialVersionUID = 1L
;
private Integer quantidadeCandles
;
private Double precoInicial
;
private Integer fastPeriod
;
private Integer slowPeriod
;
private Double capitalInicial
;
private Double capitalFinal
;
private Double retornoPercentual
;
private List<Trade
> trades
;
private LineChartModel precoModel
;
private List<Candle
> candles
; // guardar os candles gerados
private List<TriggerFinder.
TriggerPattern> gatilhos
; // padrões encontrados
private OhlcChartModel candleOhlcModel
;
private List<Level> niveisPredominantes
;
public BacktestBean
() {
}
@
Override
public GenericService
<TradeDTO
> getService
() {
return null;
}
@
Override
public TradeDTO getId
() {
return null;
}
@
Override
public void preCarregamento
() {
limparEntidade
();
}
@
Override
public void limparEntidade
() {
setEntidade
(new TradeDTO
());
quantidadeCandles =
300;
precoInicial =
20.0;
fastPeriod =
9;
slowPeriod =
21;
capitalInicial =
100_000.0
;
}
public void executar
() {
Integer tipoTemporizador =
new Integer(1);
// 1) Gera candles simulados
CandleExcelReader reader =
new CandleExcelReader
();
/*
try {
List<Candle> candles = reader.lerCandles("/dados.xlsx", 2);
System.out.println("Qtd candles lidos: " + candles.size());
// candles.stream().forEach(System.out::println);
setCandles(candles);
} catch (IOException e) {
e.printStackTrace();
}
*/
// setCandles(Candle.carregarCandles(tipoTemporizador));
// setCandles(CandleGenerator.gerarSerieSimulada(quantidadeCandles, precoInicial));
// 2) Estratégia
// Strategy strategy = new MovingAverageCrossoverStrategy(fastPeriod, slowPeriod);
Strategy strategy =
new FibTriggerStrategy
();
// 3) Backtest
BacktestResult result = Backtester.
rodarBacktest(getCandles
(), strategy, capitalInicial
);
this.
capitalFinal = result.
getCapitalFinal();
this.
retornoPercentual = result.
getRetornoPercentual();
this.
trades = result.
getTrades();
// Gatilhos
TriggerFinder finder =
new TriggerFinder
();
setGatilhos
(finder.
findTriggers(getCandles
()));
// Fundos/Topos predominantes
SwingLevelDetector levelDetector =
new SwingLevelDetector
();
this.
niveisPredominantes = levelDetector.
detectPredominantLevels(candles
);
// Monta gráfico de preços (fechamento)
montarGrafico
();
// Gráfico de candles com pavio (OHLC)
montarGraficoCandles
();
}
private void montarGraficoComGatilhos
() {
if (candles ==
null || candles.
isEmpty()) {
precoModel =
null;
return;
}
precoModel =
new LineChartModel
();
precoModel.
setTitle("Preço (Fechamento) + Gatilhos + Níveis Predominantes");
precoModel.
setLegendPosition("e");
precoModel.
setZoom(true);
// --- Série do preço (Fechamento) - AZUL ---
LineChartSeries seriePreco =
new LineChartSeries
();
seriePreco.
setLabel("Fechamento");
seriePreco.
setShowMarker(false); // só linha
int lastIndex = candles.
size() -
1;
for (int i =
0; i
<= lastIndex
; i++
) {
Candle c = candles.
get(i
);
seriePreco.
set(i, c.
getClose());
}
precoModel.
addSeries(seriePreco
);
// --- Séries para Ref, G1, G2, G3 (já tínhamos) ---
LineChartSeries serieRef =
new LineChartSeries
();
serieRef.
setLabel("Ref");
serieRef.
setShowLine(false);
serieRef.
setMarkerStyle("diamond");
LineChartSeries serieG1 =
new LineChartSeries
();
serieG1.
setLabel("G1");
serieG1.
setShowLine(false);
serieG1.
setMarkerStyle("triangle");
LineChartSeries serieG2 =
new LineChartSeries
();
serieG2.
setLabel("G2");
serieG2.
setShowLine(false);
serieG2.
setMarkerStyle("circle");
LineChartSeries serieG3 =
new LineChartSeries
();
serieG3.
setLabel("G3");
serieG3.
setShowLine(false);
serieG3.
setMarkerStyle("square");
if (gatilhos
!=
null) {
for (TriggerFinder.
TriggerPattern p : gatilhos
) {
int refIndex = p.
getRefIndex();
int g1Index = p.
getG1Index();
int g2Index = p.
getG2Index();
int g3Index = p.
getG3Index();
Candle ref = candles.
get(refIndex
);
Candle g1 = candles.
get(g1Index
);
Candle g2 = candles.
get(g2Index
);
Candle g3 = candles.
get(g3Index
);
serieRef.
set(refIndex, ref.
getClose());
serieG1.
set(g1Index, g1.
getClose());
serieG2.
set(g2Index, g2.
getClose());
serieG3.
set(g3Index, g3.
getClose());
}
}
precoModel.
addSeries(serieRef
);
precoModel.
addSeries(serieG1
);
precoModel.
addSeries(serieG2
);
precoModel.
addSeries(serieG3
);
// --- Linhas horizontais dos fundos e topos predominantes ---
if (niveisPredominantes
!=
null && !niveisPredominantes.
isEmpty()) {
int contadorTopo =
1;
int contadorFundo =
1;
for (Level nivel : niveisPredominantes
) {
LineChartSeries serieNivel =
new LineChartSeries
();
if (nivel.
getType() == LevelType.
HIGH) {
serieNivel.
setLabel("Topo Pred. " + contadorTopo++
);
} else {
serieNivel.
setLabel("Fundo Pred. " + contadorFundo++
);
}
serieNivel.
setShowMarker(false); // só linha horizontal
double y = nivel.
getPrice();
// linha horizontal do candle 0 até o último
serieNivel.
set(0, y
);
serieNivel.
set(lastIndex, y
);
precoModel.
addSeries(serieNivel
);
}
}
// As 5 primeiras cores: Fechamento, Ref, G1, G2, G3
// As linhas de níveis usarão as cores padrão subsequentes do theme
precoModel.
setSeriesColors("0000FF,000000,FF0000,FFA500,00AA00");
Axis xAxis = precoModel.
getAxis(AxisType.
X);
xAxis.
setLabel("Candle");
Axis yAxis = precoModel.
getAxis(AxisType.
Y);
yAxis.
setLabel("Preço");
}
private void montarGrafico
() {
if (candles ==
null || candles.
isEmpty()) {
precoModel =
null;
return;
}
precoModel =
new LineChartModel
();
precoModel.
setTitle("Preço Simulado (Fechamento) + Gatilhos");
precoModel.
setLegendPosition("e");
precoModel.
setZoom(true);
// Série do preço (Fechamento) - AZUL
LineChartSeries seriePreco =
new LineChartSeries
();
seriePreco.
setLabel("Fechamento");
seriePreco.
setShowMarker(false); // só linha, sem marcadores
int idx =
0;
for (Candle c : candles
) {
seriePreco.
set(idx++, c.
getClose());
}
precoModel.
addSeries(seriePreco
);
// Séries para marcar Ref, G1, G2, G3 (apenas pontos)
LineChartSeries serieRef =
new LineChartSeries
();
serieRef.
setLabel("Ref");
serieRef.
setShowLine(false); // só ponto
serieRef.
setMarkerStyle("diamond");
LineChartSeries serieG1 =
new LineChartSeries
();
serieG1.
setLabel("G1");
serieG1.
setShowLine(false);
serieG1.
setMarkerStyle("triangle");
LineChartSeries serieG2 =
new LineChartSeries
();
serieG2.
setLabel("G2");
serieG2.
setShowLine(false);
serieG2.
setMarkerStyle("circle");
LineChartSeries serieG3 =
new LineChartSeries
();
serieG3.
setLabel("G3");
serieG3.
setShowLine(false);
serieG3.
setMarkerStyle("square");
if (gatilhos
!=
null) {
for (TriggerFinder.
TriggerPattern p : gatilhos
) {
int refIndex = p.
getRefIndex();
int g1Index = p.
getG1Index();
int g2Index = p.
getG2Index();
int g3Index = p.
getG3Index();
Candle ref = candles.
get(refIndex
);
Candle g1 = candles.
get(g1Index
);
Candle g2 = candles.
get(g2Index
);
Candle g3 = candles.
get(g3Index
);
// Usamos o índice como X e o close como Y
serieRef.
set(refIndex, ref.
getClose());
serieG1.
set(g1Index, g1.
getClose());
serieG2.
set(g2Index, g2.
getClose());
serieG3.
set(g3Index, g3.
getClose());
}
}
precoModel.
addSeries(serieRef
);
precoModel.
addSeries(serieG1
);
precoModel.
addSeries(serieG2
);
precoModel.
addSeries(serieG3
);
// Definindo cores específicas (ordem das séries acima)
// Fechamento = azul, Ref = preto, G1 = vermelho, G2 = laranja, G3 = verde
precoModel.
setSeriesColors("0000FF,000000,FF0000,FFA500,00AA00");
Axis xAxis = precoModel.
getAxis(AxisType.
X);
xAxis.
setLabel("Candle");
Axis yAxis = precoModel.
getAxis(AxisType.
Y);
yAxis.
setLabel("Preço");
}
private void montarGraficoCandles
() {
if (candles ==
null || candles.
isEmpty()) {
candleOhlcModel =
null;
return;
}
candleOhlcModel =
new OhlcChartModel
();
candleOhlcModel.
setTitle("Candles (Open / High / Low / Close)");
candleOhlcModel.
setZoom(true);
// Para não poluir demais, vamos pegar só os últimos N candles
int total = candles.
size();
// int maxPontos = 80; // por exemplo
// int start = Math.max(0, total - maxPontos);
for (int i =
0; i
< total
; i++
) {
Candle c = candles.
get(i
);
OhlcChartSeries s =
new OhlcChartSeries
();
s.
setValue(i
); // pode usar índice como eixo X (0,1,2...)
s.
setOpen(c.
getOpen());
s.
setHigh(c.
getHigh());
s.
setLow(c.
getLow());
s.
setClose(c.
getClose());
candleOhlcModel.
add(s
);
}
}
// GETTERS e SETTERS
public Integer getQuantidadeCandles
() {
return quantidadeCandles
;
}
public void setQuantidadeCandles
(Integer quantidadeCandles
) {
this.
quantidadeCandles = quantidadeCandles
;
}
public Double getPrecoInicial
() {
return precoInicial
;
}
public void setPrecoInicial
(Double precoInicial
) {
this.
precoInicial = precoInicial
;
}
public Integer getFastPeriod
() {
return fastPeriod
;
}
public void setFastPeriod
(Integer fastPeriod
) {
this.
fastPeriod = fastPeriod
;
}
public Integer getSlowPeriod
() {
return slowPeriod
;
}
public void setSlowPeriod
(Integer slowPeriod
) {
this.
slowPeriod = slowPeriod
;
}
public Double getCapitalInicial
() {
return capitalInicial
;
}
public void setCapitalInicial
(Double capitalInicial
) {
this.
capitalInicial = capitalInicial
;
}
public Double getCapitalFinal
() {
return capitalFinal
;
}
public Double getRetornoPercentual
() {
return retornoPercentual
;
}
public List<Trade
> getTrades
() {
return trades
;
}
public LineChartModel getPrecoModel
() {
return precoModel
;
}
public List<TriggerFinder.
TriggerPattern> getGatilhos
() {
return gatilhos
;
}
public List<Candle
> getCandles
() {
return candles
;
}
public void setCandles
(List<Candle
> candles
) {
this.
candles = candles
;
}
public void setGatilhos
(List<TriggerFinder.
TriggerPattern> gatilhos
) {
this.
gatilhos = gatilhos
;
}
public OhlcChartModel getCandleOhlcModel
() {
return candleOhlcModel
;
}
public List<Level> getNiveisPredominantes
() {
return niveisPredominantes
;
}
}