Pine Script와 Webhook 기반 자동매매 시스템 연동: alertcondition() 및 JSON 페이로드(Payload) 활용법
안녕하세요, 트레이더 여러분!
매일 차트 앞을 지키며 손가락이 부르트도록 매수·매도 버튼을 누르느라 피곤하셨죠? " 내가 자는 동안에도 내 전략대로 알맞게 주문이 나갔으면 좋겠다"라는 생각, 차트를 보며 다들 한 번쯤은 해보셨을 텐데요.
오늘은 트레이딩뷰(TradingView)의 강력한 지표 언어인 Pine Script와 외부 서버를 연결해 주는 Webhook(웹훅), 그리고 데이터의 전달 매개체인 JSON 페이로드를 활용해 완전 자동매매 시스템의 초석을 다지는 방법을 아주 쉽게 풀어드리려고 합니다. 천천히 따라오시면 여러분의 훌륭한 전략이 24시간 일하는 나만의 분신으로 탈바꿈할 거예요!
1. Webhook 기반 자동매매의 동작 원리 이해하기
자동매매 시스템을 구축하기에 앞서, 데이터가 어떻게 흘러가는지 구조를 파악하는 것이 중요합니다.
[ 트레이딩뷰 (Pine Script) ]
│ ▼ (신호 발생 및 알림)
[ Webhook (JSON Payload 전달) ]
│ ▼ (HTTP POST 요청)
[ 중계 서버 (Python / Node.js 등) ]
│ ▼ (API 키 서명 및 서명 생성)
[ 거래소 API (Binance, Bitget, Upbit 등) ]
지표/전략 감지: 트레이딩뷰 차트에서 Pine Script로 작성한 기술적 지표나 전략 조건이 충족됩니다.
웹훅 알림(Alert) 발송: 조건이 만족되면 트레이딩뷰가 설정된 Webhook URL로 HTTP POST 요청을 보냅니다. 이때 매수/매도 정보가 담긴 JSON 페이로드가 함께 전송됩니다.
중계 서버 수신 및 시그널 처리: 서버(Python, Node.js 등)가 웹훅 데이터를 전달받아 요청을 검증하고, 거래소 규격에 맞는 API 서명(Signature)을 생성합니다.
거래소 API 주문 실행: 최종적으로 바이낸스, 비트겟, 업비트 등 거래소에 실제로 주문(Market/Limit Order)이 제출됩니다.
2. Pine Script에서 alertcondition() 작성법
Pine Script 버전 4와 버전 5에서는 알림을 발생시키기 위해 alertcondition() 함수를 사용합니다. 특정 조건이 참(True)이 되었을 때 알림 팝업을 띄우거나 웹훅을 호출할 수 있도록 설정하는 역할을 합니다.
기본 문법 구조
alertcondition(condition, title, message)
condition: 알림이 실행될 조건 (예: 이동평균선 골든크로스)
title: 트레이딩뷰 알림 설정 창에 표시될 이름
message: 웹훅 호출 시 기본으로 전달할 메시지 (JSON 형태로 작성)
실제 코드 예시 (EMA 크로스오버 전략)
Below is an example Pine Script v5 code using alertcondition() to generate long and short signals.
//@version=5
indicator("EMA Crossover Webhook Alert", overlay=true)
// 이동평균선 설정
fastLen = input.int(9, title="Fast EMA Length")
slowLen = input.int(21, title="Slow EMA Length")
fastEMA = ta.ema(close, fastLen)
slowEMA = ta.ema(close, slowLen)
// 차트 플롯
plot(fastEMA, color=color.blue, title="Fast EMA")
plot(slowEMA, color=color.orange, title="Slow EMA")
// 매수 / 매도 조건 정의
longCondition = ta.crossover(fastEMA, slowEMA)
shortCondition = ta.crossunder(fastEMA, slowEMA)
// alertcondition 함수 등록
alertcondition(longCondition, title="Long Signal (Buy)", message='{"action": "buy", "symbol": "{{ticker}}", "price": {{close}}, "volume": 0.01}')
alertcondition(shortCondition, title="Short Signal (Sell)", message='{"action": "sell", "symbol": "{{ticker}}", "price": {{close}}, "volume": 0.01}')
3. 웹훅 전달용 JSON 페이로드(Payload) 최적화
트레이딩뷰에서 중계 서버로 전송할 메시지는 표준 JSON(JavaScript Object Notation) Format을 준수해야 합니다. 구문 오류(Syntax Error)가 발생하면 중계 서버에서 데이터를 해석하지 못하므로 쌍따옴표(") 처리에 주의해야 합니다.
필수 및 주요 파라미터 구성
| 파라미터 키 | 설명 | 예시 값 |
action | 매수/매도 및 수량 조절 명령어 | "buy", "sell", "close" |
symbol | 거래 대상 종목 / 틱기호 | "BTCUSDT", "ETHUSDT" |
price | 신호 발생 시점의 가격 | {{close}} |
quantity / volume | 주문 수량 또는 시드 비중 | 0.01, "5%" |
passphrase | 인증용 보안 비밀번호 (선택) | "my_secret_token_123" |
동적 변수 동기화 (TradingView Dynamic Variables)
트레이딩뷰는 메시지 안에 중괄호 두 개({{ }})를 사용해 차트의 실시간 데이터를 동적으로 삽입할 수 있습니다.
{{ticker}}: 종목 코드 (예: BTCUSDT){{close}}: 신호 발생 봉의 종가{{timenow}}: 신호 발생 시각 (Unix Timestamp){{strategy.order.contracts}}: 전략 주문 수량
웹훅 전송용 JSON 예시
[ 매수 진입 메시지 ]
{
"passphrase": "secret_key_value",
"action": "buy",
"symbol": "{{ticker}}",
"price": {{close}}, "qty": 0.002,
"timestamp": "{{timenow}}"
}
4. 트레이딩뷰 알림(Alert) 및 Webhook URL 설정 단계
스크립트 작성을 마쳤다면 트레이딩뷰 UI에서 웹훅 연결을 활성화해야 합니다.
차트에 지표 추가: Pine Editor에서 코드를 저장하고
차트에 넣기(Add to Chart)를 클릭합니다.알림 생성 (Create Alert):
차트 상단의 시계 아이콘(Alert)을 누르거나
Alt + A단축키를 입력합니다.
조건(Condition) 선택:
드롭다운 메뉴에서 적용한 지표 이름(
EMA Crossover Webhook Alert)을 찾고,Long Signal (Buy)또는Short Signal (Sell)을 선택합니다.
메시지(Message) 확인:
alertcondition()에서 미리 작성한 JSON 문자열이 자동으로 입력되어 있는지 확인합니다.
알림 탭(Notifications) 설정:
Webhook URL 체크박스를 활성화합니다.
중계 서버의 엔드포인트주소(예:
[https://your-server-domain.com/webhook](https://your-server-domain.com/webhook))를 입력합니다.
만들기(Create) 클릭: 설정이 마무리되면 해당 조건이 충족될 때마다 지정한 서버 URL로 POST 요청이 전달됩니다.
5. 중계 서버 수신 예시 (Python Flask 기준)
웹훅 데이터를 받아 거래소 API로 전달하는 간단한 파이썬 서버 코드 구조는 다음과 같습니다.
from flask import Flask, request, jsonify
app = Flask(__name__)
# 보안용 토큰 설정
SECRET_PASSPHRASE = "secret_key_value"
@app.route('/webhook', methods=['POST'])
def webhook():
data = request.get_json()
# Passphrase 검증
if data.get('passphrase') != SECRET_PASSPHRASE:
return jsonify({"status": "error", "message": "Unauthorized"}), 401
action = data.get('action')
symbol = data.get('symbol')
price = data.get('price')
qty = data.get('qty')
print(f"[시그널 수신] {action.upper()} | 종목: {symbol} | 가격: {price} | 수량: {qty}")
# TODO: 이곳에 바이낸스, 비트겟 등 거래소 API 주문 함수(CCXT 등)를 연동합니다.
# execute_order(action, symbol, qty)
return jsonify({"status": "success", "message": "Order executed"}), 200
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
6. 자주 발생하는 오류 및 주의사항
JSON 구문 오류: JSON 문법 내에 쉼표(,) 오타나 큰따옴표 누락이 없는지 반드시 파이썬
json.loads()등으로 검증하세요.봉 완성 전 신호 튀김(Repainting): 알림 발생 빈도를
봉 마감 시 1회(Once Per Bar Close)로 설정해야 봉이 바뀌는 과정에서 임시로 발생했다 사라지는 가짜 신호에 실거래가 나가는 것을 막을 수 있습니다.서버 보안: Webhook URL이 외부에 노출될 경우 악의적인 주문 요청이 들어올 수 있습니다. 반드시 JSON 내부에 인증용
passphrase필드를 두고 서버에서 이를 검증하도록 설계하세요.
어떠셨나요? 처음에는 Pine Script 코드와 JSON이라는 용어 때문에 어렵게 느껴질 수 있지만, 개념을 차근차근 따라가다 보면 생각보다 직관적이라는 걸 알게 되실 거예요!
트레이딩뷰의 시그널 감지 능력과 거래소 API의 빠른 주문 속도가 합쳐지면 뇌동매매를 줄이고 훨씬 정교한 나만의 매매 시스템을 완성할 수 있답니다.
오늘 정리해 드린 내용을 바탕으로 소액부터 차근차근 테스트해 보시길 권장해요. 개발하시다가 막히는 부분이나 궁금한 점이 있다면 언제든 댓글로 편하게 남겨주세요! 여러 트레이더분들의 성투를 늘 응원합니다. 대박 나세요!
댓글
댓글 쓰기