콘텐츠로 이동

언어 개요

QuantiqDSL은 한국 주식시장 자동매매를 위한 Python 유사 스크립팅 언어입니다. 일반 Python과 다른 점은 세 가지입니다.

  1. 이벤트 기반 실행 — 가격 변동이나 봉 마감마다 스크립트 전체가 처음부터 다시 실행됩니다.
  2. 샌드박스 환경import, def, class 등을 사용할 수 없습니다. 보안과 예측 가능성을 위한 제약입니다.
  3. 내장 트레이딩 APIchart(), ta.*, buy(), sell() 등 트레이딩 전용 함수가 기본 제공됩니다.

스크립트 구조

모든 전략 스크립트는 아래 구조를 따릅니다.

# 1. 메타데이터 (필수)
version("1.0")
description("전략 이름")

# 2. 파라미터 선언 (선택)
param("period", "RSI 계산 기간", 14)

# 3. 청산 규칙 선언 (선택, rule.* 사용 시)
rule.order_on("5T")
rule.stop_loss(pct=3.0)

# 4. 데이터 로딩
c = chart("1D")

# 5. 지표 계산
rsi = ta.rsi(c.close, script_params["period"])

# 6. 매매 결정 (반드시 하나만)
if rsi[0] < 30:
    buy(tag="RSI 과매도")
elif rsi[0] > 70:
    sell(tag="RSI 과매수")
else:
    hold()

타입 시스템

TSeries — 시계열 데이터

chart() 함수와 ta.* 지표 함수는 모두 TSeries를 반환합니다. 인덱스 [0]이 가장 최신 값, [1]이 한 단계 이전 값입니다.

c = chart("1D")

c.close[0]   # 현재 봉 종가
c.close[1]   # 이전 봉 종가
c.close[2]   # 2봉 전 종가

# 교차 감지
sma5 = ta.sma(c.close, 5)
sma20 = ta.sma(c.close, 20)
sma5.cross_up(sma20)    # bool: 이번 봉에서 상향 교차 발생 여부
sma5.cross_down(sma20)  # bool: 이번 봉에서 하향 교차 발생 여부

유효성 확인이 필요한 경우:

if c.close.is_valid(20):    # 최소 20개 이상의 데이터가 있는지 확인
    rsi = ta.rsi(c.close, 14)

ScaleChart — 차트 객체

chart(timeframe) 함수가 반환하는 객체입니다. OHLCV 데이터와 오버레이 그리기 메서드를 제공합니다.

c = chart("5T")   # 5분봉

# OHLCV 데이터
c.open[0]    # 시가
c.high[0]    # 고가
c.low[0]     # 저가
c.close[0]   # 종가
c.volume[0]  # 거래량

# 차트 오버레이
c.line("이름", series, color="orange")
c.hline("기준선", 50, color="gray")
c.marker("신호", color="green", position="below", shape="triangle_up")

지원 타임프레임: "1T", "3T", "5T", "10T", "15T", "30T", "60T" (분봉), "1D" (일봉)


네임스페이스

네임스페이스 용도 예시
ta.* 기술 지표 ta.sma(), ta.rsi(), ta.macd()
math.* 수학 함수 math.mean(), math.abs(), math.max()
var.* 실행 간 상태 유지 var.init(), var.counter
rule.* 선언형 청산 규칙 rule.stop_loss(), rule.take_profit()

매매 결정 함수

스크립트 실행이 끝날 때 마지막으로 호출된 결정 함수가 최종 결정입니다.

함수 의미
buy(tag, qty, price) 매수
sell(tag, qty, price) 매도
hold(tag) 현재 포지션 유지
exit(tag) 포지션 청산
release(tag) 종목 감시 해제
# tag는 사유 문자열, 나중에 로그에서 확인
buy(tag="RSI 반등 진입")

# qty로 수량 지정 (생략 시 전략 설정값 사용)
sell(qty=5, tag="절반 매도")

# price로 지정가 주문 (생략 시 시장가)
buy(qty=10, price=price * 0.995, tag="현재가 -0.5% 지정가")

상태 유지 (var)

일반 변수는 이벤트마다 초기화됩니다. 실행 간 값을 유지하려면 var를 사용하세요.

# 잘못된 방법 (매 이벤트마다 0으로 초기화)
count = 0
count += 1   # 항상 1

# 올바른 방법
var.init(count=0, last_price=0.0)
var.count += 1            # 누적됨
var.last_price = price    # 이전 가격 저장

저장 제약: JSON 직렬화 가능한 타입만 허용 (int, float, str, bool, list, dict). 총 64KB 한도.


샌드박스 제약

보안을 위해 다음 구문은 사용할 수 없습니다.

import numpy as np   # ❌ import 금지
def calc():          # ❌ def (함수 정의) 금지
class Model:         # ❌ class 금지
lambda x: x * 2     # ❌ lambda 금지
eval("2+2")          # ❌ eval 금지
exec("code")         # ❌ exec 금지
open("file.txt")     # ❌ 파일 접근 금지

대신 내장 함수와 허용된 네임스페이스를 활용합니다.

# 수학 계산
result = math.mean([c.close[i] for i in range(5)])

# 리스트 컴프리헨션 (허용)
prices = [c.close[i] for i in range(10)]

자세한 목록은 샌드박스 제약 문서를 참고하세요.


파라미터 (param)

param()으로 스크립트에 파라미터를 선언합니다. 거래 탭에서 실행 전에 값을 조정할 수 있습니다.

param("period", "RSI 계산 기간", 14)       # 기본값 14
param("threshold", "과매도 기준", 30.0)    # 기본값 30.0
param("name", "전략 이름", "RSI 전략")     # 문자열 파라미터

# 값 읽기
rsi = ta.rsi(c.close, script_params["period"])
if rsi[0] < script_params["threshold"]:
    buy(tag="과매도 진입")

다음 단계