콘텐츠로 이동

첫 번째 전략 작성

이 가이드에서는 QuantiqDSL로 이동평균 크로스오버 전략을 처음부터 완성하는 과정을 단계별로 따라갑니다. 완료하면 실제로 실행 가능한 전략 코드 하나가 완성됩니다.

예상 소요 시간: 약 15분


완성 코드 미리보기

먼저 완성된 코드를 보고 시작하면 각 단계가 더 명확하게 이해됩니다.

version("1.0")
description("SMA 크로스오버 — 첫 전략")

rule.stop_loss(pct=param("손절%", "손절 기준 퍼센트", 3.0))

c = chart("1D")
fast_ma = ta.sma(c.close, 5)
slow_ma = ta.sma(c.close, 20)

c.line("5일선", fast_ma, color="orange")
c.line("20일선", slow_ma, color="blue")

if fast_ma.cross_up(slow_ma):
    buy(tag="골든크로스")
elif fast_ma.cross_down(slow_ma):
    sell(tag="데드크로스")
else:
    hold()

1단계: 스튜디오 열기

Quantiq에 접속한 후 전략 스튜디오를 엽니다. 에디터 화면이 나타나면 준비된 것입니다.

처음이라면

스튜디오에는 기본 템플릿이 로드되어 있습니다. 아래 단계를 따라 내용을 수정하거나, 새 파일을 열고 처음부터 작성할 수 있습니다.


2단계: 메타데이터 선언

모든 스크립트는 version()description()으로 시작합니다. 이 두 줄은 필수입니다.

version("1.0")
description("SMA 크로스오버 — 첫 전략")

메타데이터 바로 아래에 청산 규칙을 선언합니다. 손절 없이 실전 투자를 시작하지 마세요.

rule.stop_loss(pct=param("손절%", "손절 기준", 3.0))     # 3% 손절

3단계: 데이터 불러오기

chart() 함수로 타임프레임을 지정하면 해당 차트의 OHLCV 데이터를 가져올 수 있습니다.

c = chart("1D")   # 일봉 데이터

이제 c를 통해 시가, 고가, 저가, 종가, 거래량에 접근합니다.

속성 설명 예시
c.close[0] 현재 봉 종가 오늘 종가
c.close[1] 이전 봉 종가 어제 종가
c.volume[0] 현재 봉 거래량 오늘 거래량
c.high[0] 현재 봉 고가 오늘 고가

4단계: 지표 계산

ta.* 네임스페이스에서 기술 지표를 계산합니다.

fast_ma = ta.sma(c.close, 5)    # 5일 단순이동평균
slow_ma = ta.sma(c.close, 20)   # 20일 단순이동평균

ta.sma()TSeries(시계열)를 반환합니다. [0]으로 현재 값, [1]로 이전 값에 접근하거나, cross_up() / cross_down() 메서드로 교차를 감지할 수 있습니다.


5단계: 차트에 지표 표시

지표를 차트에 선으로 표시합니다. 백테스트 결과를 확인할 때 신호 발생 지점을 시각적으로 볼 수 있습니다.

c.line("5일선", fast_ma, color="orange")
c.line("20일선", slow_ma, color="blue")

6단계: 매매 로직 작성

if/elif/else로 매매 조건을 작성합니다. 스크립트가 실행되면 이 분기 중 하나가 반드시 실행됩니다.

if fast_ma.cross_up(slow_ma):
    buy(tag="골든크로스")          # 5일선이 20일선을 상향 돌파
elif fast_ma.cross_down(slow_ma):
    sell(tag="데드크로스")         # 5일선이 20일선을 하향 돌파
else:
    hold()                        # 크로스 없음 — 현재 포지션 유지

tag 파라미터: 매매 이유를 문자열로 기록합니다. 백테스트 결과에 표시되어 나중에 의사결정을 복기할 수 있습니다.


7단계: 저장하고 실행하기

  1. Ctrl+S 또는 저장 버튼으로 스크립트를 저장합니다.
  2. 저장된 스크립트는 내 계정에 비공개로 보관됩니다. 커뮤니티에 자동 공개되지 않습니다.
  3. 백테스트 패널에서 종목을 선택합니다. 에디터 우측 상단의 백테스트 탭을 열고, 종목명이나 마켓 코드(예: 비트코인 또는 KRW-BTC)를 입력하여 선택하세요. 검색은 KRW + BTC + USDT 마켓 전체에서 코드와 한글 이름 양쪽 부분일치로 매칭됩니다(예: BTCKRW-BTC, BTC-ETH, USDT-BTC 모두 노출).
  4. 기간을 설정하고 실행 버튼을 누릅니다.
  5. 차트에 이동평균선이 표시되고, 크로스 지점에 매매 신호가 나타납니다.

파라미터 활용

param()으로 선언한 값은 거래 탭의 전략 편집 패널에서 변경할 수 있습니다. 코드를 수정하지 않고 다양한 조건을 시험해볼 때 유용합니다.

param("fast_period", "빠른 이동평균 기간", 5)
param("slow_period", "느린 이동평균 기간", 20)

fast_ma = ta.sma(c.close, script_params["fast_period"])
slow_ma = ta.sma(c.close, script_params["slow_period"])

자주 하는 실수

실수 올바른 코드
version() 없이 시작 항상 첫 줄에 version("1.0")
타임프레임 오타 ("1d") "1D", "5T", "1H" — 대문자 확인
else 분기 누락 모든 경우에 결정 함수 호출 필요
c.close 를 직접 비교 c.close[0] 으로 현재 값 접근

분봉·시간봉 전략에서는?

분봉·시간봉 전략에서 주문 실행 타이밍을 특정 봉 마감으로 제한하려면 @trade(order_on=...) 데코레이터를 사용합니다. 허용 값: "tick", "1T" ~ "1H".

version("1.1")

@trade(order_on="5T")
def main():
    if position.qty == 0 and ta.rsi(chart("5T").close, 14).last() < 30:
        buy(qty=1, tag="rsi_low")
    else:
        hold()

데코레이터 없이 작성한 기존 top-level 스크립트는 그대로 동작합니다 — 엔진이 암묵적으로 @trade로 wrap합니다. 두 패턴은 동일한 결과를 냅니다.

rule.order_on(...) 함수 호출도 호환을 위해 동작하지만 deprecated 입니다. @trade(order_on=...) 데코레이터 인자가 정본이며, rule.order_on(...)을 호출하면 ScriptResult.warnings에 마이그레이션 안내가 한 번 누적됩니다.

일봉(1D) 전략은 일봉 마감 이벤트 자체가 트리거이므로 order_on이 필요하지 않습니다. "1D"는 지원 값이 아닙니다.


다음 단계