settfex 0.1.0__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.
Files changed (34) hide show
  1. settfex/__init__.py +63 -0
  2. settfex/py.typed +0 -0
  3. settfex/services/__init__.py +1 -0
  4. settfex/services/set/__init__.py +130 -0
  5. settfex/services/set/constants.py +19 -0
  6. settfex/services/set/list.py +207 -0
  7. settfex/services/set/stock/__init__.py +114 -0
  8. settfex/services/set/stock/board_of_director.py +240 -0
  9. settfex/services/set/stock/corporate_action.py +310 -0
  10. settfex/services/set/stock/financial/__init__.py +25 -0
  11. settfex/services/set/stock/financial/financial.py +442 -0
  12. settfex/services/set/stock/highlight_data.py +282 -0
  13. settfex/services/set/stock/nvdr_holder.py +264 -0
  14. settfex/services/set/stock/price_performance.py +290 -0
  15. settfex/services/set/stock/profile_company.py +326 -0
  16. settfex/services/set/stock/profile_stock.py +290 -0
  17. settfex/services/set/stock/shareholder.py +278 -0
  18. settfex/services/set/stock/stock.py +196 -0
  19. settfex/services/set/stock/trading_stat.py +279 -0
  20. settfex/services/set/stock/utils.py +78 -0
  21. settfex/services/tfex/__init__.py +34 -0
  22. settfex/services/tfex/constants.py +8 -0
  23. settfex/services/tfex/list.py +307 -0
  24. settfex/services/tfex/trading_statistics.py +243 -0
  25. settfex/utils/__init__.py +18 -0
  26. settfex/utils/data_fetcher.py +376 -0
  27. settfex/utils/http.py +214 -0
  28. settfex/utils/logging.py +95 -0
  29. settfex/utils/session_cache.py +265 -0
  30. settfex/utils/session_manager.py +493 -0
  31. settfex-0.1.0.dist-info/METADATA +597 -0
  32. settfex-0.1.0.dist-info/RECORD +34 -0
  33. settfex-0.1.0.dist-info/WHEEL +4 -0
  34. settfex-0.1.0.dist-info/licenses/LICENSE +21 -0
settfex/__init__.py ADDED
@@ -0,0 +1,63 @@
1
+ """settfex - Stock Exchange of Thailand (SET) and Thailand Futures Exchange (TFEX) Data Library.
2
+
3
+ A modern Python library for fetching real-time and historical data from Thai financial markets.
4
+
5
+ Usage:
6
+ >>> import asyncio
7
+ >>> from settfex.services.set import Stock, get_stock_list
8
+ >>>
9
+ >>> async def main():
10
+ ... # Fetch stock list
11
+ ... stock_list = await get_stock_list()
12
+ ... print(f"Total stocks: {stock_list.count}")
13
+ ...
14
+ ... # Fetch stock data
15
+ ... stock = Stock("CPALL")
16
+ ... highlight = await stock.get_highlight_data()
17
+ ... print(f"Market Cap: {highlight.market_cap:,.0f}")
18
+ >>>
19
+ >>> asyncio.run(main())
20
+ """
21
+
22
+ __version__ = "0.1.0"
23
+ __author__ = "batt"
24
+ __license__ = "MIT"
25
+
26
+ # Public API exports - import commonly used classes/functions
27
+ from settfex.services.set import (
28
+ CompanyProfile,
29
+ Stock,
30
+ StockHighlightData,
31
+ StockListResponse,
32
+ StockProfile,
33
+ get_company_profile,
34
+ get_highlight_data,
35
+ get_profile,
36
+ get_stock_list,
37
+ )
38
+
39
+ # Utility exports
40
+ from settfex.utils.data_fetcher import AsyncDataFetcher, FetcherConfig
41
+ from settfex.utils.logging import setup_logger
42
+
43
+ __all__ = [
44
+ # Version info
45
+ "__version__",
46
+ "__author__",
47
+ "__license__",
48
+ # SET Services - Most commonly used
49
+ "Stock",
50
+ "get_stock_list",
51
+ "get_highlight_data",
52
+ "get_profile",
53
+ "get_company_profile",
54
+ # Data Models
55
+ "StockListResponse",
56
+ "StockHighlightData",
57
+ "StockProfile",
58
+ "CompanyProfile",
59
+ # Utilities
60
+ "AsyncDataFetcher",
61
+ "FetcherConfig",
62
+ "setup_logger",
63
+ ]
settfex/py.typed ADDED
File without changes
@@ -0,0 +1 @@
1
+ # Services for SET and TFEX data
@@ -0,0 +1,130 @@
1
+ """SET (Stock Exchange of Thailand) services."""
2
+
3
+ from settfex.services.set.constants import (
4
+ SET_BASE_URL,
5
+ SET_BOARD_OF_DIRECTOR_ENDPOINT,
6
+ SET_COMPANY_PROFILE_ENDPOINT,
7
+ SET_CORPORATE_ACTION_ENDPOINT,
8
+ SET_FINANCIAL_BALANCE_SHEET_ENDPOINT,
9
+ SET_FINANCIAL_CASH_FLOW_ENDPOINT,
10
+ SET_FINANCIAL_INCOME_STATEMENT_ENDPOINT,
11
+ SET_NVDR_HOLDER_ENDPOINT,
12
+ SET_PRICE_PERFORMANCE_ENDPOINT,
13
+ SET_STOCK_HIGHLIGHT_DATA_ENDPOINT,
14
+ SET_STOCK_LIST_ENDPOINT,
15
+ SET_STOCK_PROFILE_ENDPOINT,
16
+ SET_STOCK_SHAREHOLDER_ENDPOINT,
17
+ SET_TRADING_STAT_ENDPOINT,
18
+ )
19
+ from settfex.services.set.list import (
20
+ StockListResponse,
21
+ StockListService,
22
+ StockSymbol,
23
+ get_stock_list,
24
+ )
25
+ from settfex.services.set.stock import (
26
+ Account,
27
+ BalanceSheet,
28
+ BoardOfDirectorService,
29
+ CashFlow,
30
+ CompanyProfile,
31
+ CompanyProfileService,
32
+ CorporateAction,
33
+ CorporateActionService,
34
+ Director,
35
+ FinancialService,
36
+ FinancialStatement,
37
+ IncomeStatement,
38
+ NVDRHolderData,
39
+ NVDRHolderService,
40
+ PricePerformanceData,
41
+ PricePerformanceService,
42
+ ShareholderData,
43
+ ShareholderService,
44
+ Stock,
45
+ StockHighlightData,
46
+ StockHighlightDataService,
47
+ StockProfile,
48
+ StockProfileService,
49
+ TradingStat,
50
+ TradingStatService,
51
+ get_balance_sheet,
52
+ get_board_of_directors,
53
+ get_cash_flow,
54
+ get_company_profile,
55
+ get_corporate_actions,
56
+ get_highlight_data,
57
+ get_income_statement,
58
+ get_nvdr_holder_data,
59
+ get_price_performance,
60
+ get_profile,
61
+ get_shareholder_data,
62
+ get_trading_stats,
63
+ normalize_language,
64
+ normalize_symbol,
65
+ )
66
+
67
+ __all__ = [
68
+ # Constants
69
+ "SET_BASE_URL",
70
+ "SET_STOCK_LIST_ENDPOINT",
71
+ "SET_STOCK_HIGHLIGHT_DATA_ENDPOINT",
72
+ "SET_STOCK_PROFILE_ENDPOINT",
73
+ "SET_COMPANY_PROFILE_ENDPOINT",
74
+ "SET_CORPORATE_ACTION_ENDPOINT",
75
+ "SET_STOCK_SHAREHOLDER_ENDPOINT",
76
+ "SET_NVDR_HOLDER_ENDPOINT",
77
+ "SET_BOARD_OF_DIRECTOR_ENDPOINT",
78
+ "SET_TRADING_STAT_ENDPOINT",
79
+ "SET_PRICE_PERFORMANCE_ENDPOINT",
80
+ "SET_FINANCIAL_BALANCE_SHEET_ENDPOINT",
81
+ "SET_FINANCIAL_INCOME_STATEMENT_ENDPOINT",
82
+ "SET_FINANCIAL_CASH_FLOW_ENDPOINT",
83
+ # Stock List Service
84
+ "StockListService",
85
+ "StockListResponse",
86
+ "StockSymbol",
87
+ "get_stock_list",
88
+ # Stock Class and Services
89
+ "Stock",
90
+ "StockHighlightDataService",
91
+ "StockHighlightData",
92
+ "get_highlight_data",
93
+ "StockProfileService",
94
+ "StockProfile",
95
+ "get_profile",
96
+ "CompanyProfileService",
97
+ "CompanyProfile",
98
+ "get_company_profile",
99
+ "CorporateActionService",
100
+ "CorporateAction",
101
+ "get_corporate_actions",
102
+ "ShareholderService",
103
+ "ShareholderData",
104
+ "get_shareholder_data",
105
+ "NVDRHolderService",
106
+ "NVDRHolderData",
107
+ "get_nvdr_holder_data",
108
+ "BoardOfDirectorService",
109
+ "Director",
110
+ "get_board_of_directors",
111
+ "TradingStatService",
112
+ "TradingStat",
113
+ "get_trading_stats",
114
+ "PricePerformanceService",
115
+ "PricePerformanceData",
116
+ "get_price_performance",
117
+ # Financial Service
118
+ "FinancialService",
119
+ "FinancialStatement",
120
+ "Account",
121
+ "BalanceSheet",
122
+ "IncomeStatement",
123
+ "CashFlow",
124
+ "get_balance_sheet",
125
+ "get_income_statement",
126
+ "get_cash_flow",
127
+ # Stock Utilities
128
+ "normalize_symbol",
129
+ "normalize_language",
130
+ ]
@@ -0,0 +1,19 @@
1
+ """Constants and configuration for SET (Stock Exchange of Thailand) services."""
2
+
3
+ # Base URL for all SET API endpoints
4
+ SET_BASE_URL = "https://www.set.or.th"
5
+
6
+ # API endpoints
7
+ SET_STOCK_LIST_ENDPOINT = "/api/set/stock/list"
8
+ SET_STOCK_HIGHLIGHT_DATA_ENDPOINT = "/api/set/stock/{symbol}/highlight-data"
9
+ SET_STOCK_PROFILE_ENDPOINT = "/api/set/stock/{symbol}/profile"
10
+ SET_COMPANY_PROFILE_ENDPOINT = "/api/set/company/{symbol}/profile"
11
+ SET_CORPORATE_ACTION_ENDPOINT = "/api/set/stock/{symbol}/corporate-action"
12
+ SET_STOCK_SHAREHOLDER_ENDPOINT = "/api/set/stock/{symbol}/shareholder"
13
+ SET_NVDR_HOLDER_ENDPOINT = "/api/set/stock/{symbol}/nvdr-holder"
14
+ SET_BOARD_OF_DIRECTOR_ENDPOINT = "/api/set/company/{symbol}/board-of-director"
15
+ SET_TRADING_STAT_ENDPOINT = "/api/set/factsheet/{symbol}/trading-stat"
16
+ SET_PRICE_PERFORMANCE_ENDPOINT = "/api/set/factsheet/{symbol}/price-performance"
17
+ SET_FINANCIAL_BALANCE_SHEET_ENDPOINT = "/api/set/factsheet/{symbol}/financialstatement"
18
+ SET_FINANCIAL_INCOME_STATEMENT_ENDPOINT = "/api/set/factsheet/{symbol}/financialstatement"
19
+ SET_FINANCIAL_CASH_FLOW_ENDPOINT = "/api/set/factsheet/{symbol}/financialstatement"
@@ -0,0 +1,207 @@
1
+ """SET Stock List Service - Fetch list of stock details from SET API."""
2
+
3
+ from typing import Any
4
+
5
+ from loguru import logger
6
+ from pydantic import BaseModel, ConfigDict, Field
7
+
8
+ from settfex.services.set.constants import SET_BASE_URL, SET_STOCK_LIST_ENDPOINT
9
+ from settfex.utils.data_fetcher import AsyncDataFetcher, FetcherConfig
10
+
11
+
12
+ class StockSymbol(BaseModel):
13
+ """Model for individual stock symbol information."""
14
+
15
+ symbol: str = Field(description="Stock symbol/ticker")
16
+ name_th: str = Field(alias="nameTH", description="Company name in Thai")
17
+ name_en: str = Field(alias="nameEN", description="Company name in English")
18
+ market: str = Field(description="Market type (SET, mai, etc.)")
19
+ security_type: str = Field(alias="securityType", description="Security type")
20
+ type_sequence: int = Field(alias="typeSequence", description="Type sequence number")
21
+ industry: str = Field(description="Industry classification")
22
+ sector: str = Field(description="Sector classification")
23
+ query_sector: str = Field(alias="querySector", description="Queryable sector name")
24
+ is_iff: bool = Field(alias="isIFF", description="Is Infrastructure Fund Flag")
25
+ is_foreign_listing: bool = Field(
26
+ alias="isForeignListing", description="Is foreign listing flag"
27
+ )
28
+ remark: str = Field(default="", description="Additional remarks")
29
+
30
+ model_config = ConfigDict(
31
+ populate_by_name=True, # Allow both field name and alias
32
+ str_strip_whitespace=True, # Strip whitespace from strings
33
+ )
34
+
35
+
36
+ class StockListResponse(BaseModel):
37
+ """Response model for stock list API."""
38
+
39
+ security_symbols: list[StockSymbol] = Field(
40
+ alias="securitySymbols", description="List of stock symbols"
41
+ )
42
+
43
+ model_config = ConfigDict(
44
+ populate_by_name=True, # Allow both field name and alias
45
+ )
46
+
47
+ @property
48
+ def count(self) -> int:
49
+ """Get total count of securities."""
50
+ return len(self.security_symbols)
51
+
52
+ def filter_by_market(self, market: str) -> list[StockSymbol]:
53
+ """
54
+ Filter securities by market type.
55
+
56
+ Args:
57
+ market: Market type (e.g., 'SET', 'mai')
58
+
59
+ Returns:
60
+ List of stock symbols for the specified market
61
+ """
62
+ return [s for s in self.security_symbols if s.market.upper() == market.upper()]
63
+
64
+ def filter_by_industry(self, industry: str) -> list[StockSymbol]:
65
+ """
66
+ Filter securities by industry.
67
+
68
+ Args:
69
+ industry: Industry classification
70
+
71
+ Returns:
72
+ List of stock symbols in the specified industry
73
+ """
74
+ return [s for s in self.security_symbols if s.industry.upper() == industry.upper()]
75
+
76
+ def get_symbol(self, symbol: str) -> StockSymbol | None:
77
+ """
78
+ Get a specific stock symbol.
79
+
80
+ Args:
81
+ symbol: Stock symbol to find
82
+
83
+ Returns:
84
+ StockSymbol if found, None otherwise
85
+ """
86
+ for s in self.security_symbols:
87
+ if s.symbol.upper() == symbol.upper():
88
+ return s
89
+ return None
90
+
91
+
92
+ class StockListService:
93
+ """
94
+ Service for fetching stock list from SET API.
95
+
96
+ This service provides async methods to fetch the complete list of stocks
97
+ traded on the Stock Exchange of Thailand (SET), including company names,
98
+ market classifications, and industry sectors.
99
+ """
100
+
101
+ def __init__(self, config: FetcherConfig | None = None) -> None:
102
+ """
103
+ Initialize the stock list service.
104
+
105
+ Args:
106
+ config: Optional fetcher configuration (uses defaults if None)
107
+
108
+ Example:
109
+ >>> # Uses SessionManager for automatic cookie handling
110
+ >>> service = StockListService()
111
+ """
112
+ self.config = config or FetcherConfig()
113
+ self.base_url = SET_BASE_URL
114
+ logger.info(f"StockListService initialized with base_url={self.base_url}")
115
+
116
+ async def fetch_stock_list(self) -> StockListResponse:
117
+ """
118
+ Fetch the complete list of stocks from SET API.
119
+
120
+ Returns:
121
+ StockListResponse containing all stock symbols and details
122
+
123
+ Raises:
124
+ Exception: If request fails or response cannot be parsed
125
+
126
+ Example:
127
+ >>> service = StockListService()
128
+ >>> response = await service.fetch_stock_list()
129
+ >>> print(f"Total stocks: {response.count}")
130
+ >>> print(f"SET stocks: {len(response.filter_by_market('SET'))}")
131
+ """
132
+ url = f"{self.base_url}{SET_STOCK_LIST_ENDPOINT}"
133
+
134
+ logger.info(f"Fetching stock list from {url}")
135
+
136
+ async with AsyncDataFetcher(config=self.config) as fetcher:
137
+ # Get optimized headers for SET API (includes all Incapsula bypass headers)
138
+ headers = AsyncDataFetcher.get_set_api_headers()
139
+
140
+ # Fetch JSON data from API - SessionManager handles cookies automatically
141
+ data = await fetcher.fetch_json(url, headers=headers)
142
+
143
+ # Parse and validate response using Pydantic
144
+ response = StockListResponse(**data)
145
+
146
+ logger.info(
147
+ f"Successfully fetched {response.count} stock symbols from SET API"
148
+ )
149
+
150
+ return response
151
+
152
+ async def fetch_stock_list_raw(self) -> dict[str, Any]:
153
+ """
154
+ Fetch stock list as raw dictionary without Pydantic validation.
155
+
156
+ Useful for debugging or when you need the raw API response.
157
+
158
+ Returns:
159
+ Raw dictionary from API
160
+
161
+ Raises:
162
+ Exception: If request fails
163
+
164
+ Example:
165
+ >>> service = StockListService()
166
+ >>> raw_data = await service.fetch_stock_list_raw()
167
+ >>> print(raw_data.keys())
168
+ """
169
+ url = f"{self.base_url}{SET_STOCK_LIST_ENDPOINT}"
170
+
171
+ logger.info(f"Fetching raw stock list from {url}")
172
+
173
+ async with AsyncDataFetcher(config=self.config) as fetcher:
174
+ # Get optimized headers for SET API
175
+ headers = AsyncDataFetcher.get_set_api_headers()
176
+
177
+ # Use provided session cookies or generate Incapsula-aware cookies
178
+ cookies = self.session_cookies or AsyncDataFetcher.generate_incapsula_cookies()
179
+
180
+ # Fetch JSON data
181
+ data = await fetcher.fetch_json(
182
+ url, headers=headers, cookies=cookies, use_random_cookies=False
183
+ )
184
+ logger.debug(f"Raw response keys: {list(data.keys()) if isinstance(data, dict) else type(data)}") # noqa: E501
185
+ return data
186
+
187
+
188
+ # Convenience function for quick access
189
+ async def get_stock_list(config: FetcherConfig | None = None) -> StockListResponse:
190
+ """
191
+ Convenience function to fetch stock list.
192
+
193
+ Args:
194
+ config: Optional fetcher configuration
195
+
196
+ Returns:
197
+ StockListResponse with all stock symbols
198
+
199
+ Example:
200
+ >>> from settfex.services.set import get_stock_list
201
+ >>> # Uses SessionManager for automatic cookie handling
202
+ >>> response = await get_stock_list()
203
+ >>> for stock in response.security_symbols[:5]:
204
+ ... print(f"{stock.symbol}: {stock.name_en}")
205
+ """
206
+ service = StockListService(config=config)
207
+ return await service.fetch_stock_list()
@@ -0,0 +1,114 @@
1
+ """Stock-specific utilities and services for SET stock operations."""
2
+
3
+ from settfex.services.set.stock.board_of_director import (
4
+ BoardOfDirectorService,
5
+ Director,
6
+ get_board_of_directors,
7
+ )
8
+ from settfex.services.set.stock.corporate_action import (
9
+ CorporateAction,
10
+ CorporateActionService,
11
+ get_corporate_actions,
12
+ )
13
+ from settfex.services.set.stock.financial import (
14
+ Account,
15
+ BalanceSheet,
16
+ CashFlow,
17
+ FinancialService,
18
+ FinancialStatement,
19
+ IncomeStatement,
20
+ get_balance_sheet,
21
+ get_cash_flow,
22
+ get_income_statement,
23
+ )
24
+ from settfex.services.set.stock.highlight_data import (
25
+ StockHighlightData,
26
+ StockHighlightDataService,
27
+ get_highlight_data,
28
+ )
29
+ from settfex.services.set.stock.nvdr_holder import (
30
+ NVDRHolderData,
31
+ NVDRHolderService,
32
+ get_nvdr_holder_data,
33
+ )
34
+ from settfex.services.set.stock.price_performance import (
35
+ PricePerformanceData,
36
+ PricePerformanceService,
37
+ get_price_performance,
38
+ )
39
+ from settfex.services.set.stock.profile_company import (
40
+ CompanyProfile,
41
+ CompanyProfileService,
42
+ get_company_profile,
43
+ )
44
+ from settfex.services.set.stock.profile_stock import (
45
+ StockProfile,
46
+ StockProfileService,
47
+ get_profile,
48
+ )
49
+ from settfex.services.set.stock.shareholder import (
50
+ ShareholderData,
51
+ ShareholderService,
52
+ get_shareholder_data,
53
+ )
54
+ from settfex.services.set.stock.stock import Stock
55
+ from settfex.services.set.stock.trading_stat import (
56
+ TradingStat,
57
+ TradingStatService,
58
+ get_trading_stats,
59
+ )
60
+ from settfex.services.set.stock.utils import normalize_language, normalize_symbol
61
+
62
+ __all__ = [
63
+ # Main Stock Class
64
+ "Stock",
65
+ # Utilities
66
+ "normalize_symbol",
67
+ "normalize_language",
68
+ # Highlight Data Service
69
+ "StockHighlightDataService",
70
+ "StockHighlightData",
71
+ "get_highlight_data",
72
+ # Profile Service
73
+ "StockProfileService",
74
+ "StockProfile",
75
+ "get_profile",
76
+ # Company Profile Service
77
+ "CompanyProfileService",
78
+ "CompanyProfile",
79
+ "get_company_profile",
80
+ # Corporate Action Service
81
+ "CorporateActionService",
82
+ "CorporateAction",
83
+ "get_corporate_actions",
84
+ # Shareholder Service
85
+ "ShareholderService",
86
+ "ShareholderData",
87
+ "get_shareholder_data",
88
+ # NVDR Holder Service
89
+ "NVDRHolderService",
90
+ "NVDRHolderData",
91
+ "get_nvdr_holder_data",
92
+ # Board of Director Service
93
+ "BoardOfDirectorService",
94
+ "Director",
95
+ "get_board_of_directors",
96
+ # Trading Statistics Service
97
+ "TradingStatService",
98
+ "TradingStat",
99
+ "get_trading_stats",
100
+ # Price Performance Service
101
+ "PricePerformanceService",
102
+ "PricePerformanceData",
103
+ "get_price_performance",
104
+ # Financial Service
105
+ "FinancialService",
106
+ "FinancialStatement",
107
+ "Account",
108
+ "BalanceSheet",
109
+ "IncomeStatement",
110
+ "CashFlow",
111
+ "get_balance_sheet",
112
+ "get_income_statement",
113
+ "get_cash_flow",
114
+ ]