Strategy API (ctx)

A strategy is one JavaScript function. Backtest and live use exactly the same interface — nothing exists on only one side.

function onUpdate(ctx) {
  // called per candle (backtest) / per update (live)
  // return null, one order object, or an array of orders
}

Rules

  • Pure function — no network, no imports, no async. Only the ctx below.
  • qty is always an amount of coin (not cash).
  • Indicators return null without enough data — always null-check.
  • Keep your variables in ctx.state; they persist across calls.
  • ctx.ref slots use logical names ('hedge' etc.) — real symbols are bound at deploy time.

Order objects

  • Market: { side: 'buy'|'sell', qty } — walks the book (slippage, partial fills, taker fee).
  • Limit: { side, qty, type: 'limit', price } — fills at your price with maker fee when touched. postOnly: true rejects a limit that would fill immediately.
  • Smart (work order): { side, qty, type: 'smart', chase?, slices?, trigger?, hardStopMs? } — executed over time: chasing (peg the book → cross at deadline), slicing, stop/trailing triggers, and a hard time budget, in live and paper runs. Backtests approximate it as a market order — validate with a live paper run.
  • Cancel all: { cancel: 'all' } — cancels resting limits AND all work orders (chasing can't be stopped by canceling a single order).

The table below is the entire ctx (generated from the same source as the editor autocompletion). To get strategy code from an AI, use the studio's AI-prompt button or paste the whole AI reference.

ctx

This table is generated from the same source as the editor autocompletion and the AI reference (/llms.txt) — functions not listed here do not exist.

상태

ctx.candle현재 봉 { t, o, h, l, c, v } — t 는 실데이터면 실제 봉 시각(라이브와 동일), 합성 시세만 봉 번호
ctx.price현재가(종가)
ctx.closes현재 봉까지의 종가 배열(미래 없음)
ctx.i현재 봉 번호
ctx.position보유 수량(코인). 선물(usdm)에선 부호 수량 — +롱/−숏
ctx.entryPx(선물) 평균 진입가 — 포지션 없으면/spot 이면 null
ctx.liqPx(선물) 격리 청산가(해석해) — 포지션 없으면/spot 이면 null
ctx.uPnl(선물) 미실현손익(quote) — spot 이면 null
ctx.leverage(선물) 현재 레버리지 — spot 이면 null
ctx.funding(선물) 직전 적용 펀딩 rate — 아직 없으면/spot 이면 null
ctx.marginRatio(선물 P2) cross 유지마진율 = 유지마진÷계정평가(1 이상 = 청산권). cross 포지션 없으면/spot 이면 null
ctx.marginMode(선물 P2) 현재 종목 마진 모드 'isolated'|'cross' — spot 이면 null
ctx.setMarginMode(sym, 'isolated'|'cross')(선물 P2) 마진 모드 전환 — 그 심볼 포지션이 없을 때만(거래소 동일). 반환: 적용된 모드 | null. 기본 isolated
ctx.cash주문 가능 현금
ctx.state호출 간 유지되는 내 변수 저장소 — ★ 실행 전체 공유(다종목이면 전 종목이 같은 객체). 종목별 값은 ctx.symState 에
ctx.fees수수료율 { maker, taker }

지표

ctx.sma(n)단순이동평균. 데이터 부족이면 null
ctx.ema(n)지수이동평균. 부족이면 null
ctx.rsi(n)RSI 0~100. 부족이면 null
ctx.high(n)최근 n봉 최고 종가
ctx.low(n)최근 n봉 최저 종가
ctx.change(n)n봉 전 대비 변화율 — 소수(0.05 = +5%. markets()의 ch* 퍼센트 단위와 다름!)

오더북

ctx.book()호가 전체 { bids, asks } (좋은 가격 순)
ctx.bid()최우선 매수호가
ctx.ask()최우선 매도호가
ctx.mid()중간가
ctx.spread()호가 차이(절대값)
ctx.spreadPct()호가 차이(중간가 대비 %)
ctx.fillPrice(side, qty)시장가 예상 체결 { avgPx, filled }. filled<qty면 유동성 부족
ctx.depth(side, px)px 까지 쌓인 누적 물량

주문

ctx.openOrders()대기 중인 지정가 목록(읽기 전용)

스캐너(여러 종목)

ctx.sym이번 호출의 종목(예: "BTC")
ctx.marketType시장 종류 'spot'|'usdm' — usdm 이면 position 이 부호 수량(+롱/−숏), entryPx·liqPx·uPnl·leverage·funding 필드 추가
ctx.syms시세를 받은 종목 이름 목록
ctx.markets()전 종목 요약 [{ sym, price, ch1, ch5, ch60 }] — ch 는 퍼센트(2 = +2%. change()의 소수 단위와 다름!). 봉이 모자라면 null. 단일 종목 실행에선 그 한 종목만 담긴 배열(빈 배열 아님)
ctx.market(sym)한 종목 요약 (없으면 null)
ctx.pos(sym)그 종목 보유 수량
ctx.positions종목별 보유 수량 스냅샷 { SYM: qty } — 이미 든 종목을 피할 때
ctx.symState현재 종목 전용 저장소(자동 분리) — 종목별 손절가·보유 플래그는 여기에. state.__sym[sym] 과 같은 객체

거래량

ctx.vol현재 봉 거래량 (모르면 null)
ctx.volumes봉별 거래량 배열 (모르면 null)
ctx.avgVol(n)최근 n봉 평균 거래량 (봉이 모자라거나 모르면 null)

멀티에셋·환율

ctx.ref(slot)보조 종목 현재가. 슬롯명은 논리명(예: 'hedge')
ctx.refs사용 가능한 슬롯명 목록
ctx.fx(quote)1 USD 당 해당 통화 값(예: ctx.fx('KRW')). USD 환산은 직접
ctx.fxQuotes사용 가능한 통화 목록

파생 심리(OI·청산)

ctx.binanceOi()(라이브·페이퍼) 현재 종목 최신 미결제약정 { ts, oi, oiUsd } — 바이낸스 USDT-M 5분 집계. 백테스트·수집 전·모르면 null
ctx.binanceLiqs(n)(라이브·페이퍼) 최근 n분(기본 5·최대 60) 강제청산 합계 { longUsd, shortUsd, cnt } — longUsd=롱 청산(하방 압력의 해소). 백테스트·모르면 null. ★행이 없는 분은 "청산 0" 과 "수집 공백" 을 구분할 수 없음

로그

ctx.log(...)디버그. 라이브에선 샘플링(전량은 VPS 로컬 파일)
ctx.warn(...)중요. 라이브에서 스로틀 없이 항상 전송 + 직전 맥락 동봉

Order object keys

side'buy' | 'sell'
qty수량(코인). 현금이 아니다
type'limit'=지정가, 'smart'=작업 주문(시간에 걸쳐 집행 — 체이싱·분할·트리거). 기본은 시장가. smart 는 라이브·페이퍼에서 집행되고 백테스트는 시장가로 근사
price지정가일 때의 가격
postOnlytrue 면 즉시 체결될 지정가는 거부(메이커만)
chasesmart: 호가 추격 { escalateMs?=20000, deadlineMs?=45000, bandTicks?, minRepegMs? } — 호가 조인(메이커)→1틱 전진→마감 시 크로스(테이커). 기본 켜짐, false 면 끔
slicessmart: 분할 { n, everyMs } — 수량을 n조각으로 everyMs 간격 집행
triggersmart: 조건 대기 { type:'stop'|'trail', px?, offset? } — 조건이 닿기 전엔 주문이 안 나간다. 실데이터 백테스트도 봉 h/l 로 발동 판정(2026-08, 체결 라벨 stop/trail)
hardStopMssmart: 이 시간이 지나면 무조건 종료(남은 수량 포기)
cancel'all' 이면 대기 주문 전체 취소