티스토리 뷰

전 코인에 같은 전략을 쓰고 있었다

구조적인 한계가 있었다. LLM은 recommended_strategy 하나만 응답하고, 봇은 그걸 전 코인에 똑같이 적용했다. BTC도 ENSO도 WET도 같은 전략. 시장이 혼재될 땐 어떤 코인엔 맞고 어떤 코인엔 안 맞는다.

백테스트로 확인해봤다. 코인별 최적 전략이 완전히 달랐다.

KRW-ENSO    breakout_momentum(entry=10)        +92.0%
KRW-WET     bollinger_bands(bb=2.5)            +59.9%
KRW-RENDER  ma_crossover(short=5, long=20)     +45.0%
KRW-TAO     volatility_breakout(k=0.7)         +41.6%
KRW-NEAR    volatility_breakout(k=0.7)         +36.7%

같은 기간에 bb_rsi_combined만 쓰면 ENSO -9.7%, RENDER -1.6%. 전략 선택 하나로 100%p가 갈렸다.

코인별 전략 배정을 LLM에게

처음에 떠오른 방법은 코인별로 LLM을 따로 호출하는 것. 8코인이면 8번. 토큰 시뮬레이션을 돌려보니 답이 안 나왔다.

현재 (단일 전략)         호출당 $0.064  ×  월 1080회 = $69
코인별 개별 호출(8개)    호출당 $0.384  ×  월 1080회 = $414

월 $414는 답이 아니다. 한 번의 호출로 모든 코인 전략을 받는 방식으로 갔다.

{
  "coin_strategies": {
    "KRW-BTC":  {"strategy": "volatility_breakout", "params": {"k_value": 0.7}},
    "KRW-ETH":  {"strategy": "volatility_breakout", "params": {"k_value": 0.5}},
    "KRW-ENSO": {"strategy": "breakout_momentum",   "params": {"entry_period": 10}}
  }
}

DB에는 coin_strategy_assignment 테이블 신설. coin을 PRIMARY KEY로, 전략명과 파라미터를 dict로 저장. StrategySelector.get_coin_strategy()가 매 틱마다 코인별로 전략을 분기해서 적용한다.

호출 비용은 $0.064 → $0.072로 약간 늘었다. 월 $73~78. 단일 호출 대비 약간 비싸지만, 코인별 호출 대비 1/5 수준. 다음 단계는 이걸 다시 $69로 내리는 것이었다.

프롬프트 캐싱 — 비용 80% 절감 시도

Anthropic의 Prompt Caching을 켜기로 했다. 같은 시스템 프롬프트를 반복해서 보내니까 캐시가 정확히 우리 케이스다. 1시간 TTL의 sliding window 방식.

기대효과: 시스템 프롬프트 4000+ 토큰을 캐시에서 읽어오면 비용이 80% 정도 절감된다. cache_control 플래그 하나만 붙이면 끝일 것 같았다. 그렇게 며칠 운영했다.

cache_creation/cache_read_tokens가 0이다

24시간 LLM 동작 분석을 돌렸다. cache_creation_tokens 0. cache_read_tokens 0. 캐시가 아예 작동하지 않고 있었다. 에러도 없었다. Silent skip이었다.

Anthropic 문서를 다시 읽고, 토큰 카운트를 직접 측정해봤다. 우리 SYSTEM_PROMPT는 4053 토큰이었다. Haiku 4.5의 캐시 최소 단위는 4096 토큰. 43 토큰 부족이라 캐시 자체가 적용되지 않고 있었다.

이게 끝이 아니었다. INTERVAL_ACTIVE_MIN=60으로 정확히 1시간 간격으로 호출하고 있었는데, Anthropic 1h 캐시는 sliding window라 hit하면 TTL이 1시간 자동 연장된다. 정확히 60분 후 호출은 timing race로 종종 expired 상태가 된다.

두 가지 수정

SYSTEM_PROMPT를 4096 토큰 이상으로 보강했다. 매도-매수 신호 충돌 안내 섹션 등을 추가해 4441 토큰으로 올렸다. 마진 345 토큰. 실수로 줄어들지 않게 회귀 테스트도 추가:

def test_system_prompt_meets_haiku_45_cache_minimum():
    # 4096 토큰 = 약 6000자
    assert len(SYSTEM_PROMPT) >= 6000

def test_interval_active_under_one_hour_for_cache_sliding_window():
    assert INTERVAL_ACTIVE_MIN < 60  # 55분

호출 간격은 60분 → 55분으로 줄였다. sliding window 안전 마진을 두기 위해. MAX_DAILY_CALLS는 20 → 30 (55분 × 24시간 ≈ 26회 + 여유).

결과

다음날 캐시 hit 90%+ 달성. 24시간 18건 호출 비용이 $0.66 → 약 $0.13. 비용 1/5. 30회까지 늘려도 약 $0.20 수준. 월 $69 목표를 맞췄다.

이 과정에서 두 가지를 배웠다. 첫째, 캐싱 SDK 옵션을 켰다고 캐싱이 되는 게 아니다. 모델별 최소 토큰 제약이 있고, 호출 간격이 TTL 경계에 걸리지 않게 마진을 둬야 한다. 둘째, 실측을 안 했으면 영원히 모르고 비용을 다 내고 있었을 것이다. Anthropic 청구서에 캐시 hit이 명시적으로 안 나왔다면 발견 못 했다.

다음 글

이렇게 코어 리뷰 + 코인별 전략 + 캐싱까지 마무리했다. 그리고 한 달이 지났다. 50만원 입금해서 47만원이 됐다. -6%, -3만원 손실. 승률은 67%인데 적자였다. 진짜 범인을 찾아야 했다. 다음 글에서 풀어본다.


반응형
댓글