Subversion Repositories Integrator Subversion

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
776 blopes 1
package br.com.kronus.core;
2
 
3
import java.math.BigDecimal;
4
import java.math.RoundingMode;
5
import java.util.List;
6
 
7
import br.com.kronus.core.ResultadoSinalGatilho3.Status;
8
import br.com.sl.domain.dto.robo.SinalTradeGatilho3;
9
import br.com.sl.domain.dto.robo.SinalTradeGatilho3.TipoOperacao;
10
 
11
/**
12
 * Resumo consolidado do backtest dos sinais de Gatilho 3.
13
 *
14
 * Calcula:
15
 *  - contagem de cada tipo de resultado (STOP, ALVO1, ALVO2, etc.)
16
 *  - taxa de acerto (ALVO1 + ALVO2 / trades fechados)
17
 *  - P&L total e médio (em pontos * contratos)
18
 */
19
public class ResumoBacktestGatilho3 {
20
 
21
    private int totalSinais;
22
    private int totalNaoAcionado;
23
    private int totalDescartado;
24
    private int totalStop;
25
    private int totalAlvo1;
26
    private int totalAlvo2;
27
    private int totalAberto;
28
 
29
    // Trades efetivamente fechados (STOP, ALVO1, ALVO2)
30
    private int totalTradesFechados;
31
 
32
    // P&L em "pontos x contratos" (ou moeda, dependendo da unidade do preço)
33
    private BigDecimal plTotal;
34
    private BigDecimal plMedioPorTrade;
35
    private BigDecimal taxaAcerto; // 0.00 a 1.00 (60% = 0.60)
36
 
37
    public ResumoBacktestGatilho3() {
38
        this.plTotal = BigDecimal.ZERO;
39
        this.plMedioPorTrade = BigDecimal.ZERO;
40
        this.taxaAcerto = BigDecimal.ZERO;
41
    }
42
 
43
    public int getTotalSinais() {
44
        return totalSinais;
45
    }
46
 
47
    public int getTotalNaoAcionado() {
48
        return totalNaoAcionado;
49
    }
50
 
51
    public int getTotalDescartado() {
52
        return totalDescartado;
53
    }
54
 
55
    public int getTotalStop() {
56
        return totalStop;
57
    }
58
 
59
    public int getTotalAlvo1() {
60
        return totalAlvo1;
61
    }
62
 
63
    public int getTotalAlvo2() {
64
        return totalAlvo2;
65
    }
66
 
67
    public int getTotalAberto() {
68
        return totalAberto;
69
    }
70
 
71
    public int getTotalTradesFechados() {
72
        return totalTradesFechados;
73
    }
74
 
75
    public BigDecimal getPlTotal() {
76
        return plTotal;
77
    }
78
 
79
    public BigDecimal getPlMedioPorTrade() {
80
        return plMedioPorTrade;
81
    }
82
 
83
    public BigDecimal getTaxaAcerto() {
84
        return taxaAcerto;
85
    }
86
 
87
    /**
88
     * Cria um resumo a partir da lista de resultados.
89
     *
90
     * Regras de P&L:
91
     *  - Considera somente STOP, ALVO1 e ALVO2 como trades fechados.
92
     *  - Para COMPRA: (precoSaida - precoEntrada) * contratosTotais
93
     *  - Para VENDA:  (precoEntrada - precoSaida) * contratosTotais
94
     *  - NAO_ACIONADO, DESCARTADO e ABERTO não entram no P&L.
95
     */
96
    public static ResumoBacktestGatilho3 fromResultados(List<ResultadoSinalGatilho3> resultados) {
97
        ResumoBacktestGatilho3 resumo = new ResumoBacktestGatilho3();
98
 
99
        if (resultados == null || resultados.isEmpty()) {
100
            return resumo;
101
        }
102
 
103
        resumo.totalSinais = resultados.size();
104
 
105
        BigDecimal somaPL = BigDecimal.ZERO;
106
        int tradesFechados = 0;
107
        int tradesAcertados = 0;
108
 
109
        for (ResultadoSinalGatilho3 r : resultados) {
110
            if (r == null) {
111
                continue;
112
            }
113
 
114
            Status status = r.getStatus();
115
            resumo.contabilizarStatus(status);
116
 
117
            // Só consideramos P&L se o trade foi efetivamente aberto e fechado
118
            if (status == Status.STOP || status == Status.ALVO1 || status == Status.ALVO2) {
119
                SinalTradeGatilho3 sinal = r.getSinal();
120
                if (sinal == null) {
121
                    continue;
122
                }
123
 
124
                Integer contratos = sinal.getContratosTotais();
125
                if (contratos == null) {
126
                    contratos = 1;
127
                }
128
 
129
                if (r.getPrecoEntradaEfetivo() == null || r.getPrecoSaidaEfetivo() == null) {
130
                    continue;
131
                }
132
 
133
                BigDecimal precoEntrada = r.getPrecoEntradaEfetivo();
134
                BigDecimal precoSaida   = r.getPrecoSaidaEfetivo();
135
                BigDecimal resultadoTrade;
136
 
137
                if (sinal.getTipoOperacao() == TipoOperacao.COMPRA) {
138
                    // COMPRA: ganha quando sai acima da entrada
139
                    resultadoTrade = precoSaida.subtract(precoEntrada);
140
                } else {
141
                    // VENDA: ganha quando sai abaixo da entrada
142
                    resultadoTrade = precoEntrada.subtract(precoSaida);
143
                }
144
 
145
                // Multiplica pelos contratos
146
                resultadoTrade = resultadoTrade.multiply(BigDecimal.valueOf(contratos));
147
 
148
                somaPL = somaPL.add(resultadoTrade);
149
                tradesFechados++;
150
 
151
                if (status == Status.ALVO1 || status == Status.ALVO2) {
152
                    tradesAcertados++;
153
                }
154
            }
155
        }
156
 
157
        resumo.plTotal = somaPL;
158
 
159
        if (tradesFechados > 0) {
160
            resumo.totalTradesFechados = tradesFechados;
161
            resumo.plMedioPorTrade = somaPL
162
                    .divide(BigDecimal.valueOf(tradesFechados), 4, RoundingMode.HALF_UP);
163
 
164
            resumo.taxaAcerto = BigDecimal.valueOf(tradesAcertados)
165
                    .divide(BigDecimal.valueOf(tradesFechados), 4, RoundingMode.HALF_UP);
166
        }
167
 
168
        return resumo;
169
    }
170
 
171
    private void contabilizarStatus(Status status) {
172
        if (status == null) return;
173
 
174
        switch (status) {
175
            case NAO_ACIONADO:
176
                totalNaoAcionado++;
177
                break;
178
            case DESCARTADO:
179
                totalDescartado++;
180
                break;
181
            case STOP:
182
                totalStop++;
183
                break;
184
            case ALVO1:
185
                totalAlvo1++;
186
                break;
187
            case ALVO2:
188
                totalAlvo2++;
189
                break;
190
            case ABERTO:
191
                totalAberto++;
192
                break;
193
            default:
194
                break;
195
        }
196
    }
197
 
198
    @Override
199
    public String toString() {
200
        return "ResumoBacktestGatilho3{" +
201
                "totalSinais=" + totalSinais +
202
                ", totalNaoAcionado=" + totalNaoAcionado +
203
                ", totalDescartado=" + totalDescartado +
204
                ", totalStop=" + totalStop +
205
                ", totalAlvo1=" + totalAlvo1 +
206
                ", totalAlvo2=" + totalAlvo2 +
207
                ", totalAberto=" + totalAberto +
208
                ", totalTradesFechados=" + totalTradesFechados +
209
                ", plTotal=" + plTotal +
210
                ", plMedioPorTrade=" + plMedioPorTrade +
211
                ", taxaAcerto=" + taxaAcerto +
212
                '}';
213
    }
214
}