<commit_before>package eu.yaga.stockanalyzer.service.impl;

import com.jimmoores.quandl.DataSetRequest;
import com.jimmoores.quandl.QuandlSession;
import com.jimmoores.quandl.Row;
import com.jimmoores.quandl.TabularResult;
import com.jimmoores.quandl.util.QuandlRuntimeException;
import eu.yaga.stockanalyzer.model.FundamentalData;
import eu.yaga.stockanalyzer.model.RateProgressBean;
import eu.yaga.stockanalyzer.model.StockIndex;
import eu.yaga.stockanalyzer.model.historicaldata.HistoricalDataQuote;
import eu.yaga.stockanalyzer.service.HistoricalExchangeRateService;
import eu.yaga.stockanalyzer.util.HttpHelper;
import eu.yaga.stockanalyzer.util.QuandlCode;
import eu.yaga.stockanalyzer.util.QuandlProperties;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.threeten.bp.DateTimeUtils;
import org.threeten.bp.LocalDate;
import org.threeten.bp.ZoneId;
import org.threeten.bp.format.DateTimeFormatter;
import org.threeten.bp.temporal.ChronoUnit;

import java.net.MalformedURLException;
import java.net.URL;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;

/**
 * Implementation of the {@link HistoricalExchangeRateService}
 */
public class QuandlHistoricalExchangeRateServiceImpl implements HistoricalExchangeRateService {

    @Autowired
    private QuandlProperties quandlProperties;

    private static final Logger log = LoggerFactory.getLogger(QuandlHistoricalExchangeRateServiceImpl.class);

    // Quandl Frankfurt Stock Exchange / XETRA
    private static final String FSE_PREFIX = "FSE/";
    private static final String FSE_POSTFIX = "_X";
    // Quandl Stuttgart Stock Exchange
    private static final String SSE_PREFIX = "SSE/";
    // Quandl US companies
    private static final String US_PREFIX = "WIKI/";
    // Quandl Google finance
    private static final String GOOG_FRA_PREFIX = "GOOG/FRA_";
    private static final String GOOG_NASDAQ_PREFIX = "GOOG/NASDAQ_";

    private DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    private DateTimeFormatter dtfGermany = DateTimeFormatter.ofPattern("dd.MM.yyyy");

    /**
     * This method returns historical exchange Rates of the given stock
     *
     * @param symbol Symbol of the stock
     * @param dateStringFrom   Date of the start of the historical data (yyyy-MM-dd)
     * @param dateStringTo     Date of the end of the historical data (yyyy-MM-dd)
     * @return Historical Exchange Rates
     */
    @Override
    public List<HistoricalDataQuote> getHistoricalExchangeRates(String symbol, String dateStringFrom, String dateStringTo) throws ParseException {
        log.info("Getting HistoricalExchangeRates for: " + symbol + " " + dateStringFrom + " " + dateStringTo);
        String[] splitSymbol = symbol.split("\\.");
        String cleanSymbol = splitSymbol[0];
        String exchange = "";
        if (splitSymbol.length > 1) {
            exchange = splitSymbol[1];
        }

        List<QuandlCode> quandlCodeList = buildQuandlCode(cleanSymbol, exchange);

        log.info("Clean Symbol: " + cleanSymbol);

        LocalDate dateTo = LocalDate.now();
        if (dateStringTo != null) {
            dateTo = LocalDate.parse(dateStringTo, DateTimeFormatter.ISO_LOCAL_DATE);
        }

        LocalDate dateFrom = LocalDate.now().minusYears(1);
        if (dateStringFrom != null) {
            dateFrom = LocalDate.parse(dateStringFrom, DateTimeFormatter.ISO_LOCAL_DATE);
        }

        if (dateFrom.equals(dateTo)) {
            throw new RuntimeException("The dates may not be equal!");
        }
        if (dateFrom.isAfter(dateTo)) {
            throw new RuntimeException("The from date has to be before the to date!");
        }

        List<HistoricalDataQuote> quoteList = new ArrayList<>();
        QuandlSession session = QuandlSession.create(quandlProperties.getAuth().getToken());
        for (QuandlCode quandlCode : quandlCodeList) {
            log.info("Querying: " + quandlCode.getCode() + " from: " + dateFrom + " to: " + dateTo);
            try {
                TabularResult tabularResult = session.getDataSet(
                        DataSetRequest.Builder
                                .of(quandlCode.getCode())
                                .withStartDate(dateFrom)
                                .withEndDate(dateTo)
                                .build());

                log.info(tabularResult.toPrettyPrintedString());

                for (Row row : tabularResult) {
                    String dateString = row.getString("Date");
                    double close = row.getDouble(quandlCode.getCloseColumnName());
                    quoteList.add(new HistoricalDataQuote(symbol, dateString, close));
                }
                break;
            } catch (QuandlRuntimeException e) {
                log.warn("Error requesting quandl code: " + quandlCode.getCode(), e);
            }
        }

        return quoteList;
    }

    /**
     * Generates a list of quandlCodes to try
     * @param cleanSymbol the stocks symbol
     * @param exchange the symbol of the exchange
     * @return a list of Strings with quandl codes
     */
    private List<QuandlCode> buildQuandlCode(String cleanSymbol, String exchange) {

        List<QuandlCode> quandlCodeList = new ArrayList<>();

        switch (exchange) {
            case "F":
            case "DE":
                quandlCodeList.add(new QuandlCode(GOOG_FRA_PREFIX + cleanSymbol, "EUR", "Close"));
                quandlCodeList.add(new QuandlCode(FSE_PREFIX + cleanSymbol + FSE_POSTFIX, "EUR", "Close"));
                quandlCodeList.add(new QuandlCode(SSE_PREFIX + cleanSymbol, "EUR", "Last"));
                break;
            case "US":
                quandlCodeList.add(new QuandlCode(US_PREFIX + cleanSymbol, "USD", "Close"));
                quandlCodeList.add(new QuandlCode(GOOG_NASDAQ_PREFIX + cleanSymbol, "USD", "Close"));
                break;
            default:
                quandlCodeList.add(new QuandlCode(US_PREFIX + cleanSymbol, "USD", "Close"));
                quandlCodeList.add(new QuandlCode(GOOG_FRA_PREFIX + cleanSymbol, "EUR", "Close"));
                quandlCodeList.add(new QuandlCode(GOOG_NASDAQ_PREFIX + cleanSymbol, "USD", "Close"));
        }

        return quandlCodeList;
    }

    /**
     * This method returns the stock's reaction to quarterly figures (comparing it to its index)
     *
     * @param fundamentalData of the stock
     * @return the progress difference to the index
     */
    @Override
    public double getReactionToQuarterlyFigures(FundamentalData fundamentalData) {
        try {
            Date dateLegacy = fundamentalData.getLastQuarterlyFigures();
            String symbol = fundamentalData.getSymbol();
            String indexSymbol = fundamentalData.getStockIndex().getSymbol();

            if (dateLegacy == null || symbol == null || indexSymbol == null) {
                return -9999;
            }
<commit_msg>add Euronext Stock Exchange<commit_after>package eu.yaga.stockanalyzer.service.impl;

import com.jimmoores.quandl.DataSetRequest;
import com.jimmoores.quandl.QuandlSession;
import com.jimmoores.quandl.Row;
import com.jimmoores.quandl.TabularResult;
import com.jimmoores.quandl.util.QuandlRuntimeException;
import eu.yaga.stockanalyzer.model.FundamentalData;
import eu.yaga.stockanalyzer.model.RateProgressBean;
import eu.yaga.stockanalyzer.model.StockIndex;
import eu.yaga.stockanalyzer.model.historicaldata.HistoricalDataQuote;
import eu.yaga.stockanalyzer.service.HistoricalExchangeRateService;
import eu.yaga.stockanalyzer.util.HttpHelper;
import eu.yaga.stockanalyzer.util.QuandlCode;
import eu.yaga.stockanalyzer.util.QuandlProperties;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.threeten.bp.DateTimeUtils;
import org.threeten.bp.LocalDate;
import org.threeten.bp.ZoneId;
import org.threeten.bp.format.DateTimeFormatter;
import org.threeten.bp.temporal.ChronoUnit;

import java.net.MalformedURLException;
import java.net.URL;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;

/**
 * Implementation of the {@link HistoricalExchangeRateService}
 */
public class QuandlHistoricalExchangeRateServiceImpl implements HistoricalExchangeRateService {

    @Autowired
    private QuandlProperties quandlProperties;

    private static final Logger log = LoggerFactory.getLogger(QuandlHistoricalExchangeRateServiceImpl.class);

    // Quandl Frankfurt Stock Exchange / XETRA
    private static final String FSE_PREFIX = "FSE/";
    private static final String FSE_POSTFIX = "_X";
    // Quandl Stuttgart Stock Exchange
    private static final String SSE_PREFIX = "SSE/";
    // Quandl US companies
    private static final String US_PREFIX = "WIKI/";
    // Quandl Google finance
    private static final String GOOG_FRA_PREFIX = "GOOG/FRA_";
    private static final String GOOG_NASDAQ_PREFIX = "GOOG/NASDAQ_";
    // Quandl Euronext Stock Exchange
    private static final String EURONEXT_PREFIX = "EURONEXT/";

    private DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    private DateTimeFormatter dtfGermany = DateTimeFormatter.ofPattern("dd.MM.yyyy");

    /**
     * This method returns historical exchange Rates of the given stock
     *
     * @param symbol Symbol of the stock
     * @param dateStringFrom   Date of the start of the historical data (yyyy-MM-dd)
     * @param dateStringTo     Date of the end of the historical data (yyyy-MM-dd)
     * @return Historical Exchange Rates
     */
    @Override
    public List<HistoricalDataQuote> getHistoricalExchangeRates(String symbol, String dateStringFrom, String dateStringTo) throws ParseException {
        log.info("Getting HistoricalExchangeRates for: " + symbol + " " + dateStringFrom + " " + dateStringTo);
        String[] splitSymbol = symbol.split("\\.");
        String cleanSymbol = splitSymbol[0];
        String exchange = "";
        if (splitSymbol.length > 1) {
            exchange = splitSymbol[1];
        }

        List<QuandlCode> quandlCodeList = buildQuandlCode(cleanSymbol, exchange);

        log.info("Clean Symbol: " + cleanSymbol);

        LocalDate dateTo = LocalDate.now();
        if (dateStringTo != null) {
            dateTo = LocalDate.parse(dateStringTo, DateTimeFormatter.ISO_LOCAL_DATE);
        }

        LocalDate dateFrom = LocalDate.now().minusYears(1);
        if (dateStringFrom != null) {
            dateFrom = LocalDate.parse(dateStringFrom, DateTimeFormatter.ISO_LOCAL_DATE);
        }

        if (dateFrom.equals(dateTo)) {
            throw new RuntimeException("The dates may not be equal!");
        }
        if (dateFrom.isAfter(dateTo)) {
            throw new RuntimeException("The from date has to be before the to date!");
        }

        List<HistoricalDataQuote> quoteList = new ArrayList<>();
        QuandlSession session = QuandlSession.create(quandlProperties.getAuth().getToken());
        for (QuandlCode quandlCode : quandlCodeList) {
            log.info("Querying: " + quandlCode.getCode() + " closeColumn: " + quandlCode.getCloseColumnName() + " from: " + dateFrom + " to: " + dateTo);
            try {
                TabularResult tabularResult = session.getDataSet(
                        DataSetRequest.Builder
                                .of(quandlCode.getCode())
                                .withStartDate(dateFrom)
                                .withEndDate(dateTo)
                                .build());

                log.info(tabularResult.toPrettyPrintedString());

                for (Row row : tabularResult) {
                    String dateString = row.getString("Date");
                    double close = row.getDouble(quandlCode.getCloseColumnName());
                    quoteList.add(new HistoricalDataQuote(symbol, dateString, close));
                }
                break;
            } catch (QuandlRuntimeException e) {
                log.warn("Error requesting quandl code: " + quandlCode.getCode(), e);
            }
        }

        return quoteList;
    }

    /**
     * Generates a list of quandlCodes to try
     * @param cleanSymbol the stocks symbol
     * @param exchange the symbol of the exchange
     * @return a list of Strings with quandl codes
     */
    private List<QuandlCode> buildQuandlCode(String cleanSymbol, String exchange) {

        List<QuandlCode> quandlCodeList = new ArrayList<>();

        switch (exchange) {
            case "F":
            case "DE":
                quandlCodeList.add(new QuandlCode(GOOG_FRA_PREFIX + cleanSymbol, "EUR", "Close"));
                quandlCodeList.add(new QuandlCode(FSE_PREFIX + cleanSymbol + FSE_POSTFIX, "EUR", "Close"));
                quandlCodeList.add(new QuandlCode(SSE_PREFIX + cleanSymbol, "EUR", "Last"));
                break;
            case "US":
                quandlCodeList.add(new QuandlCode(US_PREFIX + cleanSymbol, "USD", "Close"));
                quandlCodeList.add(new QuandlCode(GOOG_NASDAQ_PREFIX + cleanSymbol, "USD", "Close"));
                break;
            case "AS":
                quandlCodeList.add(new QuandlCode(EURONEXT_PREFIX + cleanSymbol, "EUR", "Last"));
            default:
                quandlCodeList.add(new QuandlCode(US_PREFIX + cleanSymbol, "USD", "Close"));
                quandlCodeList.add(new QuandlCode(GOOG_FRA_PREFIX + cleanSymbol, "EUR", "Close"));
                quandlCodeList.add(new QuandlCode(GOOG_NASDAQ_PREFIX + cleanSymbol, "USD", "Close"));
        }

        return quandlCodeList;
    }

    /**
     * This method returns the stock's reaction to quarterly figures (comparing it to its index)
     *
     * @param fundamentalData of the stock
     * @return the progress difference to the index
     */
    @Override
    public double getReactionToQuarterlyFigures(FundamentalData fundamentalData) {
        try {
            Date dateLegacy = fundamentalData.getLastQuarterlyFigures();
            String symbol = fundamentalData.getSymbol();
            String indexSymbol = fundamentalData.getStockIndex().getSymbol();

            if (dateLegacy == null || symbol == null || indexSymbol == null) {
                return -9999;
            }

{'fraction_non_alphanumeric': 0.09627393124270912, 'fraction_numerical': 0.0013724010155767516, 'mean_word_length': 2.7571539056457848, 'pattern_counts': {'":': 7, '<': 17, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3025868', 'n_tokens_mistral': 4238, 'n_tokens_neox': 4088, 'n_words': 934}