MultiFactor 0.3.2__tar.gz → 0.3.4__tar.gz
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.
- {multifactor-0.3.2 → multifactor-0.3.4}/PKG-INFO +1 -1
- {multifactor-0.3.2 → multifactor-0.3.4}/pyproject.toml +1 -1
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor/__init__.py +2 -1
- multifactor-0.3.4/src/MultiFactor/daum_consensus.py +131 -0
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor/quality.py +13 -3
- multifactor-0.3.4/src/MultiFactor/quality_one.py +31 -0
- multifactor-0.3.4/src/MultiFactor/value.py +46 -0
- multifactor-0.3.4/src/MultiFactor/value_one.py +34 -0
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor/vfinance_kr.py +11 -3
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor.egg-info/PKG-INFO +1 -1
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor.egg-info/SOURCES.txt +1 -0
- multifactor-0.3.2/src/MultiFactor/quality_one.py +0 -21
- multifactor-0.3.2/src/MultiFactor/value.py +0 -34
- multifactor-0.3.2/src/MultiFactor/value_one.py +0 -22
- {multifactor-0.3.2 → multifactor-0.3.4}/README.md +0 -0
- {multifactor-0.3.2 → multifactor-0.3.4}/setup.cfg +0 -0
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor/Visual.py +0 -0
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor/core.py +0 -0
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor/momentum.py +0 -0
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor/momentum_one.py +0 -0
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor/score.py +0 -0
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor/score_adj_weight.py +0 -0
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor/stockinfo.py +0 -0
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor/us_core.py +0 -0
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor/us_momentum.py +0 -0
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor/us_quality.py +0 -0
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor/us_stockinfo.py +0 -0
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor/us_value.py +0 -0
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor/vcompare_idx.py +0 -0
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor/vheatmap_idx.py +0 -0
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor/vheatmap_kr.py +0 -0
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor/vheatmap_us.py +0 -0
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor/vmulti_idx.py +0 -0
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor/vmulti_kr.py +0 -0
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor/vmulti_us.py +0 -0
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor/vret_idx.py +0 -0
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor/vret_kr.py +0 -0
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor/vret_us.py +0 -0
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor/vtargetprice_us.py +0 -0
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor/vtreemap_us.py +0 -0
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor.egg-info/dependency_links.txt +0 -0
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor.egg-info/requires.txt +0 -0
- {multifactor-0.3.2 → multifactor-0.3.4}/src/MultiFactor.egg-info/top_level.txt +0 -0
|
@@ -14,6 +14,7 @@ os.environ['PYTHONWARNINGS'] = 'ignore'
|
|
|
14
14
|
from .core import MultiFactorKR
|
|
15
15
|
from .us_core import MultiFactorUS
|
|
16
16
|
from .Visual import Visual
|
|
17
|
+
from .daum_consensus import get_daum_finstate, get_daum_consensus
|
|
17
18
|
|
|
18
19
|
# 패키지를 import할 때 노출할 항목을 명시합니다.
|
|
19
|
-
__all__ = ['MultiFactorKR', 'MultiFactorUS', 'Visual']
|
|
20
|
+
__all__ = ['MultiFactorKR', 'MultiFactorUS', 'Visual', 'get_daum_finstate', 'get_daum_consensus']
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"""다음증권 추정실적 컨센서스를 연간/분기 DataFrame으로 가져옵니다."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import re
|
|
5
|
+
import time
|
|
6
|
+
import ssl
|
|
7
|
+
from urllib.parse import urlencode
|
|
8
|
+
from urllib.request import Request, urlopen
|
|
9
|
+
from urllib.error import URLError
|
|
10
|
+
|
|
11
|
+
import pandas as pd
|
|
12
|
+
import numpy as np
|
|
13
|
+
|
|
14
|
+
CONSENSUS_URL = "https://wisefn.finance.daum.net/v1/company/cF1002.aspx"
|
|
15
|
+
CONSENSUS_COLUMNS = [
|
|
16
|
+
"FY-end",
|
|
17
|
+
"주재무제표",
|
|
18
|
+
"매출액 (억원)",
|
|
19
|
+
"YoY (%)",
|
|
20
|
+
"영업이익 (억원)",
|
|
21
|
+
"당기순이익 (억원)",
|
|
22
|
+
"EPS (원)",
|
|
23
|
+
"PER (배)",
|
|
24
|
+
"PBR (배)",
|
|
25
|
+
"ROE (%)",
|
|
26
|
+
"EV/EBITDA (배)",
|
|
27
|
+
"순부채 비율 (%)",
|
|
28
|
+
]
|
|
29
|
+
DATA_BLOCK_PATTERN = re.compile(
|
|
30
|
+
r'\{\s*tid\s*:\s*"(?P<tab>TB_[01])"\s*,\s*'
|
|
31
|
+
r"dest\s*:\s*(?P<rows>\[\[.*?\]\])\s*\}",
|
|
32
|
+
re.DOTALL,
|
|
33
|
+
)
|
|
34
|
+
STOCK_CODE_PATTERN = re.compile(r"(?:A)?\d{6}")
|
|
35
|
+
|
|
36
|
+
COLUMN_MAP = {
|
|
37
|
+
"매출액 (억원)": "매출액",
|
|
38
|
+
"영업이익 (억원)": "영업이익",
|
|
39
|
+
"당기순이익 (억원)": "당기순이익",
|
|
40
|
+
"PER (배)": "PER(배)",
|
|
41
|
+
"PBR (배)": "PBR(배)",
|
|
42
|
+
"ROE (%)": "ROE(%)",
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def get_daum_consensus(
|
|
47
|
+
stock_code: str = "A005930",
|
|
48
|
+
timeout: float = 15,
|
|
49
|
+
) -> tuple[pd.DataFrame, pd.DataFrame]:
|
|
50
|
+
"""다음증권에서 종목의 연간·분기 컨센서스를 가져옵니다."""
|
|
51
|
+
clean_code = str(stock_code).strip()
|
|
52
|
+
if not STOCK_CODE_PATTERN.fullmatch(clean_code):
|
|
53
|
+
clean_code = clean_code.zfill(6)
|
|
54
|
+
if not STOCK_CODE_PATTERN.fullmatch(clean_code):
|
|
55
|
+
raise ValueError(f"올바르지 않은 종목코드 형식입니다: {stock_code}")
|
|
56
|
+
|
|
57
|
+
company_code = clean_code.removeprefix("A")
|
|
58
|
+
query = urlencode({"cmp_cd": company_code, "finGubun": "MAIN"})
|
|
59
|
+
request = Request(
|
|
60
|
+
f"{CONSENSUS_URL}?{query}",
|
|
61
|
+
headers={
|
|
62
|
+
"User-Agent": (
|
|
63
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
|
|
64
|
+
"AppleWebKit/537.36 (KHTML, like Gecko) "
|
|
65
|
+
"Chrome/130.0.0.0 Safari/537.36"
|
|
66
|
+
),
|
|
67
|
+
"Referer": f"https://finance.daum.net/quotes/A{company_code}",
|
|
68
|
+
"Accept": "text/html,application/xhtml+xml",
|
|
69
|
+
},
|
|
70
|
+
)
|
|
71
|
+
html = None
|
|
72
|
+
max_retries = 3
|
|
73
|
+
last_err = None
|
|
74
|
+
|
|
75
|
+
for attempt in range(max_retries):
|
|
76
|
+
try:
|
|
77
|
+
with urlopen(request, timeout=timeout) as response:
|
|
78
|
+
html = response.read().decode(
|
|
79
|
+
response.headers.get_content_charset() or "utf-8"
|
|
80
|
+
)
|
|
81
|
+
break
|
|
82
|
+
except (URLError, ssl.SSLError, ConnectionError, OSError) as e:
|
|
83
|
+
last_err = e
|
|
84
|
+
if attempt < max_retries - 1:
|
|
85
|
+
time.sleep(1.0)
|
|
86
|
+
else:
|
|
87
|
+
raise last_err
|
|
88
|
+
|
|
89
|
+
rows_by_tab = {
|
|
90
|
+
match.group("tab"): json.loads(match.group("rows"))
|
|
91
|
+
for match in DATA_BLOCK_PATTERN.finditer(html)
|
|
92
|
+
}
|
|
93
|
+
if "TB_0" not in rows_by_tab or "TB_1" not in rows_by_tab:
|
|
94
|
+
raise ValueError(
|
|
95
|
+
"응답에서 연간/분기 컨센서스를 찾지 못했습니다. "
|
|
96
|
+
"다음증권 페이지의 데이터 형식이 변경되었을 수 있습니다."
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
def to_dataframe(rows: list[list[str]]) -> pd.DataFrame:
|
|
100
|
+
if any(len(row) != len(CONSENSUS_COLUMNS) for row in rows):
|
|
101
|
+
raise ValueError("컨센서스 데이터의 열 구성이 예상과 다릅니다.")
|
|
102
|
+
frame = pd.DataFrame(rows, columns=CONSENSUS_COLUMNS)
|
|
103
|
+
for column in CONSENSUS_COLUMNS[2:]:
|
|
104
|
+
values = frame[column].str.replace(",", "", regex=False)
|
|
105
|
+
frame[column] = pd.to_numeric(values, errors="coerce")
|
|
106
|
+
return frame
|
|
107
|
+
|
|
108
|
+
annual = to_dataframe(rows_by_tab["TB_0"])
|
|
109
|
+
quarterly = to_dataframe(rows_by_tab["TB_1"])
|
|
110
|
+
return annual, quarterly
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def get_daum_finstate(stock_code: str, freq: str = "Y", timeout: float = 15) -> pd.DataFrame:
|
|
114
|
+
"""
|
|
115
|
+
다음증권 컨센서스를 수집하여 기존 SnapDataReader와 호환되는 컬럼 및 인덱스 구조로 반환합니다.
|
|
116
|
+
- freq: 'Y' (연간) 또는 'Q' (분기)
|
|
117
|
+
"""
|
|
118
|
+
annual_df, quarterly_df = get_daum_consensus(stock_code=stock_code, timeout=timeout)
|
|
119
|
+
is_annual = freq.upper().endswith("Y") or freq.upper() == "Y"
|
|
120
|
+
df = annual_df.copy() if is_annual else quarterly_df.copy()
|
|
121
|
+
|
|
122
|
+
if "FY-end" in df.columns:
|
|
123
|
+
df.set_index("FY-end", inplace=True)
|
|
124
|
+
df.index.name = "날짜"
|
|
125
|
+
|
|
126
|
+
# 기존 SnapDataReader 컬럼명('매출액', '영업이익', 'PER(배)' 등) 매핑 추가
|
|
127
|
+
for orig_col, target_col in COLUMN_MAP.items():
|
|
128
|
+
if orig_col in df.columns:
|
|
129
|
+
df[target_col] = df[orig_col]
|
|
130
|
+
|
|
131
|
+
return df
|
|
@@ -5,6 +5,11 @@ import numpy as np
|
|
|
5
5
|
|
|
6
6
|
import time
|
|
7
7
|
|
|
8
|
+
try:
|
|
9
|
+
from .daum_consensus import get_daum_finstate
|
|
10
|
+
except ImportError:
|
|
11
|
+
from daum_consensus import get_daum_finstate
|
|
12
|
+
|
|
8
13
|
|
|
9
14
|
def get_quality(stock_list):
|
|
10
15
|
result_fin = []
|
|
@@ -18,10 +23,15 @@ def get_quality(stock_list):
|
|
|
18
23
|
print(f"{i}/{len(stock_list)} 진행 중... ({sname})")
|
|
19
24
|
|
|
20
25
|
try:
|
|
21
|
-
# 재무 데이터 추출 :
|
|
22
|
-
|
|
26
|
+
# 재무 데이터 추출 : 1. SnapDataReader 먼저 시도 -> 에러 시 다음증권 컨센서스로 대체
|
|
27
|
+
try:
|
|
28
|
+
data = fdr.SnapDataReader(f'NAVER/FINSTATE-2Q/{scode}').dropna(subset='영업이익') # 분기
|
|
29
|
+
except Exception:
|
|
30
|
+
data = get_daum_finstate(scode, freq='Q').dropna(subset='영업이익')
|
|
31
|
+
|
|
23
32
|
fin = (data[['매출액','영업이익','당기순이익']].pct_change()*100).iloc[-1].to_list()
|
|
24
|
-
|
|
33
|
+
roe_series = data['ROE(%)'].dropna()
|
|
34
|
+
roe = roe_series.iloc[-1] if not roe_series.empty else np.nan
|
|
25
35
|
result_fin.append([scode] + fin + [roe])
|
|
26
36
|
|
|
27
37
|
except:
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import FinanceDataReader as fdr
|
|
2
|
+
|
|
3
|
+
import pandas as pd
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
try:
|
|
7
|
+
from .daum_consensus import get_daum_finstate
|
|
8
|
+
except ImportError:
|
|
9
|
+
from daum_consensus import get_daum_finstate
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def get_quality_one(scode):
|
|
13
|
+
result_fin = []
|
|
14
|
+
try:
|
|
15
|
+
# 1. SnapDataReader 먼저 시도 -> 에러 시 다음증권 컨센서스로 대체
|
|
16
|
+
try:
|
|
17
|
+
data = fdr.SnapDataReader(f'NAVER/FINSTATE-2Q/{scode}').dropna(subset='영업이익') # 분기
|
|
18
|
+
except Exception:
|
|
19
|
+
data = get_daum_finstate(scode, freq='Q').dropna(subset='영업이익')
|
|
20
|
+
|
|
21
|
+
fin = (data[['매출액','영업이익','당기순이익']].pct_change()*100).iloc[-1].to_list()
|
|
22
|
+
roe_series = data['ROE(%)'].dropna()
|
|
23
|
+
roe = roe_series.iloc[-1] if not roe_series.empty else np.nan
|
|
24
|
+
result_fin.append([scode] + fin + [roe])
|
|
25
|
+
data_fin = pd.DataFrame(result_fin, columns=['scode', 'revenue_rate', 'oper_income_rate', 'net_income_rate', 'ROE'])
|
|
26
|
+
return data_fin
|
|
27
|
+
|
|
28
|
+
except Exception as e:
|
|
29
|
+
print(f"에러가 발생했습니다. 상세 내용: {e}")
|
|
30
|
+
print("추출오류 : ", scode) # 에러 종목코드 출력
|
|
31
|
+
return None
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import FinanceDataReader as fdr
|
|
2
|
+
|
|
3
|
+
import pandas as pd
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
import time
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
from .daum_consensus import get_daum_finstate
|
|
10
|
+
except ImportError:
|
|
11
|
+
from daum_consensus import get_daum_finstate
|
|
12
|
+
|
|
13
|
+
def get_value(stock_list):
|
|
14
|
+
|
|
15
|
+
result = []
|
|
16
|
+
|
|
17
|
+
for i, (scode, sname) in enumerate(stock_list.items()):
|
|
18
|
+
|
|
19
|
+
# [중요] 데이터 수집 시 서버 차단 방지 (1초 대기)
|
|
20
|
+
time.sleep(1)
|
|
21
|
+
|
|
22
|
+
# 진행 상황 모니터링 (50번째 순서마다 종목명 출력)
|
|
23
|
+
if i % 50 == 0:
|
|
24
|
+
print(f"{i}/{len(stock_list)} 진행 중... ({sname})")
|
|
25
|
+
|
|
26
|
+
try:
|
|
27
|
+
# 재무제표 데이터 추출 : 1. SnapDataReader 먼저 시도 -> 에러 시 다음증권 컨센서스로 대체
|
|
28
|
+
try:
|
|
29
|
+
data = fdr.SnapDataReader(f'NAVER/FINSTATE-2Y/{scode}').dropna(subset='영업이익') # 연간
|
|
30
|
+
except Exception:
|
|
31
|
+
data = get_daum_finstate(scode, freq='Y').dropna(subset='영업이익')
|
|
32
|
+
|
|
33
|
+
per_series = data['PER(배)'].dropna()
|
|
34
|
+
pbr_series = data['PBR(배)'].dropna()
|
|
35
|
+
per = per_series.iloc[-1] if not per_series.empty else np.nan
|
|
36
|
+
pbr = pbr_series.iloc[-1] if not pbr_series.empty else np.nan
|
|
37
|
+
result.append([scode, per, pbr])
|
|
38
|
+
|
|
39
|
+
except Exception as e:
|
|
40
|
+
print("추출오류 : ", sname, f"({type(e).__name__}: {e})") # 에러 종목코드 및 원인 출력
|
|
41
|
+
result.append([scode, None, None])
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
data_val = pd.DataFrame(result, columns=['scode', 'PER', 'PBR'])
|
|
45
|
+
|
|
46
|
+
return data_val
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import FinanceDataReader as fdr
|
|
2
|
+
|
|
3
|
+
import pandas as pd
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
try:
|
|
7
|
+
from .daum_consensus import get_daum_finstate
|
|
8
|
+
except ImportError:
|
|
9
|
+
from daum_consensus import get_daum_finstate
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def get_value_one(scode):
|
|
13
|
+
|
|
14
|
+
result = []
|
|
15
|
+
|
|
16
|
+
try:
|
|
17
|
+
# 1. SnapDataReader 먼저 시도 -> 에러 시 다음증권 컨센서스로 대체
|
|
18
|
+
try:
|
|
19
|
+
data = fdr.SnapDataReader(f'NAVER/FINSTATE-2Y/{scode}').dropna(subset='영업이익') # 연간
|
|
20
|
+
except Exception:
|
|
21
|
+
data = get_daum_finstate(scode, freq='Y').dropna(subset='영업이익')
|
|
22
|
+
|
|
23
|
+
per_series = data['PER(배)'].dropna()
|
|
24
|
+
pbr_series = data['PBR(배)'].dropna()
|
|
25
|
+
per = per_series.iloc[-1] if not per_series.empty else np.nan
|
|
26
|
+
pbr = pbr_series.iloc[-1] if not pbr_series.empty else np.nan
|
|
27
|
+
result.append([scode, per, pbr])
|
|
28
|
+
data_val = pd.DataFrame(result, columns=['scode', 'PER', 'PBR'])
|
|
29
|
+
return data_val
|
|
30
|
+
|
|
31
|
+
except Exception as e:
|
|
32
|
+
print(f"에러가 발생했습니다. 상세 내용: {e}")
|
|
33
|
+
print("추출오류 : ", scode) # 에러 종목코드 출력
|
|
34
|
+
return None
|
|
@@ -10,6 +10,10 @@ import concurrent.futures
|
|
|
10
10
|
# 데이터 수집 라이브러리
|
|
11
11
|
import FinanceDataReader as fdr
|
|
12
12
|
import yfinance as yf
|
|
13
|
+
try:
|
|
14
|
+
from .daum_consensus import get_daum_finstate
|
|
15
|
+
except ImportError:
|
|
16
|
+
from daum_consensus import get_daum_finstate
|
|
13
17
|
|
|
14
18
|
# 시각화 라이브러리
|
|
15
19
|
import matplotlib.pyplot as plt
|
|
@@ -57,13 +61,17 @@ def finance_kr():
|
|
|
57
61
|
|
|
58
62
|
# --- [2] 밸류 & 퀄리티 지표: 재무 데이터 막대그래프 ---
|
|
59
63
|
try:
|
|
60
|
-
# 연간(Y) 또는 분기(Q) 재무제표 동적 수집
|
|
61
|
-
|
|
64
|
+
# 연간(Y) 또는 분기(Q) 재무제표 동적 수집 (SnapDataReader 먼저 시도 -> 에러 시 다음증권 대체)
|
|
65
|
+
try:
|
|
66
|
+
fs = fdr.SnapDataReader(f'NAVER/FINSTATE-{YQ}/{stock_code}')
|
|
67
|
+
except Exception:
|
|
68
|
+
fs = get_daum_finstate(stock_code, freq=YQ)
|
|
69
|
+
|
|
62
70
|
period_text = "연간" if YQ == 'Y' else "분기"
|
|
63
71
|
|
|
64
72
|
cols = ['PER(배)', 'PBR(배)', 'ROE(%)', '매출액', '영업이익', '당기순이익']
|
|
65
73
|
res = fs[cols].T.dropna(axis=1, how='all')
|
|
66
|
-
res.columns = [x.strftime('%y-%m') for x in res.columns]
|
|
74
|
+
res.columns = [x.strftime('%y-%m') if hasattr(x, 'strftime') else str(x) for x in res.columns]
|
|
67
75
|
|
|
68
76
|
fig_vq, axes = plt.subplots(2, 3, figsize=(14, 8), tight_layout=True)
|
|
69
77
|
fig_vq.suptitle(f"[{stock_name}] 밸류 & 퀄리티 지표 ({period_text} 재무제표)", fontsize=15, fontweight='bold', y=1.02)
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import FinanceDataReader as fdr
|
|
2
|
-
|
|
3
|
-
import pandas as pd
|
|
4
|
-
import numpy as np
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def get_quality_one(scode):
|
|
8
|
-
result_fin = []
|
|
9
|
-
try:
|
|
10
|
-
# 재무 데이터 추출 : 분기 K-IFRS 연결 기준
|
|
11
|
-
data = fdr.SnapDataReader(f'NAVER/FINSTATE-2Q/{scode}').dropna(subset='영업이익') # 분기
|
|
12
|
-
fin = (data[['매출액','영업이익','당기순이익']].pct_change()*100).iloc[-1].to_list()
|
|
13
|
-
roe = data['ROE(%)'].iloc[-1]
|
|
14
|
-
result_fin.append([scode] + fin + [roe])
|
|
15
|
-
data_fin = pd.DataFrame(result_fin, columns=['scode', 'revenue_rate', 'oper_income_rate', 'net_income_rate', 'ROE'])
|
|
16
|
-
return data_fin
|
|
17
|
-
|
|
18
|
-
except Exception as e:
|
|
19
|
-
print(f"에러가 발생했습니다. 상세 내용: {e}")
|
|
20
|
-
print("추출오류 : ", sname) # 에러 종목코드 출력
|
|
21
|
-
return None
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import FinanceDataReader as fdr
|
|
2
|
-
|
|
3
|
-
import pandas as pd
|
|
4
|
-
import numpy as np
|
|
5
|
-
|
|
6
|
-
import time
|
|
7
|
-
|
|
8
|
-
def get_value(stock_list):
|
|
9
|
-
|
|
10
|
-
result = []
|
|
11
|
-
|
|
12
|
-
for i, (scode, sname) in enumerate(stock_list.items()):
|
|
13
|
-
|
|
14
|
-
# [중요] 데이터 수집 시 서버 차단 방지 (1초 대기)
|
|
15
|
-
time.sleep(1)
|
|
16
|
-
|
|
17
|
-
# 진행 상황 모니터링 (50번째 순서마다 종목명 출력)
|
|
18
|
-
if i % 50 == 0:
|
|
19
|
-
print(f"{i}/{len(stock_list)} 진행 중... ({sname})")
|
|
20
|
-
|
|
21
|
-
try:
|
|
22
|
-
# 재무제표 데이터 추출 (연간 K-IFRS 연결 기준)
|
|
23
|
-
data = fdr.SnapDataReader(f'NAVER/FINSTATE-2Y/{scode}').dropna(subset='영업이익') # 연간
|
|
24
|
-
per, pbr = data['PER(배)'].iloc[-1], data['PBR(배)'].iloc[-1]
|
|
25
|
-
result.append([scode, per, pbr])
|
|
26
|
-
|
|
27
|
-
except:
|
|
28
|
-
print("추출오류 : ", sname) # 에러 종목코드 출력
|
|
29
|
-
result.append([scode, None, None])
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
data_val = pd.DataFrame(result, columns=['scode', 'PER', 'PBR'])
|
|
33
|
-
|
|
34
|
-
return data_val
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import FinanceDataReader as fdr
|
|
2
|
-
|
|
3
|
-
import pandas as pd
|
|
4
|
-
import numpy as np
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def get_value_one(scode):
|
|
8
|
-
|
|
9
|
-
result = []
|
|
10
|
-
|
|
11
|
-
try:
|
|
12
|
-
# 재무제표 데이터 추출 (연간 K-IFRS 연결 기준)
|
|
13
|
-
data = fdr.SnapDataReader(f'NAVER/FINSTATE-2Y/{scode}').dropna(subset='영업이익') # 연간
|
|
14
|
-
per, pbr = data['PER(배)'].iloc[-1], data['PBR(배)'].iloc[-1]
|
|
15
|
-
result.append([scode, per, pbr])
|
|
16
|
-
data_val = pd.DataFrame(result, columns=['scode', 'PER', 'PBR'])
|
|
17
|
-
return data_val
|
|
18
|
-
|
|
19
|
-
except Exception as e:
|
|
20
|
-
print(f"에러가 발생했습니다. 상세 내용: {e}")
|
|
21
|
-
print("추출오류 : ", sname) # 에러 종목코드 출력
|
|
22
|
-
return None
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|