opendart-fss 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.
- opendart_fss/__init__.py +77 -0
- opendart_fss/_version.py +34 -0
- opendart_fss/api/__init__.py +19 -0
- opendart_fss/api/base.py +72 -0
- opendart_fss/api/disclosure.py +103 -0
- opendart_fss/api/financial.py +206 -0
- opendart_fss/api/major_event.py +1051 -0
- opendart_fss/api/registration.py +183 -0
- opendart_fss/api/report.py +821 -0
- opendart_fss/api/shareholder.py +51 -0
- opendart_fss/client.py +96 -0
- opendart_fss/constants.py +88 -0
- opendart_fss/exceptions.py +90 -0
- opendart_fss/models/__init__.py +124 -0
- opendart_fss/models/base.py +10 -0
- opendart_fss/models/disclosure.py +106 -0
- opendart_fss/models/financial.py +85 -0
- opendart_fss/models/major_event.py +863 -0
- opendart_fss/models/registration.py +186 -0
- opendart_fss/models/report.py +691 -0
- opendart_fss/models/shareholder.py +54 -0
- opendart_fss/verification/__init__.py +50 -0
- opendart_fss/verification/config.py +450 -0
- opendart_fss/verification/rate_limiter.py +92 -0
- opendart_fss/verification/reporter.py +255 -0
- opendart_fss/verification/runner.py +326 -0
- opendart_fss-0.1.0.dist-info/METADATA +308 -0
- opendart_fss-0.1.0.dist-info/RECORD +30 -0
- opendart_fss-0.1.0.dist-info/WHEEL +4 -0
- opendart_fss-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""DS004 지분공시 종합정보 API."""
|
|
2
|
+
|
|
3
|
+
from opendart_fss.api.base import BaseAPI
|
|
4
|
+
from opendart_fss.models.shareholder import (
|
|
5
|
+
ExecutiveStock,
|
|
6
|
+
ExecutiveStockListResponse,
|
|
7
|
+
MajorStock,
|
|
8
|
+
MajorStockListResponse,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ShareholderAPI(BaseAPI):
|
|
13
|
+
"""지분공시 종합정보 API (DS004)."""
|
|
14
|
+
|
|
15
|
+
async def get_major_stock(
|
|
16
|
+
self,
|
|
17
|
+
corp_code: str,
|
|
18
|
+
) -> list[MajorStock]:
|
|
19
|
+
"""대량보유 상황보고 조회.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
corp_code: 고유번호 (8자리)
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
대량보유 상황보고 목록
|
|
26
|
+
"""
|
|
27
|
+
response = await self._get(
|
|
28
|
+
"/api/majorstock.json",
|
|
29
|
+
MajorStockListResponse,
|
|
30
|
+
params={"corp_code": corp_code},
|
|
31
|
+
)
|
|
32
|
+
return response.items
|
|
33
|
+
|
|
34
|
+
async def get_executive_stock(
|
|
35
|
+
self,
|
|
36
|
+
corp_code: str,
|
|
37
|
+
) -> list[ExecutiveStock]:
|
|
38
|
+
"""임원/주요주주 소유보고 조회.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
corp_code: 고유번호 (8자리)
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
임원/주요주주 소유보고 목록
|
|
45
|
+
"""
|
|
46
|
+
response = await self._get(
|
|
47
|
+
"/api/elestock.json",
|
|
48
|
+
ExecutiveStockListResponse,
|
|
49
|
+
params={"corp_code": corp_code},
|
|
50
|
+
)
|
|
51
|
+
return response.items
|
opendart_fss/client.py
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"""OpenDART API 클라이언트."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from types import TracebackType
|
|
5
|
+
|
|
6
|
+
import httpx
|
|
7
|
+
from dotenv import load_dotenv
|
|
8
|
+
|
|
9
|
+
from opendart_fss.api.disclosure import DisclosureAPI
|
|
10
|
+
from opendart_fss.api.financial import FinancialAPI
|
|
11
|
+
from opendart_fss.api.major_event import MajorEventAPI
|
|
12
|
+
from opendart_fss.api.registration import RegistrationAPI
|
|
13
|
+
from opendart_fss.api.report import ReportAPI
|
|
14
|
+
from opendart_fss.api.shareholder import ShareholderAPI
|
|
15
|
+
|
|
16
|
+
load_dotenv()
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class OpenDartClient:
|
|
20
|
+
"""OpenDART API 클라이언트.
|
|
21
|
+
|
|
22
|
+
Example:
|
|
23
|
+
```python
|
|
24
|
+
async with OpenDartClient(api_key="YOUR_API_KEY") as client:
|
|
25
|
+
# 공시 검색
|
|
26
|
+
disclosures = await client.disclosure.search(
|
|
27
|
+
corp_code="00126380",
|
|
28
|
+
bgn_de="20240101",
|
|
29
|
+
end_de="20241231"
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
# 기업 개황
|
|
33
|
+
company = await client.disclosure.get_company("00126380")
|
|
34
|
+
print(f"회사명: {company.corp_name}")
|
|
35
|
+
|
|
36
|
+
# 재무제표 조회
|
|
37
|
+
financials = await client.financial.get_single_account(
|
|
38
|
+
corp_code="00126380",
|
|
39
|
+
bsns_year="2024",
|
|
40
|
+
reprt_code="11011"
|
|
41
|
+
)
|
|
42
|
+
```
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
def __init__(
|
|
46
|
+
self,
|
|
47
|
+
api_key: str | None = None,
|
|
48
|
+
*,
|
|
49
|
+
timeout: float = 30.0,
|
|
50
|
+
http_client: httpx.AsyncClient | None = None,
|
|
51
|
+
) -> None:
|
|
52
|
+
"""클라이언트 초기화.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
api_key: OpenDART API 키. 생략 시 OPENDART_API_KEY 환경변수 사용
|
|
56
|
+
timeout: HTTP 요청 타임아웃 (초)
|
|
57
|
+
http_client: 커스텀 httpx.AsyncClient (선택)
|
|
58
|
+
|
|
59
|
+
Raises:
|
|
60
|
+
ValueError: API 키가 제공되지 않고 환경변수도 설정되지 않은 경우
|
|
61
|
+
"""
|
|
62
|
+
self.api_key = api_key or os.environ.get("OPENDART_API_KEY")
|
|
63
|
+
if not self.api_key:
|
|
64
|
+
raise ValueError(
|
|
65
|
+
"API key is required. "
|
|
66
|
+
"Provide api_key parameter or set OPENDART_API_KEY environment variable."
|
|
67
|
+
)
|
|
68
|
+
self._timeout = timeout
|
|
69
|
+
self._external_client = http_client is not None
|
|
70
|
+
self._http = http_client or httpx.AsyncClient(timeout=timeout)
|
|
71
|
+
|
|
72
|
+
# API 모듈 초기화
|
|
73
|
+
self.disclosure = DisclosureAPI(self)
|
|
74
|
+
self.report = ReportAPI(self)
|
|
75
|
+
self.financial = FinancialAPI(self)
|
|
76
|
+
self.shareholder = ShareholderAPI(self)
|
|
77
|
+
self.major_event = MajorEventAPI(self)
|
|
78
|
+
self.registration = RegistrationAPI(self)
|
|
79
|
+
|
|
80
|
+
async def __aenter__(self) -> "OpenDartClient":
|
|
81
|
+
"""컨텍스트 매니저 진입."""
|
|
82
|
+
return self
|
|
83
|
+
|
|
84
|
+
async def __aexit__(
|
|
85
|
+
self,
|
|
86
|
+
_exc_type: type[BaseException] | None,
|
|
87
|
+
_exc_val: BaseException | None,
|
|
88
|
+
_exc_tb: TracebackType | None,
|
|
89
|
+
) -> None:
|
|
90
|
+
"""컨텍스트 매니저 종료."""
|
|
91
|
+
await self.close()
|
|
92
|
+
|
|
93
|
+
async def close(self) -> None:
|
|
94
|
+
"""HTTP 클라이언트 종료."""
|
|
95
|
+
if not self._external_client:
|
|
96
|
+
await self._http.aclose()
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""OpenDART API 상수 정의."""
|
|
2
|
+
|
|
3
|
+
from enum import StrEnum
|
|
4
|
+
|
|
5
|
+
BASE_URL = "https://opendart.fss.or.kr"
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class StatusCode(StrEnum):
|
|
9
|
+
"""API 응답 상태 코드."""
|
|
10
|
+
|
|
11
|
+
SUCCESS = "000"
|
|
12
|
+
UNREGISTERED_KEY = "010"
|
|
13
|
+
INACTIVE_KEY = "011"
|
|
14
|
+
INVALID_KEY = "012"
|
|
15
|
+
USAGE_LIMIT_EXCEEDED = "013"
|
|
16
|
+
DAILY_LIMIT_EXCEEDED_FIELD = "014"
|
|
17
|
+
DAILY_LIMIT_EXCEEDED_REQUESTS = "015"
|
|
18
|
+
MONTHLY_LIMIT_EXCEEDED = "016"
|
|
19
|
+
INVALID_PARAMETER = "020"
|
|
20
|
+
MISSING_REQUIRED_PARAMETER = "021"
|
|
21
|
+
INVALID_REPORT_CODE = "022"
|
|
22
|
+
INVALID_DATE = "023"
|
|
23
|
+
NO_DATA = "100"
|
|
24
|
+
FILE_NOT_FOUND = "101"
|
|
25
|
+
SYSTEM_ERROR = "800"
|
|
26
|
+
MAINTENANCE = "900"
|
|
27
|
+
UNKNOWN = "999"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
STATUS_MESSAGES: dict[StatusCode, str] = {
|
|
31
|
+
StatusCode.SUCCESS: "정상",
|
|
32
|
+
StatusCode.UNREGISTERED_KEY: "등록되지 않은 키",
|
|
33
|
+
StatusCode.INACTIVE_KEY: "사용할 수 없는 키",
|
|
34
|
+
StatusCode.INVALID_KEY: "잘못된 키",
|
|
35
|
+
StatusCode.USAGE_LIMIT_EXCEEDED: "일시적 사용 제한",
|
|
36
|
+
StatusCode.DAILY_LIMIT_EXCEEDED_FIELD: "필드 일일 조회 한도 초과",
|
|
37
|
+
StatusCode.DAILY_LIMIT_EXCEEDED_REQUESTS: "요청 일일 한도 초과",
|
|
38
|
+
StatusCode.MONTHLY_LIMIT_EXCEEDED: "월간 조회 한도 초과",
|
|
39
|
+
StatusCode.INVALID_PARAMETER: "잘못된 파라미터",
|
|
40
|
+
StatusCode.MISSING_REQUIRED_PARAMETER: "필수 파라미터 누락",
|
|
41
|
+
StatusCode.INVALID_REPORT_CODE: "잘못된 보고서 코드",
|
|
42
|
+
StatusCode.INVALID_DATE: "잘못된 날짜",
|
|
43
|
+
StatusCode.NO_DATA: "조회된 데이터 없음",
|
|
44
|
+
StatusCode.FILE_NOT_FOUND: "파일 없음",
|
|
45
|
+
StatusCode.SYSTEM_ERROR: "시스템 오류",
|
|
46
|
+
StatusCode.MAINTENANCE: "시스템 점검",
|
|
47
|
+
StatusCode.UNKNOWN: "알 수 없는 오류",
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class ReportCode(StrEnum):
|
|
52
|
+
"""보고서 코드."""
|
|
53
|
+
|
|
54
|
+
Q1 = "11013" # 1분기보고서
|
|
55
|
+
HALF = "11012" # 반기보고서
|
|
56
|
+
Q3 = "11014" # 3분기보고서
|
|
57
|
+
ANNUAL = "11011" # 사업보고서
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class CorpClass(StrEnum):
|
|
61
|
+
"""기업 분류 코드."""
|
|
62
|
+
|
|
63
|
+
KOSPI = "Y" # 유가증권시장
|
|
64
|
+
KOSDAQ = "K" # 코스닥시장
|
|
65
|
+
KONEX = "N" # 코넥스시장
|
|
66
|
+
ETC = "E" # 기타법인
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class DisclosureType(StrEnum):
|
|
70
|
+
"""공시 유형 코드."""
|
|
71
|
+
|
|
72
|
+
A = "A" # 정기공시
|
|
73
|
+
B = "B" # 주요사항보고
|
|
74
|
+
C = "C" # 발행공시
|
|
75
|
+
D = "D" # 지분공시
|
|
76
|
+
E = "E" # 기타공시
|
|
77
|
+
F = "F" # 외부감사관련
|
|
78
|
+
G = "G" # 펀드공시
|
|
79
|
+
H = "H" # 자산유동화
|
|
80
|
+
I = "I" # 거래소공시 # noqa: E741
|
|
81
|
+
J = "J" # 공정위공시
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class FinancialStatementType(StrEnum):
|
|
85
|
+
"""재무제표 구분 코드."""
|
|
86
|
+
|
|
87
|
+
CONSOLIDATED = "CFS" # 연결재무제표
|
|
88
|
+
SEPARATE = "OFS" # 개별재무제표
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"""OpenDART API 예외 클래스."""
|
|
2
|
+
|
|
3
|
+
from opendart_fss.constants import STATUS_MESSAGES, StatusCode
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class OpenDartError(Exception):
|
|
7
|
+
"""OpenDART API 기본 예외."""
|
|
8
|
+
|
|
9
|
+
def __init__(self, message: str, status: str | None = None):
|
|
10
|
+
self.status = status
|
|
11
|
+
self.message = message
|
|
12
|
+
super().__init__(message)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class APIError(OpenDartError):
|
|
16
|
+
"""API 응답 오류."""
|
|
17
|
+
|
|
18
|
+
def __init__(self, status: str, message: str | None = None):
|
|
19
|
+
try:
|
|
20
|
+
status_code = StatusCode(status)
|
|
21
|
+
default_message = STATUS_MESSAGES.get(status_code, "알 수 없는 오류")
|
|
22
|
+
except ValueError:
|
|
23
|
+
default_message = "알 수 없는 오류"
|
|
24
|
+
super().__init__(message or default_message, status)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class AuthenticationError(APIError):
|
|
28
|
+
"""인증 관련 오류 (010, 011, 012)."""
|
|
29
|
+
|
|
30
|
+
pass
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class RateLimitError(APIError):
|
|
34
|
+
"""요청 제한 오류 (013, 014, 015, 016)."""
|
|
35
|
+
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class ValidationError(APIError):
|
|
40
|
+
"""파라미터 검증 오류 (020, 021, 022, 023)."""
|
|
41
|
+
|
|
42
|
+
pass
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class NotFoundError(APIError):
|
|
46
|
+
"""데이터 없음 오류 (100, 101)."""
|
|
47
|
+
|
|
48
|
+
pass
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class ServerError(APIError):
|
|
52
|
+
"""서버 오류 (800, 900)."""
|
|
53
|
+
|
|
54
|
+
pass
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def raise_for_status(status: str, message: str | None = None) -> None:
|
|
58
|
+
"""상태 코드에 따른 예외 발생."""
|
|
59
|
+
if status == StatusCode.SUCCESS:
|
|
60
|
+
return
|
|
61
|
+
|
|
62
|
+
error_class: type[APIError]
|
|
63
|
+
if status in (
|
|
64
|
+
StatusCode.UNREGISTERED_KEY,
|
|
65
|
+
StatusCode.INACTIVE_KEY,
|
|
66
|
+
StatusCode.INVALID_KEY,
|
|
67
|
+
):
|
|
68
|
+
error_class = AuthenticationError
|
|
69
|
+
elif status in (
|
|
70
|
+
StatusCode.USAGE_LIMIT_EXCEEDED,
|
|
71
|
+
StatusCode.DAILY_LIMIT_EXCEEDED_FIELD,
|
|
72
|
+
StatusCode.DAILY_LIMIT_EXCEEDED_REQUESTS,
|
|
73
|
+
StatusCode.MONTHLY_LIMIT_EXCEEDED,
|
|
74
|
+
):
|
|
75
|
+
error_class = RateLimitError
|
|
76
|
+
elif status in (
|
|
77
|
+
StatusCode.INVALID_PARAMETER,
|
|
78
|
+
StatusCode.MISSING_REQUIRED_PARAMETER,
|
|
79
|
+
StatusCode.INVALID_REPORT_CODE,
|
|
80
|
+
StatusCode.INVALID_DATE,
|
|
81
|
+
):
|
|
82
|
+
error_class = ValidationError
|
|
83
|
+
elif status in (StatusCode.NO_DATA, StatusCode.FILE_NOT_FOUND):
|
|
84
|
+
error_class = NotFoundError
|
|
85
|
+
elif status in (StatusCode.SYSTEM_ERROR, StatusCode.MAINTENANCE):
|
|
86
|
+
error_class = ServerError
|
|
87
|
+
else:
|
|
88
|
+
error_class = APIError
|
|
89
|
+
|
|
90
|
+
raise error_class(status, message)
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"""OpenDART API 모델."""
|
|
2
|
+
|
|
3
|
+
from opendart_fss.models.base import BaseResponse
|
|
4
|
+
from opendart_fss.models.disclosure import (
|
|
5
|
+
Company,
|
|
6
|
+
CompanyResponse,
|
|
7
|
+
CorpCode,
|
|
8
|
+
Disclosure,
|
|
9
|
+
DisclosureListResponse,
|
|
10
|
+
)
|
|
11
|
+
from opendart_fss.models.financial import (
|
|
12
|
+
FinancialAccount,
|
|
13
|
+
FinancialAccountListResponse,
|
|
14
|
+
FinancialIndicator,
|
|
15
|
+
FinancialIndicatorListResponse,
|
|
16
|
+
XbrlTaxonomy,
|
|
17
|
+
XbrlTaxonomyListResponse,
|
|
18
|
+
)
|
|
19
|
+
from opendart_fss.models.major_event import (
|
|
20
|
+
BonusIssue,
|
|
21
|
+
BonusIssueListResponse,
|
|
22
|
+
CapitalChange,
|
|
23
|
+
CapitalChangeListResponse,
|
|
24
|
+
ConvertibleBond,
|
|
25
|
+
ConvertibleBondListResponse,
|
|
26
|
+
MergerDecision,
|
|
27
|
+
MergerDecisionListResponse,
|
|
28
|
+
SplitDecision,
|
|
29
|
+
SplitDecisionListResponse,
|
|
30
|
+
)
|
|
31
|
+
from opendart_fss.models.registration import (
|
|
32
|
+
DebtSecurities,
|
|
33
|
+
DebtSecuritiesListResponse,
|
|
34
|
+
EquitySecurities,
|
|
35
|
+
EquitySecuritiesListResponse,
|
|
36
|
+
MergerRegistration,
|
|
37
|
+
MergerRegistrationListResponse,
|
|
38
|
+
SplitRegistration,
|
|
39
|
+
SplitRegistrationListResponse,
|
|
40
|
+
)
|
|
41
|
+
from opendart_fss.models.report import (
|
|
42
|
+
DirectorCompensation,
|
|
43
|
+
DirectorCompensationListResponse,
|
|
44
|
+
DividendInfo,
|
|
45
|
+
DividendInfoListResponse,
|
|
46
|
+
Employee,
|
|
47
|
+
EmployeeListResponse,
|
|
48
|
+
Executive,
|
|
49
|
+
ExecutiveListResponse,
|
|
50
|
+
IndividualCompensation,
|
|
51
|
+
IndividualCompensationListResponse,
|
|
52
|
+
LargestShareholder,
|
|
53
|
+
LargestShareholderListResponse,
|
|
54
|
+
StockChange,
|
|
55
|
+
StockChangeListResponse,
|
|
56
|
+
TreasuryStock,
|
|
57
|
+
TreasuryStockListResponse,
|
|
58
|
+
)
|
|
59
|
+
from opendart_fss.models.shareholder import (
|
|
60
|
+
ExecutiveStock,
|
|
61
|
+
ExecutiveStockListResponse,
|
|
62
|
+
MajorStock,
|
|
63
|
+
MajorStockListResponse,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
__all__ = [
|
|
67
|
+
# Base
|
|
68
|
+
"BaseResponse",
|
|
69
|
+
# Disclosure (DS001)
|
|
70
|
+
"Disclosure",
|
|
71
|
+
"DisclosureListResponse",
|
|
72
|
+
"Company",
|
|
73
|
+
"CompanyResponse",
|
|
74
|
+
"CorpCode",
|
|
75
|
+
# Report (DS002)
|
|
76
|
+
"StockChange",
|
|
77
|
+
"StockChangeListResponse",
|
|
78
|
+
"DividendInfo",
|
|
79
|
+
"DividendInfoListResponse",
|
|
80
|
+
"TreasuryStock",
|
|
81
|
+
"TreasuryStockListResponse",
|
|
82
|
+
"LargestShareholder",
|
|
83
|
+
"LargestShareholderListResponse",
|
|
84
|
+
"Executive",
|
|
85
|
+
"ExecutiveListResponse",
|
|
86
|
+
"Employee",
|
|
87
|
+
"EmployeeListResponse",
|
|
88
|
+
"IndividualCompensation",
|
|
89
|
+
"IndividualCompensationListResponse",
|
|
90
|
+
"DirectorCompensation",
|
|
91
|
+
"DirectorCompensationListResponse",
|
|
92
|
+
# Financial (DS003)
|
|
93
|
+
"FinancialAccount",
|
|
94
|
+
"FinancialAccountListResponse",
|
|
95
|
+
"FinancialIndicator",
|
|
96
|
+
"FinancialIndicatorListResponse",
|
|
97
|
+
"XbrlTaxonomy",
|
|
98
|
+
"XbrlTaxonomyListResponse",
|
|
99
|
+
# Shareholder (DS004)
|
|
100
|
+
"MajorStock",
|
|
101
|
+
"MajorStockListResponse",
|
|
102
|
+
"ExecutiveStock",
|
|
103
|
+
"ExecutiveStockListResponse",
|
|
104
|
+
# Major Event (DS005)
|
|
105
|
+
"CapitalChange",
|
|
106
|
+
"CapitalChangeListResponse",
|
|
107
|
+
"BonusIssue",
|
|
108
|
+
"BonusIssueListResponse",
|
|
109
|
+
"ConvertibleBond",
|
|
110
|
+
"ConvertibleBondListResponse",
|
|
111
|
+
"MergerDecision",
|
|
112
|
+
"MergerDecisionListResponse",
|
|
113
|
+
"SplitDecision",
|
|
114
|
+
"SplitDecisionListResponse",
|
|
115
|
+
# Registration (DS006)
|
|
116
|
+
"EquitySecurities",
|
|
117
|
+
"EquitySecuritiesListResponse",
|
|
118
|
+
"DebtSecurities",
|
|
119
|
+
"DebtSecuritiesListResponse",
|
|
120
|
+
"MergerRegistration",
|
|
121
|
+
"MergerRegistrationListResponse",
|
|
122
|
+
"SplitRegistration",
|
|
123
|
+
"SplitRegistrationListResponse",
|
|
124
|
+
]
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"""DS001 공시정보 모델."""
|
|
2
|
+
|
|
3
|
+
import msgspec
|
|
4
|
+
|
|
5
|
+
from opendart_fss.models.base import BaseResponse
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Disclosure(msgspec.Struct, kw_only=True):
|
|
9
|
+
"""공시 검색 결과."""
|
|
10
|
+
|
|
11
|
+
corp_code: str # 고유번호
|
|
12
|
+
corp_name: str # 회사명
|
|
13
|
+
stock_code: str | None = None # 종목코드
|
|
14
|
+
corp_cls: str | None = None # 법인구분 (Y/K/N/E)
|
|
15
|
+
report_nm: str | None = None # 보고서명
|
|
16
|
+
rcept_no: str | None = None # 접수번호
|
|
17
|
+
flr_nm: str | None = None # 공시제출인명
|
|
18
|
+
rcept_dt: str | None = None # 접수일자 (YYYYMMDD)
|
|
19
|
+
rm: str | None = None # 비고
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class DisclosureListResponse(msgspec.Struct, kw_only=True):
|
|
23
|
+
"""공시 검색 응답."""
|
|
24
|
+
|
|
25
|
+
status: str
|
|
26
|
+
message: str
|
|
27
|
+
page_no: int | None = None
|
|
28
|
+
page_count: int | None = None
|
|
29
|
+
total_count: int | None = None
|
|
30
|
+
total_page: int | None = None
|
|
31
|
+
items: list[Disclosure] = msgspec.field(default_factory=list, name="list")
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class Company(msgspec.Struct, kw_only=True):
|
|
35
|
+
"""기업 개황 정보."""
|
|
36
|
+
|
|
37
|
+
corp_code: str # 고유번호
|
|
38
|
+
corp_name: str # 정식명칭
|
|
39
|
+
corp_name_eng: str | None = None # 영문명칭
|
|
40
|
+
stock_name: str | None = None # 종목명(상장사) 또는 약식명칭(기타법인)
|
|
41
|
+
stock_code: str | None = None # 상장회사인 경우 주식의 종목코드
|
|
42
|
+
ceo_nm: str | None = None # 대표자명
|
|
43
|
+
corp_cls: str | None = None # 법인구분 (Y/K/N/E)
|
|
44
|
+
jurir_no: str | None = None # 법인등록번호
|
|
45
|
+
bizr_no: str | None = None # 사업자등록번호
|
|
46
|
+
adres: str | None = None # 주소
|
|
47
|
+
hm_url: str | None = None # 홈페이지
|
|
48
|
+
ir_url: str | None = None # IR홈페이지
|
|
49
|
+
phn_no: str | None = None # 전화번호
|
|
50
|
+
fax_no: str | None = None # 팩스번호
|
|
51
|
+
induty_code: str | None = None # 업종코드
|
|
52
|
+
est_dt: str | None = None # 설립일 (YYYYMMDD)
|
|
53
|
+
acc_mt: str | None = None # 결산월 (MM)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class CompanyResponse(BaseResponse, kw_only=True):
|
|
57
|
+
"""기업 개황 응답."""
|
|
58
|
+
|
|
59
|
+
corp_code: str # 고유번호
|
|
60
|
+
corp_name: str # 정식명칭
|
|
61
|
+
corp_name_eng: str | None = None # 영문명칭
|
|
62
|
+
stock_name: str | None = None # 종목명(상장사) 또는 약식명칭(기타법인)
|
|
63
|
+
stock_code: str | None = None # 상장회사인 경우 주식의 종목코드
|
|
64
|
+
ceo_nm: str | None = None # 대표자명
|
|
65
|
+
corp_cls: str | None = None # 법인구분 (Y/K/N/E)
|
|
66
|
+
jurir_no: str | None = None # 법인등록번호
|
|
67
|
+
bizr_no: str | None = None # 사업자등록번호
|
|
68
|
+
adres: str | None = None # 주소
|
|
69
|
+
hm_url: str | None = None # 홈페이지
|
|
70
|
+
ir_url: str | None = None # IR홈페이지
|
|
71
|
+
phn_no: str | None = None # 전화번호
|
|
72
|
+
fax_no: str | None = None # 팩스번호
|
|
73
|
+
induty_code: str | None = None # 업종코드
|
|
74
|
+
est_dt: str | None = None # 설립일 (YYYYMMDD)
|
|
75
|
+
acc_mt: str | None = None # 결산월 (MM)
|
|
76
|
+
|
|
77
|
+
def to_company(self) -> Company:
|
|
78
|
+
"""Company 객체로 변환."""
|
|
79
|
+
return Company(
|
|
80
|
+
corp_code=self.corp_code,
|
|
81
|
+
corp_name=self.corp_name,
|
|
82
|
+
corp_name_eng=self.corp_name_eng,
|
|
83
|
+
stock_name=self.stock_name,
|
|
84
|
+
stock_code=self.stock_code,
|
|
85
|
+
ceo_nm=self.ceo_nm,
|
|
86
|
+
corp_cls=self.corp_cls,
|
|
87
|
+
jurir_no=self.jurir_no,
|
|
88
|
+
bizr_no=self.bizr_no,
|
|
89
|
+
adres=self.adres,
|
|
90
|
+
hm_url=self.hm_url,
|
|
91
|
+
ir_url=self.ir_url,
|
|
92
|
+
phn_no=self.phn_no,
|
|
93
|
+
fax_no=self.fax_no,
|
|
94
|
+
induty_code=self.induty_code,
|
|
95
|
+
est_dt=self.est_dt,
|
|
96
|
+
acc_mt=self.acc_mt,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class CorpCode(msgspec.Struct, kw_only=True):
|
|
101
|
+
"""고유번호 정보."""
|
|
102
|
+
|
|
103
|
+
corp_code: str # 고유번호
|
|
104
|
+
corp_name: str # 정식명칭
|
|
105
|
+
stock_code: str | None = None # 종목코드 (상장사만)
|
|
106
|
+
modify_date: str | None = None # 최종변경일 (YYYYMMDD)
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""DS003 정기보고서 재무정보 모델."""
|
|
2
|
+
|
|
3
|
+
import msgspec
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class FinancialAccount(msgspec.Struct, kw_only=True):
|
|
7
|
+
"""재무제표 주요계정."""
|
|
8
|
+
|
|
9
|
+
rcept_no: str # 접수번호
|
|
10
|
+
reprt_code: str | None = None # 보고서 코드
|
|
11
|
+
bsns_year: str | None = None # 사업연도
|
|
12
|
+
corp_code: str | None = None # 고유번호
|
|
13
|
+
stock_code: str | None = None # 종목코드
|
|
14
|
+
fs_div: str | None = None # 개별/연결구분 (CFS/OFS)
|
|
15
|
+
fs_nm: str | None = None # 개별/연결명
|
|
16
|
+
sj_div: str | None = None # 재무제표구분 (BS/IS/CIS/CF/SCE)
|
|
17
|
+
sj_nm: str | None = None # 재무제표명
|
|
18
|
+
account_id: str | None = None # 계정ID
|
|
19
|
+
account_nm: str | None = None # 계정명
|
|
20
|
+
account_detail: str | None = None # 계정상세
|
|
21
|
+
thstrm_nm: str | None = None # 당기명
|
|
22
|
+
thstrm_amount: str | None = None # 당기금액
|
|
23
|
+
thstrm_add_amount: str | None = None # 당기누적금액
|
|
24
|
+
frmtrm_nm: str | None = None # 전기명
|
|
25
|
+
frmtrm_amount: str | None = None # 전기금액
|
|
26
|
+
frmtrm_q_nm: str | None = None # 전기명(분/반기)
|
|
27
|
+
frmtrm_q_amount: str | None = None # 전기금액(분/반기)
|
|
28
|
+
frmtrm_add_amount: str | None = None # 전기누적금액
|
|
29
|
+
bfefrmtrm_nm: str | None = None # 전전기명
|
|
30
|
+
bfefrmtrm_amount: str | None = None # 전전기금액
|
|
31
|
+
ord: str | None = None # 계정과목 정렬순서
|
|
32
|
+
currency: str | None = None # 통화단위
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class FinancialAccountListResponse(msgspec.Struct, kw_only=True):
|
|
36
|
+
"""재무제표 주요계정 응답."""
|
|
37
|
+
|
|
38
|
+
status: str
|
|
39
|
+
message: str
|
|
40
|
+
items: list[FinancialAccount] = msgspec.field(default_factory=list, name="list")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class FinancialIndicator(msgspec.Struct, kw_only=True):
|
|
44
|
+
"""재무지표."""
|
|
45
|
+
|
|
46
|
+
rcept_no: str | None = None # 접수번호
|
|
47
|
+
bsns_year: str | None = None # 사업연도
|
|
48
|
+
corp_code: str | None = None # 고유번호
|
|
49
|
+
stock_code: str | None = None # 종목코드
|
|
50
|
+
reprt_code: str | None = None # 보고서 코드
|
|
51
|
+
stlm_dt: str | None = None # 결산기준일
|
|
52
|
+
idx_cl_code: str | None = None # 지표분류코드
|
|
53
|
+
idx_cl_nm: str | None = None # 지표분류명
|
|
54
|
+
idx_code: str | None = None # 지표코드
|
|
55
|
+
idx_nm: str | None = None # 지표명
|
|
56
|
+
idx_val: str | None = None # 지표값
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class FinancialIndicatorListResponse(msgspec.Struct, kw_only=True):
|
|
60
|
+
"""재무지표 응답."""
|
|
61
|
+
|
|
62
|
+
status: str
|
|
63
|
+
message: str
|
|
64
|
+
items: list[FinancialIndicator] = msgspec.field(default_factory=list, name="list")
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class XbrlTaxonomy(msgspec.Struct, kw_only=True):
|
|
68
|
+
"""XBRL 택사노미."""
|
|
69
|
+
|
|
70
|
+
sj_div: str # 재무제표구분
|
|
71
|
+
account_id: str | None = None # 계정ID
|
|
72
|
+
account_nm: str | None = None # 계정명
|
|
73
|
+
bsns_de: str | None = None # 개시일자
|
|
74
|
+
label_kor: str | None = None # 한글라벨
|
|
75
|
+
label_eng: str | None = None # 영문라벨
|
|
76
|
+
data_tp: str | None = None # 데이터타입
|
|
77
|
+
ifrs_ref: str | None = None # IFRS참조
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class XbrlTaxonomyListResponse(msgspec.Struct, kw_only=True):
|
|
81
|
+
"""XBRL 택사노미 응답."""
|
|
82
|
+
|
|
83
|
+
status: str
|
|
84
|
+
message: str
|
|
85
|
+
items: list[XbrlTaxonomy] = msgspec.field(default_factory=list, name="list")
|