Subversion Repositories Integrator Subversion

Rev

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