Pine Script v5 내장 테이블(Table)로 실시간 트레이딩 스코어보드 만들기

 트레이딩뷰(TradingView)에서 자동매매 전략이나 지표를 개발할 때, 실시간 손익(PnL), 승률(Win-Rate), 현재 RSI 지표와 같은 핵심 데이터가 차트에 한눈에 들어오지 않아 답답했던 적이 있으신가요?

Pine Script v5의 내장 객체인 table 기능을 활용하면, 차트 구석에 나만의 대시보드(스코어보드)를 배치하여 주요 성능 지표와 기술적 지표 수치를 실시간으로 모니터링할 수 있습니다.

이번 글에서는 Pine Script v5 테이블 객체의 기본 개념부터 실전 스코어보드 전체 코드 작성법까지 구체적으로 알아보겠습니다.

1. Pine Script v5 테이블(Table) 핵심 개념

Pine Script의 테이블(Table)은 차트 UI의 특정 위치에 고정된 격자 형태의 UI 레이아웃을 생성하는 기능입니다. 봉(Bar)이 업데이트될 때마다 이동하는 일반 라인이나 형태와 달리, 화면에 고정되어 데이터를 직관적으로 출력하는 데 최적화되어 있습니다.

테이블 구현의 3단계 흐름

  1. table.new(): 테이블의 위치, 행(Rows), 열(Columns), 배경색 및 테두리를 정의하여 생성합니다.

  2. table.cell(): 지정한 행과 열의 셀에 텍스트, 글자 색상, 배경색, 텍스트 크기 등을 배치하거나 업데이트합니다.

  3. var 키워드 활용: 매 봉(Bar)마다 테이블을 재생성하지 않도록 var 키워드를 사용해 최초 1회만 초기화한 뒤 셀 수치만 갱신합니다.


2. 대시보드 제작 실전 코드

아래 코드는 차트 우상단(position.top_right)에 실시간 누적 손익, 총 진입 횟수, 승률(Win-Rate), 그리고 현재 RSI 수치를 출력하는 스코어보드 예제입니다.

//@version=5

indicator("실시간 트레이딩 스코어보드", overlay=true)


// ==========================================

// 1. 사용자 설정 입력 (Input)

// ==========================================

rsiLength  = input.int(14, title="RSI 기간")

tablePos   = input.string("우측 상단", title="스코어보드 위치", 

             options=["우측 상단", "우측 하단", "좌측 상단", "좌측 하단"])


// 위치 매핑 함수

getPosition(string posStr) =>

    switch posStr

        "우측 상단" => position.top_right

        "우측 하단" => position.bottom_right

        "좌측 상단" => position.top_left

        "좌측 하단" => position.bottom_left

        => position.top_right


// ==========================================

// 2. 주요 지표 및 수치 계산

// ==========================================

rsiValue = ta.rsi(close, rsiLength)


// 모의 전략 성능 지표 계산 (예시)

// 실제 strategy Script 적용 시 strategy.netprofit, strategy.winrate 등으로 대체 가능

var float totalPnL = 0.0

var int totalTrades = 0

var int winTrades   = 0


// 모의 매매 조건 (RSI 과매도/과매수 이탈 기준)

longCondition  = ta.crossover(rsiValue, 30)

shortCondition = ta.crossunder(rsiValue, 70)


if longCondition or shortCondition

    totalTrades += 1

    // 임의의 손익 산출 예시

    pnl = (close - open) * (longCondition ? 1 : -1)

    totalPnL += pnl

    if pnl > 0

        winTrades += 1


winRate = totalTrades > 0 ? (winTrades / totalTrades) * 100 : 0.0


// ==========================================

// 3. 테이블 객체 생성 및 셀 업데이트

// ==========================================

// var 키워드를 통해 최초 1회만 생성하여 메모리 및 연산 최적화

var table scoreBoard = table.new(

     position = getPosition(tablePos), 

     columns  = 2, 

     rows     = 4, 

     bgcolor  = color.new(color.black, 20), 

     border_width = 1, 

     border_color = color.gray

 )


// 마지막 봉에서만 테이블 셀 업데이트 수행

if barstate.islast

    // 헤더 및 셀 레이아웃 구성

    // 행 0: 제목

    table.cell(scoreBoard, 0, 0, "지표 (Metric)", bgcolor=color.navy, text_color=color.white, text_size=size.small)

    table.cell(scoreBoard, 1, 0, "수치 (Value)", bgcolor=color.navy, text_color=color.white, text_size=size.small)


    // 행 1: 누적 PnL

    pnlColor = totalPnL >= 0 ? color.green : color.red

    table.cell(scoreBoard, 0, 1, "누적 PnL", text_color=color.white, text_size=size.small)

    table.cell(scoreBoard, 1, 1, str.tostring(totalPnL, "#.##"), text_color=pnlColor, text_size=size.small)


    // 행 2: 승률 (Win-Rate)

    table.cell(scoreBoard, 0, 2, "승률 (Win-Rate)", text_color=color.white, text_size=size.small)

    table.cell(scoreBoard, 1, 2, str.tostring(winRate, "#.#") + "%", text_color=color.yellow, text_size=size.small)


    // 행 3: 현재 RSI 수치

    rsiBgColor = rsiValue >= 70 ? color.new(color.red, 30) : (rsiValue <= 30 ? color.new(color.green, 30) : color.black)

    table.cell(scoreBoard, 0, 3, "현재 RSI(" + str.tostring(rsiLength) + ")", text_color=color.white, text_size=size.small)

    table.cell(scoreBoard, 1, 3, str.tostring(rsiValue, "#.##"), text_color=color.white, bgcolor=rsiBgColor, text_size=size.small)


3. 코드 핵심 포인트 해설

① var 키워드를 이용한 자원 최적화

Pine Script는 차트의 첫 번째 봉부터 마지막 봉까지 순차적으로 코드를 실행합니다. 만약 table.new()를 var 없이 사용하면 매 봉마다 새로운 테이블을 만들어 차트가 느려집니다. var table scoreBoard = table.new(...) 구문을 사용하면 테이블이 최초 1회만 초기화되므로 렌더링 성능이 향상됩니다.

② barstate.islast 조건절 활용

테이블 수치는 매 봉마다 고쳐 쓸 필요 없이, 실시간으로 갱신되는 마지막 봉(barstate.islast)에서만 업데이트하면 됩니다. 이를 통해 리소스 낭비를 방지할 수 있습니다.

③ 조건부 서명 및 동적 색상 변경 (Dynamic Coloring)

손익이 양수이면 초록색, 음수이면 빨간색으로 표기되도록 pnlColor 변수를 설정했습니다. 또한 RSI 수치가 과매수(70 이상) 영역에 도달하면 빨간색 배경, 과매도(30 이하) 영역은 초록색 배경으로 자동 변경되도록 구현하여 직관성을 높였습니다.


4. 백테스팅 전략(strategy)과의 결합 방법

지표(indicator) 대신 백테스팅 전략(strategy) 스크립트에 대시보드를 이식할 경우, 내장 변수를 활용하여 정확한 트레이딩 수치를 테이블에 바인딩할 수 있습니다.

변수 / 수식설명
strategy.netprofit총 누적 순이익
strategy.closedtrades청산된 총 트레이딩 횟수
strategy.wintrades / strategy.closedtrades * 100실시간 승률(%) 계산식
strategy.openprofit현재 진행 중인 포지션의 미실현 손익
strategy.max_drawdown최대 낙폭 (MDD)


5. 자주 묻는 질문 (FAQ)

Q1. 차트 모바일 앱에서도 테이블이 잘 보이나요?

모바일 환경에서는 화면이 좁기 때문에 text_size=size.tiny 또는 size.small 옵션을 지정하고, 행과 열의 개수를 최적화하는 것이 좋습니다.

Q2. 테이블 위치를 자유롭게 바꿀 수 있나요?

position.top_right, position.bottom_left, position.middle_center 등 총 9가지 고정 위치 옵션을 지정할 수 있으며, input.string을 통해 사용자가 설정 창에서 변경하도록 만드는 것이 편리합니다.

Q3. 셀 내부 텍스트 정렬은 어떻게 하나요?

table.cell() 함수 내에서 text_halign (가로 정렬: text.align_left, text.align_center, text.align_right) 및 text_valign (세로 정렬) 매개변수를 활용하면 깔끔하게 정렬할 수 있습니다.


요약

Pine Script v5의 table 기능은 복잡한 전략 수치와 주요 기술적 지표를 차트 위에 시각화하는 강력한 도구입니다. 위의 실전 코드를 바탕으로 본인만의 승률, MDD, 이동평균선 상태 수치 등을 추가하여 차트 환경을 커스터마이징해 보세요.



댓글

이 블로그의 인기 게시물

엔트로픽 상장일 전망과 관련주 총정리: 클로드(Claude) 개발사의 IPO 주식 투자 가이드

RSI와 MACD를 결합한 나만의 커스텀 다중 하단 지표 제작 완벽 가이드

[파이썬 자동매매] CCXT 웹소켓(WebSocket)으로 해외 거래소 호가창 실시간 수집 및 DataFrame 재구성