package br.com.kronus.core;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import br.com.ec.web.util.TipoOperacao;
import br.com.kronus.core.ResultadoSinalGatilho3.Status;
import br.com.sl.domain.dto.robo.SinalTradeGatilho3;
import br.com.sl.domain.model.tipos.TipoSinal;
/**
* Resumo consolidado do backtest dos sinais de Gatilho 3.
*
* Calcula:
* - contagem de cada tipo de resultado (STOP, ALVO1, ALVO2, etc.)
* - taxa de acerto (ALVO1 + ALVO2 / trades fechados)
* - P&L total e médio (em pontos * contratos)
*/
public class ResumoBacktestGatilho3
{
private int totalSinais
;
private int totalNaoAcionado
;
private int totalDescartado
;
private int totalStop
;
private int totalAlvo1
;
private int totalAlvo2
;
private int totalAberto
;
// Trades efetivamente fechados (STOP, ALVO1, ALVO2)
private int totalTradesFechados
;
// P&L em "pontos x contratos" (ou moeda, dependendo da unidade do preço)
private BigDecimal plTotal
;
private BigDecimal plMedioPorTrade
;
private BigDecimal taxaAcerto
; // 0.00 a 1.00 (60% = 0.60)
public ResumoBacktestGatilho3
() {
this.
plTotal =
BigDecimal.
ZERO;
this.
plMedioPorTrade =
BigDecimal.
ZERO;
this.
taxaAcerto =
BigDecimal.
ZERO;
}
public int getTotalSinais
() {
return totalSinais
;
}
public int getTotalNaoAcionado
() {
return totalNaoAcionado
;
}
public int getTotalDescartado
() {
return totalDescartado
;
}
public int getTotalStop
() {
return totalStop
;
}
public int getTotalAlvo1
() {
return totalAlvo1
;
}
public int getTotalAlvo2
() {
return totalAlvo2
;
}
public int getTotalAberto
() {
return totalAberto
;
}
public int getTotalTradesFechados
() {
return totalTradesFechados
;
}
public BigDecimal getPlTotal
() {
return plTotal
;
}
public BigDecimal getPlMedioPorTrade
() {
return plMedioPorTrade
;
}
public BigDecimal getTaxaAcerto
() {
return taxaAcerto
;
}
/**
* Cria um resumo a partir da lista de resultados.
*
* Regras de P&L:
* - Considera somente STOP, ALVO1 e ALVO2 como trades fechados.
* - Para COMPRA: (precoSaida - precoEntrada) * contratosTotais
* - Para VENDA: (precoEntrada - precoSaida) * contratosTotais
* - NAO_ACIONADO, DESCARTADO e ABERTO não entram no P&L.
*/
public static ResumoBacktestGatilho3 fromResultados
(List<ResultadoSinalGatilho3
> resultados
) {
ResumoBacktestGatilho3 resumo =
new ResumoBacktestGatilho3
();
if (resultados ==
null || resultados.
isEmpty()) {
return resumo
;
}
resumo.
totalSinais = resultados.
size();
BigDecimal somaPL =
BigDecimal.
ZERO;
int tradesFechados =
0;
int tradesAcertados =
0;
for (ResultadoSinalGatilho3 r : resultados
) {
if (r ==
null) {
continue;
}
Status status = r.
getStatus();
resumo.
contabilizarStatus(status
);
// Só consideramos P&L se o trade foi efetivamente aberto e fechado
if (status == Status.
STOP || status == Status.
ALVO1 || status == Status.
ALVO2) {
SinalTradeGatilho3 sinal = r.
getSinal();
if (sinal ==
null) {
continue;
}
Integer contratos = sinal.
getContratosTotais();
if (contratos ==
null) {
contratos =
1;
}
if (r.
getPrecoEntradaEfetivo() ==
null || r.
getPrecoSaidaEfetivo() ==
null) {
continue;
}
BigDecimal precoEntrada = r.
getPrecoEntradaEfetivo();
BigDecimal precoSaida = r.
getPrecoSaidaEfetivo();
BigDecimal resultadoTrade
;
if (sinal.
getTipoOperacao() == TipoSinal.
COMPRA_C) {
// COMPRA: ganha quando sai acima da entrada
resultadoTrade = precoSaida.
subtract(precoEntrada
);
} else {
// VENDA: ganha quando sai abaixo da entrada
resultadoTrade = precoEntrada.
subtract(precoSaida
);
}
// Multiplica pelos contratos
resultadoTrade = resultadoTrade.
multiply(BigDecimal.
valueOf(contratos
));
somaPL = somaPL.
add(resultadoTrade
);
tradesFechados++
;
if (status == Status.
ALVO1 || status == Status.
ALVO2) {
tradesAcertados++
;
}
}
}
resumo.
plTotal = somaPL
;
if (tradesFechados
> 0) {
resumo.
totalTradesFechados = tradesFechados
;
resumo.
plMedioPorTrade = somaPL
.
divide(BigDecimal.
valueOf(tradesFechados
),
4,
RoundingMode.
HALF_UP);
resumo.
taxaAcerto =
BigDecimal.
valueOf(tradesAcertados
)
.
divide(BigDecimal.
valueOf(tradesFechados
),
4,
RoundingMode.
HALF_UP);
}
return resumo
;
}
private void contabilizarStatus
(Status status
) {
if (status ==
null) return;
switch (status
) {
case NAO_ACIONADO:
totalNaoAcionado++
;
break;
case DESCARTADO:
totalDescartado++
;
break;
case STOP:
totalStop++
;
break;
case ALVO1:
totalAlvo1++
;
break;
case ALVO2:
totalAlvo2++
;
break;
case ABERTO:
totalAberto++
;
break;
default:
break;
}
}
@
Override
public String toString
() {
return "ResumoBacktestGatilho3{" +
"totalSinais=" + totalSinais +
", totalNaoAcionado=" + totalNaoAcionado +
", totalDescartado=" + totalDescartado +
", totalStop=" + totalStop +
", totalAlvo1=" + totalAlvo1 +
", totalAlvo2=" + totalAlvo2 +
", totalAberto=" + totalAberto +
", totalTradesFechados=" + totalTradesFechados +
", plTotal=" + plTotal +
", plMedioPorTrade=" + plMedioPorTrade +
", taxaAcerto=" + taxaAcerto +
'}';
}
}