kensho-kfinance 2.2.2__py3-none-any.whl → 2.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.

Potentially problematic release.


This version of kensho-kfinance might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kensho-kfinance
3
- Version: 2.2.2
3
+ Version: 2.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,16 +1,16 @@
1
- kensho_kfinance-2.2.2.dist-info/licenses/AUTHORS.md,sha256=0h9ClbI0pu1oKj1M28ROUsaxrbZg-6ukQGl6X4y9noI,68
2
- kensho_kfinance-2.2.2.dist-info/licenses/LICENSE,sha256=bsY4blvSgq6o0FMQ3RXa2NCgco--nHCCchLXzxr6kms,83
3
- kfinance/CHANGELOG.md,sha256=eX36Pj6mDG2B6AtnHpP5FAJ14X-8XqF0fNRTYOGClXw,1140
1
+ kensho_kfinance-2.2.4.dist-info/licenses/AUTHORS.md,sha256=0h9ClbI0pu1oKj1M28ROUsaxrbZg-6ukQGl6X4y9noI,68
2
+ kensho_kfinance-2.2.4.dist-info/licenses/LICENSE,sha256=bsY4blvSgq6o0FMQ3RXa2NCgco--nHCCchLXzxr6kms,83
3
+ kfinance/CHANGELOG.md,sha256=rBjrg8H9eODymBNuLyOWIRrA5FAVR92WgxswFMkGI9E,1241
4
4
  kfinance/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  kfinance/batch_request_handling.py,sha256=p6p_G4_BL06GgeKlh7P1k9CUqOMahWCLEw1NoBwbLvU,5698
6
- kfinance/constants.py,sha256=4vj0WA0xupEJexvnI-ap6LFHXEf6dn8jQwJlxz8cGTs,48767
6
+ kfinance/constants.py,sha256=UuFzqL253-2tRQfma785K9tfaZGv-o821tO2tVLwc5Q,48813
7
7
  kfinance/fetch.py,sha256=fguxYy5rjLQKNkmP7gsvZUJtmt9uDNxg6LN9FRJTAVQ,22936
8
8
  kfinance/kfinance.py,sha256=_U69k0Dcwkw1B_lzaUZy8N2-c-v93ZKoUAVVZb6wBUM,52758
9
- kfinance/meta_classes.py,sha256=nwqHRi8IFa4WLFAZpX4a6htR47doK3_qVLnYBOylQV0,20482
9
+ kfinance/meta_classes.py,sha256=1qYkj2L7jcBfdkye6TG2nuRhwzhAbmtxay6rSVY3DsA,19883
10
10
  kfinance/prompt.py,sha256=PtVB8c_FcSlVdyGgByAnIFGzuUuBaEjciCqnBJl1hSQ,25133
11
11
  kfinance/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
12
  kfinance/server_thread.py,sha256=jUnt1YGoYDkqqz1MbCwd44zJs1T_Z2BCgvj75bdtLgA,2574
13
- kfinance/version.py,sha256=YDBduKhVnvbZfZTbXbsjQMbxTwgIIXIZ646Mj9YV074,511
13
+ kfinance/version.py,sha256=Ath1yNFbHtPzluPba0J7EfQTfLH_byRzLfGjqAUl6cY,511
14
14
  kfinance/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  kfinance/tests/conftest.py,sha256=voB-w8P_6L3Nel3rdgylXKe5WWaS1q7nCFt1O04uqoY,948
16
16
  kfinance/tests/test_batch_requests.py,sha256=uXJF2IcRdyBm5SthwIUHMKtkGZ21MY84pg_k1JeSNOY,11430
@@ -18,10 +18,10 @@ kfinance/tests/test_client.py,sha256=O7icZCSDhlQ9WGhzoXlpiSvbuA-mQNJHBYVsilyP_dE
18
18
  kfinance/tests/test_example_notebook.py,sha256=XhDAJp3H5Y6usLAt3k4Ug4W3H6gLyh68nzmoWgOOLn4,6441
19
19
  kfinance/tests/test_fetch.py,sha256=O9qOsffQYJPSAR1X_P6CNoA0Buyq2kx4vfS0FOc2Goc,13564
20
20
  kfinance/tests/test_group_objects.py,sha256=SoMEZmkG4RYdgWOAwxLHHtzIQho92KM01YbQXPUg578,1689
21
- kfinance/tests/test_objects.py,sha256=PpB3q4UPi9ctRznq48Fy6sJUsOEqdAWzMzee1BYORX4,24001
22
- kfinance/tests/test_tools.py,sha256=fTN43Y8fX8l8Yyw65XJmn_xUIbrTLaPvrsuBEdKPqK0,15234
21
+ kfinance/tests/test_objects.py,sha256=CSk3iN-uDt-E6gaOX4jExuYPT8Up-YNC3hafpenadcA,23614
22
+ kfinance/tests/test_tools.py,sha256=ne4XhebhoxDHFl4kRLl10j4K-SXLrxS6jv6Ypt0Gv_E,16846
23
23
  kfinance/tool_calling/README.md,sha256=omJq7Us6r4U45QB7hRpLjRJ5BMalCkZkh4uXBjTbJXc,2022
24
- kfinance/tool_calling/__init__.py,sha256=ewTzpR4S9mzCtSRpfK7WldDX78VSRKFta-s_zBsmamA,1744
24
+ kfinance/tool_calling/__init__.py,sha256=Fb30Snu09B63NscSUJGGnFAdlXSDrTAOJlzjYvMyZXk,1873
25
25
  kfinance/tool_calling/get_business_relationship_from_identifier.py,sha256=CipXvyqEjPm6BXYP0CA9Kp1BIyiIEm7abp85x1zXRV4,1472
26
26
  kfinance/tool_calling/get_capitalization_from_identifier.py,sha256=TdWdJDeI-jSL-1YfhnnwIA9D1SXobidvoHrjK42QmqQ,1521
27
27
  kfinance/tool_calling/get_cusip_from_ticker.py,sha256=houhGCYXoSzaaTtCvOBf3pPsYiSbcV1Ej5nAyGuMWcU,644
@@ -34,9 +34,10 @@ kfinance/tool_calling/get_isin_from_ticker.py,sha256=2fJBcA-rNGbVOQmQ7qJEYxqejQw
34
34
  kfinance/tool_calling/get_latest.py,sha256=btGeVBmvX5QJutzrKfE6spatGGejDuHxtq53NoAaGNk,786
35
35
  kfinance/tool_calling/get_n_quarters_ago.py,sha256=A0ilwPKUqU0YYQSz3gNsVF0Jy4YttXrSaDhYj7y8GHA,713
36
36
  kfinance/tool_calling/get_prices_from_identifier.py,sha256=ViJkwLDvStB7grc8RuoKSDXQM399Wru4-OY3E8k1l_U,1882
37
+ kfinance/tool_calling/get_segments_from_identifier.py,sha256=WIqJ1wWE6Z87VBREGu42nRc6_eJqUbGKcE9elzqBQJE,1867
37
38
  kfinance/tool_calling/resolve_identifier.py,sha256=npslr6bBCu0qEDV1-8d24F5OC3nQ1KBMphuMbHVC1AU,626
38
39
  kfinance/tool_calling/shared_models.py,sha256=K-NPQyE_7Ew6Cs0zxG1xO2O47gp5uDHdHtWD7wUDZX4,2132
39
- kensho_kfinance-2.2.2.dist-info/METADATA,sha256=VOmB9CZIcpr2DI5tJBZuWnR039oK_iRTN4cvDFco4RQ,3436
40
- kensho_kfinance-2.2.2.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
41
- kensho_kfinance-2.2.2.dist-info/top_level.txt,sha256=kT_kNwVhfQoOAecY8W7uYah5xaHMoHoAdBIvXh6DaKM,9
42
- kensho_kfinance-2.2.2.dist-info/RECORD,,
40
+ kensho_kfinance-2.2.4.dist-info/METADATA,sha256=sx_SF7gbkLwRfyTRUw2WHaqkoSyqQfUoBUS5majgF7w,3436
41
+ kensho_kfinance-2.2.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
42
+ kensho_kfinance-2.2.4.dist-info/top_level.txt,sha256=kT_kNwVhfQoOAecY8W7uYah5xaHMoHoAdBIvXh6DaKM,9
43
+ kensho_kfinance-2.2.4.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.8.0)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
kfinance/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## v2.2.4
4
+ - Add segments as llm tools
5
+
6
+ ## v2.2.3
7
+ - Change segments return type to nested dictionary
8
+
3
9
  ## v2.2.2
4
10
  - Add segments
5
11
 
kfinance/constants.py CHANGED
@@ -102,6 +102,7 @@ class Permission(StrEnum):
102
102
  PricingPermission = "PricingPermission"
103
103
  RelationshipPermission = "RelationshipPermission"
104
104
  StatementsPermission = "StatementsPermission"
105
+ SegmentsPermission = "SegmentsPermission"
105
106
 
106
107
 
107
108
  class YearAndQuarter(TypedDict):
kfinance/meta_classes.py CHANGED
@@ -312,7 +312,7 @@ class CompanyFunctionsMetaClass:
312
312
  end_year: Optional[int] = None,
313
313
  start_quarter: Optional[int] = None,
314
314
  end_quarter: Optional[int] = None,
315
- ) -> pd.DataFrame:
315
+ ) -> dict:
316
316
  """Get the company's segments"""
317
317
  try:
318
318
  self.validate_inputs(
@@ -322,9 +322,9 @@ class CompanyFunctionsMetaClass:
322
322
  end_quarter=end_quarter,
323
323
  )
324
324
  except ValueError:
325
- return pd.DataFrame()
325
+ return {}
326
326
 
327
- results = self.kfinance_api_client.fetch_segments(
327
+ return self.kfinance_api_client.fetch_segments(
328
328
  company_id=self.company_id,
329
329
  segment_type=segment_type,
330
330
  period_type=period_type,
@@ -334,20 +334,6 @@ class CompanyFunctionsMetaClass:
334
334
  end_quarter=end_quarter,
335
335
  )["segments"]
336
336
 
337
- period_name = (
338
- "Year" if (period_type == PeriodType.annual or period_type is None) else "Period"
339
- )
340
-
341
- # flatten the nested dictionary and return as a DataFrame
342
- rows = []
343
- for period, segments in results.items():
344
- for segment_name, line_items in segments.items():
345
- for line_item, value in line_items.items():
346
- rows.append([period, segment_name, line_item, value])
347
- return pd.DataFrame(
348
- rows, columns=[period_name, "Segment Name", "Line Item", "Value"]
349
- ).replace(np.nan, None)
350
-
351
337
  def business_segments(
352
338
  self,
353
339
  period_type: Optional[PeriodType] = None,
@@ -355,7 +341,7 @@ class CompanyFunctionsMetaClass:
355
341
  end_year: Optional[int] = None,
356
342
  start_quarter: Optional[int] = None,
357
343
  end_quarter: Optional[int] = None,
358
- ) -> pd.DataFrame:
344
+ ) -> dict:
359
345
  """Retrieves the templated line of business segments for a given period_type, start_year, start_quarter, end_year and end_quarter.
360
346
 
361
347
  :param period_type: The period_type requested for. Can be “annual”, “quarterly”, "ytd". Defaults to “annual” when start_quarter and end_quarter are None.
@@ -368,8 +354,8 @@ class CompanyFunctionsMetaClass:
368
354
  :type start_quarter: int, optional
369
355
  :param end_quarter: The ending calendar quarter, defaults to None
370
356
  :type end_quarter: int, optional
371
- :return: A DataFrame with `Year`/`Period`, `Segment Name`, `Line Item` and `Value` column.
372
- :rtype: pd.DataFrame
357
+ :return: A dictionary containing the templated line of business segments for each time period, segment name, line item, and value.
358
+ :rtype: dict
373
359
  """
374
360
  return self._segments(
375
361
  segment_type=SegmentType.business,
@@ -387,8 +373,8 @@ class CompanyFunctionsMetaClass:
387
373
  end_year: Optional[int] = None,
388
374
  start_quarter: Optional[int] = None,
389
375
  end_quarter: Optional[int] = None,
390
- ) -> pd.DataFrame:
391
- """Retrieves the templated geographic segments for a given company for a given period_type, start_year, start_quarter, end_year and end_quarter.
376
+ ) -> dict:
377
+ """Retrieves the templated geographic segments for a given period_type, start_year, start_quarter, end_year and end_quarter.
392
378
 
393
379
  :param period_type: The period_type requested for. Can be “annual”, “quarterly”, "ytd". Defaults to “annual” when start_quarter and end_quarter are None.
394
380
  :type start_year: PeriodType, optional
@@ -400,8 +386,8 @@ class CompanyFunctionsMetaClass:
400
386
  :type start_quarter: int, optional
401
387
  :param end_quarter: The ending calendar quarter, defaults to None
402
388
  :type end_quarter: int, optional
403
- :return: A DataFrame with `Year`/`Period`, `Segment Name`, `Line Item` and `Value` column.
404
- :rtype: pd.DataFrame
389
+ :return: A dictionary containing the templated geographic segments for each time period, segment name, line item, and value.
390
+ :rtype: dict
405
391
  """
406
392
  return self._segments(
407
393
  segment_type=SegmentType.geographic,
@@ -337,17 +337,10 @@ class TestCompany(TestCase):
337
337
 
338
338
  def test_business_segments(self) -> None:
339
339
  """test business statement"""
340
- rows = []
341
- for period, segments in MOCK_COMPANY_DB[msft_company_id]["segments"].items():
342
- for segment_name, line_items in segments.items():
343
- for line_item, value in line_items.items():
344
- rows.append([period, segment_name, line_item, value])
345
- expected_segments = pd.DataFrame(
346
- rows, columns=["Year", "Segment Name", "Line Item", "Value"]
347
- ).replace(np.nan, None)
340
+ expected_segments = MOCK_COMPANY_DB[msft_company_id]["segments"]
348
341
 
349
342
  business_segment = self.msft_company.business_segments()
350
- pd.testing.assert_frame_equal(expected_segments, business_segment)
343
+ self.assertEqual(expected_segments, business_segment)
351
344
 
352
345
 
353
346
  class TestSecurity(TestCase):
@@ -4,7 +4,7 @@ from langchain_core.utils.function_calling import convert_to_openai_tool
4
4
  from requests_mock import Mocker
5
5
  import time_machine
6
6
 
7
- from kfinance.constants import BusinessRelationshipType, Capitalization, StatementType
7
+ from kfinance.constants import BusinessRelationshipType, Capitalization, SegmentType, StatementType
8
8
  from kfinance.kfinance import Client
9
9
  from kfinance.tests.conftest import SPGI_COMPANY_ID, SPGI_SECURITY_ID, SPGI_TRADING_ITEM_ID
10
10
  from kfinance.tool_calling import (
@@ -38,6 +38,10 @@ from kfinance.tool_calling.get_isin_from_ticker import GetIsinFromTickerArgs
38
38
  from kfinance.tool_calling.get_latest import GetLatestArgs
39
39
  from kfinance.tool_calling.get_n_quarters_ago import GetNQuartersAgoArgs
40
40
  from kfinance.tool_calling.get_prices_from_identifier import GetPricesFromIdentifierArgs
41
+ from kfinance.tool_calling.get_segments_from_identifier import (
42
+ GetSegmentsFromIdentifier,
43
+ GetSegmentsFromIdentifierArgs,
44
+ )
41
45
  from kfinance.tool_calling.shared_models import ToolArgsWithIdentifier
42
46
 
43
47
 
@@ -217,6 +221,44 @@ class TestGetFinancialStatementFromIdentifier:
217
221
  assert response == expected_response
218
222
 
219
223
 
224
+ class TestGetSegmentsFromIdentifier:
225
+ def test_get_segments_from_identifier(self, mock_client: Client, requests_mock: Mocker):
226
+ """
227
+ GIVEN the GetSegmentsFromIdentifier tool
228
+ WHEN we request the SPGI business segment
229
+ THEN we get back the SPGI business segment
230
+ """
231
+
232
+ segments_response = {
233
+ "segments": {
234
+ "2020": {
235
+ "Commodity Insights": {
236
+ "CAPEX": -7000000.0,
237
+ "D&A": 17000000.0,
238
+ },
239
+ "Unallocated Assets Held for Sale": None,
240
+ },
241
+ "2021": {
242
+ "Commodity Insights": {
243
+ "CAPEX": -2000000.0,
244
+ "D&A": 12000000.0,
245
+ },
246
+ "Unallocated Assets Held for Sale": {"Total Assets": 321000000.0},
247
+ },
248
+ },
249
+ }
250
+ requests_mock.get(
251
+ url=f"https://kfinance.kensho.com/api/v1/segments/{SPGI_COMPANY_ID}/business/none/none/none/none/none",
252
+ # truncated from the original API response
253
+ json=segments_response,
254
+ )
255
+
256
+ tool = GetSegmentsFromIdentifier(kfinance_client=mock_client)
257
+ args = GetSegmentsFromIdentifierArgs(identifier="SPGI", segment_type=SegmentType.business)
258
+ response = tool.run(args.model_dump(mode="json"))
259
+ assert response == segments_response["segments"]
260
+
261
+
220
262
  class TestGetHistoryMetadataFromIdentifier:
221
263
  def test_get_history_metadata_from_identifier(self, mock_client: Client, requests_mock: Mocker):
222
264
  """
@@ -22,6 +22,9 @@ from kfinance.tool_calling.get_isin_from_ticker import GetIsinFromTicker
22
22
  from kfinance.tool_calling.get_latest import GetLatest
23
23
  from kfinance.tool_calling.get_n_quarters_ago import GetNQuartersAgo
24
24
  from kfinance.tool_calling.get_prices_from_identifier import GetPricesFromIdentifier
25
+ from kfinance.tool_calling.get_segments_from_identifier import (
26
+ GetSegmentsFromIdentifier,
27
+ )
25
28
  from kfinance.tool_calling.resolve_identifier import ResolveIdentifier
26
29
  from kfinance.tool_calling.shared_models import KfinanceTool
27
30
 
@@ -40,4 +43,5 @@ ALL_TOOLS: list[Type[KfinanceTool]] = [
40
43
  GetFinancialLineItemFromIdentifier,
41
44
  GetBusinessRelationshipFromIdentifier,
42
45
  ResolveIdentifier,
46
+ GetSegmentsFromIdentifier,
43
47
  ]
@@ -0,0 +1,42 @@
1
+ from typing import Literal, Type
2
+
3
+ from pydantic import BaseModel, Field
4
+
5
+ from kfinance.constants import PeriodType, Permission, SegmentType
6
+ from kfinance.tool_calling.shared_models import KfinanceTool, ToolArgsWithIdentifier
7
+
8
+
9
+ class GetSegmentsFromIdentifierArgs(ToolArgsWithIdentifier):
10
+ # no description because the description for enum fields comes from the enum docstring.
11
+ segment_type: SegmentType
12
+ period_type: PeriodType | None = Field(default=None, description="The period type")
13
+ start_year: int | None = Field(default=None, description="The starting year for the data range")
14
+ end_year: int | None = Field(default=None, description="The ending year for the data range")
15
+ start_quarter: Literal[1, 2, 3, 4] | None = Field(default=None, description="Starting quarter")
16
+ end_quarter: Literal[1, 2, 3, 4] | None = Field(default=None, description="Ending quarter")
17
+
18
+
19
+ class GetSegmentsFromIdentifier(KfinanceTool):
20
+ name: str = "get_segments_from_identifier"
21
+ description: str = "Get the templated segments associated with an identifier."
22
+ args_schema: Type[BaseModel] = GetSegmentsFromIdentifierArgs
23
+ required_permission: Permission | None = Permission.StatementsPermission
24
+
25
+ def _run(
26
+ self,
27
+ identifier: str,
28
+ segment_type: SegmentType,
29
+ period_type: PeriodType | None = None,
30
+ start_year: int | None = None,
31
+ end_year: int | None = None,
32
+ start_quarter: Literal[1, 2, 3, 4] | None = None,
33
+ end_quarter: Literal[1, 2, 3, 4] | None = None,
34
+ ) -> str:
35
+ ticker = self.kfinance_client.ticker(identifier)
36
+ return getattr(ticker, segment_type.value + "_segments")(
37
+ period_type=period_type,
38
+ start_year=start_year,
39
+ end_year=end_year,
40
+ start_quarter=start_quarter,
41
+ end_quarter=end_quarter,
42
+ )
kfinance/version.py CHANGED
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '2.2.2'
21
- __version_tuple__ = version_tuple = (2, 2, 2)
20
+ __version__ = version = '2.2.4'
21
+ __version_tuple__ = version_tuple = (2, 2, 4)