중급자 트랙¶
기본 전략을 작성할 수 있다면 이 트랙부터 시작하세요. 운영 품질을 높이고 더 정교한 전략을 만드는 데 필요한 기술을 다룹니다.
각 단계는 30~60분 분량입니다.
1단계: 멀티 타임프레임 전략¶
읽을 문서
이 단계에서 배우는 것
상위 타임프레임으로 추세를 파악하고, 하위 타임프레임에서 진입 타이밍을 잡는 구조입니다.
version("1.0")
description("멀티 TF 전략 — 일봉 추세 + 5분봉 진입")
c_daily = chart("1D") # 추세 확인
c_5m = chart("5T") # 진입 타이밍
# 일봉 기준 추세 판단
daily_trend = ta.ema(c_daily.close, 20)
is_uptrend = c_daily.close[0] > daily_trend[0]
# 5분봉 기준 진입
fast = ta.ema(c_5m.close, 5)
slow = ta.ema(c_5m.close, 20)
if is_uptrend and fast.cross_up(slow):
buy(tag="상승추세 + 5분봉 골든크로스")
elif fast.cross_down(slow):
sell(tag="5분봉 데드크로스")
else:
hold()
cross_up() vs ta.crossover()의 차이
series.cross_up(other) |
ta.crossover(s1, s2) |
|
|---|---|---|
| 반환 | bool |
TSeries |
| 사용처 | if 조건 직접 사용 |
시계열 계산 후 인덱스 접근 |
| 예시 | if fast.cross_up(slow): |
ta.crossover(fast, slow)[0] |
체크포인트
- [ ]
chart("1D")와chart("5T")를 동시에 사용하는 전략을 작성했다 - [ ]
ta.valuewhen,ta.barssince중 하나를 사용해봤다
2단계: 실행 간 상태 유지 (var)¶
읽을 문서
이 단계에서 배우는 것
스크립트는 이벤트마다 처음부터 다시 실행됩니다. 따라서 이전 실행의 값을 기억하려면 var를 사용해야 합니다.
# 일반 변수 — 이벤트마다 초기화됨
counter = 0
counter += 1 # 항상 1
# var — 실행 간 유지됨
var.init(counter=0)
var.counter += 1 # 누적됨
실전 예시: 연속 상승 봉 카운팅
var.init(up_count=0)
if c.close[0] > c.close[1]:
var.up_count += 1
else:
var.up_count = 0
# 3봉 연속 상승 시 매수
if var.up_count >= 3:
buy(tag=f"{var.up_count}봉 연속 상승")
else:
hold()
주의사항
var에 저장하는 값은 JSON으로 직렬화 가능해야 합니다 (int,float,str,bool,list,dict만 허용)- 총 저장 용량 제한: 64KB
- NumPy 배열, 커스텀 객체는 저장 불가
체크포인트
- [ ]
var.init()으로 초기 상태를 선언하고 실행 간 값을 유지하는 코드를 작성했다 - [ ] JSON 직렬화 제약을 이해하고 저장 타입을 올바르게 선택했다
3단계: 시각화와 운영 로그¶
읽을 문서
이 단계에서 배우는 것
전략이 왜 매매했는지 백테스트 차트에서 바로 확인할 수 있도록 오버레이와 마커를 추가합니다.
c = chart("1D")
fast = ta.sma(c.close, 5)
slow = ta.sma(c.close, 20)
# 차트에 선 표시
c.line("단기MA", fast, color="orange")
c.line("장기MA", slow, color="blue")
if fast.cross_up(slow):
c.marker("BUY", color="green", position="below", shape="triangle_up")
buy(tag="골든크로스", reason="5일선이 20일선 상향 돌파")
elif fast.cross_down(slow):
c.marker("SELL", color="red", position="above", shape="triangle_down")
sell(tag="데드크로스", reason="5일선이 20일선 하향 돌파")
else:
hold()
운영 로그 남기기
reason 문자열은 나중에 백테스트 결과를 분석할 때 "왜 그 시점에 매매했는가"를 복기하는 데 핵심입니다. 의미 있는 값을 기록하세요.
체크포인트
- [ ]
c.line(),c.marker()로 차트에 신호를 표시했다 - [ ]
reason파라미터에 의미 있는 문자열을 남기는 습관을 들였다
4단계: 선언형 청산 규칙 (rule.*)¶
읽을 문서
이 단계에서 배우는 것
손절, 익절, 트레일링 스탑, 장마감 청산을 코드 몇 줄로 선언합니다. 직접 if 조건을 작성하는 것보다 간결하고 실수 여지가 적습니다.
version("1.0")
description("rule.* 사용 예시")
# 청산 규칙 선언 (진입 조건보다 먼저 작성)
rule.order_on("5T") # 5분봉 마감 시 주문
rule.stop_loss(pct=param("손절%", "손절 기준", 3.0)) # 3% 손절
rule.take_profit(pct=param("익절%", "익절 기준", 10.0), # 10% 익절 (50% 수량)
qty_ratio=0.5)
rule.trailing_stop(pct=param("트레일링%", "트레일링 기준", 2.0)) # 2% 트레일링
rule.close_before(minutes=param("장마감전(분)", "장마감 전 정리", 10)) # 장마감 10분 전 청산
c = chart("5T")
if barstate("5T").is_confirmed:
if ta.crossover(c.close, ta.sma(c.close, 20))[0]:
buy(qty=10)
else:
hold()
우선순위: 사용자가 명시적으로 호출한 sell()/exit()가 rule.*보다 우선합니다.
체크포인트
- [ ]
rule.stop_loss(),rule.trailing_stop()중 하나를 전략에 추가했다 - [ ]
param()과 조합하여 UI에서 값을 조정할 수 있도록 했다 - [ ]
rule.*vs 직접sell()호출의 우선순위를 이해했다
중급자 점검 기준¶
전략을 실전에 적용하기 전에 확인하세요.
- 타임프레임을 2~3개 이하로 유지했다 (많을수록 실행 비용과 복잡도가 증가)
reason문자열만 보고도 매매 의도를 복기할 수 있다var에 저장하는 값이 JSON 직렬화 가능하고 64KB를 넘지 않는다- 백테스트 결과와 실시간 실행 결과가 크게 다르지 않다