

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Stack;
import java.util.TimeZone;

import com.dukascopy.api.Configurable;
import com.dukascopy.api.Filter;
import com.dukascopy.api.IAccount;
import com.dukascopy.api.IBar;
import com.dukascopy.api.IConsole;
import com.dukascopy.api.IContext;
import com.dukascopy.api.IEngine;
import com.dukascopy.api.IEngine.OrderCommand;
import com.dukascopy.api.IMessage;
import com.dukascopy.api.IOrder;
import com.dukascopy.api.IStrategy;
import com.dukascopy.api.ITick;
import com.dukascopy.api.Instrument;
import com.dukascopy.api.JFException;
import com.dukascopy.api.OfferSide;
import com.dukascopy.api.Period;

public class Grider_DR_Fibo_V7 implements IStrategy {

    private IEngine engine;
    private IConsole console;
    private int counter = 0;
    private Stack<IOrder> buyOrdrs = new Stack<IOrder>();
    private Stack<IOrder> sellOrdrs = new Stack<IOrder>();
    @Configurable("Step pips")
    public double step = 7;
    @Configurable("Instrument")
    public Instrument instrument = Instrument.EURUSD;
    @Configurable("Period")
    public Period selectedPeriod = Period.TEN_MINS;
    @Configurable("Offer side")
    public OfferSide offerSide = OfferSide.BID;
    @Configurable("Slippage")
    public double slippage = 2;
    @Configurable("Amount")
    public double amount = 0.1;
    @Configurable("Filter")
    public Filter filter = Filter.ALL_FLATS;
    private ITick previousTick = null;

    @Override
    public void onStart(IContext context) throws JFException {
        this.console = context.getConsole();
        context.getHistory();
        this.engine = context.getEngine();
    }

    @Override
    public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {
        if (period != this.selectedPeriod || instrument != this.instrument) {
            return;
        }
    }

    public void onTick(Instrument instrument, ITick tick) throws JFException {
        if (instrument != this.instrument) {
            return;
        }

        if (previousTick == null) {
            previousTick = tick;
            return;
        }

 //if(instrument==this.instrument)  {   print(("X("+ instrument + "," + previousTick.getBid() + "  ,  "  + "PipPrice+step"+ ","+ + (getPipPrice(step))+ "  ,  " + " Spread " + " , "  + ((tick.getAsk() + tick.getBid())/10) + " )"));}
  
        if (tick.getAsk() <= previousTick.getBid() - getPipPrice(step))   { if (!buyOrdrs.isEmpty()) { closeOrder(buyOrdrs.pop()); }   if (sellOrdrs.isEmpty()) { sellOrdrs.push(submitOrder(OrderCommand.SELL, instrument)); previousTick = tick; } }
   else if (tick.getBid() >= previousTick.getAsk() + getPipPrice(step))   { if (!sellOrdrs.isEmpty()) { closeOrder(sellOrdrs.pop()); } if (buyOrdrs.isEmpty()) { buyOrdrs.push(submitOrder(OrderCommand.BUY, instrument));   previousTick = tick; }}
        if (tick.getAsk() <= previousTick.getBid() - getPipPrice(step+step)) { if (!buyOrdrs.isEmpty()) { closeOrder(buyOrdrs.pop()); }   if (!sellOrdrs.isEmpty()) { sellOrdrs.push(submitOrder(OrderCommand.SELL, instrument)); previousTick = tick; } }
   else if (tick.getBid() >= previousTick.getAsk() + getPipPrice(step+step)) { if (!sellOrdrs.isEmpty()) { closeOrder(sellOrdrs.pop()); } if (!buyOrdrs.isEmpty()) { buyOrdrs.push(submitOrder(OrderCommand.BUY, instrument));   previousTick = tick; }}
        if (tick.getAsk() <= previousTick.getBid() - getPipPrice(step+step+step)) { if (!buyOrdrs.isEmpty()) { closeOrder(buyOrdrs.pop()); }   if (!sellOrdrs.isEmpty()) { sellOrdrs.push(submitOrder(OrderCommand.SELL, instrument)); previousTick = tick; } }
   else if (tick.getBid() >= previousTick.getAsk() + getPipPrice(step+step+step)) { if (!sellOrdrs.isEmpty()) { closeOrder(sellOrdrs.pop()); } if (!buyOrdrs.isEmpty()) { buyOrdrs.push(submitOrder(OrderCommand.BUY, instrument));   previousTick = tick; }} }

   
 
    private IOrder submitOrder(OrderCommand orderCmd, Instrument instr) throws JFException {

        return engine.submitOrder(getLabel(instr), instr, orderCmd, amount, 0, slippage);
    }

    private void closeOrder(IOrder order) throws JFException {
        if (order != null && isActive(order)) {
            order.close();
        }
    }

    private boolean isActive(IOrder order) throws JFException {
        if (order != null && order.getState() != IOrder.State.CLOSED && order.getState() != IOrder.State.CREATED && order.getState() != IOrder.State.CANCELED) {
            return true;
        }
        return false;
    }

    private double getPipPrice(double pips) {
        return pips * this.instrument.getPipValue();
    }

    private String getLabel(Instrument instrument) {
        String label = instrument.name();
        label = label + (counter++);
        label = label.toUpperCase();
        return label;
    }

    public void onMessage(IMessage message) throws JFException {
        print(message);
    }

    public void onAccount(IAccount account) throws JFException {
    }

    public void onStop() throws JFException {
    }

    private void print(Object o) {
        console.getOut().println(o);
    }

    public static String toStr(double[] arr) {
        String str = "";
        for (int r = 0; r < arr.length; r++) {
            str += "[" + r + "] " + (new DecimalFormat("#.#######")).format(arr[r]) + "; ";
        }
        return str;
    }

    public static String toStr(double[][] arr) {
        String str = "";
        if (arr == null) {
            return "null";
        }
        for (int r = 0; r < arr.length; r++) {
            for (int c = 0; c < arr[r].length; c++) {
                str += "[" + r + "][" + c + "] " + (new DecimalFormat("#.#######")).format(arr[r][c]);
            }
            str += "; ";
        }
        return str;
    }

    public String toStr(double d) {
        return (new DecimalFormat("#.#######")).format(d);
    }

    public String toStr(Long time) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") {

            /**
             * 
             */
            private static final long serialVersionUID = 1L;

            {
                setTimeZone(TimeZone.getTimeZone("GMT"));
            }
        };
        return sdf.format(time);
    }
}
