trader-in-broker은(는) 무엇을 하나요?
Order Executor는 이 팩에서 실제 주문으로 이어질 수 있는 유일한 스킬이므로 가장 엄격하게 동작합니다. 주문이 시장에 도달하려면 매번, 모든 주문에 대해 다음 관문을 통과해야 합니다.
- 오늘 이 정확한 주문이 trader-in-risk를 통과해야 합니다 (지문으로 일치 확인;
trader-in-risk/check.py와 동일한ORDER_FIELDS및 해시 사용). trader-in/config.json에"paper": false가 설정되어야 합니다. 페이퍼(기본값) 모드에서는 아무것도 전송되지 않으며, 체결은 로컬 시뮬레이션 원장에 기록됩니다.- 사용자가 이 하나의 주문에 대해 명시적인 '예'를 채팅에 입력해야 합니다.
- 사용자가 각
place_order호출에 대해 Claude 자체 권한 카드에서 'Allow once'를 클릭해야 합니다. 주문 도구는 '승인 필요'로 설정되어 있기 때문입니다.
'아니오'면 주문 없음. '예'는 하나의 티켓(매수, 손절, 목표가 레그 포함)을 커버하며, 절대 배치 단위로 적용되지 않습니다.
${CLAUDE_SKILL_DIR}는 이 스킬의 폴더입니다(이 SKILL.md가 있는 곳).
python3 "${CLAUDE_SKILL_DIR}/ticket.py" show # 모든 티켓 표시 (READY 또는 NOT)
python3 "${CLAUDE_SKILL_DIR}/ticket.py" approve --index 1 --reply "yes"
python3 "${CLAUDE_SKILL_DIR}/ticket.py" paper-fill --index 1 --price 1196.30 # 페이퍼: 매수 체결
python3 "${CLAUDE_SKILL_DIR}/ticket.py" paper-fill --symbol RELIANCE --side sell --qty 12 --price 1212.70 --leg target
python3 "${CLAUDE_SKILL_DIR}/ticket.py" paper # 페이퍼 원장 및 손익 조회
python3 "${CLAUDE_SKILL_DIR}/ticket.py" result --index 1 --leg entry --status placed --broker-id ID --filled-qty 12 --filled-price 1196.30
python3 "${CLAUDE_SKILL_DIR}/ticket.py" result --index 1 --leg stop --status placed --broker-id ID
python3 "${CLAUDE_SKILL_DIR}/ticket.py" fill --symbol RELIANCE --side sell --qty 12 --price 1212.70 --leg target
python3 "${CLAUDE_SKILL_DIR}/ticket.py" flatten --symbol RELIANCE --qty 12
python3 "${CLAUDE_SKILL_DIR}/ticket.py" log
ticket.py는 절대 브로커와 통신하지 않습니다. 티켓을 렌더링하고, 응답이 해당 주문에 대한 진정한 '예'인지 확인하며, 페이퍼 원장을 유지하고, 청산(flatten) 티켓을 생성하며, 로그를 trader-in/state/broker.json에 기록합니다. --now "2026-10-27 10:15" (또는 10:15만) 옵션으로 IST 시간대의 시계를 고정할 수 있습니다. 심볼은 RELIANCE, RELIANCE.NS, NSE:RELIANCE, M&M, BSE:500325, 500325.BO 형식으로 입력 가능합니다.
읽고 쓰는 파일
| 파일 | 설명 |
|---|---|
trader-in/orders.json | 제안된 주문 목록 (trader-in-budget이 작성, flatten이 이를 대체) |
trader-in/config.json | broker (kite 또는 upstox), paper, product, flat_by, costs, capital_inr 설정 |
trader-in/state/risk.json | trader-in-risk의 판정 결과; 오늘 날짜의 PASS만 READY 상태로 간주 |
trader-in/state/broker.json | 모든 예/아니오, 주문 접수, 레그 접수 및 체결 내역, 각 항목별 최대 손실액(비용 포함) |
trader-in/state/paper.json | 페이퍼 원장: 현금, 미결제 포지션, 청산된 거래, 추정 비용 차감 후 실현 손익 |
trader-in/portfolio.json | 현금 및 주식 보유 현황 (포지션은 RELIANCE.NS와 같은 symbol과 exchange로 식별) |
trader-in/plan.json | flatten을 위한 청산 시한 시간 |
trader-in/universe.json | (Upstox) 스캐너로부터 가져온 ISIN 목록 (있는 경우) |
trader-in/state/EQUITY_L.csv | (Upstox) NSE 주식 목록. ISIN이 필요할 때 한 번 다운로드하여 저장 |
하나의 거래, 세 개의 주문 (매 브라켓 주문 전에 읽으십시오)
trader-in-budget은 하나의 "브라켓"(진입, 손절, 목표가)을 작성합니다. Zerodha와 Upstox는 더 이상 브라켓 주문을 지원하지 않으므로, 티켓은 이를 다음과 같이 변환합니다.
| 레그 | 주문 유형 | 실행 시점 |
|---|---|---|
| 1 | 매수, 진입가에 LIMIT (또는 MARKET), MIS 또는 CNC | 즉시 |
| 2 | 매도, SL-M (trigger_price = 손절가) | 레그 1이 체결된 후에만 |
| 3 | 매도, 목표가에 LIMIT | 레그 1이 체결된 후에만 |
레그 2와 3은 서로 연동되어 있지 않습니다 (OCO 미지원). 하나가 체결되어도 다른 하나는 여전히 유효합니다. 즉시 취소하지 않으면, 사용자가 숏 포지션(MIS의 경우)을 갖거나 주문이 거부될(CNC의 경우) 수 있습니다. /trader-in-alerts 스킬을 통해 손절 및 목표가 레벨을 모니터링하고 도달 시 알림을 받을 수 있습니다. 레그 1이 체결되기 전에 레그 2와 3을 제출하면 단순 매도 주문으로 처리되어 숏 포지션이 열릴 수 있습니다.
모든 티켓은 예상 비용(세부 사항 §6: MIS 레그당 수수료 min(₹20, 0.03%), STT, 거래소 및 SEBI 수수료, 인지세, 18% GST)과 손절가에서의 최대 손실액(왕복 비용 포함) 을 표시합니다. 이 수치는 trader-in-risk의 일일 손실 한도 계산을 위해 기록됩니다. 비용은 항상 추정치이며, 실제 비용은 계약 명세서를 확인해야 합니다.
페이퍼 트레이딩 (기본값)
인도 브로커들은 페이퍼 계좌를 제공하지 않으므로, 페이퍼 트레이딩은 trader-in/state/paper.json의 로컬 원장을 통해 이루어집니다. 어떤 정보도 외부로 전송되지 않습니다.
ticket.py show명령어로 READY 상태인 티켓을 확인합니다.- 사용자가 '예'라고 응답하면
ticket.py approve를 실행합니다. - 가격이 진입가에 도달하면,
ticket.py paper-fill --index N(지정가 주문의 경우) 또는--price P옵션을 사용하여 매수 체결을 기록합니다. 매수 지정가는 지정된 가격 이상으로 체결될 수 없습니다. - 손절가 또는 목표가에 도달하면 해당 매도 주문을 기록합니다:
paper-fill --symbol RELIANCE --side sell --qty 12 --price 1188.10 --leg stop. 원장은 총 손익, 예상 왕복 비용 및 순 손익을 기록합니다. ticket.py paper명령어로 현금, 미결제 포지션 및 실현 손익을 조회합니다.
페이퍼 진입은 placed (및 "paper": true)로 기록되므로, trader-in-risk는 실제 거래와 동일하게 일일 거래 횟수 및 손실 한도에 집계합니다.
설정 A: Zerodha Kite (공식 MCP 서버) — 기본 설정
Zerodha의 서버는 github.com/zerodha/kite-mcp-server (MIT 라이선스, Go 언어)입니다. 2026년 10월 27일 기준 소스 코드 및 README와 비교하여 확인했습니다 (최신 커밋 5e044dc, 태그 v0.4.0-dev24).
호스팅 서버는 주문을 실행할 수 없습니다. README에 따르면 호스팅된 https://mcp.kite.trade/mcp는 "보안상 잠재적으로 파괴적인 거래 작업을 제외"하며, Zerodha 자체 페이지에서는 읽기 전용으로 설명합니다 (한 Z-Connect 게시물에 따르면 GTT 주문이 예외였으나, 범위는 시간이 지남에 따라 변경되었으므로 연결 후 Claude의 도구 목록을 확인하십시오). 이 서버는 무료이며 API 키가 필요 없습니다: login 도구는 Kite 링크를 반환하고, 사용자는 브라우저에서 자신의 Kite 비밀번호와 2FA를 사용하여 로그인합니다 (채팅에서는 절대 안 됨).
호스팅, 읽기 전용 (시세, 잔고, 포지션, 증거금, 주문 내역, 거래 내역):
- Claude Desktop: 설정 > 개발자 > 구성 편집,
claude_desktop_config.example.json에서"kite"블록을 추가 (npx mcp-remote https://mcp.kite.trade/mcp실행, Node.js 필요), 재시작. - Claude Code:
claude mcp add --transport http kite https://mcp.kite.trade/mcp(또는 동일한npx mcp-remote명령어를 stdio 서버로 사용:claude mcp add kite -- npx mcp-remote https://mcp.kite.trade/mcp).
Claude를 통해 주문을 실행하려면 사용자는 자신만의 서버 사본을 자신의 Kite Connect 앱과 함께 실행해야 합니다.
- developers.kite.trade에서 Kite Connect 앱을 생성합니다 (현재 가격은 해당 사이트에서 확인). 리디렉션 URL은 로컬 서버의 콜백을 가리켜야 합니다. 서버 소스에서 콜백 경로는
APP_HOST:APP_PORT의/callback입니다 (기본값http://localhost:8080/callback). 우리는 이 전체 과정을 종단 간 테스트하지 않았습니다. - 2026년 4월 1일부터 Zerodha 지원 페이지에 따르면 API를 통한 주문 실행에는 Zerodha에 고정 IP가 허용 목록에 등록되어 있어야 합니다 (NSE/SEBI 소매 알고리즘 규칙). 고정 IP가 없는 가정용 연결에서는 주문이 거부될 수 있습니다. 실제 거래 전에 Zerodha의 현재 규칙을 확인하십시오.
- 서버 빌드:
git clone https://github.com/zerodha/kite-mcp-server && cd kite-mcp-server && go build -o kite-mcp-server(Go 1.21+ 필요). claude_desktop_config.example.json에서"kite-orders"블록을 추가합니다: 바이너리의 전체 경로,APP_MODE를stdio로 설정하고, 사용자가KITE_API_KEY와KITE_API_SECRET을 해당 파일에 직접 입력합니다. Claude Code에서는claude mcp add kite-orders -e APP_MODE=stdio -e KITE_API_KEY="$KITE_API_KEY" -e KITE_API_SECRET="$KITE_API_SECRET" -- /full/path/to/kite-mcp-server명령어를 사용하며, 값은 사용자 셸에 미리 export 되어 있어야 합니다. 둘 다 필요하지 않다면kite/kite-orders중 하나만 유지하십시오.- 재시작한 후, Claude에게
login을 호출하도록 요청하면 사용자가 링크를 열고 로그인합니다. Kite 세션은 매일 만료되므로 (Kite Connect 액세스 토큰은 다음 날 아침까지 지속), 매 거래일마다 다시 로그인해야 합니다.
키와 토큰은 절대 채팅에 입력하지 마십시오. 절대 키나 토큰을 요청하지 말고, 설정 파일을 대화 내용으로 다시 읽어들이지 마십시오. 사용자가 키나 토큰을 붙여넣으면 해당 메시지를 삭제하고 developers.kite.trade에서 다시 생성하도록 안내하십시오.
도구 권한 설정. Customize > Connectors (Claude Desktop)에서 Kite 서버를 열고 다음을 설정하십시오:
place_order,modify_order,cancel_order,place_gtt_order,modify_gtt_order,delete_gtt_order: 승인 필요. 절대 '항상 허용'으로 설정하지 마십시오.- 읽기 전용 도구 (
get_profile,get_margins,get_holdings,get_positions,get_orders,get_order_history,get_order_trades,get_trades,get_gtts,get_quotes,get_ltp,get_ohlc,get_historical_data,search_instruments,login): '항상 허용'으로 설정해도 무방합니다. - Claude Code에서는
.claude/settings.json파일에"permissions": {"ask": ["mcp__kite-orders__place_order", "mcp__kite-orders__modify_order", "mcp__kite-orders__cancel_order"]}와 같이 설정하여 주문 관련 도구는 항상 'ask' 상태를 유지하십시오. 서버는 읽기 전용 복사본을 위해EXCLUDED_TOOLS=place_order,modify_order,cancel_order환경 변수를 사용할 수도 있습니다.
place_order 인수 (서버 소스 기준): variety (regular), exchange (NSE/BSE), tradingsymbol, transaction_type (BUY/SELL), quantity (정수), product (MIS/CNC), order_type (MARKET/LIMIT/SL/SL-M), price (LIMIT, SL), trigger_price (SL, SL-M), validity (DAY), 선택적 tag (20자 이하, 티켓은 trin + 지문의 12자리 16진수를 추가하여 나중에 주문을 찾을 수 있도록 함). 서버의 도구에는 market_protection 인수가 없습니다. NSE는 이제 API MARKET 및 SL-M 주문에 시장 보호를 적용하므로, 시장가 주문은 브로커에 의해 보호 지정가로 전환될 수 있습니다. 지정가 진입은 이를 피할 수 있습니다. BSE의 경우 Kite의 tradingsymbol은 종목 코드가 아닌 스크립트 이름입니다. search_instruments로 조회하십시오.
설정 B: Upstox ("broker": "upstox")
- Upstox의 공식 MCP 서버 (
https://mcp.upstox.com/mcp,upstox/upstox-plugin-marketplace플러그인의upstox-mcp로 설치)는 읽기 전용입니다. Upstox 페이지에 따르면 이 서버를 통해 주문을 실행할 수 없습니다. 연결은 매일 만료됩니다 (브라우저에서 OAuth 동의). - Upstox의 공식 에이전트 스킬 (
/plugin install upstox-skill@upstox-plugins-officialin Claude Code,/plugin marketplace add upstox/upstox-plugin-marketplace후)은 v3 주문 API를 사용하여 주문을 실행할 수 있습니다.UPSTOX_ACCESS_TOKEN환경 변수 (사용자가 자신의 셸에 설정, 채팅에 절대 입력 금지)에서 일일 액세스 토큰을 읽고, 자체 미리보기를 표시한 후 확인을 기다립니다. Upstox는 이 스킬이 일반 Claude Desktop 채팅에서는 작동하지 않는다고 명시합니다. - 또는 사용자는 티켓 정보를 바탕으로 Upstox 앱에서 직접 주문을 실행할 수 있습니다.
티켓은 POST https://api-hft.upstox.com/v3/order/place (v2 /v2/order/place는 지원 중단 표시됨, slice 필드 제외하고 동일한 필드 사용)의 요청 본문을 출력합니다: quantity (정수), product (I 인트라데이 = MIS, D 일반 = CNC), validity DAY, price (MARKET / SL-M의 경우 0), instrument_token, order_type, transaction_type, disclosed_quantity 0, trigger_price (SL / SL-M가 아니면 0), is_amo false (Upstox는 무시함), tag, 그리고 market_protection: -1 (자동) (MARKET 및 SL-M 주문의 경우, API 시장가 주문에 대해 0이 거부되므로).
instrument_token은 NSE_EQ|<ISIN> (또는 BSE_EQ|<ISIN>) 형식입니다. ISIN은 다음 순서로 가져옵니다: --isin 옵션, 주문 내 isin 필드, 스캐너의 trader-in/universe.json, 또는 NSE의 EQUITY_L.csv (브라우저 User-Agent를 사용하여 trader-in/state/EQUITY_L.csv에 한 번 다운로드, archives. 다음 nsearchives. 도메인 시도). BSE 제한 사항: NSE 목록은 NSE 심볼만 매핑합니다. 500325.BO와 같은 BSE 종목 코드는 매핑할 수 없으므로 --isin을 전달하십시오. .BO 이름 심볼의 경우 NSE 목록의 ISIN을 사용합니다 (동일 회사), 하지만 확인이 필요합니다. 우리는 여기서 Upstox 인스트루먼트 파일 형식을 확인하지 않았습니다. ISIN이 없으면 실제 Upstox 티켓은 READY 상태가 되지 않습니다. 페이퍼 티켓은 ISIN이 필요 없습니다.
단계: 진입
ticket.py show를 실행합니다. READY 상태인 티켓만 사용자에게 표시됩니다. READY 또는 BLOCKED 상태가 아닌 티켓은/trader-in-risk로 돌아갑니다 (broker JSON이 없음).- 하나의 티켓을, OCO 미지원 경고와 함께 보여주고 "이 주문을 실행하시겠습니까? 예 또는 아니오로 답변해 주세요."라고 질문합니다. 한 번에 하나의 주문만 질문합니다. 절대 "모두 예" 옵션을 제공하지 마십시오.
ticket.py approve --index N --reply "<사용자의 응답, 그대로>"를 실행합니다. "Not recorded"는 응답이 이 주문에 대한 명시적인 '예'가 아님을 의미합니다 ("sure", "haan", "yes to all", 다른 종목이나 금액을 언급하는 '예' 등). 다시 질문합니다. 절대 사용자의 응답을 자의적으로 '예'로 해석하지 마십시오.- 페이퍼: 위에서 설명한 대로
paper-fill을 실행합니다. 실제, Kite: 정확히 레그 1 JSON으로place_order를 호출합니다. 사용자가 'Allow once'를 클릭합니다. 체결을 확인한 후 (get_order_history/get_positions), 레그 2, 레그 3을 각각place_order하며 각각 자체 'Allow once'가 필요합니다. 실제, Upstox: 요청 본문을 Upstox 에이전트 스킬 또는 앱에 한 번에 한 레그씩 동일한 순서로 전달합니다. - 각 실제 레그를 기록합니다:
ticket.py result --index N --leg entry|stop|target --status placed|denied|failed --broker-id <id>(진입 시--filled-qty,--filled-price포함). 진입만 trader-in-risk의 주문 횟수로 계산됩니다. 레그는leg_placed로 기록됩니다. 실패한 주문은 새로운 확인과 새로운 '예' 없이는 재시도되지 않습니다.
단계: 포지션 오픈 중 및 청산 시한까지
/trader-in-alerts는 손절가, 목표가 및 청산 시한을 모니터링합니다.- 손절 또는 목표가가 체결되면: 실제 거래의 경우
ticket.py fill ... --leg stop(다른 레그를 즉시 취소하라는 알림을 표시:get_orders호출 후cancel_order호출, '승인 필요'); 페이퍼의 경우paper-fill ... --leg stop. flat_by시간 (기본 15:10 IST)까지 아직 청산되지 않은 포지션은 모두 강제 청산됩니다. 브로커는 약 15:20 IST부터 미결제 MIS 포지션을 자동으로 청산하며 수수료를 부과합니다 (Zerodha는 주문당 ₹50 + GST 부과). 브로커에게 맡기지 마십시오:- 실제 거래: 브로커에게 보유 주식 수를 조회합니다:
get_positions(읽기 전용). ticket.py flatten --symbol RELIANCE --qty 12는trader-in/orders.json에 MARKET 매도 주문(동일 product)을 작성합니다.
- 실제 거래: 브로커에게 보유 주식 수를 조회합니다: