# CCS 앱 연동 API 거래소 API의 base URL: `https://16.176.130.206/ccs-tapbit`. 컨테이너 내부에는 `/ccs-tapbit` 접두사를 제외하고 전달합니다. 일반 메인 API `52.65.154.88` 및 기존 `3.26.221.228`의 백테스트 서비스와 분리합니다. HTTPS 인증서 검증 필수, redirect 금지. 앱은 사용자 입력 서버와 정확히 같은 origin에만 기기 토큰을 보냅니다. 브라우저 Origin과 query string을 거부합니다. Host는 `TAPBIT_PUBLIC_HOST`와 일치해야 합니다. 요청 본문: `Content-Type: application/json`, 기본 최대 4 KiB, DB 기능이 활성화된 `/v1/ops/*`는 64 KiB입니다. 성공은 `{data: ...}`, 오류는 `{error: {code: ...}}`입니다. 예외적으로 health는 `{ready:true,service:"ccs-tapbit-connector",canTrade:false}`입니다. 모든 응답은 `Cache-Control:no-store`입니다. 예시의 꺾쇠 값은 설명용이며 실제 키를 문서나 로그에 기록하지 마세요. ## 0.9.0 선물 API 전체 대조 첨부 `tapbit_openapi_docs_USDTPERP.html` SHA256 `f78ddfbfe3de455028c64f70f400a940d0fd20b823e5227555b4a07ba83d9313` 기준입니다. REST 20개(공개 8, 개인 조회 8, 쓰기 4), WS ticker·orderBook 2종입니다. 현물·제휴는 제외합니다. 전체 경로 대응표는 `/api-catalog.json`, 요청 스키마·개인 조회 응답 스키마는 `/openapi.json`, 화면은 `/docs/`에 있습니다. | 추가·보완 API | 내용 | | --- | --- | | POST `/v1/shared/market/candle-history` 또는 `/v1/market/candle-history` | `{symbol,period,start,end}`. period는 `1,3,5,15,30,60,120,240,360,720,D,W,M` 문자열. start/end는 UNIX 초. 9개 필드 정밀 문자열 반환. 미완료 봉 포함 가능, 전체 이력 보장 없음 | | POST `/v1/shared/market/ticker-details` 또는 `/v1/market/ticker-details` | `{symbol}`. 24시간 고가/저가/거래대금/변동률과 호가 수량, fresh 포함 | | POST `.../market/trades` | `{symbol}`. 요약에 `trades[{price,side,quantityContracts,at}]` 추가. at은 ms. 완전한 체결 스트림 아님 | | POST `/v1/exchange/read/account` | `{}`. 인증된 본인 잔고, DB 불필요 | | POST `/v1/exchange/read/positions` | `{symbol?}`. 생략 시 ALL | | POST `/v1/exchange/read/open-orders` | `{symbol}` | | POST `/v1/exchange/read/closed-orders` | `{symbol,cursor?}`. 큰 ID를 문자열로 전달 | | POST `/v1/exchange/read/order` | `{orderId}`. TP/SL 가격·유형·order_value 포함 | | POST `/v1/exchange/read/fills` | `{symbol,orderId}`. 주문별 체결·수수료 | | POST `/v1/exchange/read/funding` | `{symbol,page?,pageSize?}`. 펀딩 수량 null 허용 | | POST `/v1/exchange/read/plans` | `{symbol?,page?,pageSize?}`. 수정 시각·거래 유형 포함 | | POST `/v1/exchange/draft/order` | Swagger의 방향·유형·격리/교차·합산/분리·TP/SL 필드 검증. 전송 안 함 | | POST `/v1/exchange/draft/cancel` | `{orderId}`. 전송 안 함 | | POST `/v1/exchange/draft/plan` | TP/SL 생성 또는 planId가 있는 수정 초안. 전송 안 함 | | POST `/v1/exchange/draft/cancel-plan` | `{planId}`. 전송 안 함 | | POST `/v1/exchange/ws/draft` | `{op,channel,symbol,depth?}`. ticker의 all, 호가 생략/5/10/50/100/200 메시지 생성. 구독 전송 안 함 | `/v1/exchange/*`는 DeviceToken 전용입니다. 본인 조회 응답은 `persisted:false`이며 메인 DB 원장 적재를 대신하지 않습니다. 조회 중 키 변경·삭제 시 409로 폐기합니다. 일반 메인용 ServiceToken은 개인 조회에 사용할 수 없습니다. WS 실구독은 기존 단일 연결의 BTC/ETH ticker 및 50단계 호가이며, 다른 심볼·깊이 메시지의 오프라인 검증을 실수신 성공으로 표시하지 않습니다. 점검 페이지는 공개 13항목, 모의 9항목, 개인 조회 8항목을 제공합니다. 공개/모의 결과는 60초 캐시합니다. 점검 실행 한도는 그룹별 공용 사용자 키당 20회/분, 일반 시세 API는 호출자별 12회/분입니다. 선택 기간은 로컬 상한 500주기(M은28일 기준), 페이지 크기 상한은50입니다. 거래소 상한으로 단정한 값은 아닙니다. REST 요청 제한과 매매 규칙을 구별합니다. 실제 주문·취소를 테스트로 전송하지 않으며, timeout/504 후 쓰기 자동 재전송은 없습니다. 아래 버전별 설명은 구현 이력입니다. 동일 항목은 이 절 및 최신 Swagger가 우선합니다. | 메서드·경로 | 인증 | 요청 / 결과 | | --- | --- | --- | | GET `/health/ready` | 없음 | 프로세스 상태 | | POST `/v1/pair` | 일회용 코드 | `{code:"<64자리 코드>"}` → `{deviceToken:"…",expiresAt:"ISO8601"}` | | GET `/v1/connection` | 기기 Bearer | 저장 상태 | | PUT `/v1/connection` | 기기 Bearer | `{uid:"숫자 문자열",apiKey:"…",secret:"…",version:0}` → 저장 상태 | | POST `/v1/connection/check` | 기기 Bearer | `{}` → 저장 상태 + `readVerifiedAt` | | DELETE `/v1/connection` | 기기 Bearer | `{version:1}` → 삭제 후 저장 상태 | | DELETE `/v1/device` | 기기 Bearer | 본문 없음 → `{revoked:true}` | `Authorization: Bearer `은 Tapbit API Key가 아니라 서버가 발급한 기기 인증입니다. 소유자는 토큰으로 결정하며 요청에서 owner/memberId를 받지 않습니다. 저장 상태 필드: ```json { "service": "ccs-tapbit-connector", "version": 0, "configured": false, "uid": null, "savedAt": null, "keyStored": false, "canTrade": false, "uidVerified": false, "mode": "read_only" } ``` - Key·Secret은 저장/조회 응답에 포함하지 않습니다. `version`은 성공한 저장/삭제마다 증가합니다. - 같은 owner의 다른 기기가 먼저 저장하면 409입니다. 최신 상태 확인 후 사용자가 다시 제출해야 하며 자동 덮어쓰지 않습니다. - 다른 owner에 같은 UID 또는 API Key를 등록할 수 없습니다. UID 변경은 기존 연결 삭제 후 가능합니다. - `/connection/check`는 계좌 GET으로 인증을 검사하고 수치 대신 조회 시각만 반환합니다. 아래 인증된 운영 조회·진단도 해당 GET을 호출할 수 있습니다. - 알 수 없는 주문·취소·출금 경로는 인증 후 423 `LIVE_EXECUTION_DISABLED`로 거부됩니다. 거래소 범용 proxy가 아닙니다. 주요 오류: 400 `INVALID_CONNECTION`, 401 `PAIRING_CODE_INVALID`/`DEVICE_AUTH_REQUIRED`, 403 `NATIVE_CLIENT_REQUIRED`, 404 `CONNECTION_NOT_CONFIGURED`, 409 `CONNECTION_CHANGED`/`UID_ALREADY_BOUND`/`REMOVE_OLD_CONNECTION_FIRST`, 429 `RATE_LIMITED`, 503 `VAULT_BUSY`/`CONNECTOR_REQUEST_FAILED`/거래소 조회 오류. 거래소 원문 오류·본문·헤더·키는 반환하지 않습니다. 429/503은 `Retry-After:60`을 제공합니다. 현재 내부 제한(거래소 매매 한도와 별개): 전체 HTTP 300회/분, 페어링 전체 10회/분, 소유자 60회/분, 소유자별 저장 5회/분·조회 검사 3회/분. 재시작 시 HTTP 버킷은 초기화됩니다. 영속적인 UID 주문 집계가 아니며, 이를 근거로 실거래 규칙 준수를 주장하지 않습니다. 상세 클라이언트 구현은 `packages/tapbit/connection.js`, 자동 검증은 `services/tests/integration/tapbit-native.test.ts`입니다. ## 0.6.0 구현 범위와 검증 상태 — 2026-10-13 이 버전은 실시간 거래소 연계 서버의 **소스·오프라인 검증 단계**입니다. 백테스트를 실거래로 바꿔 부르는 것이 아닙니다. 실제 거래소 WebSocket 이벤트를 판단하는 worker에 실행 수명주기 runtime을 연결했습니다. runtime → 제어기 → 서명 전송 클래스가 소스상 연결되지만, runtime과 제어기/전송의 이중 출시 잠금으로 **운영 POST는 실행되지 않습니다**. 운영 HTTP 요청·환경 변수로 이 잠금을 해제할 수 없습니다. 잠금 해제 함수를 주입하는 경로는 모의 거래소 테스트용입니다. 전체 백테스트 전략의 실거래 이식이 완료된 버전이 아닙니다. `canTrade:false`는 응답 누락이나 UI 오류가 아니라 의도된 출시 잠금입니다. 구현: 해당 소스가 존재하고 fixture 검증 가능. 부분: 일부만 연결. 미검증: 실계좌/거래소 운영 증거 없음. | 기능 | 소스 상태 | 거래소 연결·남은 조건 | | --- | --- | --- | | 키 암호화·기기 인증·소유권 | 구현 | 기존 HTTPS 경로 사용, UID 실제 일치·권한 조회는 미검증 | | 서버 시각·계약 수량·호가·마크 가격 | 구현 | 공식 공개 GET, 실패·오래된 응답 차단 | | REST 호가·전체 시세 목록·현재 펀딩비율 | 구현·거래소 미검증 | 문서 기반 응답 검증, 공개 조회 API·진단, 아래 0.6.0 상세 참조 | | WebSocket 호가 | 구현·거래소 미검증 | BTC/ETH 50단계, insert/update 병합, 오래된 데이터·버전 불확실 시 무효화. 전략 입력 자동 변경 없음 | | 3/5/15분 완료 봉 | 구현 | 공개 GET, 진행 중 봉 제외·중복 충돌·누락 검사 | | 실시간 거래소 시세 이벤트 | 구현 | 공식 WS ticker, BTC/ETH, ping/pong, 수신 신선도·순서·중복·재접속 검사. 1초 봉 생성/대기 아님 | | 연속 관찰 worker | 구현 | PostgreSQL 단일 실행 잠금, 대기열 상한, 재접속 세대 검사, DB 판단 기록. 가상 체결도 만들지 않음 | | BB·상대 밴드폭·RSI·ADX·EMA·MACD·VWAP·ATR | 구현 | 3/5/15분 완료 봉 지표는 캐시하며, 진입·종료 판단은 각 실시간 시세에서 수행 | | 밴드 이탈/반등·접근 범위·과도한 이탈 금지 | 구현 | `band-reversion-v1` 판단 함수, 체결을 가정하지 않음 | | 고정 USDT·시작 자본 비율·현재 자산 비율 | 구현 | 계산·예약 테스트. 사용 이력·포지션·미체결 없는 계좌만 실제 잔고로 초기 대사 | | BTC/ETH 공통 자금·증거금 예약 | 구현 | UID 단위 PostgreSQL 행 잠금, 심볼별 자본을 복제하지 않음 | | 차수별 물타기·금액·반등·최소 손실 999% | 구현 | 실제 완료 체결 후 차수 증가, 부분 취소 시 대사 필요 | | TP·SL·물타기 전 조기 SL | 구현 | 판단 함수·실제 체결 수량 기준 초안·요청 전 영속 기록·목록 재조회. 실계좌 검수 필요 | | 물타기 종료 후 SL·무체결 시간 종료 | 구현 | 마지막 실제 체결 기준, 시간 도달 시 수익 여부와 무관하게 종료 의도 | | KST 수면·마감 정리·휴식·손절 후 중지 | 구현 | 시간/판단 테스트. 거래소 실제 정리 주문은 잠금 상태 | | 일일 손실·MDD·스프레드·청산가 접근 제한 | 구현 | 종료 의도 우선. 청산 방지나 자본 보전 보장 아님 | | 신규/추가/종료 주문 서명·전송 | 구현·잠금 | runtime·제어기·영속 dispatcher 연결. UID 전체 네트워크 사이클 잠금, 신선한 시세 확인. 운영 주문 미검증 | | 취소→대사→종료→잔여 위험 확인 | 구현·잠금 | 접수와 체결/평탄화 완료 분리. 불일치 포지션으로 종료 수량을 추측하지 않음. 보호 주문 발동 후 연결은 아래 별도 미완료 | | TP/SL 수정·수량 재설정·OCO | 부분 | 기존 plan_id 수정·부분 체결 수량 반영·단일 후보 확인 구현. 실제 OCO/반대 보호 취소와 트리거 자식 주문 추적은 미완료 | | 주문 접수·부분 체결·평단·차수 분리 | 구현 | `order_id` 접수 시 잔고/포지션 변경 없음. 체결 원장만 반영 | | 수수료·거래량·순손익 원장 | 구현 | 체결 수량×승수×체결가, 실제 fill fee; 진입·종료 모두 거래량 집계 | | 펀딩·입출금·수동 거래 자동 회계 | 부분 | 문서의 펀딩 페이지 수집·저장·중복/충돌 검사를 구현. 부호/고유 ID 확정 및 이체 원장 없는 상태에서 잔고 차이를 자동 보정하지 않음 | | 중복 체결·중복 명령·동시 주문·재시작 | 구현 | 고유 키·DB 트랜잭션·CAS·소유권 검증 | | 504/timeout 결과 불명 복구 | 수동 보조 구현 | 정확한 주문 ID 입력→계좌 인증 GET 대조→2단계 확인→실제 체결 대사·감사 로그. clientOrderId 기반 자동 복구는 미지원 | | UID 전체 수동/API 주문 이력과 운용 규칙 | 부분 | 심볼별 order cursor 페이지 저장·중복 관찰 방지. 별도 조회 원장과 실행 원장이 UID 전체 범위를 통합·인증했다는 뜻은 아님 | | 백테스트 전체 전략/P4/연구 모델 일치 | 미완료 | 별도 연구 bridge는 실시간 전략 이식 완료의 근거가 아님 | | 메인 API 봇 등록·명령·상태 보고 | 구현·운영 미검증 | 30초 agent, 명령 중복 방지, 영속 outbox·ACK 유실/재시작 재전송, 계좌/체결 보고 저장. 노드 보고를 거래소 원장으로 자동 승격하지 않음 | | 기능별 앱 진단 | 구현 | 27항목, 실제 GET/스트림 상태/모의 POST/차단 사유 분리, 실제 주문 없음 | | 데스크톱 실시간 관찰 설정·복구 | 구현 | 전체 조건, 차수/휴식, 판단 시점 지표. 추가 체크리스트·내역 페이지 조회/저장·2단계 주문 연결. 앱 재빌드 필요 | | EC2 신규 배포·외부 PostgreSQL·실계좌 검수 | 미실시 | 운영 DB 접속 가능하다는 사용자 확인과 별개로 이번 소스의 운영 마이그레이션·배포는 수행하지 않음 | ### 신호와 체결의 경계 `실시간 WS 시세 + 완료 봉 지표 → 진입/추가/종료 의도 → DB 예약 → submitting 영속화 → 서명 POST → 주문 ID → 체결 조회 → DB 체결 원장 → 평단·마진·차수·손익` 주문 단계는 전송 클래스를 주입한 모의 테스트로 검증합니다. 운영 서버는 의도 기록까지 연속 실행하고 runtime 출시 잠금에서 멈춥니다. POST/체결을 자동 생성하지 않습니다. `prepared`에 대해서만 한 번 제출할 수 있습니다. `submitting` 이후 통신/프로세스 장애를 단순 실패로 바꾸어 재전송하지 않습니다. 응답 불명은 `unknown` + `reconcile_required`가 됩니다. DB commit 실패 후 거래소 접수 가능성도 같은 취급입니다. 부분 물타기 취소는 단계 완료로 승격하지 않습니다. 반대 포지션·초과 체결·기존 외부 포지션 불일치를 자동 수용하지 않습니다. 종료 의도에는 신규 진입 대기시간을 적용하지 않습니다. 이미 전송 중인 추가 주문이 있으면 취소/체결 대사가 필요하며, 제어기는 취소 확인·체결 대사 후 종료 초안을 준비하지만, reduce-only와 트리거 자식 주문 조정 규격이 불명확하므로 운영 활성화는 차단됩니다. ## 기능별 진단 API — DB 없이도 사용 가능 | 요청 | 동작 | | --- | --- | | GET `/v1/diagnostics/features` | 27개 진단 목록, `canTrade:false`, `realOrdersSent:0` | | POST `/v1/diagnostics/run` | `{id, symbol:"BTC" 또는 "ETH", orderId?:"숫자 문자열"}` | 소유자별 12회/분. `order`와 `fills`에는 해당 계좌의 주문 ID가 필요합니다. 앱에서는 **Tapbit 서버 연결 → 기능별 연계 진단 → 진단 목록 열기 → 검사** 순서입니다. 데스크톱의 **핵심 7항목 점검**은 시각·계약 사양과 5개 모의 테스트를 순서대로 실행합니다. 계좌 조회는 별도 버튼이며 자동 실행하지 않습니다. 서버/키 버전/심볼/주문 ID 변경 시 화면 결과를 초기화합니다. 실패한 재검사에는 예전 성공 배지를 남기지 않습니다. 원문 응답·계좌 수치·키·오류 본문은 진단 결과에 포함하지 않습니다. | id | 점검 | | --- | --- | | `time`, `instruments`, `ticker` | 시계 오차·계약 단위·신선한 시세 | | `candles_3`, `candles_5`, `candles_15` | 완료 봉 60개 이상·연속성·신선도 | | `recentTrades` | 최근 체결 REST 응답 검사. 연속 스트림·전체 체결 원장과는 별개 | | `stream` | 이미 실행 중인 WS worker의 수신 상태 확인. 진단 버튼이 별도 연결을 만들지 않음 | | `account`, `positions`, `openOrders`, `closedOrders` | 실제 계좌·포지션·주문 조회 | | `order`, `fills`, `funding`, `plans` | 주문 상세·체결 비용·펀딩·예약 TP/SL 조회 | | `mock_order`, `mock_cancel`, `mock_protection` | 가짜 키와 가짜 네트워크로 POST 계약·서명 검증 | | `mock_lifecycle` | 부분 체결·물타기 차수·종료 대기시간 예외·불명 응답 재전송 차단 | | `mock_strategy` | 신호/체결 분리·건강하지 않은 실시간 피드의 진입 차단·KST 마감 판단 | | `uid`, `live` | 미충족 실거래 전환 조건 표시; 활성화 버튼 아님 | 결과 예: ```json {"data":{"id":"mock_order","symbol":"BTC","status":"mock_pass","code":"NO_EXCHANGE_ORDER_SENT","checks":["문서 경로·요청 형식","서명된 POST 모의 전송","접수와 체결/취소 확인 분리"],"checkedAt":"2026-10-13T00:00:00.000Z","durationMs":3,"canTrade":false,"realOrdersSent":0}} ``` `exchange_pass`는 GET 형식 또는 현재 WS 수신 상태 검사 성공, `mock_pass`는 모의 테스트 성공입니다. 둘 다 매매 권한·전략 수익성 증거가 아닙니다. 빈 조회는 `VALID_RESPONSE_EMPTY_DATA`: 연결 확인이지 체결/보호 주문 검증 완료가 아닙니다. `blocked`는 알려진 출시 조건 미충족, `failed`는 검사 실패입니다. 진단 실행 자체가 처리되면 HTTP 200 안에 이 상태를 반환합니다. 인증/요청 구조/호출 제한 오류는 기존 HTTP 오류 형식을 따릅니다. ## 실시간 전략 관리 API — 외부 PostgreSQL 필요 DB 설정이 없으면 `/v1/ops/*`는 503 `OPERATIONS_DATABASE_REQUIRED`입니다. 서버 시작 시 DB를 자동 생성/마이그레이션하지 않습니다. | 메서드·경로 | 입력 / 결과 | | --- | --- | | GET `/v1/ops/live/capabilities` | 엔진·기능·미지원·차단 사유와 전체 기본 `config` | | GET `/v1/ops/live/checklist` | 항목별 `source`와 `acceptance`, 남은 조건. 승인 상태를 수정하는 API는 없음 | | PUT `/v1/ops/live/config` | `{config:전체설정,revision:0}`. 이후 최신 revision 필수 | | GET `/v1/ops/live/state` | `revision,config,state,updated_at,canTrade,blockers` | | GET `/v1/ops/live/summary` | 앱용 설정·상태·실제 잔고 초기화 여부·포지션·최근 경고·복구 대상 주문 최대 50개. 전체 주문 원장은 제외 | | GET `/v1/ops/live/runtime` | 관찰 worker·수신 상태·대기열·판단 횟수·실주문 잠금 | | GET `/v1/ops/live/decisions` | 소유자 UID의 최근 20개 판단·시세·당시 지표·제출하지 않았다는 표시 | | POST `/v1/ops/live/command` | `{action,requestKey:UUID}`. 허용: `start_shadow`, `pause`, `stop`, `emergency_stop` | | POST `/v1/ops/live/preview` | `{symbol:"BTC"}`. 실제 완료 봉·ticker에서 1회 판단, 상태/자산/주문 변경 없음 | | POST `/v1/ops/live/reconcile` | `{}`. 명확히 연결된 주문 ID의 체결/포지션/잔고 대사 | | GET `/v1/ops/live/fills` | 소유자 UID에 기록된 최근 200개 체결 | | POST `/v1/ops/live/history` | `{symbol:"BTC",kind:"orders",cursor?:"정수문자열"}` 또는 `{symbol:"BTC",kind:"funding",page?:1}`. 다음 cursor/page 반환, 소유자별 4회/분 | | GET `/v1/ops/live/history` | 저장된 관찰 최근 30개, `accounting_applied:false` | | POST `/v1/ops/live/recovery` | `{localOrderId:UUID,exchangeOrderId:"정수문자열",confirmation?:"미리보기 해시"}`. 소유자별 2회/분 | `TAPBIT_REALTIME_SHADOW=true`와 DB 연결로 서버를 시작하면 관찰 worker가 동작합니다. `start_shadow`는 저장된 설정을 이 worker의 관찰 대상으로 등록합니다. worker를 설정하지 않았으면 명령만 저장되고 관찰은 실행되지 않습니다. `runtime.running`과 WS 수신 상태를 모두 확인하세요. `stop`/`emergency_stop`은 이 버전에서 **거래소 주문 취소·포지션 종료를 하지 않습니다**. 응답은 `positionsClosed:false`입니다. 열린 포지션/미확인 주문이 있으면 `reconcile_required`로 두고 거래소에서 직접 확인해야 합니다. 연결된 주문 ID 없는 불명 응답을 가격·시간 유사성으로 자동 연결하지 않습니다. 수동 미리보기는 `source:tapbit_snapshot,sourceMode:rest_preview_not_stream,persisted:false,submitted:false`입니다. REST 스냅샷은 연속 시세 수신으로 간주하지 않아 신규 진입이 차단됩니다. 기존 포지션이면 보호 종료 *의도*만 나올 수 있습니다. 주문 입력·체결 주입·`verified` 플래그 수정·실거래 활성화 HTTP 경로는 없습니다. ### 결과 불명 복구·펀딩 내역의 정확한 의미 데스크톱 **실시간 전략 관찰 → 구현 체크리스트·과거 내역·주문 복구**에서 실행합니다. 복구의 첫 요청은 조회만 합니다. 심볼·방향·주문 종류·격리 마진·레버리지·수량·가격·생성 시각을 대조하고 확인 해시를 돌려줍니다. 두 번째 요청에 해당 해시를 넣어야 로컬 주문에 ID를 연결합니다. 중간에 로컬 주문이 바뀌면 거부합니다. 연결 후에는 명확한 ID의 체결만 반영하며 `reconcile_required`, `verified.history=false`와 감사 기록을 유지합니다. 주문 ID를 가격/시간 유사성으로 자동 선택하거나 알 수 없는 주문을 다시 전송하지 않습니다. 주문·펀딩 수집은 문서에 있는 GET으로만 수행합니다. cursor는 BigInt로 비교해 큰 order ID를 손실 없이 보존합니다. 펀딩은 현재 문서에 고유 이벤트 ID가 없어 심볼·방향·시각 조합을 임시 관찰 키로 씁니다. 같은 키의 금액 변화나 한 페이지 중복은 충돌로 중단합니다. 음수 fee 예시는 존재하지만 회계 부호의 명시적 계약과 이체 원장이 없어, 이를 자동 잔고 조정이나 완전한 순손익으로 사용하지 않습니다. `nextPage:null`/`nextCursor:null`은 해당 조회의 끝일 뿐 UID 전체 거래/계좌의 완전성을 보증하지 않습니다. 취소·수정 뒤 조회 및 대사는 2초 GET 캐시와 전송 전 inflight 응답을 재사용하지 않습니다. UID별 PostgreSQL session lease로 네트워크 요청을 포함한 실행/대사/복구 사이클을 직렬화합니다. 키 버전 변경·UID 변경·DB lease 소실 시 처리 중단하며 보호 주문을 취소하기 전에도 실제 WS 시세 신선도를 검사합니다. ### 설정 계약 모든 필드를 보내며, 알 수 없는 필드는 거부합니다. 기준은 `services/tapbit-live/model.ts`의 `DEFAULT_STRATEGY`/`validateStrategy`입니다. 화면에서는 같은 설정 목록을 사용하고 `enabled`/각 boolean으로 사용 여부를 선택할 수 있는 계약입니다. 데스크톱 **Tapbit 서버 연결 → 실시간 전략 관찰 → 설정·수신 상태 읽기 → 전체 조건 설정**에서 편집할 수 있습니다. 모바일 공통 SDK/네이티브 허용 경로는 연결됐지만, 모바일 전체 설정 폼은 아직 제공하지 않습니다. | 그룹 | 주요 필드와 의미 | | --- | --- | | 공통 | `symbols:[BTC,ETH]`, `frame:3/5/15`, `name`, `leverage:1~100`(주문 시 거래소 상한 별도 적용) | | 자금 | `capitalMode:fixed/initial/compound`, `fixedMargin:USDT`, `initialCapital:USDT`, `allocationPct:%` | | 진입 | `entry.enabled`, `mode:breakout/rebound`, `bufferPct`, `nearPct`, `reboundPct`, `maxDistancePct`, `tiered`, `tiers:[5개 비중]` | | 밴드 | `lookback:20~40`, `narrowPct/widePct:과거 평균폭 대비 %`, `narrowTpRoi/wideTpRoi:마진 ROI %` | | 필터 | `rsi/longRsiMax/shortRsiMin`, `adx/adxMax`, `ema`, `vwap`, `macd` — 켠 지표가 없거나 NaN이면 진입 금지 | | 물타기 | `dca.enabled`, `steps` 최대 10개. 각 `minLossRoiPct:0.1~999`, `entryMode:immediate/rebound`, `reboundPct`, `amountMode:fixed_usdt/initial_multiple`, `amount` | | 종료 | `tp`, `sl/slRoi/slAfterAllAdds`, `beforeFirst/beforeFirstRoi`, `beforeSecond/beforeSecondRoi`, `idle/idleAfterAdds/idleHours`, `maxHold/maxHoldMinutes`, `breakEven/breakEvenStartRoi`, `atrStop/atrMultiple` | | 시간 | `schedule.sleep:{enabled,start,end}`, `windDownMinutes`, `rests:[{enabled,start,end}]`, `stopPause/stopPauseHours` — 모두 KST | | 공통 안전 | `maxMarginPct`, `dailyLossPct`, `maxDrawdownPct`, `maxSpreadPct`, `liquidationBufferPct`, `feeEstimatePct` — 안전 한도는 항상 검사 | - 금액·주문량·거래소 ID는 회계/저장 응답에서 십진 문자열입니다. ID를 JavaScript Number로 변환하지 않습니다. - 수수료 `0.06`은 주문 명목금액의 편도 **0.06%**. 50배 주문에서는 진입 마진 대비 약 **3%**에 해당합니다. - 실제 회계에는 조회한 fill fee를 사용합니다. 예상 종료 비용에만 `feeEstimatePct`를 사용하며 실체결 슬리피지를 0으로 덮지 않습니다. - 거래량(USDT)은 진입·추가·종료의 `contracts × multiplier × fillPrice` 합입니다. 입금액·마진·기초자산 수량과 다릅니다. - 고정 마진이면 구간 비중은 금액을 바꾸지 않습니다. initial은 설정 기준 자본, compound는 현재 평가자산에 비중을 적용합니다. - 구간은 안쪽~경계, 밖 0초과~0.2, 0.2초과~0.4, 0.4초과~0.6, 0.6초과입니다. 과도 이탈 차단은 별도 적용됩니다. - `breakout`은 상단 이탈 SHORT / 하단 이탈 LONG의 역추세 진입이며 추세 추종 매수가 아닙니다. - `rebound`는 LONG 저점 대비 상승, SHORT 고점 대비 하락의 **가격 비율**이며 초 단위 지연이 아닙니다. - 물타기 `200`은 현재 포지션 마진 ROI ≤ -200%에서 감시합니다. 상한 손실 구간은 없습니다. 슬리피지·청산·가용 자금 때문에 체결을 보장하지 않습니다. - 격리 마진에서는 -100%보다 전에 청산될 수 있습니다. 999 입력 허용을 999%까지 실제 보유 가능하다는 뜻으로 해석하지 않습니다. - 익절/손절 ROI는 현재 남은 체결 포지션의 마진 기준입니다. 계좌의 일일 +2%와 다른 단위입니다. - 물타기를 모두 하기 전 SL 보류는 실제로 위험합니다. 별도 청산가 접근·계좌 손실 제한은 물타기 차수와 무관하게 먼저 적용됩니다. - 수면 마감은 정리와 신규/물타기 금지, 단순 휴식 구간은 신규 위험만 금지합니다. 손절·TP·보호 종료를 휴식 때문에 늦추지 않습니다. - `initialCapital`로 만든 로컬 상태는 거래소 잔고의 증거가 아닙니다. `balanceInitializedAt`이 있어야 초기 실제 잔고를 반영한 상태입니다. 미확인 펀딩/이체 차이는 여전히 격리합니다. ### 실시간 데이터·장애 처리 - 공식 `wss://ws-openapi.tapbit.com/stream/ws`의 `usdt/ticker.BTC-SWAP`, `usdt/ticker.ETH-SWAP`을 한 연결로 구독합니다. - 거래소 시각과 수신 시각 모두 5초 이내여야 합니다. 시각이 역행하거나 완전히 같은 시세 이벤트는 무시합니다. 같은 밀리초의 다른 가격은 별도 이벤트입니다. - ping/pong과 시세 수신을 구분합니다. 최초 시세 10초 초과 또는 시세/heartbeat 15초 단절이면 재접속합니다. 재접속 간격은 60~300초이며 무한 즉시 재시도하지 않습니다. - 연결 세대가 바뀌면 반등 후보·물타기 저점/고점을 초기화합니다. 이전 연결의 대기 이벤트는 사용하지 않습니다. - 3/5/15분 완료 봉으로 지표를 계산하고, 새 완료 봉에서 캐시를 갱신합니다. 진행 중 봉을 완료 봉으로 사용하지 않습니다. - 시간 종료는 신선한 시세가 있을 때 1초 타이머로도 검사합니다. 이 타이머는 신규 진입/물타기를 만들지 않습니다. - PostgreSQL session advisory lock으로 한 DB당 관찰 worker를 하나만 허용합니다. DB 잠금 연결 상실/대기열 1,000건 초과 시 중지합니다. - 공유 계좌 다른 심볼의 시세가 오래되면 신규 위험을 막습니다. 신선한 심볼의 손절·긴급 종료 의도는 계속 검사합니다. - 현재 50개 활성 계좌까지 허용하는 개발용 worker입니다. 초과하면 일부 계좌를 조용히 누락하지 않고 worker를 중지합니다. 운영 용량·DB 지연·장애 복구의 부하 검증은 별도입니다. - 이 피드는 ticker 이벤트이지 모든 개별 거래 체결의 무손실 스트림은 아닙니다. private WS는 아직 문서가 없어 연결하지 않습니다. ## 메인 API와 봇 서버 통신 메인 API는 `52.65.154.88`, PostgreSQL은 사설 `172.31.25.188`(공인 `3.26.30.33`)에 둡니다. DB 비밀번호나 거래소 키를 봇 명령·heartbeat에 싣지 않습니다. DB 5432를 사용자 프로그램에 공개하지 않습니다. 아래는 관리 통신 계약입니다. 분산된 실거래 엔진의 자동 설치·회원 웹 인증은 이 구현에 포함되지 않습니다. | 메서드·경로 | 인증 / 입력·결과 | | --- | --- | | GET `/v1/ops/bots` | 기기 Bearer / 자기 봇 목록·마지막 보고. 토큰은 조회되지 않음 | | POST `/v1/ops/bots/register` | 기기 Bearer / `{name}` → `id,token,expiresInDays:30`. 등록한 UID에 활성 봇 하나 | | POST `/v1/ops/bots/command` | 기기 Bearer / `{botId,action,requestKey:UUID}` → pending 명령 | | POST `/v1/ops/bots/revoke` | 기기 Bearer / `{botId}` → 토큰·대기 명령 회수. 포지션 종료 아님 | | POST `/v1/ops/bots/events` | 기기 Bearer / `{botId}` → 자기 봇 보고 최근 50개, `exchange_verified:false` | | POST `/v1/bot-agent/context` | 봇 Bearer / `{}` → 토큰에 결합된 UID·botId. 로컬 UID와 비교 | | POST `/v1/bot-agent/poll` | 봇 Bearer / `{}` → 대기 명령 최대 20개, stop 우선 | | POST `/v1/bot-agent/heartbeat` | 봇 Bearer / `{sequence,state,marketState,code}`. sequence는 재시작 후에도 증가시킬 것 | | POST `/v1/bot-agent/ack` | 봇 Bearer / `{id,status:"reported" 또는 "failed",code}` | | POST `/v1/bot-agent/events` | 봇 Bearer / `{eventKey:UUID,kind:"account_snapshot" 또는 "fill_report",at:epochMs,data:객체}`. 키/비밀 등 여분 필드 금지 | 허용 명령은 `start_shadow`, `pause`, `stop`, `emergency_stop`, `sync`뿐입니다. 실주문 활성 명령은 없습니다. 동일 requestKey에 다른 명령은 409, 오래된 heartbeat는 409입니다. 명령 1시간 만료는 실행 완료가 아닙니다. ACK는 봇의 보고일 뿐 거래소 체결 검증이 아니므로 `exchangeVerified:false`입니다. `agent-runtime.ts`가 `agent-client.ts`의 명령을 받아 repository의 영속 requestKey로 중복 방지합니다. 30초마다 최대 4개 명령·2개 보고를 처리합니다. 토큰 설정은 소유자 전용 파일이며 HTTPS 리다이렉트는 금지합니다. UID/연결 버전이 바뀌면 명령·보고 처리를 중단합니다. `account_snapshot.data`: `revision`(정수), `status`, `balance/equity/fees/realised/turnover`(십진 문자열). `fill_report.data`: `tradeId/orderId`(정수 문자열), `symbol`, `direction`, `contracts`(양의 정수 문자열), `price/fee`(십진 문자열), `at`(epochMs). 중앙 저장은 botId+eventKey로 중복 방지하고 내용이 달라지면 409입니다. 로컬 outbox는 ACK 후에만 완료 처리하고 재시작 후 미완료 메시지를 재전송합니다. 노드 보고는 실제 거래소 응답 검증과 분리된 `bot_events`에 저장합니다. 보고된 잔고나 체결을 중앙 거래소 원장에 자동 적용하지 않습니다. 봇 서버에도 현재 버전은 전용 PostgreSQL 접근이 필요합니다. 사용자별 봇에 메인 DB 계정을 공유하지 마세요. 웹 회원 인증, 무DB 원격 봇, 중앙/봇 분산 실주문 운영 검수까지 완성된 시스템은 아닙니다. 구성 방법은 README의 봇 서버 역할 절을 참고하세요. ### 영속성과 저장 규칙 `ccs_tapbit.execution_accounts`: UID PK, owner UNIQUE, config와 execution state, 단조 revision. `execution_commands`: owner+request UUID 고유, 동일 키 다른 action 거부. 중복 응답의 state는 *현재* 상태입니다. `execution_fills`: UID+trade_id 고유, 입력 fingerprint 비교. 같은 ID의 다른 체결 내용은 충돌입니다. `OperationsStore.transaction`은 10초 statement timeout/3초 lock timeout을 적용하며 체결 입력·상태 반영을 함께 commit합니다. config 수정은 stopped/포지션 없음/진행 주문 없음에서만 가능합니다. 이미 거래 이력이 생긴 초기 자본은 재작성하지 않습니다. 동일 키의 재전송은 거래소에서 보장되는 clientOrderId 멱등성이 아닙니다. 서버측 제출 방지와 결과 불명 격리의 조합입니다. 이 원장은 계좌에 존재하는 모든 수동/API 키 주문을 알아서 발견했다는 뜻이 아닙니다. `recovery_audit`, `history_observations`는 수동 복구·GET 관찰 증거이며, `bot_events`, `agent_outbox`, `agent_counters`는 관리 보고·재전송·단조 heartbeat를 보존합니다. 이 릴리스는 기존 테이블 자료를 삭제하지 않습니다. ### 수령 HTML 재점검 결과 **포함:** 주문/취소/체결 GET·POST, 예약 TP/SL 생성·수정·취소·목록, 펀딩 이력 GET, 공개 ticker/orderbook WS. **찾지 못함:** 비공개 주문·체결 WS 인증/채널/복구 규격, TP/SL 발동으로 생성된 일반 주문 ID 연결, clientOrderId 멱등성·명시적 reduce-only 보장, 입출금/이체 원장, API Key의 UID·권한 조회. 펀딩 API 자체가 없다고 설명해서는 안 됩니다. 존재하는 API의 수집은 구현했으며, 불명확한 회계 의미와 누락된 다른 원장을 별도로 표시합니다. ## 기존 운영 조회·저장 API | 경로 | 의미 | | --- | --- | | GET `/v1/ops/capabilities` | DB/실거래/연구 지원 여부 | | POST `/v1/ops/account/account` | 잔고, `{}` | | POST `/v1/ops/account/positions` | `{symbol:"ALL"}` 또는 BTC/ETH | | POST `/v1/ops/account/open-orders`, `/closed-orders` | `{symbol,cursor?}` — cursor는 closed-orders만 | | POST `/v1/ops/account/order`, `/fills` | `{orderId}` / `{symbol,orderId}` | | POST `/v1/ops/account/funding`, `/plans` | `{symbol,page?,pageSize?}` | | POST `/v1/ops/sync`, GET `/v1/ops/snapshot` | 인증된 계좌 snapshot 생성/조회 | | GET/POST `/v1/ops/sync-settings` | `{enabled,intervalSeconds:30~3600}`, 기본 비활성 | | GET `/v1/ops/policy`, `/ledger` | UID 관찰 원장과 차단 사유; `completeHistory:false` | | POST `/v1/ops/intents` | 요청 초안 저장만. `submitted:false,status:blocked` | `/v1/ops/research/*`, `/presets`, `/jobs`, `/trash`는 기존 역사 데이터 연구 작업입니다. 이를 실시간 자동매매 시작·중지 API로 사용하지 않습니다. 해당 작업은 `TAPBIT_RESEARCH_ROOT`를 명시적으로 준비해야 합니다. ## 0.6.0 추가 공개 API — 추가 문서 없이 구현한 범위 근거: 수령 HTML SHA-256 `f78ddfbfe3de455028c64f70f400a940d0fd20b823e5227555b4a07ba83d9313`. 아래는 **소스 구현과 fixture 검증** 상태이며 실서버 연계 성공 확인과는 다릅니다. 기존 주문·비공개 계좌 API와 분리된 조회 전용이며 `canTrade:false`, `realOrdersSent:0`을 반환합니다. | 앱/서버 요청 (모두 POST) | JSON body | Tapbit 호출/동작 | | --- | --- | --- | | `/v1/market/depth` | `{symbol:"BTC",depth:10}` | GET `/api/usdt/instruments/depth?instrument_id=BTC&depth=10` | | `/v1/market/tickers` | `{offset:0,limit:50}` | GET `/api/usdt/instruments/ticker_list`, 로컬 페이지 분할 | | `/v1/market/funding-rate` | `{symbol:"ETH"}` | GET `/api/usdt/instruments/funding_rate?instrument_id=ETH` | | `/v1/market/orderbook` | `{symbol:"BTC"}` | 기존 실시간 워커의 최신 호가 복사본만 반환, 새 연결 없음 | 공통: HTTPS `/ccs-tapbit` 프록시 아래, 기기 Bearer 인증, 브라우저 Origin 차단, 쿼리스트링 금지, 알 수 없는 body 필드 거부. 소유자당 공개 조회 12회/분, 기존 전체 요청 한도도 적용합니다. Tapbit Key/Secret 및 DB 없이 REST 3종을 사용할 수 있습니다. WS 호가는 PostgreSQL 기반 실시간 워커를 켜야 하며, 없거나 5초 넘게 오래되면 503 `ORDERBOOK_NOT_FRESH_OR_WORKER_DISABLED`를 반환합니다. REST symbol은 대문자 영숫자 1~20자, WS는 BTC/ETH만 지원합니다. 범용 외부 URL proxy가 아닙니다. 응답은 `{data:{...}}` 형식입니다. - **호가:** `contractCode`, `depth`, `bids`, `asks`, `asOf`, `observedAt`, `source`. 각 레벨은 `{price,quantity,orders?}` 문자열입니다. 수량은 계약 단위로 다룹니다. REST는 5/10/50/100단계(기본 10), `orders`는 해당 가격의 주문 수입니다. 가격을 Number 키로 변환하지 않으며 동일 가격 충돌, 교차 호가, 잘못된 수량/시각을 거부합니다. - **전체 시세:** `tickers`, `total`, `offset`, `limit`, `observedAt`. `limit`은 1~100, 기본 50. 응답 최대 5,000개, 수신 최대 2MiB. 각 행에 계약 코드·최근가·마크가·최우선 매수/매도 가격과 수량·24시간 고저가/USDT 거래대금·변화율 원문·시각·`fresh`를 제공합니다. 30초 넘은 비활성 시세도 `fresh:false`로 보존하며 최신/거래 가능으로 오인하지 않습니다. 전체 목록 요청을 공유하고 2초만 캐시합니다. 실패 시 이전 캐시를 최신 응답으로 대체하지 않습니다. - **현재 펀딩비율:** `fundingRate`는 API 소수 문자열 그대로, 양수/0/음수를 허용합니다. 문서에 거래소 기준 시각·차기 정산 시각이 없어 `asOf:null`, `settlementAt:null`입니다. `observedAt`은 우리 서버 수신 시각입니다. 실제 지급·수취한 펀딩 금액이나 잔고 반영이 아닙니다. ### 실시간 호가 처리 정책 기존 ticker 연결 하나에서 `usdt/orderBook.BTC-SWAP.50`, `usdt/orderBook.ETH-SWAP.50`도 구독합니다. 문서처럼 응답 topic에서 depth 접미사가 빠진 경우도 처리합니다. `insert`가 초기 전체 상태이며 이후 `update`를 가격별로 반영합니다. 수량 0은 레벨 삭제로 처리합니다 (문서 예시의 0 수량을 호가 변경 관례에 따라 해석한 것으로, 실응답 검수가 필요합니다). WS에는 REST의 `orders` 필드가 없으므로 만들어 넣지 않습니다. - 버전은 문자열/BigInt로 보존, 동일 프레임 중복은 무시, 충돌·역순·오래된 시각·교차 상태는 폐기합니다. - 문서는 버전 **엄격 증가**만 명시합니다. 구현은 보수적으로 `이전+1`만 연속 변경으로 수용합니다. 점프 시 `TAPBIT_BOOK_CONTINUITY_UNCONFIRMED`로 무효화·재구독합니다. 점프가 실제 누락이라는 단정은 아닙니다. 실응답이 원래 비연속 버전을 쓴다면 호가는 반복 차단될 수 있으며, 이 정책은 운영 검수에서 확인해야 합니다. - 접속 단절·재접속에는 기존 호가를 지우고 새 `insert`를 기다립니다. REST 스냅샷으로 WS 버전을 이어 붙이지 않습니다. - 오래된 호가·초기 스냅샷 미수신은 watchdog에서 재구독합니다. 심볼별 재시도 최소 120초, feed당 구독/해제 채널 연산 120회/시간 상한, 호가 복구는 96회부터 보류하여 ticker 재접속 여유를 둡니다. 연결 시도 최소 1초, 기존 연결 장애 백오프 60~300초 유지. 이는 프로세스 로컬 한도이며 다중 서버/IP 공통 제한을 구현했다는 뜻은 아닙니다. - 호가 파싱 실패만으로 ticker 판단을 중단하지 않습니다. 소켓 자체 장애는 기존과 같이 전체 재접속합니다. 호가는 조회/검증용이며 기존 전략 신호·주문 수량·실주문 잠금을 변경하지 않습니다. 새 진단 ID: `depth`, `tickers`, `fundingRate`, `orderBookStream`. 데스크톱의 **공개 시세 조회**에서 수동 조회하며, 과거 스냅샷임을 관측 시각과 함께 표시합니다. 모바일은 공통 SDK와 네이티브 허용 경로를 제공하지만 전용 호가 화면은 이번 범위에 포함하지 않습니다. ### 다음 개발 항목 구분 - 추가 문서 없이 가능: 문서에 명시된 다른 심볼·봉 주기 조회 확대, 최근 체결 전체 행 제공, WS 동적 구독 설정, 다중 프로세스 공통 API 호출 예산, 연구 전략별 실시간 이식 및 동등성 테스트, 봇의 메인 API 전용 관리 저장 어댑터. 이번 공개 API 4종 완료와 별개로 남아 있습니다. - 추가 규격/운영 확인 필요: 비공개 체결 WS, UID/권한 인증, 결과 불명 주문 자동 식별, TP/SL 자식 주문/OCO 보장, 펀딩·이체의 완전 회계, 실거래 운용 승인. ## 실거래 전환 전 필수 승인 조건 1. 외부 PostgreSQL 준비, TLS 접속·마이그레이션·백업/복원·장애 시 동작 검수. 2. Tapbit로부터 UID/키 권한 확인 방법, 완전한 체결 스트림/누락 복구, clientOrderId 또는 결과 불명 식별 수단 확인. 3. 계좌 초기 실제 잔고·모든 심볼·수동/API 주문 이력 수집, 펀딩/이체 포함 완전 대사. 4. 각 연구 전략/P4와 실시간 신호의 동일 입력 비교, 자동 루프·시세 단절/재접속·중복 구동 검증. 5. 보호 TP/SL 설치 확인·부분 체결 수량 교체·긴급 취소 후 종료·프로세스 사망 상황 검증. 6. 운용규칙상 집계 방식·보호 종료 예외와 외부 봇 허용 범위 확인. 내부 240건/24h·16건/h·120초는 거래소 보장 기준이 아님. 7. 사용자 별도 승인 하의 제한된 실계좌 검수. 개발 진단 버튼은 이를 대신하지 않습니다. 실제 테스트 주문/취소/포지션 종료는 이번 개발 과정에서 전혀 수행하지 않습니다. 규격 근거: [공개 USDT 선물 문서](https://www.tapbit.com/openapi-docs/usdt_perpetual/), [거래 행위 규정](https://tapbitcex.zendesk.com/hc/en-us/articles/12196942202255-The-rules-on-the-definition-and-handling-of-illegal-transactions), 사용자 제공 비공개 HTML의 파일 해시와 차이는 `services/exchanges/tapbit/PRIVATE_SPEC.md`를 참고하세요. # 0.7.0 거래소 메인 서버 분리와 Swagger 거래소 서버: `https://16.176.130.206/ccs-tapbit` · 일반 메인 API: `52.65.154.88` 유지. 문서: `/docs/`, OpenAPI 3.1: `/openapi.json`, 이 상세 명세: `/docs/reference`. Swagger는 로컬 정적 자산만 사용하며 **실행 버튼·키 입력을 제공하지 않는 읽기 전용 문서**입니다. 문서를 읽는다고 인증이 부여되지는 않습니다. API에 브라우저 Origin/query를 보내면 403입니다. ## 공통 ServiceToken API (개인 계좌 접근 불가) Authorization: `Bearer <공통 전용 토큰>`; 토큰은 64자리 hex, 서버에는 SHA-256 해시만 등록합니다. 일반 메인 API·별도 봇마다 별도 토큰을 발급합니다. 거래소 API Key/Secret이 아닙니다. `GET /v1/shared/status`는 역할·실거래 잠금·공통 feed 상태를 반환합니다. `GET /v1/shared/events`는 Authorization 헤더 기반 SSE입니다. 기존 연결의 BTC/ETH `quote` 이벤트와 15초마다 `status`를 전송합니다. 토큰당1개·전체32개·5분 세션이며 재생하지 않습니다. 느린 클라이언트는 종료합니다. 연결 실패 시60초 backoff, 연결이 끊기면 신규 진입 판단을 멈추고 재연결 후 관찰 상태를 초기화하세요. 브라우저 query token, 개인 계좌 데이터, 과거 이벤트 재생, 주문 전송은 제공하지 않습니다. 다음은 모두 **POST**, JSON 본문, 결과 `{data: ...}` 형식이며 실제 거래소에는 공개 **GET**만 전송합니다. | 경로(`/v1/shared/market/` 뒤) | 본문 | 의미 | |---|---|---| | time | `{}` | 거래소 시간·offsetMs | | instruments | `{}` | 계약 승수·최소 수량·가격 단위 | | ticker | `{"symbol":"BTC"}` | BTC/ETH REST 시세 | | tickers | `{"offset":0,"limit":50}` | 전체 계약 시세, limit 최대100 | | depth | `{"symbol":"BTC","depth":10}` | REST 호가 5/10/50/100단계 | | funding-rate | `{"symbol":"BTC"}` | 현재 비율, 실제 펀딩 지급액 아님 | | candles | `{"symbol":"BTC","frame":3}` | 3/5/15분 완료 봉, 최근 최대500개 | | trades | `{"symbol":"BTC"}` | 최근 체결 count/latestAt 요약 | | quote | `{"symbol":"BTC"}` | 기존 WS의 신선한 ticker 이벤트 | | orderbook | `{"symbol":"BTC"}` | 기존 WS의 신선한 호가50단계 | | stream | `{}` | 기존 WS 상태·오류 코드 | 동일 기능을 본인 DeviceToken으로는 `/v1/market/*`에서 사용합니다. 두 경로의 공통 REST 캐시/전송 인스턴스는 공유합니다. 호출자당 공개 시세12회/분·전체 HTTP300회/분. 전체 시세2초, 펀딩5초, 계약60초, 그 외 REST1초 캐시. 시세 값의 asOf/observedAt/fresh를 확인하며, 연결 이상이나 늦은 호가/quote는 503입니다. 자동 주문 근거로 오래된 스냅샷을 쓰면 안 됩니다. API 토큰은 서로 교환할 수 없습니다. ServiceToken은 `/v1/connection`, `/v1/ops`, `/v1/bot-agent`에 접근할 수 없습니다. `primary` 단일 소유자 제한 배포이며 다른 사용자의 개인 봇/키를 받는 다중 사용자 실거래 서버가 아닙니다. 실제 거래·취소는 여전히 이중 잠금입니다. 공통 시장 데이터의 HTTP 요청 수와 Tapbit의 거래 행위 한도는 다른 개념입니다. 공식 UID 일일≥300, 시간당≥20 **및** 연속 주문간격<2분 조건, 자전/연계 거래 금지와 내부 보수적 한도는 `OPERATING_RULES.md`를 따릅니다. 본 배포 테스트는 실제 주문·취소를 보내지 않습니다. ## 0.8.0 추가 경로 ### 0.8.1 점검 통신 미리보기 `POST /test/api/run`, `POST /v1/diagnostics/run` 응답의 `data.communication`에 해당 점검의 요청·응답을 제공합니다. `kind`는 `http`(실제 REST), `websocket`(기존 연결), `mock`(가짜 전송), `local`(내부 판단 또는 조회 캐시)입니다. - `request`: method, url, query, headers, body - `response`: status, headers, body. HTTP가 아니거나 응답이 없으면 status는 null 또는 response 자체 없음. - `startedAt`, `receivedAt`: 실제 수집 시각. HTTP의 `durationMs`는 전송 시작부터 본문 수신까지이며 큐 대기는 제외. - WebSocket은 실제 전송한 구독 요청과 마지막 정상 파싱된 프레임을 복사합니다. 점검 시 새 구독은 보내지 않습니다. - 공개·모의 60초 캐시에는 원래 수집 시각을 유지합니다. 계좌 클라이언트 캐시/진행 중 조회 재사용은 local로 표시합니다. - 요청 단위 격리(AsyncLocalStorage), 최대 10건, 본문 배열 최대 20개·깊이/노드 수 제한. 미리보기는 전체 패킷 덤프가 아닙니다. 생략 표시를 확인하세요. - API Key/서명/토큰/쿠키, 임의 오류 문자열/알 수 없는 필드는 브라우저·다운로드에서 제외합니다. 개인 계좌 조회는 운영자 인증 후에도 본문 값과 식별자를 마스킹합니다. - 통신 내역은 UI에서 펼치기·복사·JSON 저장 가능. 영구 서버 로그나 타 사용자 통신 이력을 조회하는 기능은 아닙니다. - 주문·취소 실전 전송, 인증 범위, 호출 제한, 거래소 운용 잠금은 변경하지 않습니다. 메인 API 구현 계약은 [MAIN-API-HANDOFF.md](MAIN-API-HANDOFF.md)와 `/main-link.openapi.json`에 정의했습니다. 실제 일반 메인 API 서버의 구현 완료를 뜻하지 않습니다. | 경로 | 인증 | 설명 | | --- | --- | --- | | GET `/test/` | 공개 | 안전한 거래소 점검 페이지 | | GET `/test/api/features`, `/test/api/status` | 공개 | 점검 목록·비밀값 없는 연결 상태 | | POST `/test/api/run` | 공개 항목은 없음, 개인 항목은 점검 쿠키 | `{id,symbol,orderId?}`. 동일 Origin + `X-CCS-Test: 1` 필수 | | POST `/test/api/session` | 일회용 코드 | `{code}`. 15분 HttpOnly/Secure/SameSite=Strict 점검 쿠키, 네이티브 계좌 API 접근 불가 | | POST `/test/api/logout` | 점검 쿠키 | `{}`. 세션 폐기 | | GET `/v1/main-link/status` | DeviceToken | 메인 API 준비·연결 상태·보고 큐 | | GET `/v1/main-link/config` | DeviceToken | 메인 API에 저장된 설정 | | PUT `/v1/main-link/config` | DeviceToken | `{config,expectedRevision,requestId}`. 메인 API CAS·멱등 저장 | 점검 페이지 이외의 브라우저 Origin 거부는 그대로 유지합니다. 공개·모의 점검은 동일 id/symbol 기준 60초 캐시 및 요청 합치기가 적용됩니다. 개인 점검은 조회 통과 여부만 반환하며 계좌 데이터는 반환하지 않습니다. `canTrade=false`, `realOrdersSent=0`은 이 모듈의 전송 동작을 의미하며 사용자가 다른 경로에서 한 거래까지 없다는 뜻은 아닙니다. 메인 API 경유 모드에서 기존 직접 PostgreSQL `/v1/ops/*`는 `MAIN_API_EXECUTION_LEDGER_NOT_ENABLED`로 거부합니다. 신규 관찰 기능은 `/v1/main-link/*`와 메인 API 명령 큐를 사용합니다. 데이터 원장 전환을 완성한 것으로 표시하지 않습니다.