Repository: OpenBB-finance/OpenBBTerminal
File: openbb_sdk/providers/intrinio/openbb_intrinio/models/options_chains.py (Python)

Code before:
    )
    implied_volatility: Optional[float] = Field(
        description="The implied volatility for the option at the end of day."
    )
    delta: Optional[float] = Field(description="The delta value at the end of day.")
    gamma: Optional[float] = Field(description="The gamma value at the end of day.")
    vega: Optional[float] = Field(description="The vega value at the end of day.")
    theta: Optional[float] = Field(description="The theta value at the end of day.")
    eod_date: Optional[dateType] = Field(
        description="Historical date for which the options chains data is from.",
    )
    dte: Optional[int] = Field(description="The number of days until expiry.")

    @validator("expiration", pre=True, check_fields=False)
    def date_validate(cls, v):  # pylint: disable=E0213
        """Return the datetime object from the date string"""
        return datetime.strptime(v, "%Y-%m-%d")


class IntrinioOptionsChainsFetcher(
    Fetcher[IntrinioOptionsChainsQueryParams, List[IntrinioOptionsChainsData]]
):
    """Transform the query, extract and transform the data from the Intrinio endpoints"""

    @staticmethod
    def get_options_tickers(api_key: str) -> List[str]:
        """Returns all tickers that have existing options contracts.

        Parameters
        ----------
        api_key: str
            Intrinio API key.

        Returns
        -------
        List[str]
            List of tickers
        """

        url = f"https://api-v2.intrinio.com/options/tickers?api_key={api_key}"

        r = intrinio_session.get(url, timeout=10)

        if r.status_code != 200:
            raise RuntimeError("HTTP Error -> Status Code: " + str(r.status_code))

        return r.json()["tickers"]

    @staticmethod
    def get_options_expirations(
        symbol: str,

Review comment (refactor):
Functions like these use a common functionality so they must be in helpers. Setting them as `staticmethod` does not solve the issue.

Code after:
        description="The implied volatility for the option at the end of day."
    )
    delta: Optional[float] = Field(description="The delta value at the end of day.")
    gamma: Optional[float] = Field(description="The gamma value at the end of day.")
    vega: Optional[float] = Field(description="The vega value at the end of day.")
    theta: Optional[float] = Field(description="The theta value at the end of day.")
    eod_date: Optional[dateType] = Field(
        description="Historical date for which the options chains data is from.",
    )
    dte: Optional[int] = Field(description="The number of days until expiry.")

    @validator("expiration", pre=True, check_fields=False)
    def date_validate(cls, v):  # pylint: disable=E0213
        """Return the datetime object from the date string"""
        return datetime.strptime(v, "%Y-%m-%d")


class IntrinioOptionsChainsFetcher(
    Fetcher[IntrinioOptionsChainsQueryParams, List[IntrinioOptionsChainsData]]
):
    """Transform the query, extract and transform the data from the Intrinio endpoints"""

    @staticmethod
    def generate_url(symbol, expiration, date, api_key):
        return f"https://api-v2.intrinio.com/options/chain/{symbol}/{expiration}/eod?date={date}&api_key={api_key}"

    @staticmethod
    def download_json_files(urls):
        results = []  # List to store the downloaded JSON data

        def download_single_file(url):
            response = make_request(url)
            json_data = response.json()
            results.append(json_data["chain"])

        with concurrent.futures.ThreadPoolExecutor() as executor:
            executor.map(download_single_file, urls)

        return results

    @staticmethod
    def get_historical_chain_with_greeks(
        symbol: str, date: Optional[Union[str, dateType]] = "", api_key: str = ""
    ):
        symbol = symbol.upper()
        SYMBOLS = Options.get_options_tickers(api_key)
        if symbol not in SYMBOLS:
            raise RuntimeError(f"{symbol}", "is not supported by Intrinio.")

        if not date:
            date = datetime.now().strftime("%Y-%m-%d")