퀀트투자 최적값 찾기 파이썬 코드
본문 바로가기
돈을 벌기 위한 자료/투자정보

퀀트투자 최적값 찾기 파이썬 코드

by 만초손겸수익 2023. 10. 18.

2003년 ~ 2021년까지 PBR x DPS 와 시가총액, 거래대금, 월별로 가장 투자에 적합한 조건을 찾는 코드다.

 

최적조건찾기(2003-2021)1월-12월 거래대금0-1억이상 시가총액5백억-3천억이하.xlsx
0.08MB

 

 

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
108
# 경우의 수를 이용해서 최적조건 찾기
# (저PBR, 저DPS) x 12(개월) x 2(월초, 월말) x 30(시가총액 0이상~3천억이상 조건) x 100(거래금액 0이상부터 ~ 10억이상)
# col은 투자월, 투자일, CAGR, MDD, 손실횟수, 누적이익률, 손실평균
 
import pandas as pd
import sqlite3
 
con = sqlite3.connect('krx_data_new.db')
 
# 주식거래일을 구하는 함수
def near_business_day(b_start, b_month, b_day):
    df_date = pd.read_sql("SELECT 일자 FROM fund WHERE 일자 LIKE " + "'" + b_start + "%'", con)
    df_date.drop_duplicates(inplace=True)
    li_df = df_date['일자'].tolist()
 
    date = b_start + b_month + b_day
    if date in li_df:
        b_date = date
    else:
        if int(b_day) < 15:  # 날짜가 15미만이면 1씩 더해서 영업일 구하기
            while 10:  # 10번 정도 더하기 반복해서 DB에 있는 날짜 구하기
                b_day = int(b_day) + 1
                b_day = str(b_day).zfill(2)
                b_date = date[:6+ b_day
                if b_date in li_df:
                    break
        else:  # 날짜가 15이상이면 1씩 빼면서 영업일 구하기
            while 10:
                b_day = int(b_day) - 1
                b_day = str(b_day).zfill(2)
                b_date = date[:6+ b_day
                if b_date in li_df:
                    break
    return b_date
 
li = [] #CAGR, MDD, 손실횟수, 누계이익률, 손실평균 등을 담을 list
= 0
= 1
for m in [45678910]:
    for trans in range(011000000010000000):
        for cap in range(5000000000035000000000050000000000): #거래대금
            li_result = []
            for y in range(20032022): #년
                m = str(m).zfill(2)
                d = str(d).zfill(2)
                invest_day = near_business_day(str(y), m, d)
 
                df = pd.read_sql("SELECT 일자, code, 종목명, 종가, 거래량, 거래대금, 상장주식수, 시가총액, "
                                 "PBR, DPS FROM Fund WHERE 일자= " + invest_day, con)
 
                # 거래량, PBR, DPS, 0이상인 종목만 가져오고, 거래대금은과 시가총액은 조건이상
                df = df[(df['거래량'> 0& (df['PBR'> 0& (df['DPS'> 0& (df['거래대금'>= trans) & (df['시가총액'<= cap)]
 
                df['PBR_rank'= df['PBR'].rank()
                df['DPS_rank'= df['DPS'].rank()
                df['PBR_DPS'= df['PBR_rank'+ df['DPS_rank']
                df['PBR_DPS_rank'= df['PBR_DPS'].rank()
                df.sort_values(by='PBR_DPS_rank', inplace=True)
 
                df = df.iloc[:20]
 
                #1년후의 날짜 구하기
                sell_day = near_business_day(str(y + 1), m, d)
 
                # 1년후의 날짜로 데이터 가져오기
                df_later = pd.read_sql("SELECT 일자, code, 종가, 상장주식수 FROM fund WHERE 일자= " + sell_day, con)
                df_later.columns = ['1년후의_일자''code''1년후_종가''1년후_상장주식수']
 
                df = pd.merge(df, df_later, on='code')
 
                df['수익률'= (df['1년후_종가'- df['종가']) / df['종가']
                profit = df['수익률'].sum()/20
                li_result.append([invest_day, profit])
 
                if i == 0:  # 첫번째 날짜는 만들어진 dataframe이 df_t로 저장되고, 나머지는 계속 concat로 붙여넣기
                    df_t = df
                else:
                    df_t = pd.concat([df_t, df])
                print(f'{m}월 {trans}거래대금 {cap}시가총액 {y}년도 작업중')
                i += 1
 
            df_result = pd.DataFrame(data=li_result, columns=['투자년도''수익률'])  # 투자년도와 수익률로 데이터프레임 만들기
            li_acc = []
            for n, p in enumerate(df_result['수익률']):
                if n == 0:
                    li_acc.append(1 + p)
                else:
                    li_acc.append(li_acc[n - 1* (1 + p))
            print(li_acc)
 
            df_result['누적수익률'= pd.DataFrame(data=li_acc, columns=['누적수익률'])
            cagr = (df_result['누적수익률'].iloc[-1]) ** (1 / len(df_result)) - 1
 
            MDD = df_result['수익률'].min()
            return_acc = df_result['누적수익률'].iloc[-1]
 
            df_lost = df_result[df_result['수익률'< 0]
            count_lost = df_lost['수익률'].count() #손실횟수
            mean_lost = df_lost['수익률'].mean() #손실평균
 
            li.append([m, d, cap, trans, cagr, MDD, return_acc, count_lost, mean_lost])
            print(li)
 
 
df_find = pd.DataFrame(data=li, columns=['투자월''투자일''시가총액조건(이하)''거래대금조건(이상)',
                                         'CAGR''MDD''누적수익률''손실횟수''손실평균'])
 
df_find.to_excel('최적조건찾기(2003-2021)4월-10월 거래대금0-1억이상 시가총액5백억-3천억이하 11-4월초.xlsx')
cs
728x90
반응형

댓글