diff --git a/README.md b/README.md index 6855c30..7f4413c 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ pip install pycot-reports ## How to use ```python -from pycot import legacy_report, disaggregated_report, financial_report +from pycot.reports import legacy_report, disaggregated_report, financial_report ``` Lets have a look at some examples. @@ -30,7 +30,7 @@ Lets have a look at some examples. ### Legacy Report (All Contracts) ```python -from pycot import legacy_report +from pycot.reports import legacy_report contract_name = ("FED FUNDS - CHICAGO BOARD OF TRADE", "30-DAY FEDERAL FUNDS - CHICAGO BOARD OF TRADE") df = legacy_report("legacy_fut", contract_name) ``` @@ -57,7 +57,7 @@ Date ... ### Disaggregated Report (Commodities) ```python -from pycot import disaggregated_report +from pycot.reports import disaggregated_report contract_name = ("BRENT LAST DAY - NEW YORK MERCANTILE EXCHANGE", "BRENT CRUDE OIL LAST DAY - NEW YORK MERCANTILE EXCHANGE") df = disaggregated_report("disaggregated_futopt", contract_name) ``` @@ -84,7 +84,7 @@ Date . ### Financial Report (Financial Instruments) ```python -from pycot import financial_report +from pycot.reports import financial_report contract_name = ("UST 10Y NOTE - CHICAGO BOARD OF TRADE", "10-YEAR U.S. TREASURY NOTES - CHICAGO BOARD OF TRADE", "10 YEAR U.S. TREASURY NOTES - CHICAGO BOARD OF TRADE") df = financial_report("traders_in_financial_futures_fut", contract_name) ``` diff --git a/pycot/extract_report_data.py b/pycot/extract_report_data.py index fabcc91..5e75081 100644 --- a/pycot/extract_report_data.py +++ b/pycot/extract_report_data.py @@ -9,7 +9,8 @@ import pandas as pd import requests -from exceptions import InvalidReportType + +from pycot.exceptions import InvalidReportType BASE_PATH = Path(__file__).parent.parent diff --git a/pycot/pycot.py b/pycot/reports.py similarity index 79% rename from pycot/pycot.py rename to pycot/reports.py index 5738a34..6e313df 100644 --- a/pycot/pycot.py +++ b/pycot/reports.py @@ -1,42 +1,10 @@ from functools import lru_cache -import numpy as np import pandas as pd -from exceptions import InvalidReportType -from extract_report_data import COT, get_formating_data - -def format_dataframe( - data: pd.DataFrame, - names: list, - columns: list, -) -> pd.DataFrame: - """ - Helper function to format the data retrieved from the CFTC website. - """ - df = data.reindex(columns=columns) # Limit the columns to the ones we need (please adjust to your liking in format_columns.json) - df.rename(columns=dict(zip(columns, names)), inplace=True) - df["Date"] = pd.to_datetime(df["Date"]) - df.set_index(["Date", "Contract Name"], inplace=True) - df.replace(".", np.nan, inplace=True) - df = df.astype(float) - df.reset_index(inplace=True) - df.set_index("Date", inplace=True) - return df - - -def get_contract( - df: pd.DataFrame, - contract_name: str | tuple, -) -> pd.DataFrame: - """ - Retrieves the Commitment of Traders Reports data for a specific contract or list of contracts. - """ - if isinstance(contract_name, str): - return df[df["Contract Name"] == contract_name] - - data = [df[df["Contract Name"] == contract] for contract in contract_name if contract in df["Contract Name"].unique()] - return pd.concat(data) +from pycot.exceptions import InvalidReportType +from pycot.extract_report_data import COT, get_formating_data +from pycot.utils import format_dataframe, get_contract @lru_cache @@ -54,7 +22,7 @@ def legacy_report( A pandas DataFrame with the legacy futures Commitment of Traders data. Example: - >>> from pycot import legacy_report + >>> from pycot.reports import legacy_report >>> legacy_report("legacy_fut", ("FED FUNDS - CHICAGO BOARD OF TRADE", "30-DAY FEDERAL FUNDS - CHICAGO BOARD OF TRADE")) """ if report_type not in ["legacy_fut", "legacy_futopt"]: @@ -84,7 +52,7 @@ def disaggregated_report( A pandas DataFrame with the disaggregated futures and options report. Example: - >>> from pycot import disaggregated_report + >>> from pycot.reports import disaggregated_report >>> disaggregated_report("disaggregated_fut", ("BRENT LAST DAY - NEW YORK MERCANTILE EXCHANGE", "BRENT CRUDE OIL LAST DAY - NEW YORK MERCANTILE EXCHANGE")) """ if report_type not in ["disaggregated_fut", "disaggregated_futopt"]: @@ -121,7 +89,7 @@ def financial_report( A pandas DataFrame with the financial futures and options report. Example: - >>> from pycot import financial_report + >>> from pycot.reports import financial_report >>> financial_report("financial_fut", ("UST 10Y NOTE - CHICAGO BOARD OF TRADE", "10-YEAR U.S. TREASURY NOTES - CHICAGO BOARD OF TRADE", "10 YEAR U.S. TREASURY NOTES - CHICAGO BOARD OF TRADE")) """ if report_type not in ["traders_in_financial_futures_fut", "traders_in_financial_futures_futopt"]: diff --git a/pycot/utils.py b/pycot/utils.py new file mode 100644 index 0000000..87680a6 --- /dev/null +++ b/pycot/utils.py @@ -0,0 +1,35 @@ +import numpy as np +import pandas as pd + + +def format_dataframe( + data: pd.DataFrame, + names: list, + columns: list, +) -> pd.DataFrame: + """ + Helper function to format the data retrieved from the CFTC website. + """ + df = data.reindex(columns=columns) # Limit the columns to the ones we need (please adjust to your liking in format_columns.json) + df.rename(columns=dict(zip(columns, names)), inplace=True) + df["Date"] = pd.to_datetime(df["Date"]) + df.set_index(["Date", "Contract Name"], inplace=True) + df.replace(".", np.nan, inplace=True) + df = df.astype(float) + df.reset_index(inplace=True) + df.set_index("Date", inplace=True) + return df + + +def get_contract( + df: pd.DataFrame, + contract_name: str | tuple, +) -> pd.DataFrame: + """ + Retrieves the Commitment of Traders Reports data for a specific contract or list of contracts. + """ + if isinstance(contract_name, str): + return df[df["Contract Name"] == contract_name] + + data = [df[df["Contract Name"] == contract] for contract in contract_name if contract in df["Contract Name"].unique()] + return pd.concat(data) diff --git a/pycot/version.py b/pycot/version.py index 27fdca4..81f0fde 100644 --- a/pycot/version.py +++ b/pycot/version.py @@ -1 +1 @@ -__version__ = "0.0.3" +__version__ = "0.0.4" diff --git a/tests/test_reports.py b/tests/test_reports.py new file mode 100644 index 0000000..d2c531e --- /dev/null +++ b/tests/test_reports.py @@ -0,0 +1,56 @@ +import pandas as pd +import pytest + +from pycot import reports + + +@pytest.mark.parametrize( + "report_type,contract_name", + [ + ( + "legacy_fut", + ( + "FED FUNDS - CHICAGO BOARD OF TRADE", + "30-DAY FEDERAL FUNDS - CHICAGO BOARD OF TRADE", + ), + ), + ], +) +def test_legacy_report(report_type, contract_name): + df = reports.legacy_report(report_type, contract_name) + assert isinstance(df, pd.DataFrame) + + +@pytest.mark.parametrize( + "report_type,contract_name", + [ + ( + "disaggregated_futopt", + ( + "BRENT LAST DAY - NEW YORK MERCANTILE EXCHANGE", + "BRENT CRUDE OIL LAST DAY - NEW YORK MERCANTILE EXCHANGE", + ), + ), + ], +) +def test_disaggregated_report(report_type, contract_name): + df = reports.disaggregated_report(report_type, contract_name) + assert isinstance(df, pd.DataFrame) + + +@pytest.mark.parametrize( + "report_type,contract_name", + [ + ( + "traders_in_financial_futures_fut", + ( + "UST 10Y NOTE - CHICAGO BOARD OF TRADE", + "10-YEAR U.S. TREASURY NOTES - CHICAGO BOARD OF TRADE", + "10 YEAR U.S. TREASURY NOTES - CHICAGO BOARD OF TRADE", + ), + ), + ], +) +def test_financial_report(report_type, contract_name): + df = reports.financial_report(report_type, contract_name) + assert isinstance(df, pd.DataFrame)