-
Notifications
You must be signed in to change notification settings - Fork 44
/
Copy pathpython_quant.py
107 lines (88 loc) · 4.52 KB
/
python_quant.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# -*- coding: utf-8 -*-
import pandas as pd
import numpy as np
# 재무 관련 데이터 전처리하는 함수
def get_finance_data(path):
data_path = path
raw_data = pd.read_excel(data_path)
big_col = list(raw_data.columns)
small_col = list(raw_data.iloc[0])
new_big_col = []
for num, col in enumerate(big_col):
if 'Unnamed' in col:
new_big_col.append(new_big_col[num-1])
else:
new_big_col.append(big_col[num])
raw_data.columns = [new_big_col, small_col]
clean_df = raw_data.loc[ raw_data.index.dropna() ]
return clean_df
# N/A(IFRS)'를 NaN으로 바꾸기
def check_IFRS(x):
if x == 'N/A(IFRS)':
return np.NaN
else:
return x
# PER기준으로 오름차순으로 정렬하여 주는 함수
def low_per(invest_df, index_date, num):
invest_df[(index_date, 'PER')] = pd.to_numeric(invest_df[(index_date, 'PER')])
per_sorted = invest_df.sort_values(by=(index_date, 'PER'))
return per_sorted[index_date][:num]
# ROA기준으로 내림차순으로 정렬하여 주는 함수
def high_roa(fr_df, index_date, num):
fr_df[(index_date, 'ROA')] = fr_df[(index_date, 'ROA')].apply(check_IFRS)
fr_df[(index_date, 'ROA')] = pd.to_numeric(fr_df[(index_date, 'ROA')] )
sorted_roa = fr_df.sort_values(by=(index_date, 'ROA'), ascending=False)
return sorted_roa[index_date][:num]
# 마법공식
def magic_formula(fr_df, invest_df, index_date, num):
per = low_per(invest_df, index_date, None)
roa = high_roa(fr_df, index_date, None)
per['per순위'] = per['PER'].rank()
roa['roa순위'] = roa['ROA'].rank(ascending=False)
magic = pd.merge(per, roa, how='outer', left_index=True, right_index=True)
magic['마법공식 순위'] = (magic['per순위'] + magic['roa순위']).rank().sort_values()
magic = magic.sort_values(by='마법공식 순위')
return magic[:num]
# 저평가 지수를 기준으로 정렬하여 순위 만들어 주는 함수
def get_value_rank(invest_df, value_type, index_date, num):
invest_df[(index_date, value_type)] = pd.to_numeric(invest_df[(index_date, value_type)])
value_sorted = invest_df.sort_values(by=(index_date, value_type))[index_date]
value_sorted[ value_type + '순위'] = value_sorted[value_type].rank()
return value_sorted[[value_type, value_type + '순위']][:num]
# 저평가 지표 조합 함수
def make_value_combo(value_list, invest_df, index_date, num):
for i, value in enumerate(value_list):
temp_df = get_value_rank(invest_df, value, index_date, None)
if i == 0:
value_combo_df = temp_df
rank_combo = temp_df[value + '순위']
else:
value_combo_df = pd.merge(value_combo_df, temp_df, how='outer', left_index=True, right_index=True)
rank_combo = rank_combo + temp_df[value + '순위']
value_combo_df['종합순위'] = rank_combo.rank()
value_combo_df = value_combo_df.sort_values(by='종합순위')
return value_combo_df[:num]
# F-score
def get_fscore(fs_df, index_date, num):
fscore_df = fs_df[index_date]
fscore_df['당기순이익점수'] = fscore_df['당기순이익'] > 0
fscore_df['영업활동점수'] = fscore_df['영업활동으로인한현금흐름'] > 0
fscore_df['더큰영업활동점수'] = fscore_df['영업활동으로인한현금흐름'] > fscore_df['당기순이익']
fscore_df['종합점수'] = fscore_df[['당기순이익점수', '영업활동점수', '더큰영업활동점수']].sum(axis=1)
fscore_df = fscore_df[fscore_df['종합점수'] == 3]
return fscore_df[:num]
# 모멘텀 함수
def get_momentum_rank(price_df, index_date, date_range, num):
momentum_df = pd.DataFrame(price_df.pct_change(date_range).loc[index_date])
momentum_df.columns = ['모멘텀']
momentum_df['모멘텀순위'] = momentum_df['모멘텀'].rank(ascending=False)
momentum_df = momentum_df.sort_values(by='모멘텀순위')
return momentum_df[:num]
# 저평가 + F-score
def get_value_quality(invest_df, fs_df, index_date, num):
value = make_value_combo(['PER', 'PBR', 'PSR', 'PCR'], invest_df, index_date, None)
quality = get_fscore(fs_df, index_date, None)
value_quality = pd.merge(value, quality, how='outer', left_index=True, right_index=True)
value_quality_filtered = value_quality[value_quality['종합점수'] == 3]
vq_df = value_quality_filtered.sort_values(by='종합순위')
return vq_df[:num]