서론: Harness Engineer 사상
최근 AI/ML 엔지니어링 커뮤니티에서 점점 더 널리 논의되는 사고 방식이 있습니다. 바로 Harness Engineer입니다.
그 핵심 개념은 간단합니다:
스스로 답을 내놓기보다 프레임워크를 구축하여 데이터와 실험이 스스로 답을 찾도록 하는 것입니다.
전통적인 엔지니어 방식은: 내가 파라미터 A가 좋다고 생각하니, A를 구현하는 코드를 작성합니다. Harness Engineer 방식은: 나는 A, B, C 중 어떤 것이 좋은지 모르니, 프레임워크를 구축하여 A, B, C를 동시에 실행하고 데이터가 답을 알려주도록 합니다.
엔지니어는 검색 공간과 평가 기준을 정의하고, 시스템은 공간 내에서 자동 최적화를 수행합니다. 이러한 사고는 머신러닝에서는 walk-forward optimization, AutoML에 해당하며, 퀀트에서도 자연스럽게 적용될 수 있는 영역이 있습니다.
요코인(妖幣): 추세가 가장 뚜렷한 전장
암호화폐 선물 시장에서 특별히 주목할 만한 코인 유형이 있습니다. 바로 거래량이 매우 큰 "요코인"입니다.
이러한 코인 유형에는 몇 가지 공통 특징이 있습니다:
- 자금이高度集中되어 있으며, 세력 행동이 뚜렷함
- 추세 지속성이 상대적으로 강함 – 한 번 발동하면 지속 기간이 긴 편
- 변동성이 높음 – 일부 고거래량 코인은 특정 기간에 강한 추세성을 보이며, 이동평균선 전략이 이러한 종목에서 과거 백테스트 결과가 상대적으로 좋음
따라서 이러한 코인 유형에 고전적인 이중 이동평균선 교차 전략을 사용하는 것은 단순하면서도 합리적인 접근 방식입니다. 빠른 선이 느린 선을 돌파하면 추세 시작, 따라가기; 빠른 선이 느린 선을 하향 돌파하면 추세 반전, 이탈. 논리는 간단하지만, 추세가 뚜렷한 종목에서는 과거 성과가 나쁘지 않은 경우가 많습니다.
문제는 하나뿐입니다: 어떤 코인이 요코인인가? 어떤 이동평균선 파라미터를 사용할 것인가?
이 두 질문을 인위적으로 판단하려 하면 주관성이 너무 강해져서, 사람마다 완전히 다른 답이 나올 수 있습니다. 게다가 시장은 역동적이어서, 오늘의 요코인이 내일의 요코인이 아닐 수도 있고, 오늘 유효한 파라미터 조합이 내일은 무용지물이 될 수도 있습니다.
이것이 바로 Harness Engineer 사상이 등장하는 지점입니다.
인위적으로 코인을 선택하고 파라미터를 조정하는 대신, 이 두 질문을 모두 프레임워크에 맡겨 해결하도록 합시다. 평가 기준을 정의하고, 과거 데이터가 후보 공간 내에서 스스로 답을 찾아내도록 하는 것입니다. 인간은 무엇을 기준으로 좋고 나쁨을 측정할지 결정하기만 하면 되고, 나머지는 시스템에 맡깁니다.
이러한 생각을 바탕으로 전체 전략은 롤링 필터링 프레임워크로 설계되었으며, 세 단계로 작동합니다.
전략 아키텍처: 2단계 경마 메커니즘
1단계: 종목 풀 구성
전체 시장의 선물 종목 중에서 달러 거래량 기준 내림차순으로 상위 150개 코인을 후보 풀로 선정합니다.
왜 거래량인가? 거래량이 많은 곳은 자금이 가장 집중되고, 추세가 가장 쉽게 형성되며, 요코인도 가장 밀집되어 있기 때문입니다. 이 단계에서는 주관적인 판단을 하지 않고 순수하게 시장 자금이 투표하도록 하여, 거래량이 큰 코인이 풀에 들어오게 합니다.
javascript
const filtered = tickers
.filter(t => t.Symbol.endsWith('USDT.swap'))
.map(t => ({ symbol: t.Symbol, quoteVolume: t.Last * t.Volume }))
.sort((a, b) => b.quoteVolume - a.quoteVolume)
.slice(0, topN)
.map(t => t.symbol);
로직은 매우 직접적입니다: USDT 선물 종목을 필터링하고, 달러 거래량을 계산하고, 내림차순 정렬한 후 상위 N개를 취합니다. 주관적인 판단은 전혀 없으며, 시장 자금이 스스로 투표합니다.
2단계: 2단계 경마 최적 선택
이것은 전체 전략에서 가장 핵심적인 부분이며, Harness 사상이 가장 뚜렷하게 드러나는 곳입니다.
올바른 실행 순서는 다음과 같습니다:
⚠️ 참고: 최적 파라미터의 점수로 해당 코인의 능력을 대표하는 것은 그 자체로 일정한 과적합 위험을 내포합니다. 역사적으로 가장 좋은 성과를 낸 파라미터가 미래에도 동일하게 효과적일 것이라는 보장은 없습니다. 이러한 한계는 글 후반부에서 더 논의될 것입니다.
백테스트 과정
후보 풀에 있는 각 코인에 대해 여러 MA 파라미터 조합을 동시에 실행합니다. 각 파라미터 조합은 과거 K라인에서 독립적으로 실행되어 실제 교차 매매 로직을 시뮬레이션합니다:
javascript
// 각 코인 × 각 파라미터 조합 순회
for (const params of maParamsList) {
const bt = backtest_MA(records, params.fast, params.slow);
// 각 백테스트는 독립적으로: 승률, 손익비, 최대 낙폭, 신호 횟수 산출
}
각 백테스트의 핵심 로직은 표준 이중 이동평균선 교차입니다:
javascript
const crossUp = fastMA[i-1] <= slowMA[i-1] && fastMA[i] > slowMA[i];
const crossDown = fastMA[i-1] >= slowMA[i-1] && fastMA[i] < slowMA[i];
if (crossUp) position = { side: 'long', entryPrice: records[i].Close };
if (crossDown) position = { side: 'short', entryPrice: records[i].Close };
종합 점수
백테스트 완료 후, 각 파라미터 조합의 백테스트 결과에 대해 종합 점수를 계산합니다. 점수는 두 부분으로 구성됩니다:
표준화 가중치 점수 (합계 계수 0.80):
javascript
const score =
Math.min(bt.winRate * 100, 100) * 0.30 // 승률, 상한 100
+ Math.min(bt.profitFactor * 20, 60) * 0.30 // 손익비, 상한 60
+ Math.max(0, 1 - bt.maxDrawdown / maxMDD) * 100 * 0.20 // 최대 낙폭 통제
+ volPct * volPctBonus // 변동성 분위 보너스 가점 항목
변동성 분위 보너스 가점 항목: 마지막 항목 volPct × volPctBonus (기본 계수 10)은 가중치 시스템과 별개인 보너스 항목으로, 동일한 점수 조건에서 현재 변동성이 역사적 높은 분위에 있는 코인을 선호하도록 합니다. 이러한 코인은 추세가 더 활발한 경향이 있기 때문입니다.
설명하자면, 이 가중치와 보너스 계수는 모두 경험적 설정이며 최적화를 통해 도출된 것이 아닙니다. 실제 사용 시 시장 환경에 따라 추가 조정할 수 있습니다.
1단계 경쟁: 파라미터 경쟁
같은 코인의 여러 파라미터 조합이 각각 점수를 산출하고, 가장 높은 점수를 받은 조합을 해당 코인의 대표 점수 및 최적 파라미터로 사용합니다:
javascript
if (score > bestScore) {
bestScore = score;
bestResult = bt;
bestParams = params; // 현재 역사적으로 가장 좋은 성과를 낸 파라미터 조합 기록
}
2단계 경쟁: 코인 경쟁
모든 코인이 각자의 최고 점수를 내놓고, 순위를 매긴 후 상위 N개를 화이트리스트로 선정합니다:
javascript
results.sort((a, b) => b.score - a.score);
const whitelist = results.slice(0, topCoins).map(r => r.coin);
최종 출력은 각 화이트리스트 코인에 해당하는 전용 최적 이동평균선 파라미터이며, 하나의 파라미터 세트로 모든 코인을 처리하지 않습니다.
3단계: 실매매 실행 및 리스크 관리
선별된 구성으로 실매매를 진행하며, 동시에 다중 리스크 관리 메커니즘을 추가합니다:
신호 트리거: 화이트리스트 코인의 이동평균선 교차 상태를 실시간 감지하여, 골든크로스 시 매수, 데드크로스 시 매도합니다:
javascript
const crossUp = fastPrev <= slowPrev && fastCur > slowCur;
const crossDown = fastPrev >= slowPrev && fastCur < slowCur;
if (crossUp) longList.push(sym);
if (crossDown && allowShort) shortList.push(sym);
트레일링 스탑 이익: 미실현 이익이 트리거 임계값에 도달하면 활성화되며, 손절 임계값은 미실현 이익에 따라 동적으로 강화됩니다. 3단계 임계값은 경험적 설정이며, 핵심 논리는 미실현 이익이 높을수록 손실 허용 폭이 작아져 기존 이익을 보호하는 것입니다:
javascript
function getDynamicTrailDrawdown(maxPnl) {
if (maxPnl >= 7) return 3; // 미실현 이익 높음, 손실 허용 폭 축소
if (maxPnl >= 4) return 2;
return 1.5; // 미실현 이익 낮음, 시장에 더 많은 여유 제공
}
시장 상태 감지: BTC 변동성 분위를 감지하여, 높은 변동성 환경에서는 포지션 계수를 자동으로 낮추고, 극단적인 시장에서는 매도를 직접 금지합니다:
javascript
if (marketState === 'volatile') positionScaleDown = 0.5;
else if (marketState === 'high_vol') positionScaleDown = 0.8;
else if (marketState === 'low_vol') positionScaleDown = 0.7;
전체 선별 프로세스는 주기적으로 롤링 재실행되며, 하나의 구성에 고정되지 않고 시장에 따라 화이트리스트와 파라미터를 동적으로 업데이트합니다.
기본 가정: 추세의 지속성
이 프레임워크가 성립하려면 핵심 가정 하나에 의존합니다:
최근 역사에서 좋은 성과를 보인 코인과 파라미터는 단기간 내에도 어느 정도 지속성을 가질 것이다.
이것은 미신이 아닙니다. 그 뒤에는 일정한 시장 논리적 지지가 있습니다——자금 관성, 시장 감정의 지속, 주요 플레이어 행동의 일관성은 트렌드가 일정 시간 창 내에서 유효하게 유지되도록 합니다.
하지만 솔직히 말하자면: 이 가정은 엄격한 통계적 검증을 거치지 않았습니다. 그것은 경험적 판단에 가깝습니다. 프레임워크가 실제 거래에서 지속적으로 유효한지 여부는 결국 실제 거래 데이터를 통해 검증되어야 합니다.
진정한 Harness Engineer와의 차이점
이 점을 분명히 해야 합니다.
이 전략은 Harness의 형태를 갖추고 있지만, 진정한 Harness Engineer 시스템과 비교하면 여전히 명백한 차이가 있습니다:
| 차원 | 진정한 Harness | 이 전략 |
|---|---|---|
| 샘플 분할 | 훈련 세트 + 검증 세트 + 홀드아웃 테스트 세트 | 전체 과거 데이터 백테스팅, 샘플 외 검증 없음 |
| 과적합 방어 | 명확한 일반화 검증 있음 | 매개변수 다양성으로 부분적으로 상쇄하지만 불완전함 |
| 실험 격리 | 각 변형이 독립적으로 실행되어 상호 영향 없음 | 동일한 K라인 공유, 암묵적 결합 존재 |
| 출시 기준 | 배포 전 validation 통과 필요 | 점수가 가장 높으면 바로 출시, 2차 검증 단계 없음 |
| 오차 누적 | 각 계층 평가 독립적 | 두 단계 경마 모두 과거 최적에 기반, 오차 누적 |
핵심 차이는: 진정한 Harness는 "이 결과가 표본 외에서도 유효한가?"를 묻는 반면, 이 전략의 두 단계 경마에서 선택된 "최적"은 본질적으로 과거 최적에 불과합니다. 매개변수 수준의 과적합에 코인 수준의 과적합이 중첩되어, 미래까지 지속될 수 있을지는 영원한 미제로 남습니다.
결론: 새는 화살을 찾는 격인가, 시도해볼 만한가?
퀀트 세계에서 예측은 언제나 극도로 어려운 일입니다.
많은 사람들은 과거 데이터로 매개변수를 선택하여 실전 거래에 사용하는 것이 본질적으로 새는 화살을 찾는 격이라고 말합니다. 즉, 칼이 이미 물에 빠졌는데 배에 새긴 흔적이 그것을 찾는 데 도움이 되지 않는 것과 같습니다. 시장은 변하고, 유효했던 매개변수는 무효화되며, 오늘의 요정 코인은 내일 평범해질 수 있고, 어제의 최적 이동평균선은 오늘은 잡음일 수 있습니다.
이 비판이 전혀 근거가 없는 것은 아닙니다.
하지만 돌이켜 보면, 시도해볼 만한 일은 해봐야 합니다.
퀀트의 본질은 영원히 옳은 답을 찾는 것이 아니라, 불확실성 속에서 체계적으로 승률을 높이는 것입니다. 설령 새는 화살을 찾는 격이라 할지라도, 먼저 배가 있어야 하고 그 흔적을 새겨야 합니다——전략을 위치시키는 것(배) 자체가 퀀트의 시작입니다.
물론 프레임워크 자체가 수익을 보장하지는 않습니다. 프레임워크를 갖추는 것은 시작에 불과하며, 진정한 가치는 지속적인 실행과 반복에 있습니다: 화이트리스트 조정, 평가 가중치 변경, 매개변수 공간 확장, 손절 및 이익 실현 최적화 등이 가능합니다. 매번의 조정은 새로운 실험이며, 이 프레임워크를 진정한 Harness에 더 가깝게 만드는 과정입니다.
길은 생각만으로 생기는 것이 아니라, 걸어서 생기는 것입니다.
전략 소스 코드: Harness Engineer 이동평균선 선정 퀀트 전략
- 1



