Blame |
Last modification |
View Log
| Download
| RSS feed
package br.com.robo.strategy;
import java.util.ArrayList;
import java.util.List;
import br.com.robo.model.Candle;
import br.com.robo.model.TriggerFinder;
import br.com.robo.model.TriggerFinder.TriggerPattern;
/**
* Estratégia:
* - Identifica padrões de gatilhos (Ref, G1, G2, G3)
* - Para cada padrão, define um setup de Fibonacci:
* 0% = fundo do Ref
* 100% = topo do G1
* 50% = nível de entrada (compra)
* - Compra no 50% após o G2, vende no 100%.
*/
public class FibTriggerStrategy
implements Strategy
{
private static class FibSetup
{
int refIndex
;
int g1Index
;
int g2Index
;
double fib0
; // low(G2)
double fib50
; // nível de compra
double fib100
; // high(G1) = alvo
boolean triggeredEntry =
false; // já entrou?
boolean completed =
false; // trade já encerrado (por TP ou SL)
}
private List<FibSetup
> setups
;
private boolean initialized =
false;
private List<Candle
> lastCandlesRef
;
private FibSetup activeSetup =
null;
@
Override
public Signal decide
(int index,
List<Candle
> candles,
boolean hasPosition
) {
// Inicializa setups na primeira chamada (ou se a lista de candles mudar)
if (!initialized || candles
!= lastCandlesRef
) {
initializeSetups
(candles
);
lastCandlesRef = candles
;
initialized =
true;
}
// Se não há setups, não faz nada
if (setups ==
null || setups.
isEmpty()) {
return Signal.
HOLD;
}
Candle c = candles.
get(index
);
// Se JÁ estamos posicionados: procurar alvo (fib100)
if (hasPosition
&& activeSetup
!=
null && !activeSetup.
completed) {
// Take Profit: high >= fib100
if (c.
getHigh() >= activeSetup.
fib100) {
activeSetup.
completed =
true;
return Signal.
SELL;
}
// // (Opcional) Stop Loss abaixo do fib0 (fundo do G2)
// double stopLoss = activeSetup.fib0 - 0.01; // pequeno buffer
// if (c.getLow() <= stopLoss) {
// activeSetup.completed = true;
// return Signal.SELL;
// }
return Signal.
HOLD;
}
// Se NÃO estamos posicionados: procurar entrada nos setups ainda não usados
if (!hasPosition
) {
for (FibSetup setup : setups
) {
if (setup.
completed) {
continue;
}
// setup só começa a valer após o G2
if (index
<= setup.
g2Index) {
continue;
}
// se já entrou nesse setup antes, ignora
if (setup.
triggeredEntry) {
continue;
}
// Condição de compra no 50%: candle toca o nível fib50
if (c.
getLow() <= setup.
fib50 && c.
getHigh() >= setup.
fib50) {
setup.
triggeredEntry =
true;
activeSetup = setup
;
return Signal.
BUY;
}
}
}
return Signal.
HOLD;
}
/**
* Inicializa os setups de Fibonacci a partir dos padrões de gatilho.
*/
private void initializeSetups
(List<Candle
> candles
) {
TriggerFinder finder =
new TriggerFinder
();
List<TriggerPattern
> patterns = finder.
findTriggers(candles
);
List<FibSetup
> lista =
new ArrayList<>();
for (TriggerPattern p : patterns
) {
int refIndex = p.
getRefIndex();
int g1Index = p.
getG1Index();
int g2Index = p.
getG2Index();
if (g1Index
<= g2Index
) {
// Garantia: G1 é um topo anterior ao G2
// Se não for, pulamos esse padrão
continue;
}
Candle ref = candles.
get(refIndex
);
Candle g1 = candles.
get(g1Index
);
Candle g2 = candles.
get(g2Index
);
double fib0 = ref.
getLow(); // início do Fibonacci = fundo do G2
double fib100 = g1.
getHigh(); // fim do Fibonacci = topo do G1
double range = fib100 - fib0
;
if (range
<=
0) {
continue;
}
double fib50 = fib0 +
0.5 * range
;
FibSetup setup =
new FibSetup
();
setup.
refIndex = refIndex
;
setup.
g1Index = g1Index
;
setup.
g2Index = g2Index
;
setup.
fib0 = fib0
;
setup.
fib50 = fib50
;
setup.
fib100 = fib100
;
lista.
add(setup
);
}
this.
setups = lista
;
this.
activeSetup =
null;
}
}