Step 1 · BingX account and API key
1단계 · BingX 계정과 API키
레퍼럴 링크로 가입
tvhook 레퍼럴 링크를 누르면 BingX 가입 화면으로 바로 연결됩니다. 이메일이든 Google/Apple이든 상관없어요. 이 링크로 가입하는 것 자체가 웹훅 자동매매 무료 + 선물 수수료 10% 할인의 조건입니다 — 따로 신청할 게 없어요.
세 칸 중 진짜 필요한 건 하나
가입 직후 Sign Up(완료) · Identity Verification · Deposit 세 단계가 뜹니다. Deposit은 실제로 입금할 때 하면 되고, Identity Verification은 미루면 안 됩니다 — 이거 없이는 API 거래 자체가 안 열립니다.
신원인증(KYC)
신분증 사진 + 얼굴인식, BingX 자체 화면에서 진행됩니다 — tvhook은 이 과정에 관여하지 않고 서류도 보지 않습니다. BingX 안내는 2~10분이지만, 심사가 몰리는 시간대면 조금 더 걸릴 수 있습니다.
API Management 진입
왼쪽 메뉴 → API Management. 처음엔 목록이 비어있는 게 정상입니다. 여기서 누를 건 Create API 하나뿐.
키 생성 — Withdraw는 반드시 해제
이름은 아무거나 상관없습니다(사진은 tvhook으로 등록). Perpetual Futures Trading을 체크해야 주문이 나갑니다. Withdraw는 체크하지 마세요 — 출금 권한이 있는 키는 tvhook이 저장 자체를 거부하니 애초에 줄 이유가 없습니다. IP 화이트리스트는 선택사항, 이미 쓰고 있는 게 아니면 건너뛰어도 됩니다.
키 두 개 모두 복사 — 시크릿은 한 번만 보임
Access Key와 Secret Key가 이 화면에서 딱 한 번 노출됩니다. 지금 둘 다 복사해두세요 — 페이지를 벗어나면 시크릿 키는 다시 못 보고, 새로 발급해야 합니다.
Step 3 · TradingView: put a real strategy behind the alert
3단계 · 트레이딩뷰
아직 전략이 없으신가요? 이건 실제로 돌아가는 예시입니다 — EMA 크로스, 기본은 롱 온리지만 체크박스 하나로 데드크로스 때 그냥 청산 대신 숏으로 전환되게 할 수 있어요. 이평선 길이와 손절%는 인풋박스(기본 9/21·1%). 출구는 고정 목표가가 아니라 크로스언더입니다 — 추세추종은 원래 이익을 최대한 끌고 가는 게 목적이라, "익절" 인풋은 실제로 체결시키려는 값이 아니라 15%짜리 넓은 안전판이에요. Pine 에디터에 붙여넣고 차트에 추가한 다음, 아래 3단계대로 얼럿을 웹훅에 연결하세요.
심볼 입력칸이 따로 없는 건 의도한 거예요 — 얼럿이 차트에서 syminfo.ticker를 그대로 읽습니다. BTCUSDT 차트에 스크립트를 걸면 BTCUSDT를 매매하고, 같은 스크립트를 ETHUSDT 차트에 걸면 그걸 매매합니다. 스크립트 하나로 어느 차트에 올리느냐만 다르면 됩니다.
//@version=6
strategy("EMA cross + tvhook", overlay=true, pyramiding=0)
// ---- tvhook.app helpers (Pine v6). Paste once, above your logic. ----
// exchange is fixed to "bingx". syminfo.ticker gives BTCUSDT / BTCUSDT.P / BINANCE:BTCUSDT — all map to BTC-USDT.
tvhook_num(float x) =>
str.tostring(x, format.mintick)
tvhook_entry(string dir, float ep, float sl, float tp) =>
'{"source":"TV","action":"entry","symbol":"' + syminfo.ticker + '","direction":"' + dir + '","exchange":"bingx","ep":"' + tvhook_num(ep) + '","sl":"' + tvhook_num(sl) + '","tp":"' + tvhook_num(tp) + '","alert_id":"' + str.tostring(time) + '"}'
// exit: ep/sl/tp are required by the contract but ignored; the current price fills all three.
tvhook_exit(string dir) =>
'{"source":"TV","action":"exit","symbol":"' + syminfo.ticker + '","direction":"' + dir + '","exchange":"bingx","ep":"' + tvhook_num(close) + '","sl":"' + tvhook_num(close) + '","tp":"' + tvhook_num(close) + '","alert_id":"' + str.tostring(time) + '"}'
// Inputs — the chart's own symbol (syminfo.ticker, above) is what tvhook trades; there's
// nothing to type in for that. These five are what's actually worth tuning per market.
fastLen = input.int(9, "Fast EMA", minval=1)
slowLen = input.int(21, "Slow EMA", minval=1)
slPct = input.float(1.0, "Stop loss %", minval=0.01, step=0.1) / 100
// The real exit is the EMA crossunder below — this is not a profit target, it's a wide backstop.
// tvhook attaches tp as a real limit order on the exchange (the contract requires a tp field on
// every entry); a tight one would fill mid-trend, disagree with strategy.position_size here, and
// cap exactly the runs a trend-following cross is supposed to let ride. Keep it wide.
tpCapPct = input.float(15.0, "Take-profit safety cap % (not a target — see comment)", minval=1, step=0.5) / 100
// Off (default): crossunder just flattens, same as before. On: crossunder flips into a short
// (and a crossover while short closes the short before opening the long) — always in the market.
enableShort = input.bool(false, "Also trade shorts (flip on crossunder instead of just flattening)")
fast = ta.ema(close, fastLen)
slow = ta.ema(close, slowLen)
goLong = ta.crossover(fast, slow)
goShort = ta.crossunder(fast, slow)
slPriceLong = close * (1 - slPct)
tpPriceLong = close * (1 + tpCapPct)
slPriceShort = close * (1 + slPct)
tpPriceShort = close * (1 - tpCapPct)
// Visual only — the fill and background just make the regime readable on the chart, they
// don't feed the logic above.
fastLine = plot(fast, "Fast EMA", color.new(color.aqua, 0), 2)
slowLine = plot(slow, "Slow EMA", color.new(color.orange, 0), 2)
fill(fastLine, slowLine, fast > slow ? color.new(color.aqua, 90) : color.new(color.orange, 90))
bgcolor(strategy.position_size > 0 ? color.new(color.aqua, 94) : strategy.position_size < 0 ? color.new(color.red, 94) : na)
// Backtest orders stay unguarded so the Strategy Tester still works. Only the alert() calls are
// guarded by barstate.isrealtime: historical bars must not fire webhooks.
if goLong
if strategy.position_size < 0
strategy.close("S")
if barstate.isrealtime
alert(tvhook_exit("short"), alert.freq_once_per_bar)
if strategy.position_size <= 0
strategy.entry("L", strategy.long)
if barstate.isrealtime
alert(tvhook_entry("long", close, slPriceLong, tpPriceLong), alert.freq_once_per_bar)
if goShort
if strategy.position_size > 0
strategy.close("L")
if barstate.isrealtime
alert(tvhook_exit("long"), alert.freq_once_per_bar)
if enableShort and strategy.position_size >= 0
strategy.entry("S", strategy.short)
if barstate.isrealtime
alert(tvhook_entry("short", close, slPriceShort, tpPriceShort), alert.freq_once_per_bar)
얼럿 연결하기
- 차트에 스크립트를 추가한 다음, 알림 탭을 열어 그 스크립트에 알림을 만드세요(종목에 만드는 게 아님).
- 조건: 방금 추가한 스크립트를 고르고 "모든 alert() 함수 호출"을 선택하세요 — 메시지 칸은 무시되고, alert()가 JSON을 직접 채웁니다.
- 알림 발송: 웹훅 URL을 켜고 콘솔에서 받은 https://tvhook.app/hook/<토큰>을 붙여넣으세요. 만료: 무기한.
얼럿 페이로드 전체 규격 보기
BingX·트레이딩뷰 화면은 각 서비스 자체 흐름을 따른 것이라 업데이트되면 달라질 수 있습니다. 위 전략은 얼럿 연결 방법을 보여주기 위한 단순 예시이지 투자 추천이 아닙니다. tvhook은 어떠한 수익도 보장하지 않습니다.