/*
 * Copyright (c) 2009 Dukascopy (Suisse) SA. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * -Redistribution of source code must retain the above copyright notice, this
 *  list of conditions and the following disclaimer.
 *
 * -Redistribution in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 * 
 * Neither the name of Dukascopy (Suisse) SA or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. DUKASCOPY (SUISSE) SA ("DUKASCOPY")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL DUKASCOPY OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF DUKASCOPY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 */
package singlejartest_old;

import com.dukascopy.api.*;
import com.dukascopy.api.system.ISystemListener;
import com.dukascopy.api.system.ITesterClient;
import com.dukascopy.api.system.ITesterClient.DataLoadingMethod;
import com.dukascopy.api.system.TesterFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.Future;

/**
 * This small program demonstrates how to initialize Dukascopy tester and start a strategy
 */
@RequiresFullAccess
public class HistoryIntervalIndFromToPerformance {
	private static final Logger LOGGER = LoggerFactory.getLogger(Main.class);

	// url of the DEMO jnlp
	//private static String jnlpUrl = "https://www.dukascopy.com/client/demo/jclient/jforex.jnlp";
    private static String jnlpUrl = "https://www.dukascopy.com/client/demo/jclient/jforex.jnlp";
    private static String userName = "";
    private static String password = "";
    

	public static void main(String[] args) throws Exception {
		// get the instance of the IClient interface
		final ITesterClient client = TesterFactory.getDefaultInstance();
		// set the listener that will receive system events
		client.setSystemListener(new ISystemListener() {
			@Override
			public void onStart(long processId) {
				LOGGER.info("Strategy started: " + processId);
			}

			@Override
			public void onStop(long processId) {
				if (client.getStartedStrategies().size() == 0) {
					System.exit(0);
				}
			}

			@Override
			public void onConnect() {
				LOGGER.info("Connected");
			}

			@Override
			public void onDisconnect() {
				// tester doesn't disconnect
			}
		});

		LOGGER.info("Connecting...");
		// connect to the server using jnlp, user name and password
		// connection is needed for data downloading
		client.connect(jnlpUrl, userName, password);

		// wait for it to connect
		int i = 10; // wait max ten seconds
		while (i > 0 && !client.isConnected()) {
			Thread.sleep(1000);
			i--;
		}
		if (!client.isConnected()) {
			LOGGER.error("Failed to connect Dukascopy servers");
			System.exit(1);
		}

		final SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
		dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));

		Date dateFrom = dateFormat.parse("05/01/2012 00:00:00");
		Date dateTo = dateFormat.parse("05/01/2012 00:01:00");

		client.setDataInterval(DataLoadingMethod.ALL_TICKS, dateFrom.getTime(), dateTo.getTime());

		// set instruments that will be used in testing
		Set<Instrument> instruments = new HashSet<Instrument>();
		instruments.add(Instrument.EURUSD);
		LOGGER.info("Subscribing instruments...");
		client.setSubscribedInstruments(instruments);
		client.setInitialDeposit(Instrument.EURUSD.getSecondaryCurrency(), 50000);
		
		// load data
		LOGGER.info("Downloading data");
		Future<?> future = client.downloadData(null);
		// wait for downloading to complete
		future.get();
		// start the strategy
		LOGGER.info("Starting strategy");  

		client.startStrategy(new IStrategy(){

		    private Instrument instrument = Instrument.EURUSD;

		    private IConsole console;
		    private IIndicators indicators;
		    
		    private double maxTolerance = 0.1;

		    @Override
		    public void onStart(IContext context) throws JFException {

		        console = context.getConsole();
		        indicators = context.getIndicators();
		    }
		    
		    private void printIndies(ITick tick) throws JFException{
		    	
		        long start = System.nanoTime();
		        print("print indicator results for tick=" + tick);
		        print((System.nanoTime() - start), " sma=", indicators.sma(Instrument.EURUSD, Period.ONE_HOUR, OfferSide.BID, IIndicators.AppliedPrice.CLOSE, 50, Filter.ALL_FLATS, 1, tick.getTime(), 0));        
		        start = System.nanoTime();
		        
		        print((System.nanoTime() - start), " rsi=", indicators.rsi(instrument, Period.ONE_MIN, OfferSide.BID, IIndicators.AppliedPrice.HIGH, 7, Filter.ALL_FLATS, 30, tick.getTime(), 0));        
		        start = System.nanoTime();
		        
		        print((System.nanoTime() - start), " macd=", indicators.macd(instrument, Period.FIVE_MINS, OfferSide.BID, IIndicators.AppliedPrice.HIGH, 3, 9, 3, Filter.ALL_FLATS, 30, tick.getTime(), 0));        
		        start = System.nanoTime();
		        
		        print((System.nanoTime() - start), " stoch=", indicators.stoch(instrument, Period.FIVE_MINS, OfferSide.BID, 10, 3, IIndicators.MaType.SMA, 3, IIndicators.MaType.SMA, Filter.ALL_FLATS, 30, tick.getTime(), 0));        
		        start = System.nanoTime();
		        
		        print((System.nanoTime() - start), " mfi=", indicators.mfi(instrument, Period.TEN_MINS, OfferSide.BID, 7, Filter.ALL_FLATS, 30, tick.getTime(), 0));        
		        start = System.nanoTime();

		    }
		    
		    private void print(Object o) {
		        console.getOut().println(o);
		    }
		    
		    private void print(long duration, String comment, Object result) {
		    	String resultStr = result instanceof double[] ? arrayToString((double[])result) : 
		    		result instanceof double[][] ? arrayToString((double[][])result) :
		    		result.toString();
		    	double durationSecs = duration / Math.pow(10, 9);
		        String str = String.format("duration = %.9f secs %s %s", durationSecs, comment, resultStr);
		        if(durationSecs < maxTolerance){
		            print(str);
		        } else {
		            console.getErr().println(str);
		        }
		    }
		    
			private String arrayToString(double[] arr) {
				StringBuffer sb = new StringBuffer();
				for (int r = 0; r < arr.length; r++) {
					sb.append(String.format("[%s] %.5f; ", r, arr[r]));
				}
				return sb.toString();
			}
		    
			private String arrayToString(double[][] arr) {
				StringBuffer sb = new StringBuffer();
				for (int r = 0; r < arr.length; r++) {
					for (int c = 0; c < arr[r].length; c++) {
						sb.append(String.format("[%s][%s] %.5f; ", r, c, arr[r][c]));
					}
					sb.append("; ");
				}
				return sb.toString();
			}

		    @Override
		    public void onTick(Instrument instrument, ITick tick) throws JFException {
		    	if(instrument == this.instrument){
		    		printIndies(tick);
		    	}
		    	
		    }

		    @Override
		    public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {}

		    @Override
		    public void onMessage(IMessage message) throws JFException {}

		    @Override
		    public void onAccount(IAccount account) throws JFException {}

		    @Override
		    public void onStop() throws JFException {}


			
		});
		// now it's running

	}
}
