판단은 A 가, 손절은 B 가 — 도구 둘을 묶어 주문 하나로

비중만 내는 ai-hedge-fund 의 판단에 LangAlpha 가 낸 무효화·진입·목표를 붙여, 여섯 칸이 전부 채워진 주문 한 건을 만들어 weltiq 상주 실행에 넣어 본 기록입니다.

판단은 A 가, 손절은 B 가 — 도구 둘을 묶어 주문 하나로

이 글의 완료 조건: 독자는 배분만 내는 도구의 판단에, 다른 도구가 낸 손절·목표를 붙여 하나의 주문으로 만들면 성공입니다.

하는 일 비중·주수만 내는 도구(ai-hedge-fund)의 판단에, 무효화 가격·진입·목표를 내는 도구(LangAlpha)를 붙여 주문 하나로 만듭니다
맞는 사람 도구 하나가 낸 판단이 "그래서 어디서 손절하나"에서 멈춰 본 사람
안 맞는 사람 도구 하나를 그대로 쓰고 싶은 사람. 둘을 묶으면 손이 두 배로 갑니다
이 글의 결과물 종목·방향·수량·진입·무효화·목표 여섯 칸이 전부 채워진 주문 한 건, 그리고 그 숫자마다 어느 도구에서 왔는지 적힌 표
준비물·비용 코드 0원(둘 다 오픈소스) · 모델 한 바퀴 약 $0.38 · 시세 0원(무료 경로) · weltiq 모의 계정
시간·난도 두 도구가 이미 깔려 있다면 40분 · 중 (터미널·JSON 편집)
weltiq 와의 관계 붙습니다 — 두 도구 출력을 한 전략 문서로 합쳐 상주 실행에 넣습니다
검증 환경·날짜 2026-09-22 (KST) · macOS 26.6 · 미국 주식 NVDA · 모델 openai/gpt-6-astra
제휴 고지 필자는 weltiq 로부터 이 연재의 원고료를 받습니다. 아래 결과는 전부 필자가 직접 돌린 것이고, 조합이 진 항목도 그대로 적었습니다

1. 이게 뭔가요

투자 판단을 내는 오픈소스 도구를 서른 개쯤 돌려 보면, 판단의 모양이 두 가지라는 것이 보입니다.

레벨형은 "$222.94 에 사서 $221.56 아래면 틀린 것으로 보고 $228.50 에서 판다"고 말합니다. 배분형은 "이 종목에 자본의 10%"라고 말합니다. 어디서 손절할지는 말하지 않습니다.

배분형이 나쁜 도구라는 뜻이 아닙니다. 포트폴리오 매니저의 말투이고, 원래 그 자리에서는 손절을 말하지 않는 게 정상입니다. 문제는 그 판단을 실제 주문으로 만들 때 생깁니다.

주문을 받는 쪽은 "어디서 틀렸다고 인정할 것인가"를 묻습니다. weltiq 의 재량 주문 입구도 그 칸이 비면 받지 않습니다.

POST /v1/orders/oneoff  {symbol: NVDA, side: buy, qty: "1", price: "222.27", thesis: {...}}
→ 422 {"code":"invalidation_required","detail":"청산 조건(px_below/px_above)이 필요합니다"}

그러면 어떻게 될까요. 대부분의 시스템은 그 칸을 대신 채웁니다. weltiq 도 상주 실행 경로에서는 그렇게 합니다 — 진입 의도에 무효 조건이 없으면 보호 손절 폭을 밴드로 삼아 스스로 만들어 붙입니다. 그 기본값은 2% 입니다.

그래서 주문은 나갑니다. 다만 그 판의 "틀렸다고 인정하는 자리"는 도구가 정한 게 아니라 시스템의 기본값입니다. 나중에 성적표를 볼 때 이 둘이 구별되지 않습니다.

이 글이 하는 일은 그 칸의 저자를 도구 쪽으로 옮기는 것입니다. 수익률을 올리려고 묶는 게 아니고, 묶어야만 주문이 나가는 것도 아닙니다.

저장소 별 라이선스 판단 형태
ai-hedge-fund virattt/ai-hedge-fund 40k+ MIT 배분 (비중·주수)
LangAlpha ginlix-ai/LangAlpha 1.7k Apache-2.0 레벨 (진입·무효화·목표)

2. 설치

두 도구의 설치는 각각 2편과 18편에서 다뤘습니다. 여기서는 조합에 필요한 것만 적습니다.

ai-hedge-fund 쪽 — 만다테 파일 하나

이 도구는 "도구를 실행한다"기보다 만다테(펀드 규약) 하나를 실행합니다. 어느 투자자 모델을 쓸지, 자본이 얼마인지, 종목당 몇 %까지 담을지가 전부 이 파일에 있습니다. 조합에서는 이 파일이 참가자 이름표입니다. 돌리기 전에 박고 회차 내내 바꾸지 않습니다.

# ~/.hedge-fund/mandates/a2-01.yaml
name: a2-01-desk
strategies:
  - name: discretionary
    models: [buffett, lynch, druckenmiller]   # LLM 투자자 셋만
risk:
  max_position_pct: 0.10                      # 종목당 장부의 10%
  max_gross_exposure: 1.0
capital: 2500

장부를 $2,500 로 잡은 이유는 모의 계정의 주문 한도 승인이 주문당 $700 이기 때문입니다. 장부와 비중 상한은 필자가 정하고, 주수는 도구가 그 둘에서 계산합니다.

LangAlpha 쪽 — 막히는 자리 하나

막히는 자리 증상 우회
에이전트 실행에 도커가 필요 턴을 던지면 Starting workspace… 뒤 "An error occurred" 한 줄 도커가 없으면 판단 내용이 든 스킬 문서 8장을 시스템 프롬프트로 얹어 같은 모델에 직접 던집니다

이 글도 그 우회로 돌렸습니다. 그래서 이 글이 본 LangAlpha 는 전체가 아닙니다 — 샌드박스 파이썬 실행, 서브에이전트, 누적 기억, 웹 검색이 빠진 상태입니다. 도커가 있으면 다른 값이 나올 수 있습니다.

시세는 LangAlpha 백엔드의 무료 Yahoo 경로(/api/v1/market-data/*)를 그대로 씁니다. 도커 없이 뜨고, 키가 필요 없습니다.


3. 첫 결과 — 배분형이 무엇을 비워 두는지 보기

python drive.py ~/.hedge-fund/mandates/a2-01.yaml --tickers NVDA \
  --date 2026-09-19 --model openai/gpt-6-astra --out run1.json

이렇게 나오면 성공입니다.

"target_weights": {"NVDA": 1.0},
"clamps": [{"limit": "max_position_pct", "before": 1.0, "after": 0.1}],
"final_weights": {"NVDA": 0.1},
"orders": [{"ticker": "NVDA", "side": "buy", "quantity": 1, "price": 222.27}],

투자자 셋이 각각 판단하고(그 근거 문장도 같이 나옵니다), 확신도로 가중해 목표비중을 만들고, 만다테의 종목당 상한이 그걸 0.10 으로 깎고, 장부 $2,500 × 0.10 ÷ $222.27 = 1주가 됩니다.

quantity 와 price 는 있는데 stop 도 target 도 entry 도 없습니다. price 는 진입가가 아니라 그날 마크(종가)를 그대로 옮긴 값입니다. 이게 배분형의 모양입니다.

같은 조건으로 3회 돌린 결과입니다.

회차 buffett lynch druckenmiller 주문
1 매수 0.76 (확신 76) 매수 0.88 (88) 매수 0.89 (89) 1주 매수
2 매수 0.76 (76) 매수 0.86 (86) 매수 0.88 (88) 1주 매수
3 매수 0.77 (77) 매수 0.82 (82) 매수 0.89 (89) 1주 매수

4. 제일 잘 쓰는 법 — 빈 칸을 다른 도구에게 물어보기

4.1 LangAlpha 는 위임 문서를 줘야 대답합니다

그냥 "NVDA 를 거래해서 수익을 내 줘"라고 던지면 이 도구는 전부 보류합니다. 18편에서 3회 던져 3회 모두 "가격 손절 보류"였습니다.

레벨을 내게 하려면 위임 문서 네 칸을 채워 줘야 합니다. 이 글이 쓴 원문입니다.

- Risk posture: the loss budget is 150 basis points of the book, read as an absolute cap
  that must hold in any state. The book is USD 2,500, so the cap is USD 37.50.
- Horizon: ONE US regular session (09:30-16:00 ET) starting at the next open. ...
  A multi-quarter horizon is outside the mandate and must not be substituted for it.
- The analysis this pitch rests on: none is finished. ... Deliver a screen-grade pitch
  that says the underwriting is still owed rather than declining to state an expression.
- Execution: the order goes to a paper broker that requires, before it will accept
  anything, a written reason, a price level below which the idea is wrong, and a quantity.

"한 세션"만 쓰면 부족합니다. 이 도구의 기본 기간이 2~8분기라서 "다중 분기로 바꿔 쓰지 말 것"을 명시해야 하루 안에서 답합니다. "보류하지 말고 screen-grade 로 내라" 도 없으면 또 보류합니다.

4.2 조합에서 새로 더한 문장 — 분업 조항

여기가 이 글의 새로운 부분입니다. 그냥 물으면 LangAlpha 는 크기까지 다시 정하려 듭니다. 그러면 배분형을 쓴 의미가 없어집니다. 그래서 물음 앞에 이 덩이를 붙였습니다.

DIVISION OF LABOUR FOR THIS PITCH — read this before Step 1:
- The instrument, the direction and the quantity are ALREADY DECIDED by a separate
  allocation desk whose record is quoted below. They are inputs, not questions.
  Do not change them, do not re-argue them, and do not withhold the expression
  because you would have sized it differently.
- What is NOT decided ... is exactly three fields: (1) the invalidation price ...
  (2) the entry condition for the next open; (3) the target.
- The loss budget above constrains the DISTANCE of the stop, not the purchase outlay.

그리고 묻는 문장 한 줄:

Another desk has already decided to buy NVDA. Give me the price level below which that idea is wrong, the entry condition for the next open, and the target. And explain why you set them where you did.

이 뒤에 배분형이 낸 JSON 을 기계적으로 붙입니다 — 만다테 이름, 자본, 비중 상한, 목표비중, 클램프, 주문 한 줄, 그리고 투자자 셋의 근거 문장 원문. 사람이 요약하지 않습니다. 요약하면 그 순간 요약한 사람이 판단에 끼어듭니다.

4.3 나온 답

3회 모두 같은 네 숫자가 나왔습니다.

칸 값 도구가 밝힌 근거
무효화 $221.56 직전 세션 저가. "losing the entire latest session's trading range defeats this particular support-and-recovery thesis. It does not prove the business is impaired."
진입 하한 $222.94 직전 세션 시가
진입 상한 $223.87 도구가 계산. 목표까지의 보상이 손절까지의 위험의 2배가 되는 지점
목표 $228.50 직전 세션 고가. "an observable retest objective... not a fundamental fair-value estimate."

그리고 3회 모두 배분을 건드리지 않았습니다.

Depth: first pass. I retain the desk's direction, instrument and quantity.

4.4 요청하지 않은 답 하나

세 회차 모두, 묻지 않았는데 "당신이 준 손실 예산은 내가 지킬 수 있는 종류가 아니다" 를 따로 적었습니다.

At the ceiling entry, the unchanged allocation's ideal stop loss consumes approximately 6.2% of the stated loss budget, before costs. But a sufficiently large discontinuous decline can exceed that budget; a stop-limit can instead fail to execute altogether.

손절에서 정확히 체결되면 예산의 0.06배를 쓰지만, 주식이 전액 손실이면 예산의 6.0배를 씁니다. 즉 "어떤 상태에서도 지킬 절대 상한"은 보통주 매수로는 애초에 보장되지 않는다는 진단입니다.

배분형 도구는 이런 문장을 받지도, 해석하지도 않습니다. 레벨형을 붙이니 따라왔습니다. 무효화 칸을 채우려고 시작한 일에서 예상 밖으로 나온 이득입니다.


5. weltiq 로 옮기기 — 통합 실험

같은 종목·같은 방향·같은 수량으로 전략 문서를 둘 만들었습니다. 다른 것은 무효화의 출처뿐입니다.

A — 배분형 단독. 진입 조건도 청산 레벨도 없습니다.

진입: (position.size = 0) → 진입 long L
청산: 내부 청산 규칙 · 보호 손절 2%

이 "2%"는 도구가 낸 값이 아닙니다. 규칙 블록의 기본값이고, 상주 실행이 이 폭을 밴드로 삼아 무효화 가격을 스스로 만들어 붙입니다. 배분형 단독의 "틀렸다고 인정하는 자리"는 여기서 나옵니다.

B — 조합. LangAlpha 의 네 숫자가 네 칸에 그대로 들어갔습니다.

진입: ((position.size = 0) AND (개장 후 분 ≤ 1)) AND ((open ≥ 222.94) AND (open ≤ 223.87))
      → 진입 long L · 가격 조건 청산 L (stop=221.56, limit=228.50)
청산: 내부 청산 규칙 · 보호 손절 1.0%

"개장 후 분 ≤ 1"은 도구가 말한 "정규장 공식 시가에서만, 나중에 쫓아가지 않는다"를 옮긴 것입니다. 18편에서는 이 조건을 못 옮겨 장중에도 구간에 닿으면 들어가는 형태가 됐었습니다.

옮기면서 버린 칸도 있습니다. 시간 청산(16:00 ET에 무조건 정리)에는 받을 자리가 없고, "손실 예산 150bp 절대 상한"은 개념이 대응하지 않습니다.

5.1 무효화의 저자가 실제로 바뀌는 화면

글을 쓴 시각이 미국장 개장 전이라 상주 실행에서 체결을 보지는 못했습니다. 대신 같은 엔진을 직전 정규장 1분봉 390개 위에서 돌려 두 문서가 만드는 주문을 직접 봤습니다.

A — 배분형 단독

INTENT OPEN buy 1주
       invalidation = {"px_below": "217.6090"}
FILL   buy 1 @ 222.082205   (정규장 첫 1분)

이 217.6090 을 말한 도구는 없습니다. 첫 봉 종가 $222.05 에 보호 손절 폭의 두 배를 뺀 값입니다. 배분형 단독으로 주문을 내면 "어디서 틀렸다고 인정할지"가 이렇게 정해집니다.

B — 조합 (진입 하한을 1센트 내린 뒤입니다. 왜 그래야 했는지는 바로 다음 5.2절에 적습니다)

INTENT OPEN buy 1주
       invalidation = {"px_below": "221.5600"}
FILL   buy 1 @ 222.082205   (정규장 첫 1분)

같은 종목, 같은 방향, 같은 수량, 같은 분, 같은 체결가입니다. 다른 것은 무효화뿐입니다 — 한쪽은 시스템이 만든 $217.61, 한쪽은 도구가 지목한 $221.56. 이 글이 하려던 일은 이 한 칸입니다.

5.2 그런데 조합은 원래 값으로는 들어가지도 못했습니다

위 B 를 돌리려고 필자가 숫자 하나를 바꿔야 했습니다. 진입 하한 $222.94 를 $222.93 으로, 1센트 내렸습니다. 바꾸기 전에는 진입이 한 번도 걸리지 않았습니다.

원인은 판단이 아니라 자료원입니다. 도구는 일봉에서 9월 21일 시가를 $222.94 로 읽었는데, 주문을 내는 쪽이 보는 정규장 첫 1분봉의 시가는 $222.93 이었습니다.

레벨 셋을 전부 맞대 보면 같은 일이 반복됩니다.

도구가 지목한 값 무엇이라고 했나 1분봉 실측 차이
$222.94 9/21 시가 222.93 −1센트
$228.50 9/21 고가 228.49 −1센트
$221.56 9/21 저가 221.58 +2센트

세 레벨이 전부 실제 범위의 바깥쪽 한 틱에 서 있습니다. 그래서 이 재생에서는 진입도, 목표도, 손절도 하나도 걸리지 않았습니다.

도구가 틀린 게 아닙니다. 옮기는 과정에서 잃은 것입니다. 일봉과 1분봉은 개장·종가 처리와 장전·장후 포함 여부가 달라서 끝값이 어긋납니다. 레벨형 도구를 붙일 때는 그 도구에 주는 시세를, 주문을 내는 쪽이 보는 시세와 같은 계열로 맞춰야 합니다. 이 글은 그러지 않았고, 그 대가를 1센트로 치렀습니다.

(1센트 내린 그 값은 도구가 낸 숫자가 아니므로, 아래 출처 표에는 원래 값을 적고 바꾼 사실은 여기에 적습니다.)


6. 써 보니

6.1 출처 표 — 이 글의 핵심 그림

최종 주문의 모든 숫자 옆에 어느 도구의 어느 호출에서 나왔는지 적은 표입니다.

칸 값 출처
종목 NVDA 미션 입력 (이 도구는 종목을 스스로 안 고릅니다)
방향 매수 ai-hedge-fund 1·2·3회차
크기 1주 ai-hedge-fund ($2,500 × 0.10 ÷ $222.27)
진입 하한 $222.94 LangAlpha 1·2·3회차
진입 상한 $223.87 LangAlpha 1·2·3회차
무효화 $221.56 LangAlpha 1·2·3회차
목표 $228.50 LangAlpha 1·2·3회차
보호 손절 % 1.0% LangAlpha 2회차 원문
근거 문장 원문 양쪽 합본

필자가 만든 숫자: 0개. 필자가 한 일은 넷이고 전부 숫자가 아닙니다 — 만다테 두 파일을 미리 고정, 묻는 문장 작성, 한쪽 출력을 다른 쪽 프롬프트로 기계 조립, 도구가 낸 네 숫자를 규칙 문서의 네 칸에 옮기기.

두 군데는 밝혀 둡니다. 하나, 보호 손절은 처음에 필자가 $(223.87−221.56)/223.87 = 1.03\%$ 로 계산해 넣었다가 도구가 원문에 쓴 "−1.0%" 로 바꿨습니다 — 소수점 둘째 자리가 필자가 만든 정밀도였습니다. 둘, 5.2절의 1센트는 필자가 바꾼 숫자이므로 위 표에 넣지 않았고, 그 판은 조합 성적으로도 세지 않았습니다.

6.2 셋을 나란히

세 번째 갈래로 도구 없이 필자가 직접 판단한 것도 3회 만들었습니다(대조군). 원문은 검증 기록에 전부 있습니다.

단독 조합 필자 단독
여섯 칸 충족 4/7 7/7 7/7
무효화의 저자 시스템 기본값 도구 사람
3회 일관성 주수 3/3 동일 네 숫자 3/3 동일 무효화 3회 전부 다름 ($224.60 / $225.50 / $226.00)
한 바퀴 비용 $0.05 $0.38 —

칸 충족률만 보면 조합과 필자 단독이 같습니다. 갈리는 곳은 두 군데입니다.

첫째, 일관성. 조합은 세 번 다 같은 숫자를 냈고, 필자는 세 번 다 다른 자리를 짚었습니다. 셋 다 그럴듯했고, 어느 것이 옳은지 필자는 근거를 대지 못합니다.

둘째, 근거의 종류. 도구는 무효화 옆에 "직전 세션 저가"라는 관측된 사실을 달고, 그 사실이 무엇을 반증하는지까지 적습니다("지지·회복 가설이 깨진다, 사업이 훼손됐다는 뜻은 아니다"). 필자의 $224.60 은 자료에 없는 숫자입니다.

6.3 조합이 진 것

6.4 이 조합이 뜻을 갖는 이유의 절반은 제약입니다

솔직하게 적습니다. 이 조합이 의미를 갖는 이유의 절반은 weltiq 가 "어디서 틀렸다고 인정할지"를 요구하기 때문입니다.

그 요구가 없는 곳에서는 배분형 도구의 출력을 그대로 주문으로 보내면 그만이고, 무효화의 저자가 누구인지 아무도 묻지 않습니다. 그러면 이 조합은 필요 없을 수도 있습니다.

다만 그 요구가 없는 곳에서는, 나중에 성적표를 볼 때 "논거가 틀려서 나왔다"와 "그냥 빠져서 나왔다"를 가를 방법도 없습니다. 어느 쪽이 낫다고 이 글이 결론 내리지는 않겠습니다.


7. 다음 행동

이 조합은 두 도구가 겹치는 칸을 내지 않아서 성립했습니다. 그래서 고를 것이 없었습니다. 둘이 같은 칸에 다른 값을 낼 때는 규칙을 먼저 정해 공개해야 합니다 — 다음 편에서 방향이 정면으로 갈린 도구 둘을 붙여 그 경우를 다룹니다.

weltiq 준비 1. 가입 → 마이 → 연결 관리에서 키 발급 2. claude mcp add weltiq --transport http https://weltiq.ai/mcp --header "Authorization: Bearer <키>" 3. 모의 전용입니다. 실주문은 별도 승인 절차를 거칩니다


필자 토니 브라운. 검증 원문·실패한 시도·결함 목록은 검증 기록에 있습니다.