콘텐츠로 이동

바 이벤트 처리 방법

바 이벤트는 모든 cBot의 생명주기에 필수적입니다. 이러한 이벤트를 적절히 처리하는 것은 새로운 시장 조건에 대해 cBot이 어떻게 반응할지 관리하는 데 중요합니다. 이 글과 해당 비디오에서는 주요 바 이벤트 유형을 시연하고 cTrader API에서 노출된 이러한 이벤트의 핸들러에 대해 논의하겠습니다.

  • - cTrader가 트레이딩 차트에 순차적으로 그리는 다양한 유형의 객체를 의미합니다. 이는 캔들 스틱, 렌코 브릭, 레인지 바 또는 하이킨 아시 캔들일 수 있습니다.

BarOpened 이벤트 처리

Bar 이벤트는 cBot에 연결된 트레이딩 차트에 새로운 바가 그려지기 시작할 때 발생합니다. BarOpened 이벤트는 차트에 방금 그려지기 시작한 새로운 바에 대해 발생합니다.

이 이벤트를 처리하는 것은 기본 Robot 클래스에서 상속된 OnBar() 메서드를 통해 이루어집니다. 이제 우리는 시장 심리를 분석하기 위한 전략의 일환으로 BarOpened 이벤트를 처리하는 cBot을 만들 것입니다. 템플릿에서 OnStart()OnStop() 메서드를 삭제하고 OnTick() 핸들러를 OnBar() 핸들러로 대체할 것입니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
protected override void OnBar()
{
    var previousBar = Bars[Bars.Count - 2];
    var priceDifference = ((Bars.LastBar.Open - previousBar.Open) / previousBar.Open) * 100;
    if (priceDifference > 1)
    {
        ExecuteMarketOrder(TradeType.Buy, SymbolName, 10000);
    }
    else if (priceDifference < -1)
    {
        ExecuteMarketOrder(TradeType.Sell, SymbolName, 10000);
    }
    else 
    {
        foreach (var position in Positions) 
        {
            position.Close();
        }
    }
}

이 cBot은 D1(일일) 타임프레임의 차트에서 실행되도록 설계되었습니다. 모든 바에서 이전 바의 시가와 현재 바의 시가 차이를 비교하고 적절한 방향으로 새로운 주문을 실행합니다. 가격 차이가 미미한 경우, 봇은 대신 현재 열려 있는 모든 포지션을 종료합니다.

이 간단한 봇을 백테스트하면 결과는 고무적입니다.

BarClosed 이벤트 처리

새로운 바가 열릴 때, 그것은 시가를 제외하고는 어떤 가격 데이터도 가지고 있지 않습니다. 많은 경우, cBot이 이전 바의 데이터에 접근하여 전략 실행을 원활하게 하고자 할 수 있습니다. 이것이 바로 BarClosed 이벤트가 방금 닫힌 바(새로운 바 바로 이전의 바)에 대해 발생하고 그 가격 및 거래량 데이터를 쉽게 사용할 수 있게 해주는 이유입니다. BarClosed 이벤트가 트리거되면, 새로 열린 바는 Bars 컬렉션에서 완전히 제외됩니다.

BarClosed 이벤트를 처리하기 위해 API는 OnBarClosed 메서드를 제공합니다.

참고

이전 예제에서 우리는 새로 열린 바의 시가를 얻기 위해 Bars.LastBar.Open 속성을 사용했습니다. OnBarClosed() 메서드에서 동일한 속성을 사용하면 방금 닫힌 바의 시가를 얻을 수 있습니다.

우리는 다음과 같이 OnBarClosed() 핸들러를 사용하는 간단한 cBot을 만들 것입니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
protected override void OnBarClosed()
{
    var lowCloseDifference = ((Bars.LastBar.Close - Bars.LastBar.Low) / Bars.LastBar.Close) * 100;
    if (lowCloseDifference > 0.5)
    {
        foreach (var position in Positions)
        {
            position.Close();
        }
        ExecuteMarketOrder(TradeType.Buy, SymbolName, 10000, null, null, 50);

    }
}

이 cBot은 캔들 아래쪽 심지의 길이를 평가하여 강세(해머) 패턴을 감지합니다. 해머 패턴이 감지되면 이전에 열려 있던 모든 포지션을 종료하고 50핍 손절매와 함께 새로운 매수 주문을 실행합니다.

이 봇을 백테스트하면 괜찮은 결과를 얻을 수 있습니다.

사용자 정의 이벤트 핸들러 추가

BarOpenedBarClosed 이벤트를 처리할 때, 이러한 이벤트에 사용자 정의 핸들러를 할당하여 약간 다른 구문을 사용할 수도 있습니다. OnBar()OnBarClosed()는 한 번만 트리거되지만, 원하는 만큼 많은 사용자 정의 핸들러를 추가할 수 있어 복잡한 로직을 추가할 수 있습니다.

참고

사용자 정의 이벤트 핸들러는 OnStart() 메서드에서 추가해야 합니다. 사용자 정의 핸들러는 또한 BarOpenedEventArgs(BarOpened 이벤트의 경우) 또는 BarClosedEventArgs(BarClosed 이벤트의 경우) 타입의 인수를 받아야 합니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
protected override void OnStart() 
{
    Bars.BarClosed += BarClosedHandler;
    Bars.BarClosed += AnotherClosedHandler;
    Bars.BarOpened += BarOpenedHandler;
}

void BarClosedHandler(BarClosedEventArgs args) {}
void AnotherClosedHandler(BarClosedEventArgs args) {}
void BarOpenedHandler(BarOpenedEventArgs args) {}

우리는 가능한 강세 및 약세 반전에 반응하기 위해 BarOpened 이벤트에 대해 두 개의 사용자 정의 핸들러를 사용하는 또 다른 cBot을 만들 것입니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
protected override void OnStart() 
{
    Bars.BarOpened += BullishReversal;
    Bars.BarOpened += BearishReversal;

}

private void BullishReversal(BarOpenedEventArgs args) 
{
    if (Bars.LastBar.Open > Bars.Last(1).Close && Bars.LastBar.Open > Bars.Last(2).Close) 
    {
        ExecuteMarketOrder(TradeType.Buy, SymbolName, 10000, null, 10, 50);
    }
}

private void BearishReversal(BarOpenedEventArgs args) 
{
    if (Bars.LastBar.Open < Bars.Last(1).Close && Bars.LastBar.Open < Bars.Last(2).Close) 
    {
        ExecuteMarketOrder(TradeType.Sell, SymbolName, 10000, null, 10, 50);
    }
}

이 cBot은 새로 열린 바의 시가가 이전 두 바의 종가보다 높은지 확인합니다. 이 경우 매수 주문이 실행됩니다. 시가가 이전 두 바의 종가보다 낮으면 매도 주문이 실행됩니다. 두 개의 별도 이벤트 핸들러를 사용하면 트레이딩 로직을 더 작은 구성 요소로 나눌 수 있으며 나중에 필요에 따라 쉽게 수정할 수 있습니다.

D1 타임프레임에서 백테스트한 결과도 긍정적입니다.

요약

바 이벤트를 올바르게 처리하는 방법을 배우면 cBot이 정확히 원하는 대로 작동하도록 할 수 있습니다.