본문으로 건너뛰기

cBot 빌드 및 백테스트

in-browser Monaco IDE에서 cTrader cBot(C# 및 Python, 모두 .NET)을 빌드, 실행, 백테스트하고 공식 ghcr.io/spotware/ctrader-console 이미지에서 실행합니다.

빌드​

  • Builder 페이지는 Monaco 에디터를 호스팅하고, CBotBuilder는 dotnet build를 일회용 컨테이너에서(AppOptions.BuildImage, 작업 디렉토리는 /work에 바인드 마운트됨) 프로젝트를 컴파일하므로 신뢰할 수 없는 사용자 MSBuild가 호스트에 접근하지 않습니다. NuGet 복원은 공유 볼륨을 통해 빌드 간에 캐시됩니다. 웹 호스트는 Docker 소켓 접근이 필요합니다.
  • C# 및 Python 시작 템플릿은 src/Nodes/Builder/Templates/에 있습니다.

실행 및 백테스트​

  • Instance(인스턴스) = TPH 상태 계층 구조(Run/Backtest × Pending/Scheduled/Starting/Running/Stopping/Stopped/Failed). 전환은 엔티티를 교체합니다(ID 변경), 컨테이너 ID는 유지됩니다.
  • NodeScheduler는 가장 부하가 낮은 적격 노드를 선택하고, ContainerDispatcherFactory는 원격 노드 HTTP 에이전트 또는 로컬 Docker 디스패처로 라우팅합니다.
  • 완료 폴러는 종료된 컨테이너를 조정합니다(백테스트 컨테이너는 --exit-on-stop을 통해 자체 종료됨). 보고서 있음 → 완료됨(ReportJson 저장), 없음 → 실패함.
  • 라이브 컨테이너 로그는 SignalR을 통해 브라우저로 스트리밍되고, 백테스트 에퀴티 곡선은 보고서에서 파싱되어 차트로 표시됩니다.

백테스트 시장 데이터는 계정별로 캐시됩니다​

cTrader Console은 역사적 틱/봉 데이터를 --data-dir에 다운로드합니다. 해당 디렉토리는 거래 계정(계정 번호)을 키로 하는 안정적이고 영구적인 캐시로, 노드의 디스크에서 노드 자신의 컨테이너 경로(/mnt/data)에 바인드 마운트되어 있으며, 인스턴스별 작업 디렉토리에서 별도의 중첩되지 않은 마운트입니다. 따라서 같은 계정의 모든 백테스트는 이미 다운로드된 데이터를 재사용하므로 매번 백테스트할 때마다 다시 다운로드할 필요가 없습니다. (이전에는 데이터 디렉토리가 인스턴스별 작업 디렉토리 아래에 있었고, 실행할 때마다 ID가 변경되어 매번 새로 다운로드해야 했습니다.) 임시 인스턴스별 작업 디렉토리는 여전히 알고리즘, 매개변수, 암호 및 보고서를 보유합니다. 공유 데이터 캐시는 노드의 백테스트-데이터 사용량으로 계산되고 노드-클린 작업으로 삭제됩니다.

백테스트 설정​

Backtest 대화상자는 사용자가 튜닝할 수 있는 cTrader Console 백테스트 설정을 표시하므로 명령줄을 건드릴 필요가 없습니다.

  • Symbol / Timeframe — 타임프레임은 모든 cTrader 기간의 드롭다운(t1…t1000, m1…m45, h1…h12, D1/D2/D3, W1, Month1, 그리고 Renko/Range/Heikin 기간)이며, 콘솔의 정규 대소문자로 표시되므로 항상 유효한 --period를 선택합니다.
  • From / To — 백테스트 기간(--start / --end).
  • Data mode — 세 cTrader 모드 중 하나(--data-mode): Tick data (tick, 정확), m1 bars (m1, 빠름), 또는 Open prices only (open, 가장 빠름).
  • Starting balance — 기본값은 10000(--balance). 0 잔액은 거래를 하지 않고 cTrader가 빈 보고서를 내보내도록 하여 충돌시킵니다("Message expected"), 따라서 0이 아닌 잔액이 항상 전송됩니다.
  • Commission — --commission.
  • Spread — --spread, 0 아래로 갈 수 없는 수치 필드입니다. Tick data 모드에서는 숨겨집니다. cTrader는 틱 데이터 자체에서 스프레드를 도출합니다(--spread는 전송되지 않음).

데이터 디렉토리(--data-file / --data-dir)는 앱 자체에서 관리되므로(계정별 캐시, 위 참조) 대화상자에 표시되지 않습니다.

:::note cTrader는 빈 백테스트에서 충돌합니다 백테스트가 결과를 생성하지 않으면 — 거래가 없거나 선택한 날짜/심볼에 대한 시장 데이터가 없으면 — cTrader Console의 보고서 작성자가 Message expected를 발생시키고 보고서 없이 종료됩니다. 앱은 그 업스트림 버그를 수정할 수 없지만, 이를 감지하고 인스턴스를 Failed로 표시하며 원시 스택 트레이스 대신 실행 가능한 이유를 제시합니다("선택한 범위에 대한 백테스트 결과가 없음…"). 사용 가능한 시장 데이터가 있는 더 넓은 날짜 범위를 선택하고 다시 시도하세요. :::

인스턴스 상세 페이지​

인스턴스를 열면(/instance/{id}) 실시간 상태, 로그 및 백테스트의 경우 에퀴티 곡선이 표시됩니다. 브라우저 탭 제목은 특정 인스턴스를 반영합니다(cBot 이름 · 종류 · 심볼, 예: TrendBot · Backtest · EURUSD)이므로 실시간 실행 탭과 백테스트 탭을 한눈에 구별할 수 있습니다. 같은 cBot의 실행과 백테스트는 별개의 계보(상태 전환 간에 유지되는 안정적인 계보 ID)로 추적되므로 페이지는 정확히 하나의 인스턴스를 따르고 실행의 데이터와 백테스트의 데이터를 섞지 않습니다.

인스턴스 수명 주기 제어​

각 인스턴스 행(및 상세 페이지)에는 상태에 맞는 제어가 있습니다. 활성 인스턴스는 Stop을 표시하고, 터미널 인스턴스(Stopped / Completed / Failed)는 **Start (▶)**을 표시하여 같은 cBot, 계정, 심볼, 타임프레임, ParamSet 및 이미지로 다시 시작합니다(실행은 실행으로 다시 시작하고, 백테스트는 백테스트로 다시 시작합니다). Stop을 클릭하면 "Stopping…" 알림이 표시되고 해결될 때까지 아이콘이 비활성화되며, 새로 만든 실행이 목록에 즉시 나타나므로 페이지를 다시 로드할 필요가 없습니다.

콘솔 로그는 인스턴스가 종료될 때 지속됩니다 — 실행(Stop 시) 및 백테스트(완료 시) 모두이므로 마지막 실행의 로그는 상세 페이지에서 계속 볼 수 있으며, 로그 도구 모음을 통해 클립보드로 복사(로그 복사 아이콘) 또는 다운로드(로그 다운로드 아이콘)될 수 있습니다. 둘 다 온스크린 꼬리뿐만 아니라 인스턴스의 전체 콘솔 로그에서 작용합니다.

완료된 백테스트는 또한 cTrader 보고서를 두 형식 모두로 지속합니다 — 원본 JSON(에퀴티 곡선과 AI 분석이 읽는 것과 동일) 및 전체 HTML 보고서. 둘 다 백테스트 행 및 전용 아이콘을 통해 상세 페이지에서 다운로드할 수 있습니다. 마지막 실행의 보고서만 유지되고, 아이콘은 시작되지 않은, 실행 중이거나 실패한 모든 백테스트에 대해 비활성화됩니다(실행 인스턴스에 대해서는 표시되지 않음) — 완료된 백테스트만 다운로드할 보고서가 있습니다.

업로드된 .algo는 여기에서 빌드되지 않았으므로 cBot 페이지의 Last Build 열은 공백으로 남습니다(브라우저에서 빌드한 cBot에 대해서만 빌드 시간을 표시합니다).

중지된 인스턴스 편집 및 다시 실행​

중지된 인스턴스(실행 또는 백테스트)에는 Edit 제어가 있습니다 — 목록의 행에 있는 아이콘 및 상세 페이지의 Start/Stop 옆에 있으며 현재 구성으로 미리 채워진 대화상자를 엽니다. 거래 계정, 심볼, 타임프레임, ParamSet 및 이미지 태그를 변경할 수 있습니다(그리고 백테스트의 경우 기간 및 위의 모든 백테스트 설정), Save & start를 누르면 새 설정으로 다시 시작합니다(중지된 인스턴스 교체). 제어는 인스턴스가 활성인 동안 비활성화됩니다 — 중지된 인스턴스만 편집할 수 있습니다.

코드 에디터에서 실행​

코드 에디터에서 Run을 클릭하면 숨겨진 하드 코드된 실행을 하지 않고 대신 대화상자를 엽니다.

  • 거래 계정 (필수) — cBot이 연결하는 cTrader 계정입니다.
  • ParamSet (선택 사항) — 기존 집합을 선택하거나 비워두어 cBot의 기본 매개변수 값으로 실행합니다. 선택자 옆의 + 버튼은 새 ParamSet을 인라인으로 만들고 선택합니다(아래 참조).
  • Symbol / Timeframe은 기본값이 EURUSD / h1이며 변경할 수 있습니다. Cancel 또는 Run.

Run을 누르면 에디터는 현재 소스를 저장 및 빌드하고, 선택한 계정과 선택한 매개변수로 인스턴스를 시작한 다음, 라이브 컨테이너 로그를 추적합니다. (로그 스트림은 서명된 사용자의 인증 쿠키를 /hubs/logs SignalR 허브로 전달하므로 Invalid negotiation response received로 실패하지 않고 연결됩니다.)

ParamSet​

ParamSet은 각 매개변수 이름을 스칼라 값에 매핑하는 플랫 JSON 객체로 저장된 명명되고 재사용 가능한 cBot 매개변수 재정의 집합입니다(예: {"Period": 14, "Label": "trend"}). 실행/백테스트 시간에 cTrader params.cbotset 파일로 변환됩니다({ "Parameters": { … } }). cBot의 Parameter sets 대화상자에서 원본 JSON으로 집합을 만들고 편집하거나 Run 대화상자에서 인라인으로 만들 수 있습니다.

모든 ParamSet은 cBot에 속합니다: 새 ParamSet 대화상자는 모든 cBot을 나열하고 하나를 선택해야 합니다 — cBot을 선택할 때까지 생성이 차단됩니다. 집합의 이름은 cBot별로 고유합니다. 이미 같은 cBot의 다른 집합에서 사용하는 이름으로 집합을 만들거나 이름을 바꾸려고 하면 거부됩니다(대화상자의 명확한 오류, API에서 409 Conflict). 같은 이름은 다른 cBot에서 재사용될 수 있습니다.

JSON은 저장 시 검증됩니다: 값이 모두 스칼라(string / number / bool)인 단일 평면 객체여야 합니다. 비-객체 루트, 배열, 중첩 객체, null 값 또는 형식이 잘못된 JSON은 거부됩니다(대화상자의 명확한 오류, API에서 400 Bad Request). 빈 객체 {}는 허용되며 "재정의 없음"을 의미합니다.

cTrader Console CLI 메모​

백테스트에는 --data-mode(기본값 m1), dd/MM/yyyy HH:mm 형식의 날짜, 그리고 params.cbotset JSON 위치 인수가 필요합니다. run은 --data-dir을 거부합니다(백테스트 전용). ContainerCommandHelpers를 참조하세요.

노드 및 확장​

노드 에이전트를 추가하여 실행 용량을 확장합니다(자동 등록 + 하트비트). 노드 디스커버리 및 확장을 참조하세요.

거래 계정 필수​

cBot을 실행하거나 백테스트하려면 연결할 cTrader 거래 계정이 필요합니다. Trading accounts 아래에 하나를 추가할 때까지 Run New cBot / Backtest New cBot 버튼이 비활성화됩니다(도구 설명 포함) 그리고 페이지는 계정 설정으로 연결하는 프롬프트를 표시합니다 — 계정이 없는 봇의 원시 stream connect failed 오류를 더 이상 발생시키지 않습니다.