프랍 챌린지에서 탈락하는 이유는 대개 두 가지입니다. 일일 손실 한도를 넘겼거나, 최대 낙폭을 건드렸거나. 두 조건 모두 ‘알고 있었지만 실시간으로 보지 못했다’는 상태에서 발생합니다. 이 부분은 코드로 감시할 수 있습니다.

먼저 전제: 프랍 펌마다 자동매매와 계좌 접근에 대한 규정이 다릅니다. API로 계좌를 조회하는 것조차 제한하는 곳이 있습니다. 시작 전에 해당 펌의 약관을 반드시 확인해야 합니다. 아래는 규정이 허용되는 경우의 기술 구조입니다.

감시해야 하는 값은 네 개

챌린지 규정은 표현이 조금씩 달라도 대체로 이 네 가지로 환산됩니다.

  1. 일일 손실: 기준 시각(펌이 정한 서버 시간) 시작 자산과 현재 자산의 차이
  2. 최대 낙폭: 계좌 최고 자산 대비 현재 자산의 하락폭. 고점 기준인지 초기 잔고 기준인지 반드시 확인해야 합니다
  3. 목표 수익: 통과 조건
  4. 거래일 수 / 보유 시간: 최소 거래일이나 주말 보유 금지 같은 조건

1번과 2번은 실시간 감시 대상이고, 3번과 4번은 일 단위 집계로 충분합니다.

기본 감시 루프

계좌 요약을 주기적으로 조회해 규정과 비교하는 것이 전부입니다. 복잡한 부분은 조회가 아니라 ‘기준값을 어디에 저장하는가’입니다.

import requests, os, datetime

H = {"x-api-key": os.environ["MTAPI_KEY"]}
BASE = "https://api.metatraderapi.net"

RULES = {
    "daily_loss_pct": 5.0,   # 일일 손실 한도 5%
    "max_dd_pct":    10.0,   # 최대 낙폭 10%
}

def summary(acc_id):
    return requests.get(f"{BASE}/AccountSummary",
                        params={"id": acc_id}, headers=H, timeout=10).json()

def check(acc_id, state):
    s = summary(acc_id)
    equity = s["equity"]

    # 기준값 갱신: 하루 시작 자산과 역대 최고 자산
    today = datetime.datetime.utcnow().date().isoformat()
    if state.get("day") != today:
        state["day"] = today
        state["day_start_equity"] = equity
    state["peak_equity"] = max(state.get("peak_equity", equity), equity)

    daily_loss = (state["day_start_equity"] - equity) / state["day_start_equity"] * 100
    drawdown   = (state["peak_equity"]      - equity) / state["peak_equity"]      * 100

    alerts = []
    if daily_loss >= RULES["daily_loss_pct"] * 0.8:
        alerts.append(f"일일 손실 {daily_loss:.2f}% — 한도 {RULES['daily_loss_pct']}%")
    if drawdown >= RULES["max_dd_pct"] * 0.8:
        alerts.append(f"낙폭 {drawdown:.2f}% — 한도 {RULES['max_dd_pct']}%")
    return alerts, state

핵심은 한도의 80%에서 경고를 보내는 것입니다. 100%에 도달했을 때 알림을 받으면 이미 탈락입니다.

기준 시각을 틀리면 전부 틀립니다

‘일일’의 기준 시각은 펌이 정합니다. 브로커 서버 시간 자정인 경우가 많고, 서머타임에 따라 한국 시간과의 차이가 바뀝니다. 한국 시간 자정으로 계산하면 하루가 어긋나 손실 한도 계산이 무의미해집니다.

계좌를 여러 펌에 두고 있으면 펌별로 기준 시각을 따로 저장해야 합니다. 이 값을 코드에 하드코딩하지 말고 계좌 설정으로 관리하는 편이 좋습니다.

낙폭 기준을 확인하세요

같은 “최대 낙폭 10%”가 두 가지 뜻일 수 있습니다.

  • 정적(static): 초기 잔고 기준. 계좌가 수익을 내도 한도선은 그대로입니다.
  • 추적(trailing): 역대 최고 자산 기준. 수익이 나면 한도선도 따라 올라갑니다.

추적 방식이면 최고 자산을 계속 저장해야 하므로, 감시 프로세스가 재시작되어도 값이 남는 곳(파일이나 데이터베이스)에 보관해야 합니다. 메모리에만 두면 재시작 후 낙폭 계산이 리셋되어 위험을 놓칩니다.

계좌가 여러 개일 때

챌린지를 여러 개 동시에 진행하면 계좌마다 규정과 진행 상황이 다릅니다. 계좌 ID를 배열로 두고 같은 감시 함수를 돌리되, 규정과 상태는 계좌별로 분리해 저장합니다.

ACCOUNTS = [
  {"id": "...", "firm": "A", "rules": {"daily_loss_pct": 5, "max_dd_pct": 10}},
  {"id": "...", "firm": "B", "rules": {"daily_loss_pct": 4, "max_dd_pct":  8}},
]
for a in ACCOUNTS:
    alerts, a["state"] = check(a["id"], a.get("state", {}))
    for m in alerts:
        notify(f"[{a['firm']}] {m}")

이 지점에서 계좌 수에 따라 비용이 늘어나는 구조라면 챌린지 여러 개를 병행하기 어렵습니다. 계좌 수와 무관한 플랜인지 요금제에서 미리 확인하는 편이 좋습니다.

감시만 할 것인가, 개입할 것인가

경고에서 멈추지 않고 자동으로 포지션을 정리하도록 만들 수도 있습니다. 다만 자동 청산은 신중해야 합니다. 일시적인 스프레드 확대나 시세 오류로 자산이 순간적으로 튀는 경우가 있고, 그때 전량 청산되면 스스로 손실을 확정하게 됩니다.

실무적으로는 두 단계가 안전합니다. 한도 80%에서 신규 진입만 차단하고, 90%에서 단계적으로 축소합니다. 전량 청산은 마지막 수단으로 둡니다.

기록을 남겨야 다음 챌린지가 쉬워집니다

계좌별 자산 곡선과 알림 이력을 저장해 두면, 탈락했을 때 어느 시점에 무엇이 어긋났는지 확인할 수 있습니다. 다음 챌린지의 한도 설정을 감으로 정하지 않게 되는 유일한 방법입니다.

계좌 조회를 API로 처리하는 기본 연결 순서는 한국 사용자 안내에서 확인할 수 있습니다.

본 글은 기술 구현 정보이며 투자 권유가 아닙니다. 프랍 펌의 자동매매·계좌 접근 규정은 펌마다 다르므로 이용 전 약관을 직접 확인해야 합니다.

자주 묻는 질문

프랍 챌린지 계좌에 API를 연결해도 되나요?

펌마다 규정이 다릅니다. 자동매매나 외부 계좌 접근을 제한하는 곳도 있으므로 이용 전 해당 펌의 약관을 반드시 확인해야 합니다.

최대 낙폭 계산에서 가장 흔한 실수는 무엇인가요?

기준이 초기 잔고인지 역대 최고 자산인지 확인하지 않는 것, 그리고 최고 자산 값을 메모리에만 저장해 프로세스 재시작 시 초기화되는 것입니다.

MT4·MT5 계좌를 코드로 연결하기

계정을 만들고 API 키를 받으면 30분 안에 첫 계좌 조회와 주문을 실행할 수 있습니다.

계정 만들기 → API 문서 보기