Farmings Core WebSocket API 2.0.0

farmings-core 의 단일 WebSocket 엔드포인트 메시지 카탈로그.

  • 엔드포인트: GET /ws?token={jwt} → WebSocket upgrade
  • 인증: 핸드셰이크 쿼리 파라미터 token 의 Supabase JWT. 유효하지 않으면 연결 종료.
  • 메시지 형식: JSON { type, ref?, payload? }. ref 는 클라이언트가 요청·응답 매칭용으로 임의 지정.
  • 도메인: 시세(subscribe.* / chart.* / price.* / candle.*), 종목(ticker.*), 농장(farm.*), 대결(contest.*), 랭킹(rank.*).

KOSPI 종합지수: 별도 message 없이 ticker_code='KOSPI' 로 같은 메시지 사용 (subscribe.price / subscribe.candle / chart.query). 단 ticker.* 응답에는 포함되지 않음 (종목 마스터 미등록). 분 단위 수집이라 1m candle 의 OHLC 가 모두 같은 값(분 정각 close).

Servers

  • {host}/wswssproduction

    운영 환경

    object
    string
    required
    object
  • {host}/wswslocal

    로컬 개발

    object
    string
    required

Operations

  • PUB /ws

    단일 WebSocket 채널.

    클라이언트 → 서버 요청

    Operation IDclientToServer

    Available only on servers:

    Accepts one of the following messages:

    • #0subscribe.price

      현재가 구독 — 즉시 스냅샷 + 실시간 push 활성

      성공 응답: price.snapshot (즉시, 전 종목 현재가). 이후 가격 변경 시 price.update broadcast 활성.

      object

      Examples

    • #1unsubscribe.price

      성공 응답: unsubscribe.price.ok. broadcast 중지.

      object

      Examples

    • #2subscribe.candle

      종목별 1분봉 실시간 구독

      성공 응답: candle.snapshot (즉시, 현재 진행 중 1분봉. 없으면 null payload). 이후 1분봉 변경 시 candle.update broadcast 활성.

      object

      Examples

    • #3unsubscribe.candle

      성공 응답: unsubscribe.candle.ok. 해당 종목 broadcast 중지.

      object

      Examples

    • #4chart.query

      단위별 캔들 차트 조회 (1m / 1h / 1d / 1w / 1mo, 최근 limit개)

      성공 응답: chart.data (캔들 배열, bucket 오름차순). unit 미지정 시 1m (기본). tickerCode='KOSPI' 로 KOSPI 종합지수도 조회 가능.

      object

      Examples

    • #5ticker.list

      모든 종목 코드+이름 (코드 오름차순)

      성공 응답: ticker.list (요청과 같은 type, payload 만 응답 형식).

      object

      Examples

    • #6ticker.search

      종목명·코드 검색

      성공 응답: ticker.search.

      object

      Examples

    • #7ticker.ranking

      거래대금/거래량 종목 랭킹

      성공 응답: ticker.ranking.

      object

      Examples

    • #8ticker.detail

      종목 상세 (현재가 + 펀더멘털). 호출 시 최근 검색어에 자동 기록.

      성공 응답: ticker.detail. 알 수 없는 종목이면 error (code=UNKNOWN_TICKER).

      object

      Examples

    • #9ticker.recent_searches

      사용자별 최근 검색 종목 (LRU)

      성공 응답: ticker.recent_searches.

      object

      Examples

    • #10farm.info

      내 농장 기본 정보 (없으면 자동 생성 + 시드 지급)

      성공 응답: farm.info.

      object

      Examples

    • #11farm.portfolio

      보유 포지션 + 평가액 (현재가 기준)

      성공 응답: farm.portfolio.

      object

      Examples

    • #12farm.portfolio.period

      기간별 수익률 — `[start_date 자정, end_date+1 자정)` 윈도우, end_date 매매 포함

      성공 응답: farm.portfolio.period. 거절: error (INVALID_PAYLOAD — start > end / end > today / 잘못된 날짜).

      종목별 cash flow 식: 분자 = end_value - start_value - 순매수, 분모 = start_value > 0 ? start_value : 첫 매수금. 농장 전체 = 종목별 합산. trades + stock_candles_1d 영구 보존이라 retention 무관.

      object

      Examples

    • #13farm.reset

      1회 무료 청산. cash_locked > 0 또는 reset_used = true 면 거절.

      성공 응답: farm.reset.ok. 거절: error (RESET_ALREADY_USED / RESET_HAS_LOCKED_CASH).

      object

      Examples

    • #14farm.buy

      농장 매수 (정규 거래 시간 09:00–15:30 KST 한정, 시장가)

      성공 응답: farm.traded. 거절: error (INSUFFICIENT_CASH / OUT_OF_TRADING_HOURS / INVALID_QUANTITY 등).

      수수료 0.1% (amount × 10 / 10000, 정수 floor). cash 에서 amount + fee 차감, 수수료는 어디로도 입금되지 않고 소각. 평단가 식은 수수료 미포함 amount 기준 (체결가 × 수량).

      object

      Examples

    • #15farm.sell

      농장 매도 (정규 거래 시간 09:00–15:30 KST 한정, 시장가)

      성공 응답: farm.traded (매도 시 payload.realized_pnl 채워짐). 거절: error (INSUFFICIENT_QUANTITY / OUT_OF_TRADING_HOURS 등).

      수수료 0.2% (amount × 20 / 10000, 정수 floor). cash 에 amount - fee 가산, 수수료는 소각. realized_pnl = (체결가 - 평단가) × 수량 - fee (수수료 차감 후 net PnL).

      object

      Examples

    • #16contest.match

      RANDOM 자동 매칭 — 같은 duration_type 의 WAITING 방에 join, 없으면 신규 생성

      성공 응답: contest.match.ok (대결 메타). 거절: error (INSUFFICIENT_CASH 등).

      object

      Examples

    • #17contest.create_invite

      친구 초대 방 생성 — 8자리 invite_code 발급, 본인 자동 join

      성공 응답: contest.create_invite.ok (대결 메타, invite_code 포함). 거절: error (INSUFFICIENT_CASH / INVITE_CODE_GENERATION_FAILED / INVALID_PAYLOAD 등).

      object

      Examples

    • #18contest.join_invite

      성공 응답: contest.join_invite.ok. 거절: error (INVITE_CODE_NOT_FOUND / CONTEST_FULL / ALREADY_PARTICIPATING / INSUFFICIENT_CASH).

      object

      Examples

    • #19contest.cancel

      매칭 대기 중 취소 (WAITING 한정, 시작된 대결은 거절)

      성공 응답: contest.cancel.ok (CANCELLED 또는 활성 인원 0이면 contest 자체 cancel). 거절: error (CONTEST_NOT_FOUND / CANNOT_CANCEL_AFTER_START / NOT_PARTICIPATING).

      object

      Examples

    • #20contest.list_waiting

      참여 가능한 WAITING contest 목록

      성공 응답: contest.list_waiting.

      object

      Examples

    • #21contest.my_active

      내가 진행/대기 중인 대결 (PLAYING + WAITING)

      성공 응답: contest.my_active.

      object

      Examples

    • #22contest.history

      종료된 내 대결 전적 (최신순)

      성공 응답: contest.history (verdict 포함).

      object

      Examples

    • #23contest.buy

      대결 격리 자산 매수

      성공 응답: contest.traded (payload.contest_id 포함). 거절: error (CONTEST_NOT_PLAYING / INSUFFICIENT_CASH / OUT_OF_TRADING_HOURS 등).

      수수료 0.1% (농장 매수와 동일). 대결 격리 cash 에서 amount + fee 차감, 수수료는 소각.

      object

      Examples

    • #24contest.sell

      대결 격리 자산 매도

      성공 응답: contest.traded (매도 시 payload.realized_pnl 채워짐). 거절: error (INSUFFICIENT_QUANTITY 등).

      수수료 0.2% (농장 매도와 동일). 대결 격리 cash 에 amount - fee 가산, 수수료는 소각. realized_pnl 도 net (수수료 차감 후).

      object

      Examples

    • #25rank.weekly

      농장 주간(직전 7일) 수익률 TOP 10

      성공 응답: rank.weekly (요청과 같은 type, payload.rankings 에 TOP 10).

      object

      Examples

    • #26rank.monthly

      농장 월간(직전 30일) 수익률 TOP 10

      성공 응답: rank.monthly (요청과 같은 type, payload.rankings 에 TOP 10).

      object

      Examples

    • #27rank.contest

      윈도우 내 종료된 대결 수익률 TOP 10 (한 사용자가 N개 대결 시 N회 등장)

      성공 응답: rank.contest (payload.rankings 에 TOP 10).

      object

      Examples

  • SUB /ws

    단일 WebSocket 채널.

    서버 → 클라이언트 응답·broadcast

    Operation IDserverToClient

    Available only on servers:

    Accepts one of the following messages:

    • #0price.snapshot

      subscribe.price 응답 — 전 종목 현재가 (Redis HSET)

      object

      Examples

    • #1price.update

      현재가 변경 broadcast (subscribe.price 활성 세션에 push)

      object

      Examples

    • #2unsubscribe.price.ok
      object

      Examples

    • #3candle.snapshot

      subscribe.candle 응답 — 현재 진행 중 1분봉 (없으면 null)

      object

      Examples

    • #4candle.update

      1분봉 변경 broadcast (해당 종목 구독자)

      object

      Examples

    • #5unsubscribe.candle.ok
      object

      Examples

    • #6chart.data

      chart.query 응답 — 단위별 캔들 배열 (bucket 오름차순)

      bucket 은 ISO-8601 string. unit=1m/1h 면 datetime, 1d/1w/1mo 면 date (YYYY-MM-DD).

      object

      Examples

    • #7ticker.list (response)
      object

      Examples

    • #8ticker.search (response)
      object

      Examples

    • #9ticker.ranking (response)
      object

      Examples

    • #10ticker.detail (response)
      object

      Examples

    • #11ticker.recent_searches (response)
      object

      Examples

    • #12farm.info (response)
      object

      Examples

    • #13farm.portfolio (response)
      object

      Examples

    • #14farm.portfolio.period (response)
      object

      Examples

    • #15farm.reset.ok
      object

      Examples

    • #16farm.traded

      농장 매매 체결 응답

      object

      Examples

    • #17contest.match.ok
      object

      Examples

    • #18contest.create_invite.ok
      object

      Examples

    • #19contest.join_invite.ok
      object

      Examples

    • #20contest.cancel.ok
      object

      Examples

    • #21contest.list_waiting (response)
      object

      Examples

    • #22contest.my_active (response)
      object

      Examples

    • #23contest.history (response)
      object

      Examples

    • #24contest.traded

      대결 매매 체결 응답

      object

      Examples

    • #25rank.weekly / rank.monthly (response)

      농장 랭킹 응답 (메시지 type 은 요청과 동일)

      object

      Examples

    • #26rank.contest (response)
      object

      Examples

    • #27error

      공통 에러. payload.code 로 분류, message 는 사람용.

      object

      Examples

Messages

  • #1subscribe.price

    현재가 구독 — 즉시 스냅샷 + 실시간 push 활성

    Message IDSubscribePrice

    성공 응답: price.snapshot (즉시, 전 종목 현재가). 이후 가격 변경 시 price.update broadcast 활성.

    object
  • #2unsubscribe.price
    Message IDUnsubscribePrice

    성공 응답: unsubscribe.price.ok. broadcast 중지.

    object
  • #3subscribe.candle

    종목별 1분봉 실시간 구독

    Message IDSubscribeCandle

    성공 응답: candle.snapshot (즉시, 현재 진행 중 1분봉. 없으면 null payload). 이후 1분봉 변경 시 candle.update broadcast 활성.

    object
  • #4unsubscribe.candle
    Message IDUnsubscribeCandle

    성공 응답: unsubscribe.candle.ok. 해당 종목 broadcast 중지.

    object
  • #5chart.query

    단위별 캔들 차트 조회 (1m / 1h / 1d / 1w / 1mo, 최근 limit개)

    Message IDChartQuery

    성공 응답: chart.data (캔들 배열, bucket 오름차순). unit 미지정 시 1m (기본). tickerCode='KOSPI' 로 KOSPI 종합지수도 조회 가능.

    object
  • #6ticker.list

    모든 종목 코드+이름 (코드 오름차순)

    Message IDTickerList

    성공 응답: ticker.list (요청과 같은 type, payload 만 응답 형식).

    object
  • #7ticker.search

    종목명·코드 검색

    Message IDTickerSearch

    성공 응답: ticker.search.

    object
  • #8ticker.ranking

    거래대금/거래량 종목 랭킹

    Message IDTickerRanking

    성공 응답: ticker.ranking.

    object
  • #9ticker.detail

    종목 상세 (현재가 + 펀더멘털). 호출 시 최근 검색어에 자동 기록.

    Message IDTickerDetail

    성공 응답: ticker.detail. 알 수 없는 종목이면 error (code=UNKNOWN_TICKER).

    object
  • #10ticker.recent_searches

    사용자별 최근 검색 종목 (LRU)

    Message IDTickerRecentSearches

    성공 응답: ticker.recent_searches.

    object
  • #11farm.info

    내 농장 기본 정보 (없으면 자동 생성 + 시드 지급)

    Message IDFarmInfo

    성공 응답: farm.info.

    object
  • #12farm.portfolio

    보유 포지션 + 평가액 (현재가 기준)

    Message IDFarmPortfolio

    성공 응답: farm.portfolio.

    object
  • #13farm.portfolio.period

    기간별 수익률 — `[start_date 자정, end_date+1 자정)` 윈도우, end_date 매매 포함

    Message IDFarmPortfolioPeriod

    성공 응답: farm.portfolio.period. 거절: error (INVALID_PAYLOAD — start > end / end > today / 잘못된 날짜).

    종목별 cash flow 식: 분자 = end_value - start_value - 순매수, 분모 = start_value > 0 ? start_value : 첫 매수금. 농장 전체 = 종목별 합산. trades + stock_candles_1d 영구 보존이라 retention 무관.

    object
  • #14farm.reset

    1회 무료 청산. cash_locked > 0 또는 reset_used = true 면 거절.

    Message IDFarmReset

    성공 응답: farm.reset.ok. 거절: error (RESET_ALREADY_USED / RESET_HAS_LOCKED_CASH).

    object
  • #15farm.buy

    농장 매수 (정규 거래 시간 09:00–15:30 KST 한정, 시장가)

    Message IDFarmBuy

    성공 응답: farm.traded. 거절: error (INSUFFICIENT_CASH / OUT_OF_TRADING_HOURS / INVALID_QUANTITY 등).

    수수료 0.1% (amount × 10 / 10000, 정수 floor). cash 에서 amount + fee 차감, 수수료는 어디로도 입금되지 않고 소각. 평단가 식은 수수료 미포함 amount 기준 (체결가 × 수량).

    object
  • #16farm.sell

    농장 매도 (정규 거래 시간 09:00–15:30 KST 한정, 시장가)

    Message IDFarmSell

    성공 응답: farm.traded (매도 시 payload.realized_pnl 채워짐). 거절: error (INSUFFICIENT_QUANTITY / OUT_OF_TRADING_HOURS 등).

    수수료 0.2% (amount × 20 / 10000, 정수 floor). cash 에 amount - fee 가산, 수수료는 소각. realized_pnl = (체결가 - 평단가) × 수량 - fee (수수료 차감 후 net PnL).

    object
  • #17contest.match

    RANDOM 자동 매칭 — 같은 duration_type 의 WAITING 방에 join, 없으면 신규 생성

    Message IDContestMatch

    성공 응답: contest.match.ok (대결 메타). 거절: error (INSUFFICIENT_CASH 등).

    object
  • #18contest.create_invite

    친구 초대 방 생성 — 8자리 invite_code 발급, 본인 자동 join

    Message IDContestCreateInvite

    성공 응답: contest.create_invite.ok (대결 메타, invite_code 포함). 거절: error (INSUFFICIENT_CASH / INVITE_CODE_GENERATION_FAILED / INVALID_PAYLOAD 등).

    object
  • #19contest.join_invite
    Message IDContestJoinInvite

    성공 응답: contest.join_invite.ok. 거절: error (INVITE_CODE_NOT_FOUND / CONTEST_FULL / ALREADY_PARTICIPATING / INSUFFICIENT_CASH).

    object
  • #20contest.cancel

    매칭 대기 중 취소 (WAITING 한정, 시작된 대결은 거절)

    Message IDContestCancel

    성공 응답: contest.cancel.ok (CANCELLED 또는 활성 인원 0이면 contest 자체 cancel). 거절: error (CONTEST_NOT_FOUND / CANNOT_CANCEL_AFTER_START / NOT_PARTICIPATING).

    object
  • #21contest.list_waiting

    참여 가능한 WAITING contest 목록

    Message IDContestListWaiting

    성공 응답: contest.list_waiting.

    object
  • #22contest.my_active

    내가 진행/대기 중인 대결 (PLAYING + WAITING)

    Message IDContestMyActive

    성공 응답: contest.my_active.

    object
  • #23contest.history

    종료된 내 대결 전적 (최신순)

    Message IDContestHistory

    성공 응답: contest.history (verdict 포함).

    object
  • #24contest.buy

    대결 격리 자산 매수

    Message IDContestBuy

    성공 응답: contest.traded (payload.contest_id 포함). 거절: error (CONTEST_NOT_PLAYING / INSUFFICIENT_CASH / OUT_OF_TRADING_HOURS 등).

    수수료 0.1% (농장 매수와 동일). 대결 격리 cash 에서 amount + fee 차감, 수수료는 소각.

    object
  • #25contest.sell

    대결 격리 자산 매도

    Message IDContestSell

    성공 응답: contest.traded (매도 시 payload.realized_pnl 채워짐). 거절: error (INSUFFICIENT_QUANTITY 등).

    수수료 0.2% (농장 매도와 동일). 대결 격리 cash 에 amount - fee 가산, 수수료는 소각. realized_pnl 도 net (수수료 차감 후).

    object
  • #26rank.weekly

    농장 주간(직전 7일) 수익률 TOP 10

    Message IDRankWeekly

    성공 응답: rank.weekly (요청과 같은 type, payload.rankings 에 TOP 10).

    object
  • #27rank.monthly

    농장 월간(직전 30일) 수익률 TOP 10

    Message IDRankMonthly

    성공 응답: rank.monthly (요청과 같은 type, payload.rankings 에 TOP 10).

    object
  • #28rank.contest

    윈도우 내 종료된 대결 수익률 TOP 10 (한 사용자가 N개 대결 시 N회 등장)

    Message IDRankContest

    성공 응답: rank.contest (payload.rankings 에 TOP 10).

    object
  • #29price.snapshot

    subscribe.price 응답 — 전 종목 현재가 (Redis HSET)

    Message IDPriceSnapshot
    object
  • #30price.update

    현재가 변경 broadcast (subscribe.price 활성 세션에 push)

    Message IDPriceUpdate
    object
  • #31unsubscribe.price.ok
    Message IDUnsubscribePriceOk
    object
  • #32candle.snapshot

    subscribe.candle 응답 — 현재 진행 중 1분봉 (없으면 null)

    Message IDCandleSnapshot
    object
  • #33candle.update

    1분봉 변경 broadcast (해당 종목 구독자)

    Message IDCandleUpdate
    object
  • #34unsubscribe.candle.ok
    Message IDUnsubscribeCandleOk
    object
  • #35chart.data

    chart.query 응답 — 단위별 캔들 배열 (bucket 오름차순)

    Message IDChartData

    bucket 은 ISO-8601 string. unit=1m/1h 면 datetime, 1d/1w/1mo 면 date (YYYY-MM-DD).

    object
  • #36ticker.list (response)
    Message IDTickerListResponse
    object
  • #37ticker.search (response)
    Message IDTickerSearchResponse
    object
  • #38ticker.ranking (response)
    Message IDTickerRankingResponse
    object
  • #39ticker.detail (response)
    Message IDTickerDetailResponse
    object
  • #40ticker.recent_searches (response)
    Message IDTickerRecentSearchesResponse
    object
  • #41farm.info (response)
    Message IDFarmInfoResponse
    object
  • #42farm.portfolio (response)
    Message IDFarmPortfolioResponse
    object
  • #43farm.portfolio.period (response)
    Message IDFarmPortfolioPeriodResponse
    object
  • #44farm.reset.ok
    Message IDFarmResetOk
    object
  • #45farm.traded

    농장 매매 체결 응답

    Message IDFarmTraded
    object
  • #46contest.match.ok
    Message IDContestMatchOk
    object
  • #47contest.create_invite.ok
    Message IDContestCreateInviteOk
    object
  • #48contest.join_invite.ok
    Message IDContestJoinInviteOk
    object
  • #49contest.cancel.ok
    Message IDContestCancelOk
    object
  • #50contest.list_waiting (response)
    Message IDContestListWaitingResponse
    object
  • #51contest.my_active (response)
    Message IDContestMyActiveResponse
    object
  • #52contest.history (response)
    Message IDContestHistoryResponse
    object
  • #53contest.traded

    대결 매매 체결 응답

    Message IDContestTraded
    object
  • #54rank.weekly / rank.monthly (response)

    농장 랭킹 응답 (메시지 type 은 요청과 동일)

    Message IDRankFarmResponse
    object
  • #55rank.contest (response)
    Message IDRankContestResponse
    object
  • #56error

    공통 에러. payload.code 로 분류, message 는 사람용.

    Message IDErrorResponse
    object

Schemas

  • object
  • object
  • object
  • object
  • object
  • object

    기간별 수익률 — 종목별 cash flow 결과.

  • object

    대결 메타. contest.match.ok / contest.create_invite.ok / contest.join_invite.ok / contest.cancel.ok 공통.

  • object
  • object
  • object
  • object
  • object

    손실 제외 + 양수 풀 percentile 5 컷 (모집단 < 15 면 컷 skip) + 보유금액 필터 후 수익률 desc TOP 10.

  • object