포스트 DayInInterRetStockS()의 클래스를 소개하는 글에서 원 일일주가데이터로 부터 새로운 변수들을 생성하여 새로운 객체를 만들었습니다.
그 결과를 바탕으로 회귀분석을 위한 데이터 생성을 계속해 보면 다음과 같습니다.
이전의 데이터 경향으로 새로운 값을 예측하는 것이 회귀분석의 기본방향이라면 위에서 생성된 데이터들 중에 예측에 사용되는 변수들(독립변수)과 예측을 위한 변수(반응변수)를 구분해야 겠지요.
이전에 생성한 객체의 변수명은 다음과 같습니다.
>>> da.columns
Index(['Open', 'High', 'Low', 'Close', 'Volume', 'Close:Open:ret',
'Close:High:ret', 'Close:Low:ret', 'Open:intRet', 'High:intRet',
'Low:intRet', 'Close:intRet', 'Volume:intRet', 'olag', 'hlag', 'llag',
'clag', 'vlag'],
dtype='object')
위의 변수들 중에 반응변수의 대상은 'Open', 'High', 'Low', 'Close'중의 하나의 변수가 될 것입니다.
예로서 Close를 반응변수로 한다면 나머지 변수들은 독립변수가 됩니다. 독립과 반응변수는 날들로 모형의 설계는
'당일까지의 독립변수들의 성격들로 다음날의 반응변수를 예측'
으로 구축할 것입니다.
이러한 구축을 위해 먼저 독립변수들과 반응변수를 구분하고 이 두 대상의 날짜를 다르게 하여 한 행에 위치시켜야 합니다.
또한 데이터 구축 후 분석을 위해 sklearn 패키지의 함수들을 사용할 것입니다. 이 함수들의 인수들은 np.array 객체가 대상이 됩니다. 데이터는 모두 동일한 형식으로 반환됩니다.
아래 함수에서 독립변수들은 표준화됩니다. 이것은 각 변수들 간의 scale의 차이로 효과를 제거하기 위한 것으로 별도의 함수를 만들어 사용해도 되지만 sklearn에거 제공하는 함수를 사용하는 것이 편리합니다. 그러므로 다음과 같이 관련된 모듈을 부착합니다.
>>> from sklearn import preprocessing, cross_validation, svm
def DataRegS1(da, deCol, stdize=1, shiftD=1):
d_lag=da.shift(shiftD)
if type(deCol) !=str:
deCol=d_lag.columns[deCol]
d=pd.concat([d_lag.drop([deCol], axis=1), da[deCol]],axis=1)
d=d.dropna()
ind=np.array(d.drop([deCol], axis=1))
de=np.array(d[deCol])
new=da.drop([deCol], axis=1).ix[len(da)-1,:]
if stdize==0:
ind=ind
new=new
else:
ind=preprocessing.scale(ind)
ind1_mu=np.mean(ind, axis=0)
ind1_sd=np.array([np.std(ind[:,i]) for i in range(ind.shape[1])])
new=np.array((new-ind1_mu)/ind1_sd)
return(ind, de, new)
반환되는 결과는 독립변수(ind), 반응변수(de), 최종적으로 사용되는 변수(new) 입니다.
new는 원 자료의 마지막 행입니다.
>>> cpind, cpde, cpnew=DataRegS1(da, 3)
>>> cpind[:2,:]
array([[-1.9438624 , -2.0539455 , -1.97377112, -0.34551834, -0.04362155,
0.48868343, -0.36767019, -0.7867308 , -1.11823123, -0.202969 ,
-0.13116804, -0.78078135, -1.39300768, -1.33736073, -1.4881869 ,
-1.4835275 , 0.33076086],
[-2.13940978, -2.2486958 , -2.21829566, 0.30033078, -0.27026372,
0.16433956, -0.51126002, -0.67611283, -0.69818054, -0.92970837,
-0.90124321, 0.44802125, -1.58394452, -1.58412679, -1.45874598,
-1.47638189, -0.15688456]])
>>> cpde[:2,]
array([16405, 16340], dtype=int64)
>>> cpnew
array([ 1.74300000e+04, 1.74850000e+04, 1.68400000e+04,
1.59008480e+07, -3.38496845e+00, -3.68887618e+00,
2.60999799e-16, -4.00000000e-01, -1.04697227e+00,
-3.71640938e+00, -3.88127854e+00, 2.50238248e+02,
1.75800000e+04, 1.76300000e+04, 1.74850000e+04,
1.75850000e+04, 5.32917100e+06])
회귀분석을 위한 데이터가 생성되었습니다.
다음으로 위 함수에서 사용한 데이터 da를 사용하여 이전에 사용한 bootstrap 방법을 적용하여 데이터 수를 증가시켜 회귀분석을 위한 데이터를 생성하는 함수를 만들어 봅니다. 이 함수는 이전에 작성한 mkbtsSampleS()(bootstrap 방법 참조, 위 링크된 포스트)과 위 DataRegS1()와의 결합으로 실행될 수 있습니다.
DataRegS1() 함수에서 사용된 pd.shift(number)는 데이터프레임 형태의 데이터에서 지정된 수 만큼 행을 아래로(양수), 위로(음수) 이동시킵니다.
다음을 볼까요?
>>> x=np.random.randint(0, 10, 10).reshape(5,2)
>>> x=pd.DataFrame(x)
>>> x
0 1
0 4 8
1 5 8
2 1 7
3 3 8
4 6 9
>>> x.shift(1)
0 1
0 NaN NaN
1 4.0 8.0
2 5.0 8.0
3 1.0 7.0
4 3.0 8.0
>>> x.shift(-1)
0 1
0 5.0 8.0
1 1.0 7.0
2 3.0 8.0
3 6.0 9.0
4 NaN NaN
이 함수를 사용하여 분석에 대응되는 독립변수들과 반응변수를 한 행에 정리한 후 이들의resampling의 bootstrap 방법 즉, mkbtsSampleS()를 적용합니다. 그 적용후에 DataRegS1에 그 결과를 적용합니다. 다음과 같이 class를 생성하여 사용합니다.
1. 클래스 BtsDataRegS에 사용할 객체를 전달하여 클래스 객체를 생성합니다.
2. 클래스 객체에 반응변수로 사용할 열 번호 또는 열 이름을 전달하여 독립변수들과 반응변수간의 날짜를 변경시켜 분석을 위한 데이터 형태로 만듭니다. 이 과정에서 반응변수는 생성된 데이터셋의 마지막 열에 위치하게 됩니다.
3. bootstrap 방법을 적용하여 샘플의 수를 증가시킵니다.
4. 3번에서 생성된 데이터를 독립변수와 반응변수, 그리고 최종적으로 사용하게 될 독립변수들을 생성합니다. 이 과정에서 독립변수들의 표준화를 적용할 수 있습니다.
1. 클래스 BtsDataRegS에 사용할 객체를 전달하여 클래스 객체를 생성합니다.
2. 클래스 객체에 반응변수로 사용할 열 번호 또는 열 이름을 전달하여 독립변수들과 반응변수간의 날짜를 변경시켜 분석을 위한 데이터 형태로 만듭니다. 이 과정에서 반응변수는 생성된 데이터셋의 마지막 열에 위치하게 됩니다.
3. bootstrap 방법을 적용하여 샘플의 수를 증가시킵니다.
4. 3번에서 생성된 데이터를 독립변수와 반응변수, 그리고 최종적으로 사용하게 될 독립변수들을 생성합니다. 이 과정에서 독립변수들의 표준화를 적용할 수 있습니다.
class BtsDataRegS:
def __init__(self, da):
self.da=da
def MkIndDeS(self, deCol, shiftD=1):
self.deCol=deCol
d_lag=self.da.shift(shiftD)
if type(self.deCol) !=str:
self.deCol=d_lag.columns[self.deCol]
d=pd.concat([d_lag.drop([self.deCol], axis=1), self.da[self.deCol]],axis=1)
self.d=d.dropna()
return(self.d)
def MkbtsS(self, smpN=10, repN=500):
n=len(self.d)
spId=np.random.choice(n, size=smpN, replace=True)
sample=np.array(np.mean(self.d.iloc[spId,:], 0)).reshape(1,self.d.shape[1])
for i in range(repN+1):
spId=np.random.choice(n, size=smpN, replace=True)
sp=np.array(np.mean(self.d.iloc[spId,:], 0)).reshape(1,self.d.shape[1])
sample=np.r_[sample,sp]
self.sample=sample
return(self.sample)
def MkData(self,stdize=1):
ind=self.sample[:, :(self.sample.shape[1]-1)]
self.de=self.sample[:, (self.sample.shape[1]-1)]
new=self.da.drop([self.deCol], axis=1).iloc[len(self.da)-1,:]
if stdize==0:
self.ind=ind
self.new=new
else:
self.ind=preprocessing.scale(ind)
daS=preprocessing.scale(self.da.drop(["Close"], axis=1))
self.new=daS[(daS.shape[0]-1),:]
return(self.ind, self.de, self.new)
위 클래스를 적용하기 위해 위에서 생성된 데이터 da의 마지막 5행을 사용합니다.
>>> trg=da.tail(5)
>>> test=BtsDataRegS(trg)
>>> inde=test.MkIndDeS(3)
>>> sm=test.MkbtsS()
>>> ind, de, new=test.MkData()
>>> new.shape
(17,)
>>> ind.shape
(502, 17)
>>> de.shape
(502,)
위에서 생성된 cpde와 500회 반복한 샘플 de, 1000회 반복한 샘플의 정규성을 확인하여 보면 다음과 같습니다. (그래프 작성을 위한 사용자 정의 함수 histNormalplotS)
먼저 bootstrap을 적용하지 않은 경우;
(0.98360045319196987, 1.3322215876321926e-42)
상관계수와 상관분석의 p-value가 결과로 반환됩니다.
500회 반복한 샘플;
(0.98502701750103172, 0.0)
1000회 반복한 샘플;
(0.99757571983444615, 0.0)
반복회수가 증가할 수록 정규성의 부합정도가 증가됨을 알 수 있습니다.
이는 회귀분석의 기본 가정 즉, 반응변수가 정규분포에 부합한다는 것을 만족시키는 것입니다. 이 가정은 분석자 입장에서 데이터의 모수를 아는 상태에 이루어지므로 분석 결과를 적용하는 합리적 근거가 됩니다.
def __init__(self, da):
self.da=da
def MkIndDeS(self, deCol, shiftD=1):
self.deCol=deCol
d_lag=self.da.shift(shiftD)
if type(self.deCol) !=str:
self.deCol=d_lag.columns[self.deCol]
d=pd.concat([d_lag.drop([self.deCol], axis=1), self.da[self.deCol]],axis=1)
self.d=d.dropna()
return(self.d)
def MkbtsS(self, smpN=10, repN=500):
n=len(self.d)
spId=np.random.choice(n, size=smpN, replace=True)
sample=np.array(np.mean(self.d.iloc[spId,:], 0)).reshape(1,self.d.shape[1])
for i in range(repN+1):
spId=np.random.choice(n, size=smpN, replace=True)
sp=np.array(np.mean(self.d.iloc[spId,:], 0)).reshape(1,self.d.shape[1])
sample=np.r_[sample,sp]
self.sample=sample
return(self.sample)
def MkData(self,stdize=1):
ind=self.sample[:, :(self.sample.shape[1]-1)]
self.de=self.sample[:, (self.sample.shape[1]-1)]
new=self.da.drop([self.deCol], axis=1).iloc[len(self.da)-1,:]
if stdize==0:
self.ind=ind
self.new=new
else:
self.ind=preprocessing.scale(ind)
daS=preprocessing.scale(self.da.drop(["Close"], axis=1))
self.new=daS[(daS.shape[0]-1),:]
return(self.ind, self.de, self.new)
위 클래스를 적용하기 위해 위에서 생성된 데이터 da의 마지막 5행을 사용합니다.
>>> trg=da.tail(5)
>>> test=BtsDataRegS(trg)
>>> inde=test.MkIndDeS(3)
>>> sm=test.MkbtsS()
>>> ind, de, new=test.MkData()
>>> new.shape
(17,)
>>> ind.shape
(502, 17)
>>> de.shape
(502,)
위에서 생성된 cpde와 500회 반복한 샘플 de, 1000회 반복한 샘플의 정규성을 확인하여 보면 다음과 같습니다. (그래프 작성을 위한 사용자 정의 함수 histNormalplotS)
먼저 bootstrap을 적용하지 않은 경우;
(0.98360045319196987, 1.3322215876321926e-42)
상관계수와 상관분석의 p-value가 결과로 반환됩니다.
500회 반복한 샘플;
(0.98502701750103172, 0.0)
1000회 반복한 샘플;
(0.99757571983444615, 0.0)
반복회수가 증가할 수록 정규성의 부합정도가 증가됨을 알 수 있습니다.
이는 회귀분석의 기본 가정 즉, 반응변수가 정규분포에 부합한다는 것을 만족시키는 것입니다. 이 가정은 분석자 입장에서 데이터의 모수를 아는 상태에 이루어지므로 분석 결과를 적용하는 합리적 근거가 됩니다.
댓글
댓글 쓰기