본문 바로가기
시스템트레이딩

TA-Lib을 이용한 캔들스틱의 패턴인식

by 오늘밤날다 2021. 7. 17.

매번 이리저리 변수들을 바꿔서 백테스트를 하다 대충 우상향 하는 곡선을 뽑아내고

나온 결과물들을 곰곰히 살펴보면 결국엔 기존 전략들과 별반 차이가 없는 구조를 발견하게 되는 일이 많았다.

결국 어떤 스토리, 철학을 가지고 진입을 하느냐가 중요한 것 같은데

그런 측면에서 그동안 미루어왔던 캔들 유형에 따른 투자방법을 한번 생각해보기로 했다.

 

캔들 유형이 매우 다양해서 그 유형들의 특성들을 다 공부하고

이를 수식화하는 것은 단기간에 어려울 것같고

그냥 데이터베이스에 담긴 OHLC 자료를 TA-Lib을 이용해서 어떤 캔들 유형인지 판단,

해당 유형의 캔들이 출현하였을 때 단기적으로 투자한다고 가정할 경우

유형별 수익성, 복리투자를 가정한 자본, MDD 등을 산출해볼 것이다.

 

그런데 생각할수록 '패턴인식'이라니... 너무 거창한 느낌이다.

TA-Lib의 functions에서 'pattern recognition'으로 분류되어 있긴 한데...

아무래도 결과는 초라하게 나와서 실망할 것 같은 불안감이 엄습해온다.

 

아무튼 1차적으로 구성한 전체 코드는 아래와 같다.

  • candlestick pattern recognition에 사용할 일봉 데이터 준비 및 읽어오기
  • TA-Lib에서의 전체 'Pattern Recognition'을 변수에 저장 (총 60개)
  • 일자별로 전체 Patern recognition 중 어떤 유형에 해당되는지 판단하여 해당 유형명에 해당하는 칼럼에 기록한다. 이 경우 통상 -100 (Negative), 0(N/A), 100 (Positive)으로 표시되나, 간혹 -200, 200과 같이 표시되는 값들이 있는데 일단 무시하기로 했다
  • 특정 유형이 출현하였을 때 100 이상이면 Long 포지션, -100이면 Short 포지션, 당일 종가 진입 - 익일 종가 청산으로 단순화하여 유형별 투자성과를 집계
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
109
110
111
112
113
import pandas as pd
import sqlite3
import numpy as np
import talib
import warnings
 
warnings.filterwarnings("ignore")
pd.set_option('display.max_columns'10000)
pd.set_option('display.max_rows'10000)
pd.set_option('display.max_colwidth'0)
pd.options.display.expand_frame_repr = False
 
 
class Talib_main():
    def __init__(self):
        # TA-Lib에서 인식가능한 전체 pattern list를 가져온다.
        self.candle_names = talib.get_function_groups()['Pattern Recognition']
 
    # OHLC Database에서 특정 table을 DF으로 반환
    def load_db1_table(self, table_name):
        con = sqlite3.connect('C:/backtest_db.db')
        df = pd.read_sql("SELECT * FROM '" + table_name + "'", con, index_col='index')
        return df
 
    # name에 해당하는 캔들유형에 해당하는지 여부를 판단
    def get_candle_pattern(self, df, name):
        df[name] = getattr(talib, name)(df['open'], df['high'], df['low'], df['close'])
        return df
 
    # 전체 캔들유형을 검사하여 DF로 반환 
    def get_all_candlestick(self, df):
        df['total_score'= 0
        df[f'plr'= df['close'].shift(-1/ df['close'- 1  # 익일 종가 / 당일 종가
 
        for i in self.candle_names:
            df = self.get_candle_pattern(df, i)
            df['total_score'= df['total_score'+ df[i]
 
        total_candle_count = len(df)
        print(f'전체캔들수:{total_candle_count}')
        return df
 
    # 캔들유형별 당일 종가 진입 후 익일 종가 청산 시 Long/short포지션의 성과 산출
    def candlestick_plr(self, df, name, thres):
        con1 = df[name] > thres
        fdb1 = df[con1]
        ttc1 = len(fdb1)
 
        con2 = df[name] < thres
        fdb2 = df[con2]
        ttc2 = len(fdb2)
 
        result = {'name': name}
 
        # condition1 - Long포지션
        result['l_count'= ttc1
        plr = fdb1['plr'].sum()
        equity = (fdb1['plr'+ 1).cumprod()
        equity = equity.fillna(method='pad')
        dd = equity / equity.cummax() - 1
        win = np.sum(fdb1['plr'> 0)
        win_ratio = win / ttc1
        result['l_plr'= round(plr, 4)
        if ttc1 == 0:
            result['l_eq'= 0
            result['l_mdd'= 0
        else:
            result['l_eq'= round(equity.iat[-1], 4)
            result['l_mdd'= round(dd.min(), 4)
        result['l_wr'= round(win_ratio, 4)
 
        # condition2 - short포지션
        result['s_count'= ttc2
        plr2 = - fdb2['plr'].sum()
        equity2 = (- fdb2['plr'+ 1).cumprod()
        equity2 = equity2.fillna(method='pad')
        dd2 = equity2 / equity2.cummax() - 1
        win2 = np.sum(- fdb2['plr'> 0)
        win_ratio2 = win2 / ttc2
        result['s_plr'= round(plr2, 4)
        if ttc2 == 0:
            result['s_eq'= 0
            result['s_mdd'= 0
        else:
            result['s_eq'= round(equity2.iat[-1], 4)
            result['s_mdd'= round(dd2.min(), 4)
        result['s_wr'= round(win_ratio2, 4)
        return result
 
    # 전체 캔들에 대한 성과 산출
    def all_candlestick_plr(self, df):
        thres = 0
        all_result = {}
        for candle_name in self.candle_names:
            ret = self.candlestick_plr(df, candle_name, thres)
            all_result[len(all_result)] = ret
 
        return all_result
 
 
if __name__ == "__main__":
    main = Talib_main()
    table_name = 'OOOOOOOOO'
    df = main.load_db1_table(table_name)
    df2 = main.get_all_candlestick(df)
    df2.to_csv(f'all_cs_{table_name}.csv')
 
    # all_candlestick_plr 실행 후 결과값 dictionary -> dataframe화
    results = main.all_candlestick_plr(df2)
    df_ret = pd.DataFrame(results).transpose()
    df_ret = df_ret.fillna(0)
    print(df_ret)
 
cs

 

일단 실행결과는 여기까지 나오는 걸 확인했다.

이제 하나하나 뜯어서 검증해봐야겠다.

1
2
3
4
5
6
7
8
9
10
11
12
13
                   name  l_count   l_plr    l_eq   l_mdd    l_wr  s_count   s_plr    s_eq   s_mdd    s_wr
0   CDL2CROWS            0        0.0000  0.0000  0.0000  0.0000  3        0.0046  1.0043 -0.0138  0.3333
1   CDL3BLACKCROWS       0        0.0000  0.0000  0.0000  0.0000  0       -0.0000  0.0000  0.0000  0.0000
2   CDL3INSIDE           61      -0.0146  0.9815 -0.0909  0.5082  38       0.1627  1.1673 -0.0436  0.4474
3   CDL3LINESTRIKE       1        0.0023  1.0023  0.0000  1.0000  1        0.0030  1.0030  0.0000  1.0000
4   CDL3OUTSIDE          71      -0.0743  0.9229 -0.1230  0.5352  75      -0.0200  0.9632 -0.1909  0.4533
5   CDL3STARSINSOUTH     0        0.0000  0.0000  0.0000  0.0000  0       -0.0000  0.0000  0.0000  0.0000
6   CDL3WHITESOLDIERS    1       -0.0133  0.9867  0.0000  0.0000  0       -0.0000  0.0000  0.0000  0.0000
7   CDLABANDONEDBABY     1        0.0085  1.0085  0.0000  1.0000  0       -0.0000  0.0000  0.0000  0.0000
8   CDLADVANCEBLOCK      0        0.0000  0.0000  0.0000  0.0000  29      -0.0179  0.9790 -0.0872  0.4138
9   CDLBELTHOLD          437      0.1528  1.1219 -0.2059  0.5469  413     -0.5380  0.5560 -0.5043  0.4383
10  CDLBREAKAWAY         0        0.0000  0.0000  0.0000  0.0000  0       -0.0000  0.0000  0.0000  0.0000
......
cs

 

'시스템트레이딩' 카테고리의 다른 글

무지성 종가베팅 - 개선판  (0) 2021.09.01
무지성 종가베팅  (0) 2021.08.31
변화하는 시장  (0) 2021.08.16
주문사고  (1) 2021.07.15
코스닥150ETF 전략재개  (0) 2021.07.12