다종목 스캐너: 한 전략이 같은 거래소의 여러 종목(최대 200개)을 동시에 봅니다 — 종목별 포지션·주문·상태 자동 분리.
한 전략에서 두 거래소에 동시 주문(legs — 거래소 간 차익거래·헷지): 백테스트(잡 포함)·페이퍼·라이브 실주문까지 지원합니다. 다리별 지갑·수수료·킬스위치 연동, 라이브는 모든 다리의 API 키가 있어야 시작합니다(한 다리만 실행되는 반쪽 헷지 방지 — 조용한 강등 없음). 통화가 다른 다리의 손익은 합산하지 않습니다(참고용 근사 USD 만 표기).
보조 종목 참조: 다른 종목·다른 거래소의 시세를 신호로 씁니다(ctx.ref 슬롯 — 예: 바이낸스 BTC 를 보며 업비트에서 거래). 백테스트·모의·실거래 모두 지원.
여러 거래소 동시 운용: 거래소마다 실행을 따로 띄워도 됩니다 — 에이전트 하나가 여러 거래소 키를 보유하고 전부 병렬로 돌립니다(업비트 A전략 + 바이낸스 선물 B전략).
멀티 에이전트 클러스터: 스캐너 종목을 여러 에이전트에 자동 분배해 병렬 실행합니다(엘리트 플랜 + 온보딩 후 활성화).
데이터: 캔들(1분~1일)·거래량·호가·펀딩비·미결제약정(OI)/청산 + 거시 지표(달러지수·미 10년물 금리·나스닥100·금 — ctx.macro) + 실환율(USD/KRW — ctx.fx, 김프 계산은 전략 몫) + 외부 신호(웹훅). 모르는 값은 null — 0 으로 위조하지 않습니다.
주문: 시장가·지정가·분할 진입, 라이브 전용 스마트 주문(추격·트리거).
안전장치: 주문 한도(가드레일), 수수료 포함 손실 킬스위치, dry-run.
검증: 최대 10만 봉 백테스트, 종료일 고정으로 여러 구간 검증(walk-forward) + 스튜디오 틱 판단시간 예측·라이브 틱 실측 모니터(서버가 일 잘하나 실행 카드에서 확인).
아직 안 되는 것 (지원하는 척하지 않습니다):
다리별로 서로 다른 에이전트에 나눠 실행(legs 분산) — 지금은 한 에이전트가 모든 다리 키를 갖고 실행합니다. 계산-중앙/집행-엣지 구조는 개발 중입니다.
클러스터 자동 재배분 — 분배는 정적입니다. 에이전트가 이탈하면 그 종목들은 대기하며 화면에 정직하게 표시됩니다(몰래 다른 에이전트로 옮기지 않음).
스마트(작업 주문): { side, qty, type: 'smart', chase?, slices?, trigger?, hardStopMs? } — 시간에 걸쳐 집행합니다. 체이싱(호가 추격→마감 시 크로스)·분할·스톱/트레일링 트리거·강제 마감을 조합할 수 있고, 라이브·페이퍼에서 집행됩니다. 백테스트는 시장가로 근사하니 라이브 페이퍼로 검증하세요.
전체 취소: { cancel: 'all' } — 대기 지정가와 작업 주문 전부 취소(체이싱은 개별 주문 취소로 못 멈춥니다).
아래 표가 ctx 의 전부입니다(자동완성과 같은 출처에서 생성). AI 에게 전략 코드를 받으려면 AI 전략 만들기를 쓰거나, AI 문서를 통째로 붙여넣으세요.
ctx
이 표는 에디터 자동완성·AI 문서(/llms.txt)와 같은 출처(코드)에서 생성됩니다 — 여기 없는 함수는 존재하지 않습니다.
상태
ctx.candle현재 봉 { t, o, h, l, c, v } — t 는 실데이터면 실제 봉 시각(epoch ms), 합성 시세만 봉 번호. ★라이브·페이퍼도 실제 봉 시작 시각(에이전트 1.66.0+ — 그 이전 라이브는 링버퍼 인덱스(499)로 굳어 있었다: 요일·시간대 로직을 쓰면 반드시 1.66.0 이상에서 확인할 것). 시각을 모르는 경로는 null(인덱스를 시각인 척 주지 않는다)
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.macd(fast=12, slow=26, sig=9)MACD → {macd, signal, hist} | null. 구간이 모자라면 signal·hist 만 null(macd 는 준다)
ctx.atr(n=14)ATR(평균 진폭) → number | null. 변동성 기반 손절폭·포지션 크기에 쓴다. 구간이 모자라거나 라이브에서 고가·저가를 못 얻으면 null
ctx.stoch(n=14, d=3)스토캐스틱 → {k, d} | null. %K=(종가−최저)/(최고−최저)×100, %D=%K의 SMA(d). 구간이 완전 횡보면 k=50(중립). d 구간이 모자라면 d만 null
오더북
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()대기 중인 지정가 목록(읽기 전용, 행에 ex — 작업주문은 workOrders 로)
ctx.workOrders()활성 작업주문(스마트 — 체이싱·분할·트리거 대기) 목록. 백테스트는 트리거 대기분만(체이싱은 봉 해상도에 개념 없음)
스캐너(여러 종목)
ctx.sym이번 호출의 종목(예: "BTC")
ctx.ex이번 틱 종목이 속한 거래소(예: 'upbit'). legs 백테스트·라이브에선 실값, 호출부가 거래소를 안 알려준 단일 백테스트는 null
ctx.wallets()거래소(다리)별 지갑 맵 { upbit: { quote, cash, reserved? }, … } — 단일 실행도 한 다리짜리 맵(거래소를 모르면 'default' 키). 통화가 달라 합산값은 없다 — 환산은 ctx.fx 로 직접
ctx.marketType시장 종류 'spot'|'usdm' — usdm 이면 position 이 부호 수량(+롱/−숏), entryPx·liqPx·uPnl·leverage·funding 필드 추가
ctx.syms시세를 받은 종목 이름 목록
ctx.markets()전 종목 요약 [{ sym, ex, price, ch1, ch5, ch60 }] — ch 는 퍼센트(2 = +2%. change()의 소수 단위와 다름!). 봉이 모자라면 null. 단일 종목 실행에선 그 한 종목만 담긴 배열(빈 배열 아님). ex 는 legs 면 그 다리 거래소, 모르면 null
ctx.market(sym)한 종목 요약 (없으면 null)
ctx.pos(sym, ex?)그 종목 보유 수량(이번 틱 다리 기준). 2번째 인자로 다른 다리(거래소) 지정 조회 — 모르는 다리는 null(0 은 "없음"을 단정하는 거짓)
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.macro('dxy')거시 지표 { value, day, chg1d, chg7d, chg30d(%) } — 계열: dxy(달러지수)·ust10y(미국채 10년 금리)·ndx(나스닥100)·gold(금). ★전일(완결된 날) 값 — 당일 값은 마감 전 미존재 정보라 주지 않음. 데이터 없거나 14일 이상 낡으면 null. dxy 는 ICE 공식(고정 가중치 동일)을 현물 UTC 종가로 재구성한 값 — 원본 지수 호가와 스냅샷 시각·현물/선물 차이로 ±0.1~0.3 정도 다를 수 있음(추세·변화율 무영향). ust10y 는 공표 지연으로 보통 1~2영업일 늦음(구조적 — chg1d 는 마지막 두 공표일 비교). ★chg 는 **달력일 as-of**: chgNd = (현재값 − '기준일−N일 이하의 가장 최근 관측값')/그 값 — 배열의 N행 전이 아니다(주말·휴장이 있으므로 7행 전 ≠ 7일 전). 외부에서 재현할 땐 이 정의로. 데이터가 첨부한 격자는 **관측일 그대로**(공개 API 기본과 동일 — GET /api/market/macro 는 grid:'raw', ?ffill=1 은 표시용 채움)
ctx.macroSeries사용 가능한 거시 계열 이름 배열(데이터가 실제로 첨부된 것만)
외부 신호(웹훅)
ctx.signal(slot)외부 신호(TradingView 웹훅 등) 조회 { payload, at, age } — payload 는 보낸 JSON 그대로(파싱·해석 안 함), at 은 신호 시각(epoch ms), age 는 경과 초(내림). 백테스트는 현재 봉 시각 이하의 가장 최근 신호(as-of — 미래 신호는 안 보인다), 라이브·페이퍼는 60초 캐시 스냅샷. 신호가 아직 없거나 모르는 slot 이면 null(0·빈객체로 지어내지 않음 — 반드시 null 검사)
로그
ctx.log(...)디버그. 라이브는 분당 20건 서버 전송 제한 — 초과분은 VPS 로컬 파일(runstate/run-<id>.log)에 전량 보존. 백테스트는 500건 상한
ctx.warn(...)중요. 라이브에서 스로틀 없이 항상 서버 전송 + 직전 로그 맥락 동봉 — 촘촘한 검증·이상 신호는 log 대신 이걸 쓰세요
ctx.alert(msg)조건 근접 알림 — 전략이 "진입 조건에 근접했다"고 스스로 판정해 유저에게 알림을 보낸다. msg 는 문자열로 강제(200자 컷)·반환값 없음. 라이브·페이퍼는 run 당 60초 쿨다운으로 발송(60초 내 재호출은 무시 — 로그에 남음), 백테스트는 발송 없이 로그에 [알림] 으로만 기록(상한 50개, 초과는 개수만 alertsDropped)
주문 객체 키
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)