Subversion Repositories Integrator Subversion

Rev

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;
    }
}