kensho-kfinance 3.2.4__py3-none-any.whl → 3.2.6__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.
Potentially problematic release.
This version of kensho-kfinance might be problematic. Click here for more details.
- {kensho_kfinance-3.2.4.dist-info → kensho_kfinance-3.2.6.dist-info}/METADATA +1 -1
- {kensho_kfinance-3.2.4.dist-info → kensho_kfinance-3.2.6.dist-info}/RECORD +43 -43
- kfinance/CHANGELOG.md +6 -0
- kfinance/client/fetch.py +7 -5
- kfinance/client/kfinance.py +38 -39
- kfinance/client/models/date_and_period_models.py +8 -7
- kfinance/client/tests/test_fetch.py +3 -1
- kfinance/client/tests/test_objects.py +38 -95
- kfinance/domains/business_relationships/business_relationship_tools.py +4 -4
- kfinance/domains/business_relationships/tests/test_business_relationship_tools.py +18 -16
- kfinance/domains/capitalizations/capitalization_models.py +3 -3
- kfinance/domains/capitalizations/capitalization_tools.py +7 -5
- kfinance/domains/capitalizations/tests/test_capitalization_tools.py +46 -36
- kfinance/domains/companies/company_tools.py +8 -12
- kfinance/domains/companies/tests/test_company_tools.py +21 -9
- kfinance/domains/competitors/competitor_tools.py +2 -3
- kfinance/domains/competitors/tests/test_competitor_tools.py +22 -19
- kfinance/domains/cusip_and_isin/cusip_and_isin_tools.py +4 -6
- kfinance/domains/cusip_and_isin/tests/test_cusip_and_isin_tools.py +13 -8
- kfinance/domains/earnings/earning_tools.py +12 -9
- kfinance/domains/earnings/tests/test_earnings_tools.py +52 -43
- kfinance/domains/line_items/line_item_models.py +121 -0
- kfinance/domains/line_items/line_item_tools.py +2 -3
- kfinance/domains/line_items/tests/test_line_item_tools.py +20 -23
- kfinance/domains/mergers_and_acquisitions/merger_and_acquisition_models.py +46 -2
- kfinance/domains/mergers_and_acquisitions/merger_and_acquisition_tools.py +13 -68
- kfinance/domains/mergers_and_acquisitions/tests/test_merger_and_acquisition_tools.py +61 -59
- kfinance/domains/prices/price_tools.py +4 -7
- kfinance/domains/prices/tests/test_price_tools.py +47 -39
- kfinance/domains/segments/segment_tools.py +2 -3
- kfinance/domains/segments/tests/test_segment_tools.py +16 -11
- kfinance/domains/statements/statement_tools.py +2 -3
- kfinance/domains/statements/tests/test_statement_tools.py +40 -35
- kfinance/integrations/tool_calling/static_tools/get_n_quarters_ago.py +5 -0
- kfinance/integrations/tool_calling/static_tools/tests/test_get_lastest.py +13 -10
- kfinance/integrations/tool_calling/static_tools/tests/test_get_n_quarters_ago.py +2 -1
- kfinance/integrations/tool_calling/tests/test_tool_calling_models.py +8 -2
- kfinance/integrations/tool_calling/tool_calling_models.py +11 -5
- kfinance/version.py +2 -2
- {kensho_kfinance-3.2.4.dist-info → kensho_kfinance-3.2.6.dist-info}/WHEEL +0 -0
- {kensho_kfinance-3.2.4.dist-info → kensho_kfinance-3.2.6.dist-info}/licenses/AUTHORS.md +0 -0
- {kensho_kfinance-3.2.4.dist-info → kensho_kfinance-3.2.6.dist-info}/licenses/LICENSE +0 -0
- {kensho_kfinance-3.2.4.dist-info → kensho_kfinance-3.2.6.dist-info}/top_level.txt +0 -0
|
@@ -8,6 +8,7 @@ from kfinance.domains.business_relationships.business_relationship_models import
|
|
|
8
8
|
from kfinance.domains.business_relationships.business_relationship_tools import (
|
|
9
9
|
GetBusinessRelationshipFromIdentifiers,
|
|
10
10
|
GetBusinessRelationshipFromIdentifiersArgs,
|
|
11
|
+
GetBusinessRelationshipFromIdentifiersResp,
|
|
11
12
|
)
|
|
12
13
|
|
|
13
14
|
|
|
@@ -27,21 +28,23 @@ class TestGetBusinessRelationshipFromIdentifiers:
|
|
|
27
28
|
{"company_id": 8182358, "company_name": "Eloqua, Inc."},
|
|
28
29
|
],
|
|
29
30
|
}
|
|
30
|
-
expected_result =
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
"
|
|
43
|
-
|
|
44
|
-
|
|
31
|
+
expected_result = GetBusinessRelationshipFromIdentifiersResp.model_validate(
|
|
32
|
+
{
|
|
33
|
+
"business_relationship": "supplier",
|
|
34
|
+
"results": {
|
|
35
|
+
"SPGI": {
|
|
36
|
+
"current": [{"company_id": 883103, "company_name": "CRISIL Limited"}],
|
|
37
|
+
"previous": [
|
|
38
|
+
{"company_id": 472898, "company_name": "Morgan Stanley"},
|
|
39
|
+
{"company_id": 8182358, "company_name": "Eloqua, Inc."},
|
|
40
|
+
],
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"errors": [
|
|
44
|
+
"No identification triple found for the provided identifier: NON-EXISTENT of type: ticker"
|
|
45
|
+
],
|
|
46
|
+
}
|
|
47
|
+
)
|
|
45
48
|
|
|
46
49
|
requests_mock.get(
|
|
47
50
|
url=f"https://kfinance.kensho.com/api/v1/relationship/{SPGI_COMPANY_ID}/supplier",
|
|
@@ -54,5 +57,4 @@ class TestGetBusinessRelationshipFromIdentifiers:
|
|
|
54
57
|
business_relationship=BusinessRelationshipType.supplier,
|
|
55
58
|
)
|
|
56
59
|
resp = tool.run(args.model_dump(mode="json"))
|
|
57
|
-
resp["results"]["SPGI"]["previous"].sort(key=lambda x: x["company_id"])
|
|
58
60
|
assert resp == expected_result
|
|
@@ -20,9 +20,9 @@ class DailyCapitalization(BaseModel):
|
|
|
20
20
|
"""DailyCapitalization represents market cap, TEV, and shares outstanding for a day"""
|
|
21
21
|
|
|
22
22
|
date: date
|
|
23
|
-
market_cap: Money
|
|
24
|
-
tev: Money
|
|
25
|
-
shares_outstanding: Shares
|
|
23
|
+
market_cap: Money | None
|
|
24
|
+
tev: Money | None
|
|
25
|
+
shares_outstanding: Shares | None
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
class Capitalizations(BaseModel):
|
|
@@ -26,6 +26,7 @@ class GetCapitalizationFromIdentifiersArgs(ToolArgsWithIdentifiers):
|
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
class GetCapitalizationFromIdentifiersResp(ToolRespWithErrors):
|
|
29
|
+
capitalization: Capitalization
|
|
29
30
|
results: dict[str, Capitalizations]
|
|
30
31
|
|
|
31
32
|
|
|
@@ -50,13 +51,13 @@ class GetCapitalizationFromIdentifiers(KfinanceTool):
|
|
|
50
51
|
capitalization: Capitalization,
|
|
51
52
|
start_date: str | None = None,
|
|
52
53
|
end_date: str | None = None,
|
|
53
|
-
) ->
|
|
54
|
+
) -> GetCapitalizationFromIdentifiersResp:
|
|
54
55
|
"""Sample response:
|
|
55
56
|
|
|
56
57
|
{
|
|
58
|
+
'capitalization': 'market_cap'
|
|
57
59
|
'results': {
|
|
58
60
|
'SPGI': {
|
|
59
|
-
'capitalizations': [
|
|
60
61
|
{'date': '2024-04-10', 'market_cap': {'value': '132766738270.00', 'unit': 'USD'}},
|
|
61
62
|
{'date': '2024-04-11', 'market_cap': {'value': '132416066761.00', 'unit': 'USD'}}
|
|
62
63
|
]
|
|
@@ -100,7 +101,8 @@ class GetCapitalizationFromIdentifiers(KfinanceTool):
|
|
|
100
101
|
if capitalization is not Capitalization.shares_outstanding:
|
|
101
102
|
daily_capitalization.shares_outstanding = None
|
|
102
103
|
|
|
103
|
-
|
|
104
|
-
|
|
104
|
+
return GetCapitalizationFromIdentifiersResp(
|
|
105
|
+
capitalization=capitalization,
|
|
106
|
+
results=capitalization_responses,
|
|
107
|
+
errors=list(id_triple_resp.errors.values()),
|
|
105
108
|
)
|
|
106
|
-
return resp_model.model_dump(mode="json", exclude_none=True)
|
|
@@ -1,11 +1,20 @@
|
|
|
1
|
+
from datetime import date
|
|
2
|
+
from decimal import Decimal
|
|
3
|
+
|
|
1
4
|
from requests_mock import Mocker
|
|
2
5
|
|
|
3
6
|
from kfinance.client.kfinance import Client
|
|
7
|
+
from kfinance.client.models.decimal_with_unit import Money
|
|
4
8
|
from kfinance.conftest import SPGI_COMPANY_ID
|
|
5
|
-
from kfinance.domains.capitalizations.capitalization_models import
|
|
9
|
+
from kfinance.domains.capitalizations.capitalization_models import (
|
|
10
|
+
Capitalization,
|
|
11
|
+
Capitalizations,
|
|
12
|
+
DailyCapitalization,
|
|
13
|
+
)
|
|
6
14
|
from kfinance.domains.capitalizations.capitalization_tools import (
|
|
7
15
|
GetCapitalizationFromIdentifiers,
|
|
8
16
|
GetCapitalizationFromIdentifiersArgs,
|
|
17
|
+
GetCapitalizationFromIdentifiersResp,
|
|
9
18
|
)
|
|
10
19
|
from kfinance.domains.companies.company_models import COMPANY_ID_PREFIX
|
|
11
20
|
|
|
@@ -40,25 +49,30 @@ class TestGetCapitalizationFromCompanyIds:
|
|
|
40
49
|
json=self.market_caps_resp,
|
|
41
50
|
)
|
|
42
51
|
|
|
43
|
-
expected_response =
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
expected_response = GetCapitalizationFromIdentifiersResp(
|
|
53
|
+
capitalization=Capitalization.market_cap,
|
|
54
|
+
results={
|
|
55
|
+
"SPGI": Capitalizations(
|
|
56
|
+
market_caps=[
|
|
57
|
+
DailyCapitalization(
|
|
58
|
+
date=date(2024, 4, 10),
|
|
59
|
+
market_cap=Money(value=Decimal(132766738270), unit="USD"),
|
|
60
|
+
tev=None,
|
|
61
|
+
shares_outstanding=None,
|
|
62
|
+
),
|
|
63
|
+
DailyCapitalization(
|
|
64
|
+
date=date(2024, 4, 11),
|
|
65
|
+
market_cap=Money(value=Decimal(132416066761), unit="USD"),
|
|
66
|
+
tev=None,
|
|
67
|
+
shares_outstanding=None,
|
|
68
|
+
),
|
|
55
69
|
]
|
|
56
|
-
|
|
70
|
+
)
|
|
57
71
|
},
|
|
58
|
-
|
|
72
|
+
errors=[
|
|
59
73
|
"No identification triple found for the provided identifier: NON-EXISTENT of type: ticker"
|
|
60
74
|
],
|
|
61
|
-
|
|
75
|
+
)
|
|
62
76
|
|
|
63
77
|
tool = GetCapitalizationFromIdentifiers(kfinance_client=mock_client)
|
|
64
78
|
args = GetCapitalizationFromIdentifiersArgs(
|
|
@@ -73,26 +87,22 @@ class TestGetCapitalizationFromCompanyIds:
|
|
|
73
87
|
WHEN we request most recent market caps for multiple companies
|
|
74
88
|
THEN we only get back the most recent market cap for each company
|
|
75
89
|
"""
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
]
|
|
93
|
-
},
|
|
94
|
-
}
|
|
95
|
-
}
|
|
90
|
+
|
|
91
|
+
capitalization = Capitalizations(
|
|
92
|
+
market_caps=[
|
|
93
|
+
DailyCapitalization(
|
|
94
|
+
date=date(2024, 4, 11),
|
|
95
|
+
market_cap=Money(value=Decimal(132416066761), unit="USD"),
|
|
96
|
+
tev=None,
|
|
97
|
+
shares_outstanding=None,
|
|
98
|
+
)
|
|
99
|
+
]
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
expected_response = GetCapitalizationFromIdentifiersResp(
|
|
103
|
+
capitalization=Capitalization.market_cap,
|
|
104
|
+
results={"C_1": capitalization, "C_2": capitalization},
|
|
105
|
+
)
|
|
96
106
|
|
|
97
107
|
company_ids = [1, 2]
|
|
98
108
|
for company_id in company_ids:
|
|
@@ -27,7 +27,7 @@ class GetInfoFromIdentifiers(KfinanceTool):
|
|
|
27
27
|
args_schema: Type[BaseModel] = ToolArgsWithIdentifiers
|
|
28
28
|
accepted_permissions: set[Permission] | None = None
|
|
29
29
|
|
|
30
|
-
def _run(self, identifiers: list[str]) ->
|
|
30
|
+
def _run(self, identifiers: list[str]) -> GetInfoFromIdentifiersResp:
|
|
31
31
|
"""Sample response:
|
|
32
32
|
|
|
33
33
|
{ "results": {
|
|
@@ -65,10 +65,9 @@ class GetInfoFromIdentifiers(KfinanceTool):
|
|
|
65
65
|
info_responses: dict[str, dict] = process_tasks_in_thread_pool_executor(
|
|
66
66
|
api_client=api_client, tasks=tasks
|
|
67
67
|
)
|
|
68
|
-
|
|
68
|
+
return GetInfoFromIdentifiersResp(
|
|
69
69
|
results=info_responses, errors=list(id_triple_resp.errors.values())
|
|
70
70
|
)
|
|
71
|
-
return resp_model.model_dump(mode="json")
|
|
72
71
|
|
|
73
72
|
|
|
74
73
|
class GetCompanyOtherNamesFromIdentifiersResp(ToolRespWithErrors):
|
|
@@ -88,7 +87,7 @@ class GetCompanyOtherNamesFromIdentifiers(KfinanceTool):
|
|
|
88
87
|
def _run(
|
|
89
88
|
self,
|
|
90
89
|
identifiers: list[str],
|
|
91
|
-
) ->
|
|
90
|
+
) -> GetCompanyOtherNamesFromIdentifiersResp:
|
|
92
91
|
api_client = self.kfinance_client.kfinance_api_client
|
|
93
92
|
id_triple_resp = api_client.unified_fetch_id_triples(identifiers=identifiers)
|
|
94
93
|
tasks = [
|
|
@@ -102,10 +101,9 @@ class GetCompanyOtherNamesFromIdentifiers(KfinanceTool):
|
|
|
102
101
|
info_responses: dict[str, CompanyOtherNames] = process_tasks_in_thread_pool_executor(
|
|
103
102
|
api_client=api_client, tasks=tasks
|
|
104
103
|
)
|
|
105
|
-
|
|
104
|
+
return GetCompanyOtherNamesFromIdentifiersResp(
|
|
106
105
|
results=info_responses, errors=list(id_triple_resp.errors.values())
|
|
107
106
|
)
|
|
108
|
-
return resp_model.model_dump(mode="json")
|
|
109
107
|
|
|
110
108
|
|
|
111
109
|
class GetCompanySummaryFromIdentifiersResp(ToolRespWithErrors):
|
|
@@ -125,7 +123,7 @@ class GetCompanySummaryFromIdentifiers(KfinanceTool):
|
|
|
125
123
|
def _run(
|
|
126
124
|
self,
|
|
127
125
|
identifiers: list[str],
|
|
128
|
-
) ->
|
|
126
|
+
) -> GetCompanySummaryFromIdentifiersResp:
|
|
129
127
|
api_client = self.kfinance_client.kfinance_api_client
|
|
130
128
|
id_triple_resp = api_client.unified_fetch_id_triples(identifiers=identifiers)
|
|
131
129
|
|
|
@@ -147,10 +145,9 @@ class GetCompanySummaryFromIdentifiers(KfinanceTool):
|
|
|
147
145
|
for identifier, descriptions in company_description_responses.items()
|
|
148
146
|
}
|
|
149
147
|
|
|
150
|
-
|
|
148
|
+
return GetCompanySummaryFromIdentifiersResp(
|
|
151
149
|
results=summary_results, errors=list(id_triple_resp.errors.values())
|
|
152
150
|
)
|
|
153
|
-
return resp_model.model_dump(mode="json")
|
|
154
151
|
|
|
155
152
|
|
|
156
153
|
class GetCompanyDescriptionFromIdentifiersResp(ToolRespWithErrors):
|
|
@@ -170,7 +167,7 @@ class GetCompanyDescriptionFromIdentifiers(KfinanceTool):
|
|
|
170
167
|
def _run(
|
|
171
168
|
self,
|
|
172
169
|
identifiers: list[str],
|
|
173
|
-
) ->
|
|
170
|
+
) -> GetCompanyDescriptionFromIdentifiersResp:
|
|
174
171
|
api_client = self.kfinance_client.kfinance_api_client
|
|
175
172
|
id_triple_resp = api_client.unified_fetch_id_triples(identifiers=identifiers)
|
|
176
173
|
|
|
@@ -192,7 +189,6 @@ class GetCompanyDescriptionFromIdentifiers(KfinanceTool):
|
|
|
192
189
|
for identifier, descriptions in company_description_responses.items()
|
|
193
190
|
}
|
|
194
191
|
|
|
195
|
-
|
|
192
|
+
return GetCompanyDescriptionFromIdentifiersResp(
|
|
196
193
|
results=description_results, errors=list(id_triple_resp.errors.values())
|
|
197
194
|
)
|
|
198
|
-
return resp_model.model_dump(mode="json")
|
|
@@ -4,9 +4,13 @@ from kfinance.client.kfinance import Client
|
|
|
4
4
|
from kfinance.conftest import SPGI_COMPANY_ID
|
|
5
5
|
from kfinance.domains.companies.company_tools import (
|
|
6
6
|
GetCompanyDescriptionFromIdentifiers,
|
|
7
|
+
GetCompanyDescriptionFromIdentifiersResp,
|
|
7
8
|
GetCompanyOtherNamesFromIdentifiers,
|
|
9
|
+
GetCompanyOtherNamesFromIdentifiersResp,
|
|
8
10
|
GetCompanySummaryFromIdentifiers,
|
|
11
|
+
GetCompanySummaryFromIdentifiersResp,
|
|
9
12
|
GetInfoFromIdentifiers,
|
|
13
|
+
GetInfoFromIdentifiersResp,
|
|
10
14
|
)
|
|
11
15
|
from kfinance.integrations.tool_calling.tool_calling_models import ToolArgsWithIdentifiers
|
|
12
16
|
|
|
@@ -20,12 +24,14 @@ class TestGetInfoFromIdentifiers:
|
|
|
20
24
|
"""
|
|
21
25
|
|
|
22
26
|
info_resp = {"name": "S&P Global Inc.", "status": "Operating"}
|
|
23
|
-
expected_response =
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
expected_response = GetInfoFromIdentifiersResp.model_validate(
|
|
28
|
+
{
|
|
29
|
+
"results": {"SPGI": info_resp},
|
|
30
|
+
"errors": [
|
|
31
|
+
"No identification triple found for the provided identifier: NON-EXISTENT of type: ticker"
|
|
32
|
+
],
|
|
33
|
+
}
|
|
34
|
+
)
|
|
29
35
|
requests_mock.get(
|
|
30
36
|
url=f"https://kfinance.kensho.com/api/v1/info/{SPGI_COMPANY_ID}",
|
|
31
37
|
json=info_resp,
|
|
@@ -61,7 +67,9 @@ class TestGetCompanyDescriptions:
|
|
|
61
67
|
tool = GetCompanySummaryFromIdentifiers(kfinance_client=mock_client)
|
|
62
68
|
args = ToolArgsWithIdentifiers(identifiers=["SPGI"])
|
|
63
69
|
response = tool.run(args.model_dump(mode="json"))
|
|
64
|
-
expected_response =
|
|
70
|
+
expected_response = GetCompanySummaryFromIdentifiersResp.model_validate(
|
|
71
|
+
{"results": {"SPGI": self.summary}}
|
|
72
|
+
)
|
|
65
73
|
assert response == expected_response
|
|
66
74
|
|
|
67
75
|
def test_get_company_description_from_identifier(
|
|
@@ -81,7 +89,9 @@ class TestGetCompanyDescriptions:
|
|
|
81
89
|
tool = GetCompanyDescriptionFromIdentifiers(kfinance_client=mock_client)
|
|
82
90
|
args = ToolArgsWithIdentifiers(identifiers=["SPGI"])
|
|
83
91
|
response = tool.run(args.model_dump(mode="json"))
|
|
84
|
-
expected_response =
|
|
92
|
+
expected_response = GetCompanyDescriptionFromIdentifiersResp.model_validate(
|
|
93
|
+
{"results": {"SPGI": self.description}}
|
|
94
|
+
)
|
|
85
95
|
assert response == expected_response
|
|
86
96
|
|
|
87
97
|
|
|
@@ -121,5 +131,7 @@ class TestGetCompanyOtherNames:
|
|
|
121
131
|
tool = GetCompanyOtherNamesFromIdentifiers(kfinance_client=mock_client)
|
|
122
132
|
args = ToolArgsWithIdentifiers(identifiers=["SPGI"])
|
|
123
133
|
response = tool.run(args.model_dump(mode="json"))
|
|
124
|
-
expected_response =
|
|
134
|
+
expected_response = GetCompanyOtherNamesFromIdentifiersResp.model_validate(
|
|
135
|
+
{"results": {"SPGI": self.company_other_names_info}}
|
|
136
|
+
)
|
|
125
137
|
assert response == expected_response
|
|
@@ -27,7 +27,7 @@ class GetCompetitorsFromIdentifiers(KfinanceTool):
|
|
|
27
27
|
self,
|
|
28
28
|
identifiers: list[str],
|
|
29
29
|
competitor_source: CompetitorSource,
|
|
30
|
-
) ->
|
|
30
|
+
) -> GetCompetitorsFromIdentifiersResp:
|
|
31
31
|
"""Sample response:
|
|
32
32
|
|
|
33
33
|
{
|
|
@@ -56,7 +56,6 @@ class GetCompetitorsFromIdentifiers(KfinanceTool):
|
|
|
56
56
|
competitor_responses: dict[str, CompetitorResponse] = process_tasks_in_thread_pool_executor(
|
|
57
57
|
api_client=api_client, tasks=tasks
|
|
58
58
|
)
|
|
59
|
-
|
|
59
|
+
return GetCompetitorsFromIdentifiersResp(
|
|
60
60
|
results=competitor_responses, errors=list(id_triple_resp.errors.values())
|
|
61
61
|
)
|
|
62
|
-
return resp_model.model_dump(mode="json")
|
|
@@ -6,6 +6,7 @@ from kfinance.domains.competitors.competitor_models import CompetitorSource
|
|
|
6
6
|
from kfinance.domains.competitors.competitor_tools import (
|
|
7
7
|
GetCompetitorsFromIdentifiers,
|
|
8
8
|
GetCompetitorsFromIdentifiersArgs,
|
|
9
|
+
GetCompetitorsFromIdentifiersResp,
|
|
9
10
|
)
|
|
10
11
|
|
|
11
12
|
|
|
@@ -24,25 +25,27 @@ class TestGetCompetitorsFromIdentifiers:
|
|
|
24
25
|
{"company_id": 4003514, "company_name": "London Stock Exchange Group plc"},
|
|
25
26
|
]
|
|
26
27
|
}
|
|
27
|
-
expected_response =
|
|
28
|
-
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"
|
|
44
|
-
|
|
45
|
-
|
|
28
|
+
expected_response = GetCompetitorsFromIdentifiersResp.model_validate(
|
|
29
|
+
{
|
|
30
|
+
"results": {
|
|
31
|
+
"SPGI": {
|
|
32
|
+
"competitors": [
|
|
33
|
+
{
|
|
34
|
+
"company_id": 35352,
|
|
35
|
+
"company_name": "The Descartes Systems Group Inc.",
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"company_id": 4003514,
|
|
39
|
+
"company_name": "London Stock Exchange Group plc",
|
|
40
|
+
},
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"errors": [
|
|
45
|
+
"No identification triple found for the provided identifier: NON-EXISTENT of type: ticker"
|
|
46
|
+
],
|
|
47
|
+
}
|
|
48
|
+
)
|
|
46
49
|
|
|
47
50
|
requests_mock.get(
|
|
48
51
|
url=f"https://kfinance.kensho.com/api/v1/competitors/{SPGI_COMPANY_ID}/named_by_competitor",
|
|
@@ -23,7 +23,7 @@ class GetCusipFromIdentifiers(KfinanceTool):
|
|
|
23
23
|
args_schema: Type[BaseModel] = ToolArgsWithIdentifiers
|
|
24
24
|
accepted_permissions: set[Permission] | None = {Permission.IDPermission}
|
|
25
25
|
|
|
26
|
-
def _run(self, identifiers: list[str]) ->
|
|
26
|
+
def _run(self, identifiers: list[str]) -> GetCusipOrIsinFromIdentifiersResp:
|
|
27
27
|
"""Sample response:
|
|
28
28
|
|
|
29
29
|
{
|
|
@@ -45,14 +45,13 @@ class GetCusipFromIdentifiers(KfinanceTool):
|
|
|
45
45
|
]
|
|
46
46
|
|
|
47
47
|
cusip_responses = process_tasks_in_thread_pool_executor(api_client=api_client, tasks=tasks)
|
|
48
|
-
|
|
48
|
+
return GetCusipOrIsinFromIdentifiersResp(
|
|
49
49
|
results={
|
|
50
50
|
identifier: cusip_resp["cusip"]
|
|
51
51
|
for identifier, cusip_resp in cusip_responses.items()
|
|
52
52
|
},
|
|
53
53
|
errors=list(id_triple_resp.errors.values()),
|
|
54
54
|
)
|
|
55
|
-
return resp_model.model_dump(mode="json")
|
|
56
55
|
|
|
57
56
|
|
|
58
57
|
class GetIsinFromIdentifiers(KfinanceTool):
|
|
@@ -61,7 +60,7 @@ class GetIsinFromIdentifiers(KfinanceTool):
|
|
|
61
60
|
args_schema: Type[BaseModel] = ToolArgsWithIdentifiers
|
|
62
61
|
accepted_permissions: set[Permission] | None = {Permission.IDPermission}
|
|
63
62
|
|
|
64
|
-
def _run(self, identifiers: list[str]) ->
|
|
63
|
+
def _run(self, identifiers: list[str]) -> GetCusipOrIsinFromIdentifiersResp:
|
|
65
64
|
"""Sample response:
|
|
66
65
|
|
|
67
66
|
{
|
|
@@ -83,10 +82,9 @@ class GetIsinFromIdentifiers(KfinanceTool):
|
|
|
83
82
|
]
|
|
84
83
|
|
|
85
84
|
isin_responses = process_tasks_in_thread_pool_executor(api_client=api_client, tasks=tasks)
|
|
86
|
-
|
|
85
|
+
return GetCusipOrIsinFromIdentifiersResp(
|
|
87
86
|
results={
|
|
88
87
|
identifier: isin_resp["isin"] for identifier, isin_resp in isin_responses.items()
|
|
89
88
|
},
|
|
90
89
|
errors=list(id_triple_resp.errors.values()),
|
|
91
90
|
)
|
|
92
|
-
return resp_model.model_dump(mode="json")
|
|
@@ -4,6 +4,7 @@ from kfinance.client.kfinance import Client
|
|
|
4
4
|
from kfinance.conftest import SPGI_SECURITY_ID
|
|
5
5
|
from kfinance.domains.cusip_and_isin.cusip_and_isin_tools import (
|
|
6
6
|
GetCusipFromIdentifiers,
|
|
7
|
+
GetCusipOrIsinFromIdentifiersResp,
|
|
7
8
|
GetIsinFromIdentifiers,
|
|
8
9
|
)
|
|
9
10
|
from kfinance.integrations.tool_calling.tool_calling_models import ToolArgsWithIdentifiers
|
|
@@ -18,10 +19,12 @@ class TestGetCusipFromIdentifiers:
|
|
|
18
19
|
"""
|
|
19
20
|
|
|
20
21
|
spgi_cusip = "78409V104"
|
|
21
|
-
expected_response =
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
expected_response = GetCusipOrIsinFromIdentifiersResp.model_validate(
|
|
23
|
+
{
|
|
24
|
+
"results": {"SPGI": "78409V104"},
|
|
25
|
+
"errors": ["private_company is a private company without a security_id."],
|
|
26
|
+
}
|
|
27
|
+
)
|
|
25
28
|
requests_mock.get(
|
|
26
29
|
url=f"https://kfinance.kensho.com/api/v1/cusip/{SPGI_SECURITY_ID}",
|
|
27
30
|
json={"cusip": spgi_cusip},
|
|
@@ -43,10 +46,12 @@ class TestGetIsinFromIdentifiers:
|
|
|
43
46
|
|
|
44
47
|
spgi_isin = "US78409V1044"
|
|
45
48
|
|
|
46
|
-
expected_response =
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
expected_response = GetCusipOrIsinFromIdentifiersResp.model_validate(
|
|
50
|
+
{
|
|
51
|
+
"results": {"SPGI": "US78409V1044"},
|
|
52
|
+
"errors": ["private_company is a private company without a security_id."],
|
|
53
|
+
}
|
|
54
|
+
)
|
|
50
55
|
requests_mock.get(
|
|
51
56
|
url=f"https://kfinance.kensho.com/api/v1/isin/{SPGI_SECURITY_ID}",
|
|
52
57
|
json={"isin": spgi_isin},
|
|
@@ -35,7 +35,7 @@ class GetEarningsFromIdentifiers(KfinanceTool):
|
|
|
35
35
|
Permission.TranscriptsPermission,
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
def _run(self, identifiers: list[str]) ->
|
|
38
|
+
def _run(self, identifiers: list[str]) -> GetEarningsFromIdentifiersResp:
|
|
39
39
|
"""Sample response:
|
|
40
40
|
|
|
41
41
|
{
|
|
@@ -52,10 +52,9 @@ class GetEarningsFromIdentifiers(KfinanceTool):
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
"""
|
|
55
|
-
|
|
55
|
+
return get_earnings_from_identifiers(
|
|
56
56
|
identifiers=identifiers, kfinance_api_client=self.kfinance_client.kfinance_api_client
|
|
57
57
|
)
|
|
58
|
-
return earnings_responses.model_dump(mode="json")
|
|
59
58
|
|
|
60
59
|
|
|
61
60
|
class GetLatestEarningsFromIdentifiers(KfinanceTool):
|
|
@@ -71,7 +70,7 @@ class GetLatestEarningsFromIdentifiers(KfinanceTool):
|
|
|
71
70
|
Permission.TranscriptsPermission,
|
|
72
71
|
}
|
|
73
72
|
|
|
74
|
-
def _run(self, identifiers: list[str]) ->
|
|
73
|
+
def _run(self, identifiers: list[str]) -> GetNextOrLatestEarningsFromIdentifiersResp:
|
|
75
74
|
"""Sample response:
|
|
76
75
|
|
|
77
76
|
{
|
|
@@ -95,7 +94,7 @@ class GetLatestEarningsFromIdentifiers(KfinanceTool):
|
|
|
95
94
|
output_model.results[identifier] = most_recent_earnings
|
|
96
95
|
else:
|
|
97
96
|
output_model.errors.append(f"No latest earnings available for {identifier}.")
|
|
98
|
-
return output_model
|
|
97
|
+
return output_model
|
|
99
98
|
|
|
100
99
|
|
|
101
100
|
class GetNextEarningsFromIdentifiers(KfinanceTool):
|
|
@@ -111,7 +110,7 @@ class GetNextEarningsFromIdentifiers(KfinanceTool):
|
|
|
111
110
|
Permission.TranscriptsPermission,
|
|
112
111
|
}
|
|
113
112
|
|
|
114
|
-
def _run(self, identifiers: list[str]) ->
|
|
113
|
+
def _run(self, identifiers: list[str]) -> GetNextOrLatestEarningsFromIdentifiersResp:
|
|
115
114
|
"""Sample response:
|
|
116
115
|
|
|
117
116
|
{
|
|
@@ -135,7 +134,7 @@ class GetNextEarningsFromIdentifiers(KfinanceTool):
|
|
|
135
134
|
output_model.results[identifier] = next_earnings
|
|
136
135
|
else:
|
|
137
136
|
output_model.errors.append(f"No next earnings available for {identifier}.")
|
|
138
|
-
return output_model
|
|
137
|
+
return output_model
|
|
139
138
|
|
|
140
139
|
|
|
141
140
|
def get_earnings_from_identifiers(
|
|
@@ -170,12 +169,16 @@ class GetTranscriptFromKeyDevIdArgs(BaseModel):
|
|
|
170
169
|
key_dev_id: int = Field(description="The key dev ID for the earnings call")
|
|
171
170
|
|
|
172
171
|
|
|
172
|
+
class GetTranscriptFromKeyDevIdResp(BaseModel):
|
|
173
|
+
transcript: str
|
|
174
|
+
|
|
175
|
+
|
|
173
176
|
class GetTranscriptFromKeyDevId(KfinanceTool):
|
|
174
177
|
name: str = "get_transcript_from_key_dev_id"
|
|
175
178
|
description: str = "Get the raw transcript text for an earnings call by key dev ID."
|
|
176
179
|
args_schema: Type[BaseModel] = GetTranscriptFromKeyDevIdArgs
|
|
177
180
|
accepted_permissions: set[Permission] | None = {Permission.TranscriptsPermission}
|
|
178
181
|
|
|
179
|
-
def _run(self, key_dev_id: int) ->
|
|
182
|
+
def _run(self, key_dev_id: int) -> GetTranscriptFromKeyDevIdResp:
|
|
180
183
|
transcript = self.kfinance_client.transcript(key_dev_id)
|
|
181
|
-
return transcript.raw
|
|
184
|
+
return GetTranscriptFromKeyDevIdResp(transcript=transcript.raw)
|