/*******************************************************************************
 * MyExpotData - Strategy example on how to export JForex to text files in     *
 * textual manner or to csv files to import in other programs                  *
 *                                                                             *
 * Developed by Dukascopy Community member JLongo                              *
 ******************************************************************************/

package myJForex.strategies;

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.IHistory;
import com.dukascopy.api.IIndicators;
import com.dukascopy.api.IMessage;
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.RequiresFullAccess;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.util.Calendar;
import java.util.HashSet;
import java.util.Set;
import javax.swing.JOptionPane;

/**
 * Strategy start
 */
@RequiresFullAccess
public class MyExportData implements IStrategy {
    // Base objects creation
    private IContext myContext;
    private IHistory myHistory;
    private IConsole myConsole;
    private IIndicators myIndicators;
    // Parameters window
    @Configurable("CSV (comma separated values) ? :")
    public boolean myCsv = false;
    @Configurable("Path and file name:")
    public String myFileName = "c:/temp/expordata.txt";
    // Some of the instruments that exits on Instrument enumeration don't are
    // tradable and we get exceptions if we try to subscribe them. We use this
    // string where we place all non tradable instruments
    private String myNotAllowedInstruments = "CHF/PLN EUR/BRL EUR/HUF EUR/MXN "
            + "EUR/RUB EUR/ZAR HUF/JPY MXN/JPY NZD/SGD USD/BRL USD/CZK USD/HUF "
            + "USD/RON ZAR/JPY";
    
    // other variables
    private int myMultiplier;
    private String date;
    
    /*
     *  onStart 
     */
    @Override
    public void onStart(IContext context) throws JFException {
        // as we use two areas where we sbscribe instruments, we use two
        // independent variables for them.
        Set subscribedInstruments = new HashSet();
        Set subscribedInstruments2 = new HashSet();
        // Base objects initialization
        myContext = context;
        myHistory = myContext.getHistory();
        myConsole = myContext.getConsole();
        myIndicators = myContext.getIndicators();
        // other variables
        Calendar myCalendar = Calendar.getInstance();
        int day = myCalendar.get(Calendar.DAY_OF_MONTH);
        int month = myCalendar.get(Calendar.MONTH) + 1;
        int year = myCalendar.get(Calendar.YEAR);
        int hour = myCalendar.get(Calendar.HOUR_OF_DAY);
        int minute = myCalendar.get(Calendar.MINUTE);
        date = "" + year + "-" + month + "-" + day + " " + hour + ":" + minute;
        // if myCsv is true, format for comma separated values 
        if (myCsv){
            // First line with field names to understand the fields values
            String myText = "Date, Instrument, Previous month high, Previous month open,"
                    + " Previous month close, Previous month low, Previous month range,"
                    + " Actual month high, actual month open, Actual month close,"
                    + " Actual month low, Actual month range, Previous week high,"
                    + " Previous week open, Previous week close, Previous week low,"
                    + " Previous week range, Actual week high, Actual week open,"
                    + " Actual week close, Actual week low, Actual week range, Previous day high,"
                    + " Previous day open, Previous day close, Previous day low,"
                    + " Previous day range, Monthly ATR14, Weekly ATR14, daily ATR14 \n";
            // loop by all instruments on Instrument
            for (Instrument i : Instrument.values()){
                // if the instrument is one the not allowed instruments, skip it
                if (myNotAllowedInstruments.contains(i.toString())){
                    continue;
                }
                // subscribe the instrument
                subscribedInstruments.add(i);
                myContext.setSubscribedInstruments(subscribedInstruments);
                // we need to be sure to give some time to the instrument to be 
                // subscribed, maximum 11 secs and show alerts on message 
                // window. We need to have the instrument subscribed to get the
                // values from
                int c = 10;
                while (!myContext.getSubscribedInstruments().contains(i) && c >= 0) {
                    try {
                        myConsole.getOut().println("Instrument not subscribed yet " + i);
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        myConsole.getOut().println(e.getMessage());
                    }
                c--;
                }
                // beggin the csv output
                myText += date + ",[" + i.name() + "]";
                try{
                    // p = previous, m = monthly, w = weekly, d = daily
                    // r = range
                    IBar pm, m, pw, w, pd, d;
                    int m14, w14, d14;
                    int rm, rw, rd, prm, prw, prd;
                    // get the pip scale
                    int pipScale = i.getPipScale();
                    // we use the multiplier to get the values in pips where needed
                    if (pipScale < 4){
                        myMultiplier = 100;
                    } else {
                        myMultiplier = 10000;
                    }
                    // get some values
                    pm = myHistory.getBar(i, Period.MONTHLY, OfferSide.BID, 1);
                    m = myHistory.getBar(i, Period.MONTHLY, OfferSide.BID, 0);
                    pw = myHistory.getBar(i, Period.WEEKLY, OfferSide.BID, 1);
                    w = myHistory.getBar(i, Period.WEEKLY, OfferSide.BID, 0);
                    pd = myHistory.getBar(i, Period.DAILY_SUNDAY_IN_MONDAY, OfferSide.BID, 1);
                    d = myHistory.getBar(i, Period.DAILY_SUNDAY_IN_MONDAY, OfferSide.BID, 0);
                    prm = (int) (myMultiplier * (pm.getHigh() - pm.getLow()));
                    rm = (int) (myMultiplier * (m.getHigh() - m.getLow()));
                    prw = (int) (myMultiplier * (pw.getHigh() - pw.getLow()));
                    rw = (int) (myMultiplier * (w.getHigh() - w.getLow()));
                    prd = (int) (myMultiplier * (pd.getHigh() - pd.getLow()));
                    rd = (int) (myMultiplier * (d.getHigh() - d.getLow()));
                    // process the values and format output
                    myText += "," + pm.getHigh();
                    myText += "," + pm.getOpen() + "," + pm.getClose();
                    myText += "," + pm.getLow();
                    myText += "," + prm;
                    myText += "," + m.getHigh();
                    myText += "," + m.getOpen() + "," + m.getClose();
                    myText += "," + m.getLow();
                    myText += "," + rm;
                    myText += "," + pw.getHigh();
                    myText += "," + pw.getOpen() + "," + pw.getClose();
                    myText += "," + pw.getLow();
                    myText += "," + prw;
                    myText += "," + w.getHigh();
                    myText += "," + w.getOpen() + "," + w.getClose();
                    myText += "," + w.getLow();
                    myText += "," + rw;
                    myText += "," + pd.getHigh();
                    myText += "," + pd.getOpen() + "," + pd.getClose();
                    myText += "," + pd.getLow();
                    myText += "," + prd;
                    myText += "," + d.getHigh();
                    myText += "," + d.getOpen() + "," + d.getClose();
                    myText += "," + d.getLow();
                    myText += "," + rd;
                    // get more values
                    m14 = (int) (myIndicators.atr(i, Period.MONTHLY, OfferSide.BID, 14, 1) * myMultiplier);
                    w14 = (int) (myIndicators.atr(i, Period.WEEKLY, OfferSide.BID, 14, 1) * myMultiplier);
                    d14 = (int) (myIndicators.atr(i, Period.DAILY_SUNDAY_IN_MONDAY, OfferSide.BID, 14, 1) * myMultiplier);
                    // process them
                    myText += "," + m14;
                    myText += "," + w14 + "," + d14 + "\n";
                } catch (Exception e) {
                    // if we can't get some of the values write this error to the output
                    myConsole.getOut().println(e.getMessage());
                    myText += "**** Error getting some values for this pair!!!**** \n";    
                }
                // write the instrument data to the file
                writeToFile(myText);
                // for new instrument
                myText = "";
                // remove previous subscribed instrument
                subscribedInstruments.remove(i);
            }
            myContext.stop();
        } else {
            // top of report
            String myText = "Report generated in " + date + "\n\n";
            // loop on all instruments of Instrument
            for (Instrument i : Instrument.values()){
                // if instrument not allowed, skip it
                if (myNotAllowedInstruments.contains(i.toString())){
                    continue;
                }
                // beggin the pair
                myText += "-*-*-*-*-*-*-*-*-*-*-\n";
                // subscribe the instrument
                subscribedInstruments2.add(i);
                myContext.setSubscribedInstruments(subscribedInstruments2);
                // we need to be sure to give some time to the instrument to be 
                // subscribed, maximum 11 secs and show alerts on message 
                // window. We need to have the instrument subscribed to get the
                // values from
                int c = 10;
                while (!myContext.getSubscribedInstruments().contains(i) && c >= 0) {
                    try {
                        myConsole.getOut().println("Instrument not subscribed yet " + i);
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        myConsole.getOut().println(e.getMessage());
                    }
                    c--;
                }
                // start precessing the information
                myText += "[" + i.name() + "] \n";
                try{
                    // p = previous, m = monthly, w = weekly, d = daily
                    // r = range
                    IBar pm, m, pw, w, pd, d;
                    int m14, w14, d14;
                    int rm, rw, rd, prm, prw, prd;
                    // get pip scale
                    int pipScale = i.getPipScale();
                    // to transform some values in real pips
                    if (pipScale < 4){
                        myMultiplier = 100;
                    } else {
                        myMultiplier = 10000;
                    }
                    //get some values
                    pm = myHistory.getBar(i, Period.MONTHLY, OfferSide.BID, 1);
                    m = myHistory.getBar(i, Period.MONTHLY, OfferSide.BID, 0);
                    pw = myHistory.getBar(i, Period.WEEKLY, OfferSide.BID, 1);
                    w = myHistory.getBar(i, Period.WEEKLY, OfferSide.BID, 0);
                    pd = myHistory.getBar(i, Period.DAILY_SUNDAY_IN_MONDAY, OfferSide.BID, 1);
                    d = myHistory.getBar(i, Period.DAILY_SUNDAY_IN_MONDAY, OfferSide.BID, 0);
                    prm = (int) (myMultiplier * (pm.getHigh() - pm.getLow()));
                    rm = (int) (myMultiplier * (m.getHigh() - m.getLow()));
                    prw = (int) (myMultiplier * (pw.getHigh() - pw.getLow()));
                    rw = (int) (myMultiplier * (w.getHigh() - w.getLow()));
                    prd = (int) (myMultiplier * (pd.getHigh() - pd.getLow()));
                    rd = (int) (myMultiplier * (d.getHigh() - d.getLow()));
                    // process the values 
                    myText += "Previous month bar -> High: " + pm.getHigh();
                    myText += " Open: " + pm.getOpen() + " Close: " + pm.getClose();
                    myText += " Low: " + pm.getLow();
                    myText += " Range: " + prm + "\n";
                    myText += "This month bar -> High: " + m.getHigh();
                    myText += " Open: " + m.getOpen() + " Close: " + m.getClose();
                    myText += " Low: " + m.getLow();
                    myText += " Range: " + rm + "\n";
                    myText += "Previous week bar -> High: " + pw.getHigh();
                    myText += " Open: " + pw.getOpen() + " Close: " + pw.getClose();
                    myText += " Low: " + pw.getLow();
                    myText += " Range: " + prw + "\n";
                    myText += "This week bar -> High: " + w.getHigh();
                    myText += " Open: " + w.getOpen() + " Close: " + w.getClose();
                    myText += " Low: " + w.getLow();
                    myText += " Range: " + rw + "\n";
                    myText += "Previous day bar -> High: " + pd.getHigh();
                    myText += " Open: " + pd.getOpen() + " Close: " + pd.getClose();
                    myText += " Low: " + pd.getLow();
                    myText += " Range: " + prd + "\n";
                    myText += "This day bar -> High: " + d.getHigh();
                    myText += " Open: " + d.getOpen() + " Close: " + d.getClose();
                    myText += " Low: " + d.getLow();
                    myText += " Range: " + rd + "\n";
                    // get other values
                    m14 = (int) (myIndicators.atr(i, Period.MONTHLY, OfferSide.BID, 14, 1) * myMultiplier);
                    w14 = (int) (myIndicators.atr(i, Period.WEEKLY, OfferSide.BID, 14, 1) * myMultiplier);
                    d14 = (int) (myIndicators.atr(i, Period.DAILY_SUNDAY_IN_MONDAY, OfferSide.BID, 14, 1) * myMultiplier);
                    // process them
                    myText += "ATR(14) values -> Monthly: " + m14;
                    myText += " Weekly: " + w14 + " Daily: " + d14 + "\n\n";
                } catch (Exception e) {
                    // if we can't get some pair values write the error to the output
                    myConsole.getOut().println(e.getMessage());
                    myText += "**** Error getting some values for this pair!!!**** \n\n";    
                }
                // write the output to the file
                writeToFile(myText);
                // remove instrument  
                subscribedInstruments.remove(i);
                myText = "";
            }
            //stop the strategy at end of loop
            myContext.stop();
        }
    }

    @Override
    public void onTick(Instrument instrument, ITick tick) throws JFException {
        
    }

    @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 {
        
    }

    /*
     * Called at strategy stop
     */
    @Override
    public void onStop() throws JFException {
        // warn the user at strategy end
        JOptionPane.showMessageDialog(null, "This strategy has finished !", "Strategy Alert",JOptionPane.WARNING_MESSAGE);
    }
    
    /*
     * Writes the string to the file provided on parameter
     */
    public void writeToFile(String text){
        try {
            // create or open for add
            FileWriter fileOpenWithAppendMode = new FileWriter(myFileName, true);
            BufferedWriter contentToWrite = new BufferedWriter(fileOpenWithAppendMode);
            // write to the file
            contentToWrite.append(text);
            // close file
            contentToWrite.close();
        } catch (Exception e) {
            // if any error fond, put it on message window
            myConsole.getOut().print("Error creating or accessing the file: " + e.getMessage());
        }
    }
}
