4.6 C++ 언어에서 전략을 구현하는 방법

저자:선함, 2019-05-06 13:00:27, 업데이트:

요약

이전 기사에서 우리는 C++ 언어, 기본 문법, 전략 구조의 도입에서 거래 전략을 구현하는 전제를 설명했습니다. 이 기사에서는 이전 부분을 계속하고 실행 가능한 양적 거래 전략을 단계적으로 구현합니다.

전략 소개

기술 분석에서 가장 일반적으로 사용되는 지표 중 하나인 KDJ는 전 세계 대부분의 트레이더에 의해 인식되었습니다. KDJ의 전체 이름은 Random 지표입니다. 이는 상품 선물 시장에서 사용되는 매우 새롭고 실용적인 기술 분석 지표였습니다. 또한 주식 및 외환 거래의 단기 트렌드 분석에도 널리 사용되었습니다.

KDJ는 통계 이론에 기초하여, 최근 9K 라인의 최고, 최저 및 폐쇄 가격의 비율로 무작위 값 (RSV) 을 계산했습니다.

img

동력 개념, 강도 지표 및 이동 평균의 장점을 결합하여, 우리는 주식 가격의 일반 범위 움직임에서 변하는 정도를 측정합니다. K 값이 D 값보다 크면, 그것은 주식 가격이 현재 상승 추세에 있음을 나타냅니다. 따라서, K 선이 아래에서 위로 D 선을 넘을 때, 주식을 구매 할 때입니다. 반대로, K 값이 D 값보다 작을 때, 그것은 주식 시장이 현재 하락 추세에 있음을 나타냅니다. 따라서, K 선이 위에서 아래로 D 선을 넘을 때, 주식을 판매 할 때입니다.

KDJ 지표 계산 방법

KDJ 지표의 계산은 복잡합니다. 먼저 무작위 값 (RSV) 을 계산하고 K 값, D 값, J 값을 계산합니다. 계산 방법은 다음과 같습니다.

  • RSV = (폐기 가격 - N 기간 최저 가격) / (N 사이클 최고 가격 - N 사이클 최저 가격) * 100

  • K 값 = N 주기의 평균 RSV

  • D 값 = N 주기의 평균 K

  • J 값 = 3 * K 값 -2 * D 값

void main(){ // the program starts from this main function
    while (true){ // enter the loop
        auto ct = exchange.SetContractType(symblo); //set the contract type
        auto r = exchange.GetRecords(); // get the K line array
        auto arr = TA.KDJ(r, 9, 3, 3); // calculate the KDJ indicator 
        auto k = arr[0]arr[0].size() - 2]; // get the previous k line KDJ indicator K value
        auto d = arr[1]arr[1].size() - 2]; // get the previous k line KDJ indicator D value
        auto j = arr[2]arr[2].size() - 2]; // get the previous k line KDJ indicator J value
    }
}

전략 논리

KDJ를 사용하는 방법에는 여러 가지가 있는데, 단독으로 또는 다른 지표와 결합하여 사용할 수 있습니다. 이 문서에서는 가장 간단한 방법으로 사용할 것입니다. 즉: K 값이 D 값보다 크면 구매력이 강화되고 상승 시장의 물결이 형성되어 오픈 긴 포지션 신호가 생성됩니다. K 값이 D 값보다 작으면 판매력이 강화되고 하락 트렌드 신호가 형성되어 오픈 쇼트 포지션을 생성한다고 믿습니다.

img

포지션 개척 후 D 값이 상위에서 아래로 변하면 구매력이 약화되거나 판매력이 강화되고 긴 포지션을 닫는 신호가 생성됩니다. 짧은 포지션이 열리면 D 값이 하위에서 상위로 변하면 판매력의 힘이 약화되거나 구매력이 강화되고 짧은 포지션을 닫는 신호가 생성됩니다.

거래 조건

  • 긴 포지션 오픈: 포지션이 없고 K 값이 D 값보다 크면

  • 짧은 지점: 지점이 없고 K 값이 D 값보다 작다면

  • 긴 포지션 폐쇄: 긴 포지션 보유가 있고, D 값이 관통 K 라인의 D 값보다 작다면

  • 마감 마감 포지션: 마감 포지션 보유가 있고 D 값이 관통 K 라인의 D 값보다 크면

전략 코드 시행

코드와 전략을 구현하는 첫 번째 단계는 먼저 우리가 필요한 데이터를 고려하는 것입니다. 어떤 API를 통해 얻을 수 있습니까? 데이터를 얻은 후, 거래 논리를 계산하는 방법? 다음으로, 주문을 배치하는 방법은 무엇입니까? 마지막으로, 단계별로 구현하자:

단계 1: 전략 아키텍처 및 거래 클래스 라이브러리를 사용

이른바 전략 아키텍처는 전체 전략을 설계하는 방법이다. 아래와 같이 아키텍처는 두 가지 기능으로 구성되어 있습니다. 하나는 주요 기능이며, 프로그램은 주요 기능에서 시작하며, 그 기능은 전략 논리의 핵심을 처리하는 것입니다.

bool onTick(){  // onTick function
    // strategy logic
}

void main(){ // program starts from here
    while (true){  // enter the loop
        if (exchange.IO("status") == 0) // if the connection with the exchange if not stable.
            sleep(1000); // pause for 1 second
            continue; // skip this loop, enter the next loop
        }
        if(!onTick()){ // if the connection with the exchange is stable, enter this if loop, start executing the onTick function
            sleep(1000); // pause for 1 second
        }
    }
} 

위의 코드는 FMZ Quant 플랫폼 도구에 의해 만들어진 C++ 전략 프레임워크입니다. 이것은 고정된 코딩 형식이며, 모든 거래 논리는 2 행에서 시작되며 다른 곳에서 변경되지 않습니다. 또한, 당신이 베테랑이라면 필요에 따라 기능을 추가하거나 수정할 수 있습니다.

트레이딩 클래스 라이브러리를 기능 모듈로 생각할 수 있습니다. 트레이딩 클래스 라이브러리를 사용하는 장점은 전략 논리를 작성하는 데 집중할 수 있다는 것입니다. 예를 들어, 트레이딩 클래스 라이브러리를 사용할 때 포지션을 열거나 닫기 위해 트레이딩 클래스 라이브러리의 API 인터페이스를 직접 사용할 수 있습니다. 그러나 트레이딩 클래스 라이브러리를 사용하지 않으면 포지션을 열 때 시장 가격을 얻어야합니다. 실행되지 않은 주문의 문제와 철수 주문의 문제를 고려해야합니다.

2단계: 모든 종류의 데이터를 수집

다양한 원료 데이터는 거래 논리의 중요한 부분입니다. 어떤 종류의 데이터가 필요합니다? 전략 거래 논리에서 우리는 먼저 K-라인 데이터를 얻어야합니다. 원래 K-라인 데이터를 사용하여 KDJ 지표를 계산하고 마지막으로 K-값과 D-값 사이의 관계를 비교하여 주문을 할 것인지 여부를 결정할 수 있습니다.

  • K-라인 데이터를 가져와

먼저, K-라인 배열을 얻어야 합니다. K-라인 배열이 KDJ 지표를 계산하는 데 사용되기 때문입니다.

double position = 0; // position status parameter, the default is 0 

bool onTick(string symbol){ // onTick function, all strategy logic are in this function
    auto ct = exchange.SetContractType(symbol); // set the contract type and trading variety
    if(ct == false){ // if the setting contract type and trading variety is not successful 
        return false; // return false
    }
    auto r = exchange.GetRecords(); // get the k-line array
    if(!r.Valid || r.size() < 10){ // if getting the k-line array or the number of k-line is less than 10
        return false; // return false
    }
}

void main(){ // program starts from here
    while (true){  // enter the loop
        if (exchange.IO("status") == 0) // if the connection with the exchange if not stable.
            sleep(1000); // pause for 1 second
            continue; // skip this loop, enter the next loop
        }
        if(!onTick("this_week")){ // if the connection with the exchange is stable, enter this if loop, start executing the onTick function
            sleep(1000); // pause for 1 second
        }
    }
} 

위 그림과 같이:

라인 1: 위치 상태를 수신하는 데 사용되는 변수를 정의합니다.

3-12 줄: onTick 함수가 정의되고 이 함수는 매개 변수와 함께 전달됩니다. 이 매개 변수는 이번 경우 주간 k-줄을 사용하여 거래 범주에 전달됩니다.

14부터 24 줄: 전략이 아닌 논리를 처리하는 주요 함수를 정의합니다. 변경할 수있는 유일한 것은 20 줄의 계약 코드입니다. 이것은 고정된 형식이기 때문에 다른 곳에서 수정 할 필요가 없습니다.

이제 onTick 함수에 초점을 맞추고 K-라인 데이터를 어떻게 얻는지를 봅시다:

4-7 행: 계약 유형 및 거래 종류를 설정합니다. 계약 유형 및 거래 종류를 설정하는 것이 성공하지 않으면 false를 반환합니다.

8줄: 고정된 형식인 K줄 배열을 얻습니다.

9-11 행: K 직선의 길이를 필터링합니다. 왜냐하면 KDJ 지표를 계산하는 매개 변수는 9이기 때문입니다. K 직선의 숫자가 9보다 작을 때 KDJ 지표를 계산하는 것은 불가능합니다. 그래서 여기서 우리는 K 직선의 길이를 필터링하고 싶습니다. K 직선이 10보다 작으면 바로 false를 반환하고 다음 K 직선을 계속 기다립니다.

  • KDJ 지표, K 값과 D 값을 얻으십시오

다음으로, 우리는 KDJ 지표의 K와 D 값을 계산해야 합니다. 먼저 KDJ 지표의 배열을 얻고, 이 배열에서 K값과 D값을 얻어야 합니다. FMZ 퀀트 플랫폼에서, KDJ 배열을 얻는 것은 매우 간단합니다. KDJ의 API를 호출하면 KDJ 배열이 2차원 배열이기 때문에 K와 D 값의 값을 얻는 것이 어렵습니다.

2차원 배열은 실제로 이해하기 쉽습니다. 배열의 배열입니다. 얻을 수 있는 순서는 다음과 같습니다. 먼저 배열에서 지정된 배열을 얻고 다음에는 아래와 같이 지정된 배열에서 지정된 요소를 얻습니다.

#include <iostream>
using namespace std;

int main(){
    int hour [3][2] = {{100, 50}, {66, 88}, {10, 90}};
    cout << hours[0][0]; // get the hours array first elements of first element, the result is 100
    cout << hours[0][1]; // get the hours array first elements of second element, the result is 50
    cout << hours[1][0]; // get the hours array second elements of first element, the result is 66
    return(0);
}

아래와 같이 12번째 줄은 FMZ Quant의 API를 직접 사용하여 2차원 배열인 KDJ 지표 배열을 얻습니다. arr = [[K 값, K 값, K 값...], [D 값, D 값, D 값...], [J 값, J 값, J 값...]]

13 행은 이전 K 행의 k 값을 얻는데, K 값은 arr[0], 그 다음 arr[0], arr[0].size (() 에서 penultimate 요소를 얻으며, arr[0], arr[0].size (() - 2의 배열의 길이를 얻기 위해 사용할 수 있습니다.

double position = 0; // position status parameter, the default is 0 

bool onTick(string symbol){ // onTick function, all strategy logic are in this function
    auto ct = exchange.SetContractType(symbol); // set the contract type and trading variety
    if(ct == false){ // if the setting contract type and trading variety is not successful 
        return false; // return false
    }
    auto r = exchange.GetRecords(); // get the k-line array
    if(!r.Valid || r.size() < 10){ // if getting the k-line array or the number of k-line is less than 10
        return false; // return false
    }
    auto arr = TA.KDJ(r, 9, 3, 3); // calculate the KDJ indicator 
    auto k = arr[0][arr[0].size() - 2]; // get the K value of the previous K line 
    auto d = arr[1][arr[1].size() - 2]; // get the D value of the previous K line
    auto dPre = arr[1][arr[1].size() - 3]; // get the D value of the second last of the K line
}

void main(){ // program starts from here
    while (true){  // enter the loop
        if (exchange.IO("status") == 0) // if the connection with the exchange if not stable.
            sleep(1000); // pause for 1 second
            continue; // skip this loop, enter the next loop
        }
        if(!onTick("this_week")){ // if the connection with the exchange is stable, enter this if loop, start executing the onTick function
            sleep(1000); // pause for 1 second
        }
    }
} 

단계 3: 주문

위의 데이터로, 우리는 거래 논리와 주문을 배치하는 부분을 지금 쓸 수 있습니다. 그것은 또한 매우 간단합니다. 가장 일반적으로 사용되는 것은: 조건 1 및 조건 2가 사실이라면, 명령을 배치; 조건 3 또는 조건 4가 사실이라면, 명령을 배치합니다. 아래와 같이 설명 할 수 있습니다.

double position = 0; // position status parameter, the default is 0 

bool onTick(string symbol){ // onTick function, all strategy logic are in this function
    auto ct = exchange.SetContractType(symbol); // set the contract type and trading variety
    if(ct == false){ // if the setting contract type and trading variety is not successful 
        return false; // return false
    }
    auto r = exchange.GetRecords(); // get the k-line array
    if(!r.Valid || r.size() < 10){ // if getting the k-line array or the number of k-line is less than 10
        return false; // return false
    }
    auto arr = TA.KDJ(r, 9, 3, 3); // calculate the KDJ indicator 
    auto k = arr[0][arr[0].size() - 2]; // get the K value of the previous K line 
    auto d = arr[1][arr[1].size() - 2]; // get the D value of the previous K line
    auto dPre = arr[1][arr[1].size() - 3]; // get the D value of the second last of the K line
    string action; // define a string variable action
    // if currently holding long position, and the previous K line's D value is less than the second last k line's D value, close all position
    // if currently holding short position, and the previous K line's D value is greater than the second last k line's D value, close all position
    if((d < dPre && position > 0) || (d > dPre && position <0)){
        action = "cover";
    }else if (k > d && position <= 0){ // if the previous K line's K value is greater than the previous K line's D value, and there are no long positions
        action = "buy"; // set the variable action to "buy"
    }else if (k < d && position >= 0){ // if the previous K line's K value is less than the previous K line's D value, and there are no short positions
        action = "sell"; // set the variable action to "sell"
    }
    if (action.size() > 0){ // if there are placing order instruction
        position = ext::Trade(action, symbol, 1); // calling the C++ trading class library, placing orders according the direction of variable "action". and also renew the position status. 
    }
    return true; // return true
    } 
}

void main(){ // program starts from here
    while (true){  // enter the loop
        if (exchange.IO("status") == 0) // if the connection with the exchange if not stable.
            sleep(1000); // pause for 1 second
            continue; // skip this loop, enter the next loop
        }
        if(!onTick("this_week")){ // if the connection with the exchange is stable, enter this if loop, start executing the onTick function
            sleep(1000); // pause for 1 second
        }
    }
} 

위의 코드에서, 19부터 28까지의 줄은 거래 논리와 주문을 배치하는 코드입니다. 그러나, 이 전에, 우리는 줄 16에 문자열 변수 "행동"을 정의해야합니다.

라인 19에서 라인 21은: 현재 긴 포지션을 보유하고 있고, 이전 K 라인 D 값은 두 번째 마지막 k 라인 D 값보다 작다면 모든 포지션을 닫습니다. 현재 짧은 포지션을 보유하고 있으며, 이전 K 라인 D 값은 두 번째 마지막 k 라인 D 값보다 크다면 모든 포지션을 닫습니다. 그리고 변수 actioncover로 변경하십시오.

라인 21에서 라인 25은: 긴 포지션과 짧은 포지션을 개설하는 조건입니다. 조건이 사실이라면, actionbuy 또는 sell로 설정합니다.

라인 26에서 라인 28은 배치 주문 논리를 실행합니다. 첫째, 문자열 변수 action의 길이에 따라 주문을 배치하는 명령어가 있는지 여부를 판단합니다. 만약 그렇다면 코드는 라인 27에 입력하고 FMZ Quant 거래 클래스 라이브러리를 호출하여 주문을 배치 함수를 수행합니다.

두 가지 점을 주목해야 합니다.

  1. 현재 K-라인 조건이 설정됨에 따라 전략 논리를 작성하려고 노력하지만 반드시하지 않습니다. 다음 k-라인에 순서를 배치합니다. 또는 이전 k-라인 조건이 설정되어 현재 k-라인에 순서를 배치합니다. 이렇게하면 백테스트 결과와 실제 시장 성과가 크게 다르지 않습니다. 이렇게 작성하지 않는 것이 좋습니다. 그러나 전략 논리가 올바르는지에 유의하십시오.

  2. 일반적으로, 포지션을 닫는 논리는 오픈 포지션 논리의 앞에 써야 한다. 그 목적은 전략 논리를 당신의 기대에 부응하도록 하는 것이다. 예를 들어, 전략 논리가 단지 포지션을 막 닫은 후에 거래의 반대 방향으로 해야 하는 상황을 충족한다면, 이 같은 상황의 규칙은 먼저 포지션을 닫고 새로운 포지션을 열어야 한다. 만약 우리가 오픈 포지션 논리의 앞에 종료 포지션 논리를 써면, 그것은 완벽하게 이 규칙을 충족시킬 것이다.

요약하면

위에서 우리는 KDJ 기술 지표를 분석하고 완전한 양적 거래 전략으로 변환하는 방법을 배웠습니다. 전략 소개, KDJ 지표 계산 방법, 전략 논리, 거래 조건, 전략 코드 구현 등이 포함됩니다. 이 전략 사례를 통해 FMZ 퀀트 플랫폼에서 C ++ 프로그래밍 방법에 익숙해질뿐만 아니라이 섹션의 사례에 따라 다른 전략을 조정 할 수 있습니다.

양적 거래 전략을 달성하기 위해서는 자신의 주관적 거래 경험이나 시스템을 요약하고 필요한 원료를 별도로 얻고 전략 논리에 필요한 데이터를 계산하고 마지막으로 거래를 실현하기 위해 주문 배치 API를 호출하는 것입니다. 간단한 양적 거래 전략의 대부분은 이러한 단계에 따라 구현됩니다!

다음 섹션에 대한 알림

지금까지, 이 시리즈의 전략 작성 자습서는 끝났습니다, 여기로 인도하는 단계별 자습서를 따라가면 많은 것을 얻을 수 있다고 믿습니다. 어쨌든, 양적 거래 기본 과정의 관점에서, 긴 길은 절반 이상 진행되었습니다. 마지막 장에서는 FMZ 양적 백테스팅 거래 도구를 사용하는 방법을 알려주고, 백테스팅에서 구멍을 피하고 실제 시장 거래에 대한 최종 준비를하는 방법을 알려줍니다. 콘텐츠의 작은 부분이지만 양적 거래 세계로 진입하는 데 큰 단계입니다!

학교 밖 운동

  1. FMZ 퀀트 플랫폼에서 C++ 언어를 사용하여 KDJ 지표 알고리즘을 구현하려고 노력하십시오.

  2. 이 섹션의 지식을 사용하여 CCI 지표 전략을 세우는 것을 시도하십시오.


더 많은