alvarobartt / investpy

Financial Data Extraction from Investing.com with Python
https://investpy.readthedocs.io/
MIT License
1.59k stars 374 forks source link

New way to get technical analysis from investing.com #614

Open danielWagnerr opened 1 year ago

danielWagnerr commented 1 year ago

I used the techincal_indicators function to get analysis of currency crosses, but with these new changes from Investing, this method stopped working.

I created one that gets the analyzes ONLY OF CURRENCY CROSSES:

technical.py:

def currency_crosses_analysis(name, interval):
    """
    This function retrieves the technical analysis calculated by Investing.com for a given currency cross for different
    time intervals. So on, the user must provide the name of the currency cross and the interval which defines the update frequency of the calculations of the technical indicators (mainly momentum indicators).

    Args:
        name (:obj:`str`):
            name of the currency cross to retrieve the technical indicators table from. (e.g. 'eur/usd').
        interval (:obj:`str`):
            time interval of the resulting calculations, available values are: `5mins`, `15mins`, `30mins`, `1hour`,
            `5hours`, `daily`, `weekly` and `monthly`.

    Returns:
        :obj:`str` - A string containing the current analysis calculated by Investing.com

    Raises:
        ValueError: raised if any of the introduced parameters is not valid or errored.
        ConnectionError: raised if the connection to Investing.com errored or could not be established.
    """

    if not name or not isinstance(name, str):
        raise ValueError("ERR#0116: the parameter name must be specified and must be a string.")

    if not interval or not isinstance(interval, str):
        raise ValueError("ERR#0121: interval value is mandatory and must be a string.")

    if interval not in cst.INTERVAL_FILTERS.keys():
        raise ValueError(
            "ERR#0120: introduced interval value does not exist. Available values are: "
            + ", ".join(cst.INTERVAL_FILTERS.keys())
        )

    currency_data = resource_to_data(path_to_data=cst.PRODUCT_TYPE_FILES["currency_cross"], technical_analysis=True)
    name = unidecode(name.lower().strip())
    check = "name"

    if name not in list(currency_data[check].apply(unidecode).str.lower()):
        raise ValueError("ERR#0122: introduced name does not exist in the introduced country (if required).")

    url = "https://br.investing.com/technical/Service/GetSummaryTable"
    headers = CaseInsensitiveDict(
        {
            "authority": "www.investing.com",
            "accept": "application/json, text/javascript, */*; q=0.01",
            "accept-language": "en-US,en;q=0.9",
            "content-type": "application/x-www-form-urlencoded",
            "origin": "https://www.investing.com",
            "referer": "https://www.investing.com/technical/technical-summary",
            "sec-fetch-dest": "empty",
            "sec-fetch-mode": "cors",
            "sec-fetch-site": "same-origin",
            "x-requested-with": "XMLHttpRequest",
            "user-agent": random_user_agent(),
        }
    )

    product_id = currency_data.loc[(currency_data[check].apply(unidecode).str.lower() == name).idxmax(), "id"]
    data = f"tab=forex&options%5Bperiods%5D%5B%5D={cst.INTERVAL_FILTERS[interval]}&options%5Breceive_email%5D=false&options%5Bcurrencies%5D%5B%5D={product_id}"

    response = requests.post(url, headers=headers, data=data)
    if response.status_code != 200:
        raise ConnectionError("ERR#0015: error " + str(response.status_code) + ", try again later.")

    root = fromstring(json.loads(response.text)["html"])

    for element in cst.TECHNICAL_INDICATORS_CSS_CLASSES:
        summary_root = root.xpath(f"//td[@class='{element}']")
        if summary_root:
            break

    action = summary_root[0].text_content()
    return action

constant.py:

TECHNICAL_INDICATORS_CSS_CLASSES = [
    "redFont bold left arial_14 js-socket-elem",
    "lightgrayFont bold left arial_14 js-socket-elem",
    "greenFont bold left arial_14 js-socket-elem",
]

I didn't open a pull request because I don't know if my code complies with the standards, I created this issue to help in case anyone has the same problem

alvarobartt commented 1 year ago

Hi @danielWagnerr thanks for posting this alternate solution, I'll try to test it on investiny in the meantime!

InnovArul commented 1 year ago

@alvarobartt Is this method useful in investiny?