[팁] 트레이딩 뷰를 활용해서 캔들 차트 백테스트 : 최고의 캔들은 인버티드 해머!

대표이미지

트레이딩뷰는 수많은 트레이더들이 사랑하는 차트 분석 플랫폼입니다. 트레이딩 뷰를 아직 모르시는 분은 아래의 링크를 참고해주세요.

최고의 투자 백테스트 툴 트레이딩뷰(Trading view)
트레이딩뷰 100% 활용하고 있으신가요? 요즘 유튜브에서 주식 방송을 하는 분들이 사용하는 차트를 보면, 10명 중 9명은 트레이딩뷰를 이용하는 것 같습니다. 저도 매일 한 번씩은 접속할 정도로 트레이딩뷰를 애용하는데요, 많은 분들이 트레이딩뷰를 단순히 차트를 보는 용도로만 사용하는 것이 아까워 이 글을 쓰게 되었습니다. 트레이딩뷰에 대한 오해? 트레이딩뷰는 일반적으로 웹 기반 차트

차트를 통해 손쉽게 나만의 전략을 만들고 백테스트를 통해 전략의 성과를 즉시 확인할 수 있다는 점이 큰 장점입니다. 하지만, 트레이딩뷰를 사용하다 보면 한 가지 아쉬운 점이 생기기 마련입니다. 바로 전략의 성과를 한번에 하나만 확인할수 있다는 점입니다.

예를들면 '적삼병','흑삼병'에서 진입하고 그 다음 봉에서 매도하는 전략을 테스트 한다면 트레이딩뷰에서는 우선 '적삼병'과 '흑삼병' 전략을 작성하고 적어도 두번 테스트를 거쳐야 합니다. 

다행이도 이 경우에는 비교 대상이 2가지 밖에 없으니까 그렇게 까지 큰 문제는 아닙니다만 만약 여러종류의 캔들 패턴을 전부 비교하고 싶다면 그 비교 대상만큼 전략 코드를 만들어야 하고 여러가지 티커의 차트에 넣었다 빼었다 하면서 수익률을 스프레드 시트등에 기입하고 다시 평균을 구하는 작업이 필요해집니다.

이런 번거로운 작업없이 여러가지 전략의 예후를 한눈에 비교할 수 있다면 어떨까요? 이번 글에서는 트레이딩뷰의 파인스크립트를 활용하여 캔들 패턴별 다음날의 상승률을 효율적으로 분석하는 방법을 소개하고 결국 어떤 캔들이 최고의 성과를 냈는지 검증해 보겠습니다.

파인스크립트 코드

//@version=5
indicator("캔들 예후 조사", overlay=true)

// 캔들 패턴 정의 (중복되지 않도록 엄격한 기준 적용)
hammerBullish = close > open and (open - low) > 2 * (high - close) and (high - low) > 3 * math.abs(close - open)
hammerBearish = close < open and (open - low) > 2 * (high - close) and (high - low) > 3 * math.abs(close - open)
invertedHammer = close > open and (high - close) > 2 * (close - low) and (high - low) > 3 * math.abs(close - open)
shootingStar = close < open and (high - open) > 2 * (close - low) and (high - low) > 3 * math.abs(close - open)
doji = math.abs(close - open) / (high - low) < 0.05 and (high - low) > 3 * math.abs(close - open)
engulfingBullish = close > open and close[1] < open[1] and open <= close[1] and close >= open[1] and (close - open) > (open[1] - close[1])
engulfingBearish = close < open and close[1] > open[1] and open >= close[1] and close <= open[1] and (open - close) > (close[1] - open[1])
threeWhiteSoldiers = close > open and close[1] > open[1] and close[2] > open[2] and close > close[1] and close[1] > close[2] and (close - open) > (close[1] - open[1]) and (close[1] - open[1]) > (close[2] - open[2])
threeBlackCrows = close < open and close[1] < open[1] and close[2] < open[2] and close < close[1] and close[1] < close[2] and (open - close) > (open[1] - close[1]) and (open[1] - close[1]) > (open[2] - close[2])

// 다음날 및 5일 후 수익률 계산
nextDayReturn = na(close[1]) ? na : ((close - close[1]) / close[1]) * 100


// 패턴별 수익률 저장 배열
var float[] patternReturns = array.new_float(9, 0)
var float[] patternReturns5 = array.new_float(9, 0)
var int[] patternCounts = array.new_int(9, 0)

// 특정 캔들 패턴 리스트 생성
patternNames = array.new_string(9)
patternConditions = array.new_bool(9)

array.set(patternNames, 0, "Hammer Bullish")
array.set(patternNames, 1, "Hammer Bearish")
array.set(patternNames, 2, "Inverted Hammer")
array.set(patternNames, 3, "Shooting Star")
array.set(patternNames, 4, "Doji")
array.set(patternNames, 5, "Engulfing Bullish")
array.set(patternNames, 6, "Engulfing Bearish")
array.set(patternNames, 7, "Three White Soldiers")
array.set(patternNames, 8, "Three Black Crows")

// 패턴 조건 배열 설정
array.set(patternConditions, 0, hammerBullish[1])
array.set(patternConditions, 1, hammerBearish[1])
array.set(patternConditions, 2, invertedHammer[1])
array.set(patternConditions, 3, shootingStar[1])
array.set(patternConditions, 4, doji[1])
array.set(patternConditions, 5, engulfingBullish[1])
array.set(patternConditions, 6, engulfingBearish[1])
array.set(patternConditions, 7, threeWhiteSoldiers[1])
array.set(patternConditions, 8, threeBlackCrows[1])

// 각 패턴별 수익률 누적 저장
for i = 0 to 8
    if array.get(patternConditions, i)
        array.set(patternReturns, i, array.get(patternReturns, i) + nextDayReturn)
        array.set(patternCounts, i, array.get(patternCounts, i) + 1)

// 테이블 생성 (행과 열을 바꿈)
var table logTable = table.new(position.top_right, 3, 10)

// 테이블 헤더 추가 (한 번만 실행되도록 보장)
if bar_index == 1
    table.cell(logTable, 0, 0, "Pattern", text_color=color.gray, bgcolor=color.white)
    for i = 0 to 8
        table.cell(logTable, 0, i + 1, array.get(patternNames, i), text_color=color.white, bgcolor=color.gray)
    

// 헤더 아래에 데이터 추가 (평균값 표시)
if bar_index > 1
    table.cell(logTable, 1, 0, "Next Day Avg", text_color=color.gray)
    table.cell(logTable, 2, 0, "count", text_color=color.gray)
    for i = 0 to 8
        avgReturn = array.get(patternCounts, i) > 0 ? array.get(patternReturns, i) / array.get(patternCounts, i) : na
        textColor = avgReturn > 0 ? color.green : color.red
        resultText = not na(avgReturn) ? str.tostring(avgReturn, '#.##') + "%" : "-"
        table.cell(logTable, 1, i + 1, resultText, text_color=textColor)
        table.cell(logTable, 2, i + 1, str.tostring(array.get(patternCounts, i)), text_color=textColor)

// 캔들 위에 라벨 추가 (중복 방지 적용)
atrValue = ta.atr(14)
yOffset = high

patternText = ""
for i = 0 to 8
    if array.get(patternConditions, i)
        patternText := array.get(patternNames, i)

if patternText == "Inverted Hammer"
    label.new(x=bar_index, y=yOffset, text=patternText, textcolor=color.black, color=color.yellow, size=size.normal, style=label.style_label_down)

위의 파인스크립트 코드는 다음과 같은 방식으로 동작합니다:

  1. 다양한 캔들 패턴을 정의하고, 각 캔들이 나타나는 조건을 설정합니다.
  2. 각 캔들 패턴이 나타난 날의 다음 거래일의 수익률을 계산하여 각 패턴별로 수익률을 누적하여 저장합니다.
  3. 특정 캔들 패턴이 발생했을 때 화면 상단에 테이블 형태로 패턴별 평균 상승률과 발생 횟수를 표시하여 사용자가 쉽게 분석할 수 있도록 돕습니다.
  4. 특히 '인버티드 해머'와 같은 특정 패턴이 나타나면 차트 위에 노란색 라벨을 추가하여 시각적으로 강조합니다.

이렇게 함으로써 캔들 패턴별 전략의 성과를 빠르고 정확하게 확인할 수 있게 됩니다.

위의 코드를 트레이딩뷰에 넣고 실행하면 아래와 같이 각 차트에 어떤 패턴의 캔들이 어느정도의 성과가 있었는지 표시됩니다.

실제 실행화면

코인베이스 차트에서의 실행화면

코인 베이스 일봉에서 인버티드 햄머가 발생했을 경우 다음날 시가에 사서 종가에 팔면 평균적으로 매일 1.36%의 수익이 발생

백테스트 결과: 최고의 캔들 패턴은?

여러 가지 캔들 패턴을 동일한 조건으로 백테스트한 결과, 다른 캔들에 비하여 '인버티드 해머'가 승률과 평균 수익률 모두 높게 나타났습니다. 하지만 이 결과는 절대적인 것은 아닙니다. 결국 투자하고자 하는 주식의 특성에 따라 달라질 수 있으며, 실제로 중요한 것은 이런 결과보다는 직접 전략을 만들고 실행해보는 과정입니다.

본 홈페이지에서는 코딩에 거부감이 있지만 자신만의 전략을 검증해보고 싶은 분들을 위한 컨설팅을 진행하고 있습니다. 도움이 필요하신 분은 오른쪽 아래 채팅 봇으로 문의해 주세요.

아직 트레이딩뷰를 이용해 본 경험이 없으시다면, 아래 버튼을 통해 홈페이지를 방문하실 수 있습니다.