시스템트레이딩 게시글

MetaTrader 5를 위한 Support Vector Machine 데모: Schnick 탐지기

첨부파일
1370.zip (2.63 KB, 다운로드 0회)

안녕하세요, 트레이더 여러분! 오늘은 'Machine Learning: Support Vector Machines을 트레이딩에 활용하는 방법'라는 기사의 일환으로, Support Vector Machine 학습 도구의 데모 스크립트를 소개하고자 합니다.

이 스크립트는 무료로 제공되는 Support Vector Machine 학습 도구의 데모 버전과 함께 사용하기 위해 특별히 작성되었습니다. 해당 도구는 MQL5 마켓에서 확인하실 수 있습니다.

상상해 보세요. 여러분은 극지방 깊숙한 곳에 사는 희귀 동물인 Schnick을 연구하는 연구자입니다. 이 동물들은 매우 외진 지역에 살기 때문에, 지금까지 발견된 개체 수는 약 5,000마리 정도입니다. 여러분은 'Schnick을 어떻게 식별할 수 있을까?'라는 질문에 직면하게 됩니다.

여러분이 활용할 수 있는 것은 이 동물을 본 몇몇 연구자들이 작성한 연구 논문뿐입니다. 이 논문들에서 저자들은 발견한 Schnick의 특정 특성들, 즉 높이, 무게, 다리 수 등을 설명하지만, 이 특성들은 논문마다 제각각이고 뚜렷한 패턴이 없습니다…

그렇다면 우리는 이 데이터를 어떻게 활용해 새로운 동물을 Schnick으로 식별할 수 있을까요?

한 가지 가능한 해결책은 Support Vector Machine을 사용하여 데이터의 패턴을 식별하고, 동물을 Schnick 또는 비스니크로 분류할 수 있는 프레임워크를 만드는 것입니다. 첫 번째 단계는 Support Vector Machine을 훈련시키기 위해 사용할 데이터 세트를 만드는 것입니다. 훈련 데이터는 Support Vector Machine이 분석하고 패턴을 추출할 수 있도록 입력과 일치하는 출력의 집합입니다.

이 스크립트는 Support Vector Machine 학습 도구를 사용하여 분류 문제를 해결하는 능력을 시연하고자 합니다. 이 가상의 문제와 스크립트에 대한 자세한 설명은 'Machine Learning: Support Vector Machines을 트레이딩에 활용하는 방법'에서 확인하실 수 있으며, 스크립트 사용법과 이 문제를 통해 머신 러닝을 활용하여 시장 동향을 평가하는 방법에 대한 통찰을 얻을 수 있습니다.

코드:

//+------------------------------------------------------------------+
//|                                                          Schnick_Demo.mq5 |
//|                        Copyright 2011, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2011, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"

//+------------------------------------------------------------------+
//| 이 스크립트는 Support Vector의 기능을 시연합니다
//|                     머신 러닝 도구
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| 다음 구문은 Support Vector Machine 도구 'svMachineTool.ex5'에 포함된 모든 기능을 가져옵니다
//+------------------------------------------------------------------+
#import "svMachineTool_demo.ex5"
enum ENUM_TRADE {BUY,SELL};
enum ENUM_OPTION {OP_MEMORY,OP_MAXCYCLES,OP_TOLERANCE};
int  initSVMachine(void);
void setIndicatorHandles(int handle,int &indicatorHandles[],int offset,int N);
void setParameter(int handle,ENUM_OPTION option,double value);
bool genOutputs(int handle,ENUM_TRADE trade,int StopLoss,int TakeProfit,double duration);
bool genInputs(int handle);
bool setInputs(int handle,double &Inputs[],int nInputs);
bool setOutputs(int handle,bool &Outputs[]);
bool training(int handle);
bool classify(int handle);
bool classify(int handle,int offset);
bool classify(int handle,double &iput[]);
void deinitSVMachine(void);
#import
//--- 사용할 입력의 수
int N_Inputs=7;
//+------------------------------------------------------------------+
//| 전문가 초기화 함수                                                       |
//+------------------------------------------------------------------+
int OnInit()
  {
   double inputs[];           //훈련 입력을 위한 빈 배열
   bool   outputs[];          //훈련 출력을 위한 빈 배열
   int N_TrainingPoints=5000; //훈련 샘플 수 정의
   int N_TestPoints=5000;     //테스트 샘플 수 정의

   genTrainingData(inputs,outputs,N_TrainingPoints); //svm 훈련을 위한 입력과 출력을 생성합니다

   int handle1=initSVMachine();             //새로운 SVM을 초기화하고 핸들 반환
   setInputs(handle1,inputs,7);             //입력을 SVM에 전달합니다
   setOutputs(handle1,outputs);             //출력을 SVM에 전달합니다
   setParameter(handle1,OP_TOLERANCE,0.01); //오류 허용 한계를 설정합니다
   training(handle1);                       //SVM 훈련

   insertRandomErrors(inputs,outputs,500);  //원본 데이터에 랜덤 오류 추가

   int handle2=initSVMachine();             //새로운 SVM을 초기화하고 핸들 반환
   setInputs(handle2,inputs,7);             //입력을 SVM에 전달합니다
   setOutputs(handle2,outputs);             //출력을 SVM에 전달합니다
   setParameter(handle2,OP_TOLERANCE,0.01); //오류 허용 한계를 설정합니다
   training(handle2);                       //SVM 훈련

   double t1=testSVM(handle1,N_TestPoints); //SVM 정확도 테스트
   double t2=testSVM(handle2,N_TestPoints); //SVM 정확도 테스트

   Print("SVM 정확도: ",NormalizeDouble(t1,2),"% (훈련 입력/출력 오류 없음)");
   Print("SVM 정확도: ",NormalizeDouble(t2,2),"% (훈련 입력/출력 오류 포함)");
   deinitSVMachine(); //메모리 정리
   return(0);
  }
//+------------------------------------------------------------------+
//| 전문가 비초기화 함수                                                     |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- OnDeinit()에서 실행되는 함수 없음
  }
//+------------------------------------------------------------------+
//| 전문가 틱 함수                                                       |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- OnTick()에서 실행되는 함수 없음   
  }
//+------------------------------------------------------------------+
//| 이 함수는 관찰된 동물의 특성을 기반으로 선택한 기준에 따라
//| true/false를 반환하여 Schnick인지 여부를 판단합니다
//+------------------------------------------------------------------+
bool isItASchnick(double height,double weight,double N_legs,double N_eyes,double L_arm,double av_speed,double f_call)
  {
   if(height   < 1000  || height   > 1100)  return(false); //높이가 기준을 벗어나면 false 반환
   if(weight   < 40    || weight   > 50)    return(false); //무게가 기준을 벗어나면 false 반환
   if(N_legs   < 8     || N_legs   > 10)    return(false); //다리 수가 기준을 벗어나면 false 반환
   if(N_eyes   < 3     || N_eyes   > 4)     return(false); //눈 수가 기준을 벗어나면 false 반환
   if(L_arm    < 400   || L_arm    > 450)   return(false); //팔 길이가 기준을 벗어나면 false 반환
   if(av_speed < 2     || av_speed > 2.5)   return(false); //속도가 기준을 벗어나면 false 반환
   if(f_call   < 11000 || f_call   > 15000) return(false); //주파수가 기준을 벗어나면 false 반환
   return(true);                                           //모두 만족하면 true 반환
  }
//+------------------------------------------------------------------+
//| 이 함수는 빈 double 배열과 빈 boolean 배열을 받아서
//| SVM 훈련에 사용할 입력/출력을 생성합니다
//+------------------------------------------------------------------+ 
void genTrainingData(double &inputs[],bool &outputs[],int N)
  {
   double in[];                    //빈 double 배열 생성
                                   //임시로 생성된 입력을 저장할 배열
   ArrayResize(in,N_Inputs);       //in[] 배열 크기를 N_Inputs로 조정
   ArrayResize(inputs,N*N_Inputs); //inputs[] 배열의 크기를 N*N_Inputs로 조정
   ArrayResize(outputs,N);         //outputs[] 배열의 크기를 N으로 조정
   for(int i=0;i<N;i++)
     {
      in[0]=    randBetween(980,1120);    //높이를 위한 랜덤 입력 생성
      in[1]=    randBetween(38,52);       //무게를 위한 랜덤 입력 생성
      in[2]=    randBetween(7,11);        //다리 수를 위한 랜덤 입력 생성
      in[3]=    randBetween(3,4.2);       //눈 수를 위한 랜덤 입력 생성
      in[4]=    randBetween(380,450);     //팔 길이를 위한 랜덤 입력 생성
      in[5]=    randBetween(2,2.6);       //속도를 위한 랜덤 입력 생성
      in[6]=    randBetween(10500,15500); //주파수를 위한 랜덤 입력 생성

      //--- 새로 생성된 랜덤 입력을 훈련 입력 배열로 복사
      ArrayCopy(inputs,in,i*N_Inputs,0,N_Inputs);
      //--- 랜덤 입력을 평가하여 Schnick인지 확인
      outputs[i]=isItASchnick(in[0],in[1],in[2],in[3],in[4],in[5],in[6]);
   }
  }
//+------------------------------------------------------------------+
//| 이 함수는 훈련된 SVM 핸들을 받아 새로운 랜덤 입력을 분류하는 성공률을 테스트합니다
//+------------------------------------------------------------------+ 
double testSVM(int handle,int N)
  {
   double in[];
   int atrue=0;
   int afalse=0;
   int N_correct=0;
   bool Predicted_Output;
   bool Actual_Output;
   ArrayResize(in,N_Inputs);
   for(int i=0;i<N;i++)
     {
      in[0]=    randBetween(980,1120);    //높이를 위한 랜덤 입력 생성
      in[1]=    randBetween(38,52);       //무게를 위한 랜덤 입력 생성
      in[2]=    randBetween(7,11);        //다리 수를 위한 랜덤 입력 생성
      in[3]=    randBetween(3,4.2);       //눈 수를 위한 랜덤 입력 생성
      in[4]=    randBetween(380,450);     //팔 길이를 위한 랜덤 입력 생성
      in[5]=    randBetween(2,2.6);       //속도를 위한 랜덤 입력 생성
      in[6]=    randBetween(10500,15500); //주파수를 위한 랜덤 입력 생성

      //--- isItASchnick 함수를 사용하여 실제 원하는 출력을 결정합니다
      Actual_Output=isItASchnick(in[0],in[1],in[2],in[3],in[4],in[5],in[6]);
      //--- 훈련된 SVM을 사용하여 예측된 출력을 반환합니다.
      Predicted_Output=classify(handle,in);
      if(Actual_Output==Predicted_Output)
        {
         N_correct++; //예측된 출력이 정확할 때 카운트
        }
     }
//--- 훈련된 SVM의 정확도를 백분율로 반환합니다
   return(100*((double)N_correct/(double)N));
  }
//+------------------------------------------------------------------+
//| 이 함수는 생성된 훈련 입력 및 출력에 N개의 랜덤 오류를 삽입합니다
//+------------------------------------------------------------------+ 
void insertRandomErrors(double &inputs[],bool &outputs[],int N)
  {
   int nTrainingPoints=ArraySize(outputs); //훈련 포인트 수 계산
   int index;                              //새로운 정수 'index' 생성
   bool randomOutput;                      //새로운 bool 'randomOutput' 생성
   double in[];                            //빈 double 배열 생성
                                           //임시로 생성된 입력을 저장할 배열
   ArrayResize(in,N_Inputs);           //in[] 배열의 크기를 N_Inputs로 조정
   for(int i=0;i<N;i++)
     {
      in[0]=    randBetween(980,1120);    //높이를 위한 랜덤 입력 생성
      in[1]=    randBetween(38,52);       //무게를 위한 랜덤 입력 생성
      in[2]=    randBetween(7,11);        //다리 수를 위한 랜덤 입력 생성
      in[3]=    randBetween(3,4.2);       //눈 수를 위한 랜덤 입력 생성
      in[4]=    randBetween(380,450);     //팔 길이를 위한 랜덤 입력 생성
      in[5]=    randBetween(2,2.6);       //속도를 위한 랜덤 입력 생성
      in[6]=    randBetween(10500,15500); //주파수를 위한 랜덤 입력 생성

      //--- 훈련 입력 중 하나를 선택하여 오류 삽입
      index=(int)MathRound(randBetween(0,nTrainingPoints-1));
      //--- 랜덤 boolean 출력 생성하여 오류 생성
      if(randBetween(0,1)>0.5) randomOutput=true;
      else                       randomOutput=false;

      //--- 새로 생성된 랜덤 입력을 훈련 입력 배열로 복사
      ArrayCopy(inputs,in,index*N_Inputs,0,N_Inputs);
      //--- 랜덤 출력을 훈련 출력 배열에 삽입
      outputs[index]=randomOutput;
     }
  }
//+------------------------------------------------------------------+
//| 이 함수는 t1과 t2 사이의 랜덤 값을 생성합니다
//+------------------------------------------------------------------+ 
double randBetween(double t1,double t2)
  {
   return((t2-t1)*((double)MathRand()/(double)32767)+t1);
  }
//+------------------------------------------------------------------+

연관 포스트

댓글 (0)