본문으로 건너뛰기

오프라인 Pine Script 백테스트: 동일한 트레이드 48건

방향, 시각, 가격, 순 P&L이 TradingView에서 내보낸 목록과 행마다 일치합니다.

4,2004,4004,6004,800
8월 22일8월 23일
USDT

차트를 탭하거나 드래그하면 원하는 지점의 값이 보입니다.

출처: 프로브 composite-vcp-fvg-active-zones-01, pineforge-corpus d75b4fa, 2025-03-31~2026-05-01: CSV 파일, 갤러리 페이지.

차트를 표로 보기

같은 전략의 연속된 트레이드 48건을 해당 구간의 Binance ETHUSDT 무기한 선물 15분봉 178개 위에 표시했습니다. TradingView 내보내기와 PineForge 트레이드 목록은 포지션 방향, 진입 시각과 청산 시각, 진입가와 청산가, 순손익이 행마다 일치합니다.

트레이드포지션TradingView 진입PineForge 진입TradingView 청산PineForge 청산TradingView 순 P&LPineForge 순 P&L
4,100롱4,306.954,306.954,296.644,296.64−10.31−10.31
4,106롱4,279.174,279.174,276.804,276.80−2.37−2.37
4,112롱4,327.734,327.734,315.744,315.74−11.99−11.99
4,118롱4,272.714,272.714,242.194,242.19−30.52−30.52
4,124롱4,779.504,779.504,760.734,760.73−18.77−18.77
4,129롱4,749.874,749.874,738.934,738.93−10.94−10.94
4,135롱4,718.894,718.894,731.004,731.0012.1112.11
4,141롱4,723.344,723.344,718.714,718.71−4.63−4.63
4,147롱4,752.764,752.764,745.124,745.12−7.64−7.64
측정 방법

pineforge-corpus 커밋 d75b4fa의 프로브 composite-vcp-fvg-active-zones-01: Binance ETHUSDT 무기한 선물, 15분봉, 2025-03-31~2026-05-01. 이 프로브의 PineForge 트레이드 목록은 2026-10-02에 엔진 v1.0.1이 생성했습니다. CSV 파일 보기 또는 갤러리에서 열기

PineForge는 TradingView 밖에서, Docker 이미지 하나로 Pine Script를 오프라인으로 백테스트합니다. 입력이 같으면 트레이드도 같습니다.

왜 오프라인?

브라우저 백테스트는 차트 옆에서 빠르게 반복해 보기에 좋습니다. 오프라인 백테스트는 다음 단계가 전략에 돈을 싣는 일일 때 손이 갑니다. 감사 추적이 필요할 때, CI로 모든 커밋에 게이트를 걸어야 할 때, 두 달 전 결과가 오늘도 트레이드 하나하나까지 그대로 재현돼야 할 때죠.

오프라인으로 돌리면 브라우저 테스터가 못 주는 게 생깁니다: 결과가 결정론적입니다. 스크립트, 데이터, 이미지 버전이 같으면 트레이드도 같습니다. 이미지 버전을 고정하고, 리포트를 저장소에 커밋하고, 커밋 사이의 트레이드 목록을 디프하고, 이 모든 걸 CI에서 헤드리스로 돌리면 됩니다. 넣는 CSV는 내 것이고, 엔진은 로컬에서 돌며, 리포트에는 그 결과를 만든 요소의 핑거프린트가 기록됩니다.

실제로 얻는 것들: 이미지 버전을 고정하므로 두 달 전 커밋도 오늘 같은 트레이드 목록을 냅니다. OHLCV이기만 하면 거래소 캔들부터 틱을 모아 직접 만든 봉까지 내 데이터를 쓸 수 있습니다. 회귀가 생기면 CI 검사가 빌드를 실패시킵니다. 그리고 전략은 특정 플랫폼에 묶이지 않는 파일로 남습니다.

백테스트 결과를 동료와 나눠야 하는데 ‘공유’할 방법이 차트 스크린샷뿐이라는 걸 깨달은 적이 있다면, 빠진 조각은 바로 오프라인 실행입니다.

Pine Script를 오프라인으로 백테스트하는 방법

PineForge는 PineScript v6를 네이티브 C++로 트랜스파일하고, Docker 이미지 하나로 내 머신에서 실행합니다.

세 단계면 됩니다. 이미지는 한 번만 받으면 되고, 그 뒤로는 모든 과정이 오프라인에서 돌아갑니다.

1단계: 런타임 받기

이미지는 ghcr.io/pineforge-4pass/pineforge-release 하나입니다. pip도, 키도, 가입도 필요 없습니다. 트랜스파일, 컴파일, 백테스트가 모두 이미지 안에서 오프라인으로 돌아갑니다. 이미지 안의 엔진은 Apache-2.0이고, 함께 들어 있는 트랜스파일러는 개인 트레이딩에 무료입니다.

2단계: 내 Pine을 C++로 트랜스파일하기

이미지를 트랜스파일 전용 모드로 실행하면 PineScript v6를 로컬에서 완결된 C++ 소스 파일로 바꿔 줍니다. 백테스트할 때 Pine 인터프리터는 돌지 않습니다. 이미지가 C++를 네이티브 코드로 컴파일합니다.

docker run --rm --network=none \
  -e PINEFORGE_TRANSPILE_ONLY=1 \
  -v "$(pwd)/my_strategy.pine":/in/strategy.pine:ro \
  ghcr.io/pineforge-4pass/pineforge-release:1.10.0 > strategy.cpp

3단계: 백테스트하기

생성된 C++ 옆에 OHLCV CSV를 마운트하고 이미지를 실행하세요. CSV에는 timestamp,open,high,low,close,volume 헤더가 있어야 하고, 타임스탬프는 UNIX 밀리초 단위입니다. 엔진이 전략을 봉 단위로 실행하고 JSON 리포트를 stdout으로 출력합니다. 2단계는 건너뛰어도 됩니다. 대신 strategy.pine을 마운트하면 이미지가 먼저 트랜스파일합니다.

docker run --rm --network=none \
  -v "$(pwd)/strategy.cpp":/in/strategy.cpp:ro \
  -v "$(pwd)/ohlcv.csv":/in/ohlcv.csv:ro \
  ghcr.io/pineforge-4pass/pineforge-release:1.10.0 > report.json

JSON 리포트에는 요약 블록(총 트레이드 수, 승패 수, 승률, 순손익, 최대 낙폭), 전체 트레이드 목록(진입과 청산 시각, 가격, 수량, 손익, 봉 인덱스), 프로핏 팩터, 샤프 지수, 소르티노 지수 같은 지표, 에퀴티 커브, 그리고 실행에 쓰인 엔진, 트랜스파일러, 입력값, 데이터의 핑거프린트(계산할 수 없으면 null)가 들어 있습니다.

워크플로 전부입니다. GUI 없음, 재인증 없음, 차트 로딩 없음. Docker만 되면 PineForge 오프라인 백테스트도 됩니다.

무엇을 백테스트할 수 있나

짧게: OHLCV로 직렬화할 수 있는 것이라면 무엇이든. PineForge는 시세 벤더와 직결돼 있지 않습니다. 데이터를 가져오면 엔진이 전략을 실행합니다.

  • 내 거래소 크립토. Binance, Bybit, Kraken, 혹은 REST/WebSocket API 있는 거래소에서 원시 체결 데이터를 가져와 전략 타임프레임으로 집계하고 CSV를 바로 넣습니다. 실제로 거래할 페어·장소 조합으로 테스트합니다.
  • 틱으로 만든 봉. 틱이나 호가창 데이터로 봉을 만든다면 OHLCV로 넣으면 됩니다. 엔진은 봉이 어디서 왔는지 따지지 않습니다.
  • 다른 시계열. 엔진은 timestamp, open, high, low, close, volume만 읽고 그 밖의 열은 무시합니다. 센티먼트 점수나 온체인 지표는 이 열에 인코딩해야만 백테스트할 수 있습니다.

갤러리의 전략 312개는 공개 코퍼스에서 왔고, 모두 TradingView 자체 내보내기와 대조해 등급을 매겼습니다. 엔진 main의 코퍼스 검사는 그중 311개를 우수로 고정해 둡니다. 트레이드 수가 같고, 90번째 백분위수에서 가격 차이 0.01% 이내, 손익 차이 1% 이내라는 기준이며, trail_* 청산을 프로덕션 프로파일로 채점하는 전략 7개에는 더 느슨한 청산가 한도와 손익 한도를 적용합니다. 남은 하나는 이상 사례로 지정돼 있습니다. 우수 등급에서는 정확히 같은 시각, 가격, 방향에 TradingView가 서로 다른 진입 Signals를 둘 이상 표시하는 경우, 엔진도 그 지점에 같은 수의 서로 다른 진입을 표시합니다(개별 진입 식별).

다음 단계