SVM Classifier - 기본전략

이번 포스팅에서는 서포트벡터머신 분류기를 이용해서 일일주가트렌드 분석을 분석해본다.

소스코드 & 코드설명

데이터는 2000년도부터의 삼성전자 일일 주가데이터를 사용한다.

dataframe = fdr.DataReader('005930', '2000')
dataframe.dropna(inplace=True) # 결측치제거
dataframe
Date Open High Low Close Volume Change
2000-01-04 6000 6110 5660 6110 1483967 0.148496
2000-01-05 5800 6060 5520 5580 1493604 -0.086743
2000-01-06 5750 5780 5580 5620 1087810 0.007168
2000-01-07 5560 5670 5360 5540 806195 -0.014235
2000-01-10 5600 5770 5580 5770 937615 0.041516
2021-11-29 71700 73000 71400 72300 16682559 0.000000
2021-11-30 73200 73900 70500 71300 30364841 -0.013831
2021-12-01 72000 74800 71600 74400 21954856 0.043478
2021-12-02 73900 75800 73800 75800 23652940 0.018817
2021-12-03 75600 76000 74100 75600 17616621 -0.002639

따로 전처리과정없이 데이터에 있는 모든 특성을 변수로 이용한다.

def trend_separater(x):
	if x > 0.0016639: # 상승과 하락 트렌드의 절대적인 개수를 비슷하게 맞춰주기 위한 기준점을 선정한다.
    	return 1
	elif x < -0.001:
    	return -1

def updown(dataframe):
	dataframe['UD_Trend'] = dataframe['Change'].map(lambda x : trend_separater(x)) 
	dataframe['UD_Trend'] = dataframe['UD_Trend'].shift(-1)  # 다음날 트렌드를 예측해야하므로 다음날 트렌드를 앞으로 한 행 당긴다
	dataframe.dropna(inplace=True)  # 결측치 제거
	return dataframe

다음날 변화율을 상승하락 트렌드로 변환하여 전날의 레코드에 추가한다. UD_Trend 특성이 다음날 주가의 변화 트렌드이다.

labeled_df = dataframe.copy()
labeled_df = updown(labeled_df)
total_count = labeled_df.UD_Trend.count()
labeled_df['UD_Trend'].value_counts()
target_df = labeled_df.copy()
target_df.reset_index(inplace=True)
target_df
  Date Open High Low Close Volume Change UD_Trend
0 2000-01-04 6000 6110 5660 6110 1483967 0.148496 -1.0
1 2000-01-05 5800 6060 5520 5580 1493604 -0.086743 1.0
2 2000-01-06 5750 5780 5580 5620 1087810 0.007168 -1.0
3 2000-01-07 5560 5670 5360 5540 806195 -0.014235 1.0
4 2000-01-10 5600 5770 5580 5770 937615 0.041516 -1.0
5407 2021-11-26 73500 74100 72000 72300 13002242 -0.018996 -1.0
5408 2021-11-29 71700 73000 71400 72300 16682559 0.000000 -1.0
5409 2021-11-30 73200 73900 70500 71300 30364841 -0.013831 1.0
5410 2021-12-01 72000 74800 71600 74400 21954856 0.043478 1.0
5411 2021-12-02 73900 75800 73800 75800 23652940 0.018817 -1.0

레코드 개수가 5411개이다. 임의대로 앞에 4000개를 훈련세트로 사용하고 그 뒤의 데이터를 검증세트로 사용하겠다.

# 전체 세트
X_all = np.array(target_df.loc[:, target_df.drop(['UD_Trend', 'Date'], axis=1).columns])
y_all = np.array(target_df.loc[:, ['UD_Trend']])
# 훈련 세트
X_train = X_all[:4000]
y_train = y_all[:4000]
# 검증 세트
X_test = X_all[4000:]
y_test = y_all[4000:]

StandardScaler로 스케일링한 데이터를 사용하는 SVC 모델을 파이프라인으로 생성한다.

svm_cla = Pipeline([
				("scaler", StandardScaler()),
                ("svc", SVC()),
        ])

훈련세트로 훈련을 진행하고 훈련세트와 검증세트에서의 점수를 측정한다.

svm_cla.fit(X_train, y_train) # 훈련 세트로 훈련진행
print("train_set score: ", svm_cla.score(X_train, y_train)) # 훈련세트 점수
print("test_set score : ", svm_cla.score(X_test, y_test)) # 검증세트 점수

sample = target_df.loc[4000:,].copy()
sample['predicted'] = svm_cla.predict(X_all[4000:])
sample

검증세트에서 예측한 array를 원래 검증세트부분의 데이터프레임에 column 으로 추가시키자

  Date Open High Low Close Volume Change UD_Trend predicted
4000 2017-04-26 42700 42800 42520 42800 295896 0.002342 1.0 1.0
4001 2017-04-27 42700 44520 41960 43840 460645 0.024299 1.0 1.0
4002 2017-04-28 45780 45800 44520 44620 453714 0.017792 1.0 1.0
4003 2017-05-02 45500 45500 44760 44900 281366 0.006275 1.0 1.0
4004 2017-05-04 45700 45700 44860 45520 273802 0.013808 1.0 1.0
5024 2021-11-25 75100 75100 73600 73700 12559258 -0.014706 -1.0 1.0
5025 2021-11-29 71700 73000 71400 72300 16682559 0.000000 -1.0 1.0
5026 2021-11-30 73200 73900 70500 71300 30364841 -0.013831 1.0 1.0
5027 2021-12-01 72000 74800 71600 74400 21954856 0.043478 1.0 1.0
5028 2021-12-02 73900 75800 73800 75800 23652940 0.018817 -1.0 1.0

이상한 점이 발견되었는데 예측한 값이 모두 1이다. 훈련세트에 과적합되어서 올바른 예측을 하지 못한것이다. 다음 포스팅에서는 하이퍼파라미터 조정을 통해 이 현상을 조절한다.

Updated: