안녕하세요, 트레이더 여러분! 오늘은 'Machine Learning: Support Vector Machines을 트레이딩에 활용하는 방법'라는 기사의 일환으로, Support Vector Machine 학습 도구의 데모 스크립트를 소개하고자 합니다.
상상해 보세요. 여러분은 극지방 깊숙한 곳에 사는 희귀 동물인 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); } //+------------------------------------------------------------------+