콘텐츠로 이동

cTrader에서 기술 지표 생성하기

이 문서는 cTrader에서 알고리즘 트레이딩 또는 수동 작업을 위한 도구를 포함하여 맞춤형 기술 지표를 생성하는 단계를 설명합니다.

Algo 앱의 지표 탭에서 새로 만들기 버튼을 클릭하여 알고리즘 생성 마법사를 엽니다.

지표의 이름을 입력한 후 C#Python 중 프로그래밍 언어를 선택하세요.

생성 방법을 선택하세요:

  • 처음부터 – 새로운 지표는 기본 템플릿만 포함합니다.

  • 템플릿 사용Python# 또는 C# 템플릿 목록에서 미리 만들어진 알고리즘을 선택할 수 있으며, 다양한 지표 유형, 기술적 분석 도구 등을 포함합니다.

참고

미리 만들어진 알고리즘은 이미 계산 및 맞춤 설정 가능한 매개변수를 위한 로직을 포함하고 있습니다. 이러한 지표는 저장하고 빌드한 후 바로 차트에 표시할 수 있습니다.

생성을 클릭하면 코드 편집기가 열리고 지표 코드를 편집할 수 있습니다.

코드 편집

생성 방법에 따라 지표 코드 샘플은 다음 요소 중 하나 이상을 포함해야 합니다:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[Indicator(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class SimpleIndicator : Indicator
{
    [Parameter(DefaultValue = "Hello world!")]
    public string Message { get; set; }

    [Output("Main")]
    public IndicatorDataSeries Result { get; set; }

    protected override void Initialize()
    {
    // Called once when the indicator is launched
    // Initialise variables, nested indicators or series

        Print(Message);
    }

    public override void Calculate(int index)
    {
    // Called automatically on each historical bar
    // Also called in real-time on each tick
    // Place the indicator formula and logic here
    }

    // === Custom Methods ===
    // Add helper methods below to structure your indicator logic

}

Indicator 속성은 TimeZoneAccessRights와 같은 선택적 속성과 함께 지표 클래스(SimpleIndicator) 선언 앞에 옵니다.

이러한 메서드는 기본적으로 모든 지표에 포함됩니다:

  • Initialize() 메서드는 지표가 시작될 때 한 번 호출됩니다. 이 메서드는 일반적으로 변수, 중첩 지표 및 시리즈를 설정하는 데 사용됩니다.
  • Calculate() 메서드는 각 역사적 바에서 자동으로 호출되며, 새로운 틱마다 실시간으로 호출됩니다. 이 메서드에서 지표의 공식을 구현하고 결과가 계산 및 표시되는 방식을 정의합니다.

[Output()] 속성은 지표가 생성하는 값과 차트에 표시되는 방식을 지정합니다. 각 출력의 이름과 스타일을 맞춤 설정할 수 있습니다. 예를 들어, 라인 색상을 설정할 수 있습니다.

Initialize()Calculate() 메서드는 모든 맞춤형 지표의 기초를 형성하며 절대 생략해서는 안 됩니다. cBot을 코딩할 때와 마찬가지로 기능을 확장하기 위해 자신만의 메서드를 추가할 수 있습니다. 알고리즘에 대해 더 알아보려면 C# 기본 가이드를 시작하고 지표 코드 예제를 탐색하세요.

참고

참조에는 cTrader에서 알고리즘을 구축하기 위한 모든 클래스, 이벤트, 메서드, 변수 등이 포함되어 있으며, 전체 알고리즘 예제와 템플릿은 GitHub 저장소에서 확인할 수 있습니다.

새로운 지식을 적용하여 지표 코드를 편집하고 필요에 맞게 조정하세요.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class SimpleIndicator:
    def initialize(self):
        # Called once when the indicator is launched
        # Initialise variables, nested indicators or series
        api.Print(api.Message)

    def calculate(self, index):
        # Called automatically on each historical bar
        # Also called in real-time on each tick
        # Place the indicator formula and logic here
        api.Result[index] = 100 # Example calculation

    # === Custom Methods ===
    # Add helper methods below to structure your indicator logic

SimpleIndicator 클래스는 Python에서 맞춤형 지표를 정의합니다.

이러한 메서드는 기본적으로 모든 지표에 포함됩니다:

  • initialize(self) 메서드는 지표가 시작될 때 한 번 호출됩니다. 이 메서드는 일반적으로 변수, 중첩 지표 및 시리즈를 초기화하는 데 사용됩니다.
  • calculate(self, index) 메서드는 각 역사적 바에서 자동으로 호출되며, 새로운 틱마다 실시간으로 호출됩니다. 이 메서드에서 지표의 공식을 구현하고 결과가 계산 및 표시되는 방식을 정의합니다.

initialize(self)calculate(self, index) 메서드는 모든 맞춤형 지표의 기초를 형성하며 절대 생략해서는 안 됩니다. cBot을 코딩할 때와 마찬가지로 클래스 내부에 자신만의 도우미 메서드를 추가하여 기능을 확장할 수도 있습니다. 알고리즘에 대해 더 알아보려면 Python 기본을 시작하고 지표 코드 예제를 탐색하세요.

새로운 지식을 적용하여 지표 코드를 편집하고 필요에 맞게 조정하세요.

저장 및 빌드

코드 편집기 상단의 저장 버튼을 클릭하거나 Ctrl+S 단축키를 사용하여 코드를 저장하세요.

지표를 사용하기 전에 지표 프로젝트를 빌드하여 코드를 검증해야 합니다. 코드 편집기 상단의 빌드 버튼을 클릭하거나 Ctrl+B를 누르세요.

코드 편집기 상단의 저장 아이콘을 클릭하거나 Cmd+S 단축키를 사용하여 코드를 저장하세요.

지표를 사용하기 전에 지표 프로젝트를 빌드하여 코드를 검증해야 합니다. 코드 편집기 상단의 빌드 아이콘을 클릭하거나 Cmd+B를 누르세요.

빌드가 성공하면 빌드 결과에 확인 메시지가 표시됩니다. 빌드가 실패하면 발생한 모든 오류 요약이 대신 표시됩니다.

마지막 빌드 이후 코드에 변경 사항이 있으면 빌드 아이콘 옆에 별표가 나타납니다. 이 경우, 지표를 차트에 추가하기 전에 다시 빌드해야 합니다.

지표를 차트에 사용하거나 표시하려면 지표의 인스턴스를 추가하거나, 설명된 대로 지표 코드를 계속 수정할 수 있습니다.

NaN 산술 사용

지표는 특정 시각적 출력을 위해 계산을 수행하며, 이러한 계산 중에 경계 조건과 특수한 경우를 올바르게 처리하는 것이 중요합니다.

다음은 디트렌드 가격 오실레이터를 출력하는 지표의 코드 조각입니다:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private MovingAverage movingAverage;

protected override void Initialize()
{
    movingAverage = Indicators.SimpleMovingAverage(Source, Periods);
}

public override void Calculate(int index)
{
    Result[index] = Source[index] - movingAverage.Result[index - Periods / 2 - 1];
}

위 코드는 일반적인 계산 규칙을 정의하지만 경계 조건을 생략했습니다. 예를 들어, Periods10으로 설정되고 index0–9 범위에 속하면 계산 결과는 NaN(Not a Number)을 반환합니다. 이 문제는 지표가 음수 인덱스를 가진 바 차트에 대한 값을 계산할 수 없기 때문에 발생합니다.

이 문제를 해결하기 위해 아래와 같이 조건을 추가할 수 있습니다:

1
2
3
4
5
6
7
public override void Calculate(int index)
{
    if (index >= Periods + Periods / 2 + 1)
    {
        Result[index] = Source[index] - movingAverage.Result[index - Periods / 2 - 1];
    }
}

단순 이동 평균 자체의 코드도 index >= Periods를 확인해야 합니다. 다른 유형의 이동 평균과 같은 중첩 지표를 사용하는 경우, 추가 계산을 고려하여 조건이 달라집니다.

명시적인 경계 조건을 정의할 수 있지만, C#은 NaN 산술을 통해 이러한 문제를 편리하게 피할 수 있는 방법을 제공합니다. 특히, double 데이터 타입은 NaN 계산을 완전히 지원합니다. 예를 들어:

1
2
3
4
5
double result = double.NaN + 1.4; 
// result will be NaN

bool isNaN = double.IsNaN(result); 
// isNaN will be true

그러나 계산에서 피연산자 중 하나가 NaN이면 결과도 NaN이 됩니다. 맞춤형 cTrader 지표는 DataSeries 타입에서 작동하므로, 음수 인덱스로 DataSeries 요소에 접근하려고 하면 NaN을 반환하고, 값은 트레이딩 차트에 그려지지 않습니다. 이 동작은 지표가 예외를 발생시키지 않고 계속 작동할 수 있게 합니다. 대부분의 경우, 경계 조건을 안전하게 무시하고 일반적인 계산 로직에만 집중할 수 있습니다.

명시적인 확인 추가

NaN 산술은 경계 조건을 처리하는 것을 단순화하지만, 일부 경우에는 여전히 명시적인 NaN 확인이 필요합니다. 재귀 지표는 일반적인 예입니다. 재귀 지표는 이전에 계산된 값을 기반으로 현재 값을 계산합니다.

Exponential Moving Average의 다음 구현을 고려해 보세요:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public override void Calculate(int index)
{
    var previousValue = Result[index - 1];

    if (double.IsNaN(previousValue))
    {
        Result[index] = Source[index];
    }
    else
    {
        Result[index] = Source[index] * _exp + previousValue * (1 - _exp);
    }
}

지표가 첫 번째 기간을 계산할 때, 초기 값을 명시적으로 NaN이 아닌 타입으로 설정해야 합니다. 그렇지 않으면 모든 후속 계산이 NaN을 반환하여 지표를 쓸모없게 만듭니다.

위 코드에서는 double.IsNaN(previousValue) 메서드를 사용하여 이를 처리합니다. == 연산자는 이 확인에 사용할 수 없습니다 (previousValue == double.NaN), 왜냐하면 NaN과 다른 값(자신을 포함)의 비교는 항상 false로 평가되기 때문입니다.

지표 코드에 만족하면, 빌드한 후 인스턴스 추가를 통해 차트에 사용하세요.

Image title