1. 실전 연동 4단계 퀵스타트 가이드 (Quick-Start Manual)
내려받은 4종의 파일을 본인의 트레이딩뷰(TradingView), n8n 자동화 서버(https://auto.alphapulse.kr), 그리고 터미널 환경에 연결하는 표준 절차입니다.
-
Step 1 — TradingView에 통합 마스터 코드 등록:
AlphaPulse_Dual_Engine_Master_v5.pine 파일을 열어 전체 코드를 복사한 뒤 트레이딩뷰 하단 Pine 에디터(Pine Editor)에 붙여넣고 "차트에 넣기"를 클릭합니다. 우측 상단에 기관용 실시간 레짐 대시보드가 바로 표시됩니다.
-
Step 2 — n8n 자동 주문 라우터 워크플로우 확인:
n8n 대시보드(
https://auto.alphapulse.kr)에 "AlphaPulse Pro - TradingView Dual-Engine Webhook Order Router" 워크플로우를 AlphaPulse_n8n_TradingView_Order_Router.json 파일에서 Import from File로 불러옵니다.
-
Step 3 — TradingView 얼러트(Alert) 웹훅 연결:
트레이딩뷰 얼러트 생성 창에서 조건을
AlphaPulse All-Weather Dual Engine Portfolio로 선택하고 메시지 창에 {{strategy.order.alert_message}}를 입력한 뒤 Webhook URL을 등록하면 자동 라우팅이 시작됩니다.
-
Step 4 — Engine 3 델타 뉴트럴 베이시스 스캐너 실행:
터미널에서
node AlphaPulse_Delta_Neutral_Basis_Scanner.mjs 명령을 실행하면 외부 패키지 설치 없이 BTC, ETH, SOL, BNB의 실시간 10일 평균 펀딩비 연환산 수익률(APY)과 왕복 수수료 손익분기 보유 기간(TBE)을 즉시 진단합니다.
2. 시드머니별 Half-Kelly & ATR 포지션 사이징 조견표 (CSV 요약본)
동봉된 CSV 파일의 Part 1에 수록된 계좌 규모별 권장 포지션 사이징 기준표입니다. 1회 거래당 손절이 발생할 때 전체 계좌 자산의 -1.2% 이내로 손실을 제한하도록 설계했습니다.
| 계좌 총 시드머니 |
1회 최대 허용 손실 (1.2%) |
Engine 1 권장 진입액 (돌파) |
Engine 2 권장 진입액 (스윕) |
권장 레버리지 |
| $5,000 |
-$60 |
$4,137 |
$3,076 |
1.0x (현물·무레버리지) |
| $10,000 |
-$120 |
$8,275 |
$6,153 |
1.0x ~ 1.5x |
| $25,000 |
-$300 |
$20,689 |
$15,384 |
1.0x ~ 1.5x |
| $50,000 |
-$600 |
$41,379 |
$30,769 |
1.0x ~ 1.2x |
| $100,000 |
-$1,200 |
$82,758 |
$61,538 |
1.0x (기관 무레버리지) |
3. 통합 듀얼 엔진 마스터 PineScript v5 전체 코드 미리보기
파일을 내려받지 않고도 웹에서 바로 복사해 쓰실 수 있도록 통합 마스터 스크립트 전문을 함께 수록했습니다.
//@version=5
strategy("AlphaPulse All-Weather Dual Engine Portfolio [Pro Master v5]",
shorttitle="AP_DualEngine_Pro",
overlay=true,
initial_capital=10000,
default_qty_type=strategy.percent_of_equity,
default_qty_value=50,
pyramiding=2,
commission_type=strategy.commission.percent,
commission_value=0.05,
calc_on_every_tick=false)
// ============================================================================
// AlphaPulse Pro Trader Vault - Master Quantitative Script
// ----------------------------------------------------------------------------
// 통합 아키텍처:
// [Engine 1] 20 EMA & 볼린저 밴드 스퀴즈 변동성 돌파 (추세장 30% 구간 알파 수확)
// [Engine 2] 20 Rolling VWAP 표준편차 밴드 & RSI 유동성 스윕 (횡보장 70% 구간 알파 수확)
// [Portfolio] 50:50 자본 배분 + ADX(14) 레짐 자동 전환 + n8n 자동주문 Webhook JSON 생성
// ============================================================================
// ----------------------------------------------------------------------------
// 1. 포트폴리오 및 웹훅(n8n) 마스터 설정
// ----------------------------------------------------------------------------
grpPortfolio = "1. 포트폴리오 자본 배분 & n8n 웹훅 설정"
useEngine1 = input.bool(true, "Engine 1 가동 (20 EMA 스퀴즈 돌파)", group=grpPortfolio)
useEngine2 = input.bool(true, "Engine 2 가동 (VWAP 유동성 스윕 역추세)", group=grpPortfolio)
engine1WeightPct = input.float(50.0, "Engine 1 자본 배분 비중 (%)", minval=10.0, maxval=100.0, step=5.0, group=grpPortfolio)
engine2WeightPct = input.float(50.0, "Engine 2 자본 배분 비중 (%)", minval=10.0, maxval=100.0, step=5.0, group=grpPortfolio)
webhookSecret = input.string("AP_PRO_2026_SECRET", "n8n Webhook 인증 시크릿 토큰", group=grpPortfolio)
showDashboard = input.bool(true, "차트 우측 상단 기관용 실시간 대시보드 표시", group=grpPortfolio)
// ----------------------------------------------------------------------------
// 2. Engine 1 파라미터 (20 EMA & 볼린저 스퀴즈 돌파)
// ----------------------------------------------------------------------------
grpE1 = "2. Engine 1: 20 EMA & 볼린저 스퀴즈 돌파"
e1EmaLen = input.int(20, "EMA 기준 기간", minval=5, group=grpE1)
e1BbLen = input.int(20, "볼린저 밴드 기간", minval=5, group=grpE1)
e1BbMult = input.float(2.0, "볼린저 밴드 표준편차 승수", step=0.1, group=grpE1)
e1SqueezeThresh = input.float(0.042, "볼린저 대역폭 스퀴즈 임계치 (4.2%)", step=0.002, group=grpE1)
e1VolMult = input.float(1.35, "돌파 캔들 거래량 스파이크 배수", step=0.05, group=grpE1)
e1TpPct = input.float(0.042, "Engine 1 목표 익절 폭 (+4.2%)", step=0.005, group=grpE1)
e1SlEmaBuffer = input.float(0.014, "Engine 1 20 EMA 하방 손절 버퍼 (-1.4%)", step=0.002, group=grpE1)
// ----------------------------------------------------------------------------
// 3. Engine 2 파라미터 (VWAP 표준편차 밴드 & RSI 유동성 스윕)
// ----------------------------------------------------------------------------
grpE2 = "3. Engine 2: VWAP 밴드 & RSI 유동성 스윕"
e2VwapLen = input.int(20, "롤링 VWAP 기간", minval=5, group=grpE2)
e2SweepSigma = input.float(2.0, "유동성 스윕 하단 밴드 (σ)", step=0.1, group=grpE2)
e2ReclaimSigma = input.float(1.5, "종가 복귀(Reclaim) 밴드 (σ)", step=0.1, group=grpE2)
e2RsiLen = input.int(14, "RSI 기간", minval=5, group=grpE2)
e2RsiOversold = input.float(38.0, "RSI 스윕 과매도 임계치", step=1.0, group=grpE2)
e2AtrLen = input.int(14, "ATR 변동성 기간", minval=5, group=grpE2)
e2AtrStopMult = input.float(1.8, "ATR 샹들리에 손절 배수 (1.8x)", step=0.1, group=grpE2)
e2MaxAdx = input.float(42.0, "ADX 추세 폭주 시 역추세 차단 임계치", step=1.0, group=grpE2)
// ----------------------------------------------------------------------------
// 4. 코어 수학 및 기술적 지표 연산
// ----------------------------------------------------------------------------
// [Engine 1 연산]
ema20 = ta.ema(close, e1EmaLen)
[bbMid, bbUp, bbLow] = ta.bb(close, e1BbLen, e1BbMult)
bbBandwidth = (bbUp - bbLow) / bbMid
volSma20 = ta.sma(volume, 20)
isE1Squeezed = ta.lowest(bbBandwidth, 3) < e1SqueezeThresh
isE1VolSpike = volume > (volSma20 * e1VolMult)
e1LongSignal = useEngine1 and (close > bbUp) and (close[1] <= bbUp[1]) and (close > ema20) and isE1Squeezed and isE1VolSpike
// [Engine 2 연산]
tp = hlc3
vwapCenter = ta.vwma(tp, e2VwapLen)
vwapVar = ta.vwma(math.pow(tp - vwapCenter, 2), e2VwapLen)
vwapStd = math.sqrt(math.max(vwapVar, 0))
vwapLower2_0 = vwapCenter - (e2SweepSigma * vwapStd)
vwapLower1_5 = vwapCenter - (e2ReclaimSigma * vwapStd)
vwapUpper1_5 = vwapCenter + (e2ReclaimSigma * vwapStd)
vwapUpper2_0 = vwapCenter + (e2SweepSigma * vwapStd)
rsi14 = ta.rsi(close, e2RsiLen)
atr14 = ta.atr(e2AtrLen)
[diPlus, diMinus, adx14] = ta.dmi(14, 14)
candleRange = math.max(high - low, syminfo.mintick)
lowerWickRatio = (math.min(open, close) - low) / candleRange
isE2SweepReclaim = (low <= vwapLower1_5) and (close > vwapLower1_5) and (lowerWickRatio >= 0.35)
isE2RegimeSafe = adx14 < e2MaxAdx
isE2RsiReady = (rsi14 <= e2RsiOversold) or (rsi14[1] <= e2RsiOversold)
e2LongSignal = useEngine2 and isE2SweepReclaim and isE2RegimeSafe and isE2RsiReady and (volume > volSma20 * 1.15)
// ----------------------------------------------------------------------------
// 5. n8n 자동매매 라우터 전용 JSON Webhook 생성 함수
// ----------------------------------------------------------------------------
buildWebhookJson(engineName, actionType, entryPx, stopPx, tp1Px, tp2Px, allocPct) =>
'{"secret":"' + webhookSecret +
'","symbol":"' + syminfo.tickerid +
'","timeframe":"' + timeframe.period +
'","engine":"' + engineName +
'","action":"' + actionType +
'","price":' + str.tostring(entryPx, "#.##") +
',"stopLoss":' + str.tostring(stopPx, "#.##") +
',"tp1":' + str.tostring(tp1Px, "#.##") +
',"tp2":' + str.tostring(tp2Px, "#.##") +
',"allocationPct":' + str.tostring(allocPct, "#.#") +
',"rsi":' + str.tostring(rsi14, "#.#") +
',"adx":' + str.tostring(adx14, "#.#") +
',"atr":' + str.tostring(atr14, "#.##") + '}'
// ----------------------------------------------------------------------------
// 6. 포지션 진입 및 리스크 관리 실행
// ----------------------------------------------------------------------------
var float e2ActiveStop = na
// Engine 1 진입 (돌파)
if (e1LongSignal)
e1Stop = ema20 * (1.0 - e1SlEmaBuffer)
e1Tp1 = close * (1.0 + e1TpPct)
e1Tp2 = close * (1.0 + e1TpPct * 1.85)
e1Json = buildWebhookJson("ENGINE_1_BREAKOUT", "BUY_LONG", close, e1Stop, e1Tp1, e1Tp2, engine1WeightPct)
strategy.entry("E1_Breakout", strategy.long, comment="[E1] 스퀴즈 돌파", alert_message=e1Json)
// Engine 2 진입 (유동성 스윕 역추세)
if (e2LongSignal)
e2ActiveStop := low - (atr14 * e2AtrStopMult)
e2Json = buildWebhookJson("ENGINE_2_VWAP_SWEEP", "BUY_LONG", close, e2ActiveStop, vwapCenter, vwapUpper1_5, engine2WeightPct)
strategy.entry("E2_VwapSweep", strategy.long, comment="[E2] 유동성 스윕", alert_message=e2Json)
// Engine 1 청산 규칙
if (strategy.position_size > 0)
e1StopDyn = ema20 * (1.0 - e1SlEmaBuffer)
e1TpDyn = strategy.position_avg_price * (1.0 + e1TpPct)
strategy.exit("E1_Exit", "E1_Breakout", stop=e1StopDyn, limit=e1TpDyn)
// Engine 2 2단계 분할 익절 (60% 중심 VWAP / 40% 상단 +1.5σ)
strategy.exit("E2_TP1_60%", "E2_VwapSweep", qty_percent=60, limit=vwapCenter, stop=e2ActiveStop)
strategy.exit("E2_TP2_40%", "E2_VwapSweep", qty_percent=100, limit=vwapUpper1_5, stop=e2ActiveStop)
// ----------------------------------------------------------------------------
// 7. 차트 시각화 & 기관용 실시간 퀀트 대시보드 테이블
// ----------------------------------------------------------------------------
plot(ema20, "E1: 20 EMA 추세선", color=color.new(#2563eb, 0), linewidth=2)
plot(vwapCenter, "E2: 20 Rolling VWAP 중심선", color=color.new(#0284c7, 20), linewidth=2, style=plot.style_circles)
pVwapL1 = plot(vwapLower1_5, "VWAP -1.5σ 리클레임", color=color.new(#10b981, 50), linewidth=1)
pVwapL2 = plot(vwapLower2_0, "VWAP -2.0σ 스윕 밴드", color=color.new(#10b981, 15), linewidth=2)
fill(pVwapL1, pVwapL2, color=color.new(#10b981, 85), title="기관 유동성 스윕 존")
plotshape(e1LongSignal, title="E1 돌파 시그널", style=shape.triangleup, location=location.belowbar, color=#2563eb, size=size.small, text="E1 돌파")
plotshape(e2LongSignal, title="E2 스윕 시그널", style=shape.labelup, location=location.belowbar, color=#10b981, textcolor=color.white, size=size.small, text="E2 스윕")
var table dash = table.new(position.top_right, 2, 7, bgcolor=color.new(#0f172a, 10), border_width=1, border_color=#334155)
if (barstate.islast and showDashboard)
regimeText = adx14 >= e2MaxAdx ? "🔥 강한 추세장 (Engine 1 우위)" : isE1Squeezed ? "⚡ 변동성 압축 스퀴즈 (돌파 대기)" : "⚖️ 박스권 평균회귀 (Engine 2 우위)"
table.cell(dash, 0, 0, "AlphaPulse Dual Engine", text_color=#38bdf8, text_size=size.small, bgcolor=#1e293b)
table.cell(dash, 1, 0, "Pro Master v5", text_color=#f8fafc, text_size=size.small, bgcolor=#1e293b)
table.cell(dash, 0, 1, "현재 시장 레짐", text_color=#94a3b8, text_size=size.tiny)
table.cell(dash, 1, 1, regimeText, text_color=#4ade80, text_size=size.tiny)
table.cell(dash, 0, 2, "20 EMA / 20 VWAP", text_color=#94a3b8, text_size=size.tiny)
table.cell(dash, 1, 2, str.tostring(ema20, "#.##") + " / " + str.tostring(vwapCenter, "#.##"), text_color=#f8fafc, text_size=size.tiny)
table.cell(dash, 0, 3, "볼린저 대역폭 (Squeeze)", text_color=#94a3b8, text_size=size.tiny)
table.cell(dash, 1, 3, str.tostring(bbBandwidth * 100, "#.##") + "%", text_color=isE1Squeezed ? #fbbf24 : #f8fafc, text_size=size.tiny)
table.cell(dash, 0, 4, "VWAP 스윕 존 (-1.5σ~-2σ)", text_color=#94a3b8, text_size=size.tiny)
table.cell(dash, 1, 4, str.tostring(vwapLower2_0, "#.##") + " ~ " + str.tostring(vwapLower1_5, "#.##"), text_color=#34d399, text_size=size.tiny)
table.cell(dash, 0, 5, "RSI(14) / ADX(14)", text_color=#94a3b8, text_size=size.tiny)
table.cell(dash, 1, 5, str.tostring(rsi14, "#.1") + " / " + str.tostring(adx14, "#.1"), text_color=#f8fafc, text_size=size.tiny)
table.cell(dash, 0, 6, "ATR(14) / 1.8x 손절폭", text_color=#94a3b8, text_size=size.tiny)
table.cell(dash, 1, 6, str.tostring(atr14, "#.##") + " (-" + str.tostring(atr14 * e2AtrStopMult, "#.##") + ")", text_color=#f87171, text_size=size.tiny)