package com.pc.strategy;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

import com.dukascopy.api.Configurable;
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.IHistory;
import com.dukascopy.api.IIndicators;
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;
import com.dukascopy.api.IEngine.OrderCommand;
import com.dukascopy.api.IIndicators.MaType;

public class Stochastic implements IStrategy {

	@Configurable("Instrument")
	public Instrument instrument = Instrument.EURUSD;

	@Configurable("Amount")
	public double amount = 0.001;

	@Configurable("Stop loss")
	public int stopLossPips = 40;

	@Configurable("Take profit")
	public int takeProfitPips = 40;

	@Configurable("Period")
	public Period selectedPeriod = Period.ONE_HOUR;

	@Configurable("Fast KPeriod")
	public int fastKPeriod = 5;

	@Configurable("Slow KPeriod")
	public int slowKPeriod = 3;

	@Configurable("Slow KMa Type")
	public MaType slowKMaType = MaType.EMA;

	@Configurable("Slow DPeriod")
	public int slowDPeriod = 3;

	@Configurable("Slow DMa Type")
	public MaType slowDMaType = MaType.EMA;
	
	public final static DateFormat df = new SimpleDateFormat("MMddHHmmss");

	static
	{
		Stochastic.df.setTimeZone(TimeZone.getTimeZone("GMT"));
	}
	protected IEngine engine;
	protected IHistory history;
	protected IConsole console;
	protected IIndicators indicators;
	
	@Override
	public void onStart(IContext context) throws JFException {
		this.engine = context.getEngine();
		this.history = context.getHistory();
		this.console = context.getConsole();
		this.indicators = context.getIndicators();
	}

	@Override
	public void onAccount(IAccount account) throws JFException {
		// TODO Auto-generated method stub

	}

	@Override
	public void onBar(Instrument instrument, Period period, IBar askBar,
			IBar bidBar) throws JFException {
		if (period.equals(this.selectedPeriod)) {

			long currentBarTime = history.getBar(instrument, selectedPeriod,
					OfferSide.BID, 0).getTime();			
			long lastBarTime = history.getBar(instrument, selectedPeriod,
					OfferSide.BID, 1).getTime();
			long nextToLastBarTime = history.getBar(instrument, selectedPeriod,
					OfferSide.BID, 2).getTime();
			
			/*
			 * stoch[0][0] - %K_2 Value 
			 * stoch[0][1] - %K_1 Value 
			 * stoch[1][0] - %D_2 Value
			 * stoch[1][1] - %D_1 Value
			 */
			double[][] stoch = indicators.stoch(instrument, selectedPeriod,
					OfferSide.BID, fastKPeriod, slowKPeriod, slowKMaType,
					slowDPeriod, slowDMaType, nextToLastBarTime, lastBarTime);

			if (stoch[0][0] > 75 && stoch[0][1] < stoch[0][0] && stoch[0][1] < stoch[1][1]
					&& stoch[0][0] > stoch[1][0]) { // %K_2 > 80 &&
													// %K_1 < %K_2 && 
													// %K_1 < %D_1 && 
													// %K_2 > %D_2
				writeMessage(df.format(currentBarTime) + " K%2: " + stoch[0][0] + " D%2: " + stoch[1][0] + " K%1: "
						+ stoch[0][1] + " D%1: " + stoch[1][1]);
				submitSingleOrder(amount, OrderCommand.SELL, currentBarTime);
			} else if (stoch[0][0] < 25 && stoch[1][1] > stoch[1][0] && stoch[1][1] < stoch[0][1]
					&& stoch[1][0] > stoch[0][0]) { // %K_2 < 20 &&
													// %D_1 > %D_2 && 
													// %D_1 < %K_1 &&
													// %D_2 > %K_2
				writeMessage(df.format(currentBarTime) + " K%2: " + stoch[0][0] + " D%2: " + stoch[1][0] + " K%1: "
						+ stoch[0][1] + " D%1: " + stoch[1][1]);
				submitSingleOrder(amount, OrderCommand.BUY, currentBarTime);
			}
		}

	}

	@Override
	public void onMessage(IMessage message) throws JFException {
		// TODO Auto-generated method stub

	}

	@Override
	public void onStop() throws JFException {
		// TODO Auto-generated method stub

	}

	@Override
	public void onTick(Instrument instrument, ITick tick) throws JFException {
		// TODO Auto-generated method stub

	}

	protected IOrder submitSingleOrder(double amount, OrderCommand orderCmd, long barTime)
			throws JFException {
		if (engine.getOrders().size() == 0) {
			return submitOrder(amount, orderCmd, barTime);
		} else {
			return null;
		}

	}

	protected IOrder submitOrder(double amount, OrderCommand orderCmd, long barTime)
			throws JFException {
		double stopLossPrice, takeProfitPrice;
		if (orderCmd == OrderCommand.BUY) {
			stopLossPrice = history.getLastTick(this.instrument).getBid()
					- this.stopLossPips * this.instrument.getPipValue();
			takeProfitPrice = history.getLastTick(this.instrument).getBid()
					+ this.takeProfitPips * this.instrument.getPipValue();
		} else {
			stopLossPrice = history.getLastTick(this.instrument).getAsk()
					+ this.stopLossPips * this.instrument.getPipValue();
			takeProfitPrice = history.getLastTick(this.instrument).getAsk()
					- this.takeProfitPips * this.instrument.getPipValue();
		}
		// Submitting an order for the specified instrument at the current
		// market price
		return this.engine.submitOrder(getLabel(orderCmd, barTime), instrument,
				orderCmd, amount, 0, 20, stopLossPrice, takeProfitPrice);
	}

	protected String getLabel(OrderCommand cmd, long barTime) {
		return cmd.toString() + df.format(new Date(barTime));
	}

	protected void writeMessage(String message) {
		console.getOut().println(message);
	}

}

