kensho-kfinance 3.2.3__py3-none-any.whl → 3.2.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kensho-kfinance
3
- Version: 3.2.3
3
+ Version: 3.2.4
4
4
  Summary: Python CLI for kFinance
5
5
  Author-email: Luke Brown <luke.brown@kensho.com>, Michelle Keoy <michelle.keoy@kensho.com>, Keith Page <keith.page@kensho.com>, Matthew Rosen <matthew.rosen@kensho.com>, Nick Roshdieh <nick.roshdieh@kensho.com>
6
6
  Project-URL: source, https://github.com/kensho-technologies/kfinance
@@ -1,11 +1,11 @@
1
- kensho_kfinance-3.2.3.dist-info/licenses/AUTHORS.md,sha256=0h9ClbI0pu1oKj1M28ROUsaxrbZg-6ukQGl6X4y9noI,68
2
- kensho_kfinance-3.2.3.dist-info/licenses/LICENSE,sha256=bsY4blvSgq6o0FMQ3RXa2NCgco--nHCCchLXzxr6kms,83
3
- kfinance/CHANGELOG.md,sha256=DVWdxUssDxF0aqYQZwHmHEuG03gLFCJ4MVQU5JSbaMc,2836
1
+ kensho_kfinance-3.2.4.dist-info/licenses/AUTHORS.md,sha256=0h9ClbI0pu1oKj1M28ROUsaxrbZg-6ukQGl6X4y9noI,68
2
+ kensho_kfinance-3.2.4.dist-info/licenses/LICENSE,sha256=bsY4blvSgq6o0FMQ3RXa2NCgco--nHCCchLXzxr6kms,83
3
+ kfinance/CHANGELOG.md,sha256=X2CjISKbQr2oXL2f3r3X_grVSulqoOKOcaOfISxR_ls,2895
4
4
  kfinance/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
5
- kfinance/conftest.py,sha256=O9e1ddyTfqnZ1T-9ehnkXwK8PfxPdCHAI7-fke52Ouk,3281
5
+ kfinance/conftest.py,sha256=FIZNQyfFbldyVmzaLfWbnMGh6RiC4MZwOVax6815_Ms,3754
6
6
  kfinance/mcp.py,sha256=LTzCIlqsDKRD-0Xcpa_P99-JmJ8duAneO_-GzM43kjw,424
7
7
  kfinance/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- kfinance/version.py,sha256=TNj-kvOWGvYoPhrgqpaiE88yQqMnl_5-Khjy6DXZyxo,704
8
+ kfinance/version.py,sha256=l9_iMqlxiCOGrY70L8JWiTjDNINwByOH0aKGS6QXJ4I,704
9
9
  kfinance/client/README.md,sha256=DA5vg4uz1JmJNiqvYywrj46YNhOr584WO8L83Ysx_Mk,372
10
10
  kfinance/client/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  kfinance/client/batch_request_handling.py,sha256=opwJJAU2JtqH-s4vt8wRqhH34MiU4tQP6Ng7K6b3upA,6561
@@ -66,10 +66,10 @@ kfinance/domains/line_items/line_item_tools.py,sha256=C-E7W1cNSYRtqXp1ULAaXcxMh6
66
66
  kfinance/domains/line_items/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
67
67
  kfinance/domains/line_items/tests/test_line_item_tools.py,sha256=kZXbi_2oaR5cxxQk9Qj7pY0bvL7G3ch9-z9mprvxMGo,4106
68
68
  kfinance/domains/mergers_and_acquisitions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
69
- kfinance/domains/mergers_and_acquisitions/merger_and_acquisition_models.py,sha256=TLDYiR2TX-gb13px7xEYzOuYpwqRDjKCSnJFJaeAI8o,287
70
- kfinance/domains/mergers_and_acquisitions/merger_and_acquisition_tools.py,sha256=mSFFOODsWAh2qF5hrwjYU4Yr7pp9NtILdc_jNmgpSSM,8063
69
+ kfinance/domains/mergers_and_acquisitions/merger_and_acquisition_models.py,sha256=hJ87rnRj14FpmeEJDmEXLdUv37pBrcpKSWtb19j_vLQ,418
70
+ kfinance/domains/mergers_and_acquisitions/merger_and_acquisition_tools.py,sha256=8cTI5E6nAUbC45xFshIkNrICjujGo99Ane2xW8Y0IEo,9735
71
71
  kfinance/domains/mergers_and_acquisitions/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
72
- kfinance/domains/mergers_and_acquisitions/tests/test_merger_and_acquisition_tools.py,sha256=h9h8Z2fW3nZ-1f81C9gKn3GcnKvzvmvQJGjQGIqfauU,5924
72
+ kfinance/domains/mergers_and_acquisitions/tests/test_merger_and_acquisition_tools.py,sha256=ad4vv3qevHAaLZI0t5qEUPqEKTQm-e800ybA2ID5S_o,6640
73
73
  kfinance/domains/prices/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
74
74
  kfinance/domains/prices/price_models.py,sha256=6K2Yi8PQKJ92rf6ulcOSh9rBVOiPcUQD_WIRjpIRuSo,2156
75
75
  kfinance/domains/prices/price_tools.py,sha256=KrcJz3GT8iQElfLp0pArVVcV-jckX_Ggj4lgO0s3wkE,7192
@@ -95,7 +95,7 @@ kfinance/integrations/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMp
95
95
  kfinance/integrations/tests/test_example_notebook.py,sha256=NrqYFn_XyOn0YlV9QYEnNMBB7LEkg70pP1eqiLGxcBE,6529
96
96
  kfinance/integrations/tool_calling/README.md,sha256=TSk-AJddoEctzc0HXQvGNac2CckbnWxHcRDtEifSe1w,2029
97
97
  kfinance/integrations/tool_calling/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
98
- kfinance/integrations/tool_calling/all_tools.py,sha256=pgPSXtFNO9pD9Y2FRk97ofIcdHHtpah4pEdipYktwxQ,2366
98
+ kfinance/integrations/tool_calling/all_tools.py,sha256=UsmCupFumXx2J5AZU9M0fbihbZhlirzVrOQehpcgbfo,2724
99
99
  kfinance/integrations/tool_calling/prompts.py,sha256=4qeW_VLLcxutUFuXnMKa0QD-_jq9qufo03BY-Slz-XU,1718
100
100
  kfinance/integrations/tool_calling/tool_calling_models.py,sha256=o1LGGwx8ikwEiZaHEALS4rvymF9O1Mp5dO9LcfFheUI,5856
101
101
  kfinance/integrations/tool_calling/static_tools/README.md,sha256=lWQWdLY1tkGxqE8o4f61gc-RCX0doaCnZM0GmcNO6Jo,97
@@ -108,7 +108,7 @@ kfinance/integrations/tool_calling/static_tools/tests/test_get_n_quarters_ago.py
108
108
  kfinance/integrations/tool_calling/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
109
109
  kfinance/integrations/tool_calling/tests/test_tool_calling_models.py,sha256=Ts1pvaYjq9BTR71dMZ73X__bQ7gQynPkQjy-9x2CuyQ,2605
110
110
  kfinance/models/permission_models.py,sha256=G0so8ZOsD1YDsCM4he0z5R9M_shUbSRwD3hUDJdqZl0,635
111
- kensho_kfinance-3.2.3.dist-info/METADATA,sha256=xovbKJI3SJnJUr_Us2zsKJ3bUDo3rgiMHOG8zJUQrhY,6197
112
- kensho_kfinance-3.2.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
113
- kensho_kfinance-3.2.3.dist-info/top_level.txt,sha256=kT_kNwVhfQoOAecY8W7uYah5xaHMoHoAdBIvXh6DaKM,9
114
- kensho_kfinance-3.2.3.dist-info/RECORD,,
111
+ kensho_kfinance-3.2.4.dist-info/METADATA,sha256=rc_-W3DvkZ-X_MtcKpQUD3I5rcf4pPVZa9BIaBvjyUE,6197
112
+ kensho_kfinance-3.2.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
113
+ kensho_kfinance-3.2.4.dist-info/top_level.txt,sha256=kT_kNwVhfQoOAecY8W7uYah5xaHMoHoAdBIvXh6DaKM,9
114
+ kensho_kfinance-3.2.4.dist-info/RECORD,,
kfinance/CHANGELOG.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # Changelog
2
2
 
3
+ ## v3.2.4
4
+ - Add Mergers & Acquisitions tools to ALL_TOOLS
5
+
3
6
  ## v3.2.3
4
7
  - Disable low level MCP SDK input validation
5
8
 
kfinance/conftest.py CHANGED
@@ -52,7 +52,18 @@ def mock_client(requests_mock: Mocker) -> Client:
52
52
  additional_matcher=lambda req: req.json().get("identifiers") == ["SPGI"],
53
53
  json={"data": {"SPGI": spgi_id_triple}},
54
54
  )
55
-
55
+ # Fetch a non-existent company (which will include an error)
56
+ requests_mock.post(
57
+ url="https://kfinance.kensho.com/api/v1/ids",
58
+ additional_matcher=lambda req: req.json().get("identifiers") == ["non-existent"],
59
+ json={
60
+ "data": {
61
+ "non-existent": {
62
+ "error": "No identification triple found for the provided identifier: NON-EXISTENT of type: ticker"
63
+ },
64
+ }
65
+ },
66
+ )
56
67
  # Fetch SPGI and a non-existent company (which will include an error)
57
68
  requests_mock.post(
58
69
  url="https://kfinance.kensho.com/api/v1/ids",
@@ -6,10 +6,16 @@ from pydantic import BaseModel
6
6
  class MergerSummary(BaseModel):
7
7
  transaction_id: int
8
8
  merger_title: str
9
- closed_date: date
9
+ closed_date: date | None
10
10
 
11
11
 
12
12
  class MergersResp(BaseModel):
13
13
  target: list[MergerSummary]
14
14
  buyer: list[MergerSummary]
15
15
  seller: list[MergerSummary]
16
+
17
+
18
+ class AdvisorResp(BaseModel):
19
+ advisor_company_id: str
20
+ advisor_company_name: str
21
+ advisor_type_name: str | None
@@ -7,7 +7,10 @@ from kfinance.client.batch_request_handling import Task, process_tasks_in_thread
7
7
  from kfinance.client.kfinance import Company, MergerOrAcquisition, ParticipantInMerger
8
8
  from kfinance.client.permission_models import Permission
9
9
  from kfinance.domains.companies.company_models import prefix_company_id
10
- from kfinance.domains.mergers_and_acquisitions.merger_and_acquisition_models import MergersResp
10
+ from kfinance.domains.mergers_and_acquisitions.merger_and_acquisition_models import (
11
+ AdvisorResp,
12
+ MergersResp,
13
+ )
11
14
  from kfinance.integrations.tool_calling.tool_calling_models import (
12
15
  KfinanceTool,
13
16
  ToolArgsWithIdentifier,
@@ -23,9 +26,7 @@ class GetMergersFromIdentifiersResp(ToolRespWithErrors):
23
26
  class GetMergersFromIdentifiers(KfinanceTool):
24
27
  name: str = "get_mergers_from_identifiers"
25
28
  description: str = dedent("""
26
- Get the transaction IDs that involve the given identifiers.
27
-
28
- For example, "Which companies did Microsoft purchase?" or "Which company bought Ben & Jerrys?"
29
+ "Retrieves all merger and acquisition transactions involving the specified company identifier for each specified company identifier. The results are categorized by the company's role in each transaction: target, buyer, or seller. Provides the transaction_id, merger_title, and transaction closed_date (finalization) . Use this tool to answer questions like 'Which companies did Microsoft purchase?', 'Which company acquired Ben & Jerry's?', and 'Who did Pfizer acquire?'"
29
30
  """).strip()
30
31
  args_schema: Type[BaseModel] = ToolArgsWithIdentifiers
31
32
  accepted_permissions: set[Permission] | None = {Permission.MergersPermission}
@@ -91,9 +92,7 @@ class GetMergerInfoFromTransactionIdArgs(BaseModel):
91
92
  class GetMergerInfoFromTransactionId(KfinanceTool):
92
93
  name: str = "get_merger_info_from_transaction_id"
93
94
  description: str = dedent("""
94
- Get the timeline, the participants, and the consideration of the merger or acquisition from the given transaction ID.
95
-
96
- For example, "How much was Ben & Jerrys purchased for?" or "What was the price per share for LinkedIn?" or "When did S&P purchase Kensho?"
95
+ "Provides comprehensive information about a specific merger or acquisition transaction, including its timeline (announced date, closed date), participants' company_name and company_id (target, buyers, sellers), and financial consideration details (including monetary values). Use this tool to answer questions like 'When was the acquisition Ben & Jerry's announced?', 'What was the transaction size of Vodafone's acquisition of Mannesmann?', 'How much did S&P purchase Kensho for?'. Always call this for announcement related questions"
97
96
  """).strip()
98
97
  args_schema: Type[BaseModel] = GetMergerInfoFromTransactionIdArgs
99
98
  accepted_permissions: set[Permission] | None = {Permission.MergersPermission}
@@ -162,32 +161,53 @@ class GetAdvisorsForCompanyInTransactionFromIdentifierArgs(ToolArgsWithIdentifie
162
161
  transaction_id: int | None = Field(description="The ID of the merger.", default=None)
163
162
 
164
163
 
164
+ class GetAdvisorsForCompanyInTransactionFromIdentifierResp(ToolRespWithErrors):
165
+ results: list[AdvisorResp]
166
+
167
+
165
168
  class GetAdvisorsForCompanyInTransactionFromIdentifier(KfinanceTool):
166
169
  name: str = "get_advisors_for_company_in_transaction_from_identifier"
167
- description: str = 'Get the companies advising a company in a given transaction. For example, "Who advised S&P Global during their purchase of Kensho?"'
170
+ description: str = dedent("""
171
+ "Returns a list of advisor companies that provided advisory services to the specified company during a particular merger or acquisition transaction. Use this tool to answer questions like 'Who advised S&P Global during their purchase of Kensho?', 'Which firms advised Ben & Jerry's in their acquisition?'."
172
+ """).strip()
168
173
  args_schema: Type[BaseModel] = GetAdvisorsForCompanyInTransactionFromIdentifierArgs
169
174
  accepted_permissions: set[Permission] | None = {Permission.MergersPermission}
170
175
 
171
- def _run(self, identifier: str, transaction_id: int) -> list:
172
- ticker = self.kfinance_client.ticker(identifier)
176
+ def _run(self, identifier: str, transaction_id: int) -> dict:
177
+ api_client = self.kfinance_client.kfinance_api_client
178
+ id_triple_resp = api_client.unified_fetch_id_triples(identifiers=[identifier])
179
+ # If the identifier cannot be resolved, return the associated error.
180
+ if id_triple_resp.errors:
181
+ output_model = GetAdvisorsForCompanyInTransactionFromIdentifierResp(
182
+ results=[], errors=list(id_triple_resp.errors.values())
183
+ )
184
+ return output_model.model_dump(mode="json")
185
+
186
+ id_triple = id_triple_resp.identifiers_to_id_triples[identifier]
187
+
173
188
  participant_in_merger = ParticipantInMerger(
174
- kfinance_api_client=ticker.kfinance_api_client,
189
+ kfinance_api_client=api_client,
175
190
  transaction_id=transaction_id,
176
191
  company=Company(
177
- kfinance_api_client=ticker.kfinance_api_client,
178
- company_id=ticker.company.company_id,
192
+ kfinance_api_client=api_client,
193
+ company_id=id_triple.company_id,
179
194
  ),
180
195
  )
196
+
181
197
  advisors = participant_in_merger.advisors
182
198
 
199
+ advisors_response: list[AdvisorResp] = []
183
200
  if advisors:
184
- return [
185
- {
186
- "advisor_company_id": prefix_company_id(advisor.company.company_id),
187
- "advisor_company_name": advisor.company.name,
188
- "advisor_type_name": advisor.advisor_type_name,
189
- }
190
- for advisor in advisors
191
- ]
192
- else:
193
- return []
201
+ for advisor in advisors:
202
+ advisors_response.append(
203
+ AdvisorResp(
204
+ advisor_company_id=prefix_company_id(advisor.company.company_id),
205
+ advisor_company_name=advisor.company.name,
206
+ advisor_type_name=advisor.advisor_type_name,
207
+ )
208
+ )
209
+
210
+ output_model = GetAdvisorsForCompanyInTransactionFromIdentifierResp(
211
+ results=advisors_response, errors=list(id_triple_resp.errors.values())
212
+ )
213
+ return output_model.model_dump(mode="json")
@@ -46,28 +46,42 @@ class TestGetCompaniesAdvisingCompanyInTransactionFromIdentifier:
46
46
  def test_get_companies_advising_company_in_transaction_from_identifier(
47
47
  self, requests_mock: Mocker, mock_client: Client
48
48
  ):
49
- api_response = {
50
- "advisors": [
51
- {
52
- "advisor_company_id": 251994106,
53
- "advisor_company_name": "Kensho Technologies, Inc.",
54
- "advisor_type_name": "Professional Mongo Enjoyer",
55
- }
56
- ]
49
+ advisor_data = {
50
+ "advisor_company_id": 251994106,
51
+ "advisor_company_name": "Kensho Technologies, Inc.",
52
+ "advisor_type_name": "Professional Mongo Enjoyer",
57
53
  }
58
- expected_response = deepcopy(api_response)
59
- expected_response["advisors"][0]["advisor_company_id"] = f"{COMPANY_ID_PREFIX}251994106"
60
- transaction_id = 517414
54
+ api_response = {"advisors": [deepcopy(advisor_data)]}
55
+ expected_response = {"results": [deepcopy(advisor_data)]}
56
+ expected_response["results"][0]["advisor_company_id"] = f"{COMPANY_ID_PREFIX}251994106"
57
+ transaction_id = 554979212
61
58
  requests_mock.get(
62
- url=f"https://kfinance.kensho.com/api/v1/merger/info/{transaction_id}/advisors/21835",
59
+ url=f"https://kfinance.kensho.com/api/v1/merger/info/{transaction_id}/advisors/{SPGI_COMPANY_ID}",
63
60
  json=api_response,
64
61
  )
65
62
  tool = GetAdvisorsForCompanyInTransactionFromIdentifier(kfinance_client=mock_client)
66
63
  args = GetAdvisorsForCompanyInTransactionFromIdentifierArgs(
67
- identifier="MSFT", transaction_id=transaction_id
64
+ identifier="SPGI", transaction_id=transaction_id
65
+ )
66
+ response = tool.run(args.model_dump(mode="json"))
67
+ assert response == expected_response
68
+
69
+ def test_get_companies_advising_company_in_transaction_from_bad_identifier(
70
+ self, requests_mock: Mocker, mock_client: Client
71
+ ):
72
+ expected_response = {
73
+ "results": [],
74
+ "errors": [
75
+ "No identification triple found for the provided identifier: NON-EXISTENT of type: ticker"
76
+ ],
77
+ }
78
+ transaction_id = 554979212
79
+ tool = GetAdvisorsForCompanyInTransactionFromIdentifier(kfinance_client=mock_client)
80
+ args = GetAdvisorsForCompanyInTransactionFromIdentifierArgs(
81
+ identifier="non-existent", transaction_id=transaction_id
68
82
  )
69
83
  response = tool.run(args.model_dump(mode="json"))
70
- assert response == expected_response["advisors"]
84
+ assert response == expected_response
71
85
 
72
86
 
73
87
  class TestGetMergerInfoFromTransactionId:
@@ -20,6 +20,11 @@ from kfinance.domains.earnings.earning_tools import (
20
20
  GetTranscriptFromKeyDevId,
21
21
  )
22
22
  from kfinance.domains.line_items.line_item_tools import GetFinancialLineItemFromIdentifiers
23
+ from kfinance.domains.mergers_and_acquisitions.merger_and_acquisition_tools import (
24
+ GetAdvisorsForCompanyInTransactionFromIdentifier,
25
+ GetMergerInfoFromTransactionId,
26
+ GetMergersFromIdentifiers,
27
+ )
23
28
  from kfinance.domains.prices.price_tools import GetPricesFromIdentifiers
24
29
  from kfinance.domains.segments.segment_tools import GetSegmentsFromIdentifiers
25
30
  from kfinance.domains.statements.statement_tools import GetFinancialStatementFromIdentifiers
@@ -60,4 +65,8 @@ ALL_TOOLS: list[type[KfinanceTool]] = [
60
65
  GetSegmentsFromIdentifiers,
61
66
  # Statements
62
67
  GetFinancialStatementFromIdentifiers,
68
+ # Mergers & Acquisitions
69
+ GetAdvisorsForCompanyInTransactionFromIdentifier,
70
+ GetMergerInfoFromTransactionId,
71
+ GetMergersFromIdentifiers,
63
72
  ]
kfinance/version.py CHANGED
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '3.2.3'
32
- __version_tuple__ = version_tuple = (3, 2, 3)
31
+ __version__ = version = '3.2.4'
32
+ __version_tuple__ = version_tuple = (3, 2, 4)
33
33
 
34
34
  __commit_id__ = commit_id = None