diff options
author | James Maslek <jmaslek11@gmail.com> | 2023-08-28 10:50:30 -0400 |
---|---|---|
committer | James Maslek <jmaslek11@gmail.com> | 2023-08-28 10:50:30 -0400 |
commit | f0e1fb79fee1378abaf55c9b8403ec07bc819583 (patch) | |
tree | 9195c68605dc2b517124abd2212a3073170cf29f | |
parent | 0b7b63ebfa0c10861c257617a1f51eac10e24392 (diff) | |
parent | db9d462188d6115d9a3e215ea3b633bb26fcd97e (diff) |
Merge branch 'develop' of https://github.com/OpenBB-finance/OpenBBTerminal into develop
35 files changed, 2209 insertions, 83 deletions
diff --git a/build/pyinstaller/macOS_package_assets/OpenBB Terminal/OpenBB Terminal b/build/pyinstaller/macOS_package_assets/OpenBB Terminal/OpenBB Terminal index cec491e5f10..8975d7a8604 100755 --- a/build/pyinstaller/macOS_package_assets/OpenBB Terminal/OpenBB Terminal +++ b/build/pyinstaller/macOS_package_assets/OpenBB Terminal/OpenBB Terminal @@ -15,7 +15,17 @@ echo " |___/ " BOOTUP_MESSAGE=" The boot up process might take a while. Please be patient... + +Have you checked out Community Routines yet? You can access them through the OpenBB Hub! +Get started in less than 3 minutes: https://www.youtube.com/watch?v=UFh_Ku0fdtY + " echo "$BOOTUP_MESSAGE" +# Add some messages we can print out +messages=("" "" "" "" "Did you know that you can search for stocks from a given country by running stocks/search --exchangecountry COUNTRY") +# Pick a random one +index=$((RANDOM % ${#messages[@]})) +echo ${messages[$index]} + "$SCRIPTDIR"/.OpenBB/OpenBBTerminal diff --git a/openbb_terminal/alternative/alt_controller.py b/openbb_terminal/alternative/alt_controller.py index cc4e7e1713d..4352e8193df 100644 --- a/openbb_terminal/alternative/alt_controller.py +++ b/openbb_terminal/alternative/alt_controller.py @@ -22,7 +22,7 @@ class AlternativeDataController(BaseController): """Alternative Controller class""" CHOICES_COMMANDS: List[str] = ["hn"] - CHOICES_MENUS = ["covid", "oss", "realestate"] + CHOICES_MENUS = ["covid", "oss", "realestate", "companieshouse"] PATH = "/alternative/" CHOICES_GENERATION = True @@ -41,6 +41,7 @@ class AlternativeDataController(BaseController): mt.add_menu("covid") mt.add_menu("oss") mt.add_menu("realestate") + mt.add_menu("companieshouse") mt.add_raw("\n") mt.add_cmd("hn") console.print(text=mt.menu_text, menu="Alternative") @@ -94,3 +95,12 @@ class AlternativeDataController(BaseController): ) self.queue = self.load_class(RealEstateController, self.queue) + + @log_start_end(log=logger) + def call_companieshouse(self, _): + """Process companieshouse command.""" + from openbb_terminal.alternative.companieshouse.companieshouse_controller import ( + CompaniesHouseController, + ) + + self.queue = self.load_class(CompaniesHouseController, self.queue) diff --git a/openbb_terminal/alternative/companieshouse/companieshouse_controller.py b/openbb_terminal/alternative/companieshouse/companieshouse_controller.py new file mode 100644 index 00000000000..40353ba5b00 --- /dev/null +++ b/openbb_terminal/alternative/companieshouse/companieshouse_controller.py @@ -0,0 +1,337 @@ +"""Companies House Controller.""" +__docformat__ = "numpy" + +import argparse +import logging +from typing import List, Optional + +from openbb_terminal.alternative.companieshouse import companieshouse_view +from openbb_terminal.core.session.current_user import get_current_user +from openbb_terminal.custom_prompt_toolkit import NestedCompleter +from openbb_terminal.decorators import check_api_key, log_start_end +from openbb_terminal.helper_funcs import ( + EXPORT_ONLY_RAW_DATA_ALLOWED, + check_positive, +) +from openbb_terminal.menu import session +from openbb_terminal.parent_classes import BaseController +from openbb_terminal.rich_config import MenuText, console + +logger = logging.getLogger(__name__) + + +class CompaniesHouseController(BaseController): + + """Companies House Controller class.""" + + CHOICES_COMMANDS = [ + "search", + "load", + "officers", + "signifcontrol", + "filings", + "filingdocument", + "charges", + ] + PATH = "/alternative/companieshouse/" + CHOICES_GENERATION = True + + def __init__(self, queue: Optional[List[str]] = None): + """Construct Data.""" + super().__init__(queue) + + self.companyNo = "" + self.companyName = "" + self.filingCategory = "" + self.filing_total_count = 0 + self.filing_end_index = 0 + self.filing_start_index = 0 + if session and get_current_user().preferences.USE_PROMPT_TOOLKIT: + choices: dict = self.choices_default + self.completer = NestedCompleter.from_nested_dict(choices) + + def print_help(self): + """Print help""" + company_string = ( + f"{self.companyNo} ({self.companyName})" if self.companyNo else "" + ) + + mt = MenuText("alternative/companieshouse/") + mt.add_param("_company", company_string) + mt.add_raw("\n") + mt.add_cmd("search") + mt.add_cmd("load") + mt.add_cmd("officers") + mt.add_cmd("signifcontrol") + mt.add_cmd("filings") + mt.add_cmd("filingdocument") + mt.add_cmd("charges") + + console.print(text=mt.menu_text, menu="UK Companies House Data") + + @log_start_end(log=logger) + @check_api_key(["API_COMPANIESHOUSE_KEY"]) + def call_search(self, other_args: List[str]): + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="search", + description="Select the company name to search for. [Source: UK Companies House]", + ) + parser.add_argument( + "-n", + "--name", + help="name", + type=str.upper, + required="-h" not in other_args, + dest="name", + metavar="name", + nargs="+", + ) + + parser.add_argument( + "-l", + "--limit", + help="Number of entries to return", + type=check_positive, + required=False, + dest="limit", + metavar="limit", + default=20, + ) + + if ( + other_args + and "-n" not in other_args[0] + and "--name" not in other_args[0] + and "-h" not in other_args + ): + other_args.insert(0, "-n") + + ns_parser = self.parse_known_args_and_warn( + parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED + ) + + if ns_parser: + if ns_parser.name: + query = " ".join(ns_parser.name) + companieshouse_view.display_search( + query, ns_parser.limit, export=ns_parser.export + ) + else: + console.print("[red]No entries found for search string[/red]\n") + + @log_start_end(log=logger) + @check_api_key(["API_COMPANIESHOUSE_KEY"]) + def call_load(self, other_args: List[str]): + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="load", + description="Select the company number to get detailed info on. [Source: UK Companies House]", + ) + parser.add_argument( + "-c", + "--companyNo", + help="companyNo", + type=str.upper, + required="-h" not in other_args, + dest="companyNo", + metavar="companyNo", + ) + + if ( + other_args + and "-c" not in other_args[0] + and "--companyNo" not in other_args[0] + and "-h" not in other_args + ): + other_args.insert(0, "-c") + + ns_parser = self.parse_known_args_and_warn( + parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED + ) + + if ns_parser and ns_parser.companyNo: + self.companyNo = ns_parser.companyNo + company = companieshouse_view.display_company_info( + ns_parser.companyNo, export=ns_parser.export + ) + if company.dataAvailable(): + self.companyName = company.name + self.filing_total_count = 0 + self.filing_end_index = 0 + console.print(company.name) + console.print(company.address) + console.print(company.lastAccounts) + else: + console.print( + f"[red]No data found for company number {ns_parser.companyNo}[/red]\n" + ) + + @log_start_end(log=logger) + @check_api_key(["API_COMPANIESHOUSE_KEY"]) + def call_officers(self, other_args: List[str]): + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="officers", + description="Select the company number to retrieve officers for. [Source: UK Companies House]", + ) + + ns_parser = self.parse_known_args_and_warn( + parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED + ) + + if self.companyNo: + if ns_parser: + companieshouse_view.display_officers( + self.companyNo, export=ns_parser.export + ) + else: + console.print("Must load a company prior to using this command") + + @log_start_end(log=logger) + @check_api_key(["API_COMPANIESHOUSE_KEY"]) + def call_signifcontrol(self, other_args: List[str]): + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="signifcontrol", + description="Select the company number to retrieve persons with significant control of company. \ + [Source: UK Companies House]", + ) + + ns_parser = self.parse_known_args_and_warn( + parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED + ) + + if self.companyNo: + if ns_parser: + companieshouse_view.display_persons_with_significant_control( + self.companyNo, export=ns_parser.export + ) + else: + console.print("Must load a company prior to using this command") + + @log_start_end(log=logger) + @check_api_key(["API_COMPANIESHOUSE_KEY"]) + def call_filings(self, other_args: List[str]): + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="filings", + description="Select the company number to retrieve filling history for. [Source: UK Companies House]", + ) + + parser.add_argument( + "-k", + "--category", + help="category", + type=str.lower, + required=False, + dest="category", + metavar="category", + choices=[ + "accounts", + "address", + "capital", + "incorporation", + "officers", + "resolution", + ], + ) + + parser.add_argument( + "-l", + "--limit", + help="Number of entries to return", + type=check_positive, + required=False, + dest="limit", + metavar="limit", + default=100, + ) + + ns_parser = self.parse_known_args_and_warn( + parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED + ) + + if self.companyNo: + if ns_parser: + category = ns_parser.category if ns_parser.category else "" + self.filingCategory = category + filing_data = companieshouse_view.display_filings( + self.companyNo, category, ns_parser.limit, export=ns_parser.export + ) + self.filing_total_count = filing_data.total_count + self.filing_end_index = filing_data.end_index + self.filing_start_index = filing_data.start_index + else: + console.print("Must load a company prior to using this command") + + @log_start_end(log=logger) + @check_api_key(["API_COMPANIESHOUSE_KEY"]) + def call_filingdocument(self, other_args: List[str]): + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="filingdocument", + description="Select the company number and transaction ID to retrieve filling history for. \ + [Source: UK Companies House]", + ) + + parser.add_argument( + "-t", + "--transactionID", + help="transactionID", + action="store", + required=("-h" not in other_args), + dest="transactionID", + metavar="transactionID", + ) + + if ( + other_args + and "-t" not in other_args[0] + and "--transactionID" not in other_args[0] + and "-h" not in other_args + ): + other_args.insert(0, "-t") + + ns_parser = self.parse_known_args_and_warn( + parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED + ) + + if self.companyNo: + if ns_parser: + companieshouse_view.download_filing_document( + self.companyNo, + self.companyName, + ns_parser.transactionID, + export=ns_parser.export, + ) + else: + console.print("Must load a company prior to using this command") + + @log_start_end(log=logger) + @check_api_key(["API_COMPANIESHOUSE_KEY"]) + def call_charges(self, other_args: List[str]): + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="charges", + description="Select the company number to retrieve officers for. [Source: UK Companies House]", + ) + + ns_parser = self.parse_known_args_and_warn( + parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED + ) + + if self.companyNo: + if ns_parser: + companieshouse_view.display_charges( + self.companyNo, export=ns_parser.export + ) + else: + console.print("Must load a company prior to using this command") diff --git a/openbb_terminal/alternative/companieshouse/companieshouse_model.py b/openbb_terminal/alternative/companieshouse/companieshouse_model.py new file mode 100644 index 00000000000..462553956f8 --- /dev/null +++ b/openbb_terminal/alternative/companieshouse/companieshouse_model.py @@ -0,0 +1,481 @@ +""" UK Companies House Model """ +__docformat__ = "numpy" + +import logging + +import pandas as pd +import requests + +from openbb_terminal.alternative.companieshouse.company import Company +from openbb_terminal.alternative.companieshouse.company_doc import CompanyDocument +from openbb_terminal.alternative.companieshouse.filing_data import Filing_data +from openbb_terminal.core.session.constants import ( + TIMEOUT, +) +from openbb_terminal.core.session.current_user import get_current_user +from openbb_terminal.decorators import check_api_key, log_start_end + +logger = logging.getLogger(__name__) + + +@log_start_end(log=logger) +@check_api_key(["API_COMPANIESHOUSE_KEY"]) +def get_search_results(searchStr: str, limit: int = 20) -> pd.DataFrame: + """All companies with searchStr in their name. + + Parameters + ---------- + searchStr : str + The search string + limit : int + number of rows to return + + Returns + ------- + pd.DataFrame + All comapanies with the search string in their name. + + Example + ------- + >>> from openbb_terminal.sdk import openbb + >>> companies = openbb.alt.companieshouse.get_search_results("AstraZeneca") + """ + + df = pd.DataFrame() + + if not searchStr: + return df + + auth = requests.auth.HTTPBasicAuth( + get_current_user().credentials.API_COMPANIESHOUSE_KEY, "" + ) + r = requests.get( + "https://api.company-information.service.gov.uk/search/companies?q=" + + searchStr + + f"&items_per_page={limit}", + auth=auth, + timeout=TIMEOUT, + ) + returned_data = r.json() + company_data = [] + for index, item in enumerate(returned_data["items"]): + company_data.append( + { + "Name": item["title"], + "Company Number": item["company_number"], + "Status": item["company_status"], + } + ) + + df = pd.DataFrame(company_data) + return df + + +@log_start_end(log=logger) +@check_api_key(["API_COMPANIESHOUSE_KEY"]) +def get_company_info(company_number: str) -> Company: + """Gets company info by company number + + Parameters + ---------- + company_number : str + The company number. Use get_search_results() to lookup company numbers. + + Returns + ------- + self.address: str + Company address. + self.name: str + Company name. + self.dataAvailable(): bool + True if data is available. + self.lastAccounts: str + Period start and end. + + Example + ------- + >>> companies = openbb.alt.companieshouse.get_search_results("AstraZeneca") + >>> company_info = openbb.alt.companieshouse.get_company_info("02723534") + >>> name = company_info.name + """ + + auth = requests.auth.HTTPBasicAuth( + get_current_user().credentials.API_COMPANIESHOUSE_KEY, "" + ) + r = requests.get( + f"https://api.company-information.service.gov.uk/company/{company_number}", + auth=auth, + timeout=TIMEOUT, + ) + + last_accounts = {} + returned_data = r.json() + if returned_data.get("company_name"): + company_name = returned_data["company_name"] + if returned_data.get("accounts"): + last_accounts = returned_data["accounts"]["last_accounts"] + address = returned_data["registered_office_address"] + address_lines = [] + if address.get("address_line_1"): + address_lines.append(address.get("address_line_1") |