Labeling - jaeaehkim/trading_system_beta GitHub Wiki
Motivation
- Data Structures ํํธ์์ Financial Raw Data๊ฐ ์ด๋ค ์ข ๋ฅ ๋ฐ ํํ๋ก ์กด์ฌํ๋ ์ง๋ถํฐ IIDํ ํํ์ ๊ตฌ์กฐํ Bar๋ก ๋ง๋ค๊ณ , Bar๋ฅผ Event-Based Sampling ํ๋ ๋ฐฉ๋ฒ๊น์ง ์ฐ๊ตฌ๋ฅผ ์งํํ์๋ค.
- ์ด์ Data๊ฐ ์กด์ฌํ๋ ์ํ์์ ์ด ๋ฐ์ดํฐ๋ฅผ ์ด๋ป๊ฒ Labeling ํ์ฌ ML Model์๊ฒ ์ ๋ฌํด์ค ๊ฒ์ธ๊ฐ ๋ผ๋ ๋ฌธ์ ๊ฐ ๋จ์๋ค. ์ง๋ํ์ต์ ํน์ฑ์ Input์ (๋ฌธ์ X - ๋ต์ง y)๋ก ๊ตฌ์ฑํด์ฃผ์ด์ผ ํ๋ค.
- ์ ๋ฐ์ ์ผ๋ก Trading, Finance Paper๋ฅผ ๋ณด๋ฉด ๋๋ถ๋ถ Time Bar๋ก ์์ํด์ ์ผ์ ์๊ฐ ๊ตฌ๊ฐ์ Return์ ๊ฐ์ง๊ณ 0๋ณด๋ค ํฌ๋ฉด 1, ์๋๋ฉด -1 ํน์ 0์ด ์๋ ๊ธฐ์ค์ผ๋ก ํ๋ค๋ ์ง ํน์ 3-4๊ฐ์ง class๋ก labeling ๋ฐฉ์์ ์ฌ์ฉํ๋ค. ์ด๋ฒ ์ฅ์์ ML Model์ด ์ฌ๋์ ์๊ฐ์ ํนํํด์ ํ์ตํ๋ค๋ ์ธ์ฌ์ดํธ๋ฅผ ์ ์ฉํ์ฌ Path-dependentํ Labeling ๊ธฐ๋ฒ์ ์๊ฐํ ๊ฒ์ด๋ค.
The Fixed-Time Horizon Method
- ๋๋ถ๋ถ์ ํ์ดํผ๋ "๊ณ ์ -์๊ฐ Horizon" ๋ฐฉ์์ผ๋ก Labeling์ ์๋ํ๋ค. ์ง๊ด์ ์ด๋ ๋จ์ํ๋ค. ์ด๋ฅผ ์์์ผ๋ก generalํ๊ฒ ํํํ๋ฉด ์์ ๊ฐ๋ค.
- X๋ ์ด๋ค feature vector๋ผ๊ณ ๋ณด๋ฉด ๋๋ค. (ex. close price ์ฝ๊ฒ) y๋ ์๊ฐ ๊ตฌ๊ฐ ๋ด์์์ ์์ต๋ฅ (r_(t~t+h))์ ์๊ณ๊ฐ(tau)์ ๋ฐ๋ฅธ label
- ๋ฌธ์ ์
- ์ผ๋จ Fixed-Time์ ์ฐ๊ธฐ ์ํด์ ๊ธฐ์ด Bar๊ฐ Time Bar์ฌ์ผ ํ๋ค. ์ด๋ Data Structures ์์ ๋ดค๋ฏ ์ข์ ํต๊ณ์ ์ฑ์ง (IID)์ ๊ฐ์ง ๋ชปํ๋ ๊ฒ์์ ๋ถํฐ ๋ฌธ์ ๊ฐ ๋๋ค.
- ์ถ๊ฐ๋ก, Fixed-Time์ผ๋ก Bar๋ฅผ ๊ตฌ์ฑํ๊ฒ ๋๋ฉด ๋ชจ๋ ์๊ฐ์ ๋์ผํ ์ ๋ณด๊ฐ ์๋ค๊ณ ๊ฐ์ ํ๋ ์ค๋ฅ๋ฅผ ๋ฒํ๋๋ฐ ์ด๋ก ์ธํด ๋ณ๋์ฑ์ด ์ ์ ๋ง์ ๊ตฌ๊ฐ์์ label์ด ์๊ณ๊ฐ์ ๋์ง ๋ชปํ๊ฒ ๋ ๊ฒ์ด๊ณ (๋๋ถ๋ถ label=0) ML Model์ด Accuracy๋ง ๋์ด๋ ๋ฐฉํฅ์ผ๋ก ํ์ต๋ ๊ฐ๋ฅ์ฑ์ด ๋๋ค. ์ฆ, ์ค์ง์ ์ ํจ์ฑ์ด ๋จ์ด์ง๋ค.
- ๊ธฐ๋ณธ ํด๊ฒฐ์ฑ
- ์๊ณ๊ฐ tau๋ฅผ ์์๋ก ๊ณ ์ ํ์ง ์๊ณ return's rolling std๋ฅผ ํ์ฉํ์ฌ ๋ณ๋ํ๋ ์๊ณ๊ฐ sigma_t๋ฅผ ํ์ฉํ๋ ๊ฒ์ด๋ค. ๊ทธ๋ผ ์๊ธฐ๋ณ๋ก ์ ์ ํ๊ฒ ์๊ณ๋ฅผ ๋๋ label=1์ด ์์ฑ๋ ๊ฒ์ด๋ค.
- ์ฒ์๋ถํฐ Volume/Dollar Bar๋ฅผ ํ์ฉํ์ฌ constantํ ์๊ณ๊ฐ tau๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค. ์ด๋ฏธ Bar ์์ฒด์ ๊ฑฐ๋๋/๊ฑฐ๋๋๊ธ์ ๋น๋กํด ์ ๋ณด๊ฐ์ค์ด ๋์ด ์๊ธฐ ๋๋ฌธ์ constantํ tau์ฌ๋ ์ข ๋ ๋ซ๊ฒ labeling์ด ๋ ์ ์๋ค.
The Triple-Barrier Method
- AFML(Advances in Financial Machine Learning)์์ Marcos Lopez ๊ต์๊ฐ ์๊ฐํ Labeling ๊ธฐ๋ฒ์ด๋ค. ์ด๋ฅผ Triple-Barrier Method(ํธ๋ฆฌํ ๋ฐฐ๋ฆฌ์ด ๊ธฐ๋ฒ)๋ผ ๋ถ๋ฅด์.
- ํด๋น ๊ธฐ๋ฒ์ 2๊ฐ์ Horizontal Barrier(์ํ์ )๊ณผ 1๊ฐ์ Vertical Barrier(์์ง์ )์ ์ ์ํ๋ ๊ฒ์ด๋ค.
- ํฌ์ ์์ t์์ ์ง์ฌ๊ฐํ์ Barrier Box๋ฅผ ๊ทธ๋ฆด ์ ์๊ณ , price์ ์์ง์์ด ์ด๋ค barrier๋ฅผ ๋ฟ๋ ๊ทธ ์๊ฐ์ ๊ฐ์ผ๋ก labeling ํ๋ ๋ฐฉ์์ด๋ค.
- ์ฆ, ๋์ ์ผ๋ก ํ์์ปท, ์ต์ , ์์ ์ ๋ผ์ธ์ ์ก์์ฃผ๋ ๊ทธ generalํ ํ์๋ฅผ labeling ํจ์ผ๋ก์จ ML Model์ด ์ด๋ฅผ ๋์ ์ผ๋ก ๊ณ์ฐํ inference ๊ฐ์ ๋ด๊ฒ ํด์ค๋ค.
- ์ด๋, bar ์ฒซ ์์์ ์์ ์ํ์ 2๊ฐ์ ์์ง์ 1๊ฐ ์ค์์ ์ฒ์ ๋ง๋ ๋ถ๋ถ์ผ๋ก ๋์ด์ labeling์ ์งํํ๋ค.
- ์ด๋ฅผ ์ดํดํ๊ธฐ ์ฝ๊ฒ ๊ทธ๋ฆผ์ผ๋ก ํํํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
Method Flow
getTEvents
def getTEvents(gRaw, upper, lower=None):
if lower is None:
lower = - upper
assert (upper >=0 and lower <= 0)
tEvents, sPos, sNeg = [], 0, 0
diff = gRaw.diff()
for i, change in enumerate(diff.values[1:]):
sPos, sNeg = max(0, sPos + change), min(0, sNeg + change)
if sNeg < lower:
sNeg = 0
tEvents.append(i)
if sPos > upper:
sPos = 0
tEvents.append(i)
return gRaw.index[tEvents]
-
- Data Structures ์์ VB/DB or TIB/VIB/DIB or TRB/VRB/DRB์ ํํ์ Bar๋ก ๋ง๋ค๊ณ CUSUM Filter๋ฅผ ์ด์ฉํด์ ํด๋น ์์ ์ T index๋ฅผ ์ถ์ถ
getBins : Triple Barrier labeling ์์
def getBins(events, price):
"""
refer to the explanation before snippet 3.5
:param events: returned value of getEvents, columns=['trgt','tl']
:param price: volume_df.price
:return: columns=['ret', 'bin']
"""
events_ = events.dropna(subset=['tl'])
px = events_.index.union(events_['tl'].values).drop_duplicates()
px = price.reindex(px, method='bfill')
out = pd.DataFrame(index=events_.index)
out['ret'] = px.loc[events_['tl'].values].values / px.loc[events_.index] - 1
if 'side' in events_:
out['ret'] *= events_['side']
out['bin'] = np.sign(out['ret'])
if 'side' in events_:
out.loc[out['ret']<=0, 'bin'] = 0
return out
- getBins๋ฅผ ํตํด ์ต์ข ์ ์ธ Triple Barrier Method์ output์ด ์ ๋ฌ๋จ. ์ค๊ฐ ๊ณผ์ ์ add Vertical Barrier๋ก ์์ง์ ์ ๋ณด, add Horizontal Barrier๋ก ์ํ์ ์ ๋ณด๋ฅผ ๋ฐ์ํ์ฌ ์ด ๋์ ๋ฐ์ํ ๋ฐ์ดํฐ๋ฅผ getEvents์์ ๊ฐ๊ณตํ์ฌ getBins๋ก ์ ๋ฌํจ.
- getBins์ output์ผ๋ก ์ถ๊ฐ์ ์ธ feature๋ฅผ ๊ฐ๊ณตํ๊ณ ์ด๋ฅผ ML Model์ ํ์ต์ํด.
getEvents
def getEvents(price, tEvents, ptSl, trgt, minRet, numThreads, tl=False, side=None):
"""
refer to the explanation before and after snippet 3.3, with enhancements explained right before snippet 3.6
:param price:
:param tEvents:
:param ptSl:
:param trgt: dailyVol(horizontal bar unit width), index = price.index which contains tEvents
:param minRet: at last dailyVol must be larger than this scalar
:param numThreads:
:param tl: index = tEvents
:param side: side
:return: index=subset of trgt.index(tEvents), columns=['tl','trgt', 'side'(if side is not None)] where 'tl' is not vertical bar timestamp but first-time for barrier touch
"""
trgt = trgt.loc[trgt.index.isin(tEvents)]
trgt = trgt[trgt > minRet]
if tl is False:
tl = pd.Series(pd.NaT, index=tEvents)
if side is None:
side_, ptSl_ = pd.Series(1., index=trgt.index), [ptSl[0],ptSl[0]]
else:
side_, ptSl_ = side.loc[trgt.index], ptSl[:]
events = pd.concat({'tl': tl, 'trgt': trgt, 'side': side_}, axis=1).dropna(subset=['trgt'])
df0 = mpPandasObj(func=applyPtSlonTl, pdObj=('molecule', events.index), numThreads=numThreads, price=price, events=events, ptSl=ptSl_)
events['tl'] = df0.dropna(how='all').min(axis=1)
if side is None:
events = events.drop('side', axis=1)
return events
- ์ต์ข getBins์์ ๋์จ ๊ฒ๊ณผ bin column์ ์๊ณ์ ์ ํ์ฉํ labeling ์ฐจ์ด๋ง ์กด์ฌํ๋ค. getEvents๋ Vertical/Horizontal Barrier๋ฅผ ๋ฐ์ํ ์ต์ข ์ ๋ณด๋ฅผ ์ฐ์ถํ๋ค.
add Vertical Barrier
def addVerticalBarrier(tEvents, price, numDays=None):
"""
refer to snippet 3.4, in book, it resorts to pd.Timedelta(days=Numdays), but here we assume general-bars, which are not necessarily time-bars, so I set h=10
:param tEvents: getTEvents(returns(volume_df.price), threshold) = pd.DateTimeIndex(sampled with cumsum)
:param price: whole data before sampling, volume_df.price with index=np.datetime64
:param horizon: vertical barrier size, initialization=10
:return: Series with values of tl timestamp and index of tEvents timestamp
"""
tl = price.index.searchsorted(tEvents) + 10 if numDays is None else price.index.searchsorted(tEvents+pd.Timedelta(days=numDays))
tl = tl[tl < len(price)]
return pd.Series(price.index[tl], index=tEvents[:len(tl)])
- getTEvents์ T Index๋ง ์๋ ๊ฐ์์ ์๋ฌด๋ฆฌ ์์ต์ (ptsl:profit taking / stop loss)์ด ์ ๊ฑธ๋ฆฌ๋๋ผ๋ ์ต๋๋ก Time cut์ผ๋ก ๋์ด์ฃผ์ด ์์์ (index)์ ๋ง์ง๋ง์ (vertical)์ด ์กด์ฌํ๋ output์ด ๋์จ๋ค.
add Horizontal Barrier (add ptsl line)
def applyPtSlonTl(price, events, ptSl, molecule):
"""
refer to the explanation before snippet 3.2
:param price: volume_df.price
:param events: index=tEvents, columns=['tl','target'(dailyvol), 'side']
:param ptSl: horizontal bar width ratio
:param molecule: a list with the subset of event indices that will be processed by a single thread
:return: index=tEvents, columns=['pt', 'sl'], first time touching each barrier
"""
events_ = events.loc[molecule]
out = events_['tl'](/jaeaehkim/trading_system_beta/wiki/'tl').copy(deep=True)
if ptSl[0] > 0:
pt = ptSl[0]*events_['trgt']
else:
pt = pd.Series(index=events.index) # NaNs
if ptSl[1] > 0:
sl = -ptSl[1]*events_['trgt']
else:
sl = pd.Series(index=events.index)
for loc, tl in events_['tl'].fillna(price.index[-1]).iteritems():
df0 = price[loc:tl]
df0 = (df0 / price[loc] - 1) * events_.at[loc,'side']
out.loc[loc, 'sl'] = df0[df0 < sl[loc]].index.min()
out.loc[loc, 'pt'] = df0[df0 > pt[loc]].index.min()
return out
- vertical์ ์ผ๋จ ์๊ฐํ์ง ์๊ณ ์ต์ (pt),์์ (sl)๋ผ์ธ์ ์ต๊ทผ ๋ณ๋์ฑ์ ํ์ฉํ์ฌ ๋์ ์ผ๋ก ์ก์์ฃผ๋ ์ญํ ์ ํ๊ณ ์ฒซ ๋ฒ์งธ ๋๋ฌํ๋ ์์ ์ ๊ธฐ๋กํ๋ค.
Meta-Labeling
- Triple-Barrier๋ฅผ ํ์ฉํด์ Labeling์ ํ๊ณ ์ด๋ฅผ ML Model์ ์ ์ฉํ๋ ๊ฒฝ์ฐ์๋ ML Model์ Inference๋ก side(Long/Short), size(probability)๋ฅผ ์ถ๋ ฅํ ์ ์๋ค. ์ด๋ฅผ ๊ทธ๋๋ก ํ์ฉํด๋ ๋๋ค. Meta-Labeling์ ๋ชฉ์ ์ ํ๋์ ๋ชจ๋ธ๋ก ์ฒ๋ฆฌ๋ ์ ์๋ ํ๋ก์ธ์ค๋ฅผ Decomposition ํด์ ์ค๊ณํ์ฌ Model์ Metric ์ค์์ F1-Score๋ฅผ ๊ทน๋ํ ์ํด์ ์๋ค. ์ด๊ฒ์ side,size๋ฅผ ๊ฒฐ์ ํ๋ ๋ชจ๋ธ ์์์์ decomposition์ ์ ์์์ ์๊ธฐํ๊ณ ์์ง๋ง ํฌ์ํ๋ ํ๋ก์ธ์ค์ ๋ชจ๋ ๋ถ๋ถ์์ Meta-Labelingํ ์ํฌ ์ ์๊ณ decomposition๋ ๋ชจ๋ ๋ถ๋ถ์ด ML Model์ผ ํ์๋ ์๋ค๊ณ ์๊ฐํ๋ค. (Quantametal Way)
- Meta-Labeling : Detailed decomposition of model
- label์ 1์ฐจ์ ์ผ๋ก min return ๊ฐ์ ์ด์ฉํด 1,0์ผ๋ก ๋ถ์ฌ์ ๋ฒ ํ ์ฌ๋ถ๋ฅผ ๊ฒฐ์
- pt,sl ์์น
- Question
- model์ decomposingํด์ ์ด์ํ๋๊ฒ ๋ฌด์กฐ๊ฑด ์ข์๊น?
- ๋ชจ๋ธ ๊ด๋ฆฌ ๋น์ฉ์ด ๋ง์ด ๋ค์ด๊ฐ.
- ํ๋์ model ๋ง๋ค ์ด๋ป๊ฒ labeling ํ ๊ฒ์ธ์ง, feature๋ค์ ์ด๋ป๊ฒ ๊ด๋ฆฌํ ๊ฒ์ธ์ง etc
- single-labeling์ ์ด๋ฏธ ๋ค ํฌํจ๋ ๊ฒ์ ์๊ฒ ๋๋์ด์ ์ธ๋ถ์ ์ผ๋ก ํ๋ ๊ฒ ๋ฟ์ด๊ธฐ ๋๋ฌธ์ main model์ triple-barrier method๋ฅผ ํ์ฉํด์ train ํ ์ดํ์ ๋๋จธ์ง ๋ถ๋ถ์ rule-based๋ก ์ฒ๋ฆฌํ๋๊ฒ ๋์ ๊ฒ์ด๋ผ๋๊ฒ ๊ฐ์ธ์ ์ธ ์๊ฐ.
- ๋ค์ํ 1-config = 1-strategy ๋ฅผ ์ฐพ์๋ด์ด ensemble ์ํค๋ ๋ฐฉ์
- rule์์ ํ์ํ hyper parameter ๊ฐ๋ค์ config์ ํฌํจ์ํค๋ ๋ฐฉ์์ผ๋ก ์ค๊ณํ์ฌ ์ต๋ํ model search๋ฅผ ํ ๋ ๋์ ์์ญ์ ํ๊ตฌํ ์ ์๋๋ก ์งํ
- pt,sl ๋น๋์นญ
- betting model : single prob betting, average prob betting etc
- ensemble ์ํฌ ๋ ๊ฑฐ๋๋น์ฉ/ํ์ ์จ์ ๊ทน๋ํ์ํฌ ์ ์๋ ๋ฐฉ์์ผ๋ก ์ค๊ณํด์ผ ํจ.
- ๋จ์ผ ์ ๋ต ์๋ฎฌ๋ ์ดํฐ / ๋ฉํ ์ ๋ต ์๋ฎฌ๋ ์ดํฐ -> Point in Time ๋ฐฉ์
- rule์์ ํ์ํ hyper parameter ๊ฐ๋ค์ config์ ํฌํจ์ํค๋ ๋ฐฉ์์ผ๋ก ์ค๊ณํ์ฌ ์ต๋ํ model search๋ฅผ ํ ๋ ๋์ ์์ญ์ ํ๊ตฌํ ์ ์๋๋ก ์งํ
- Model์ Metric๊ณผ Backtest์ Metric์ ๊ตฌ๋ณํ๋ ๋ฐฉ์์ผ๋ก ์ด๋์ ๋ Meta-Labeling ๊ธฐ๋ฒ์ด ์ค๋ฉฐ๋ค์ด ๊ฐ ๊ฒ์ด๋ผ๊ณ ์๊ฐ. Meta-Labeling์ ๋น์ฉ๊ณผ ํจ์ฉ๊ฐ์ Trade-off ๊ด๊ณ์ ์์ผ๋ฏ๋ก ์ ๋นํ ์ ์์ Decision์ ๋ด๋ ค์ค์ผ ํจ.
Qunatamental Way
- Meta-Labeling์ ํ์ฅ์ํจ ๊ฐ๋ ์ด๋ค. ๊ฒฐ๊ตญ์ Meta-Labeling์ ์ ๋ํ๋ ๊ฒ ์์์ ๋ ์ธ๋ถ์ ์ผ๋ก ์ชผ๊ฐ๋ค์ด๊ฐ๋ ๊ฒ์ ์๊ธฐํ๋ค๋ฉด, Quantamental Way๋ ๋น์ ๋ํ๋ ๋ชจ๋ ๊ฒฝํ์ ์ ๋ํ ํ๋ ๊ณผ์ ์ ์๊ธฐํ๋ ๊ฒ์ด๋ค. ์ ๋ํ๋ ํค์งํ๋๊ฐ ์ผํ๋ ํ๋ก์ธ์ค์์ ๋ฐ์ํ๋ ๋ชจ๋ ์์ฌ๊ฒฐ์ ์ ์ ์ฉ๋ ์ ์์ผ๋ฉฐ ํ์ฌ ๋ด๋ถ์์ ์ผ๋ง๋ ๋ง์ ๋ถ๋ถ์ด ์ ๋ํ ๋์๋์ง๊ฐ ๋งค์ฐ ์ค์ํ ์๋๊ฐ ์ฌ ๊ฒ์ด๋ค.
Application to Quant System
- Lagbeling์ ์ฒซ barrier๊ฐ touch ํ๋ ๋ถ๋ถ์ผ๋ก๋ง ํ ํ์๊ฐ ์์๊น?
- barrier touchํ๋ ๊ฒ๋ ๋ค์ํ๊ฒ ํ๋ค๋ฉด ๋ค์ํ ๋ชจ๋ธ์ด ๋ง๋ค์ด์ง ๊ฒ์ผ๋ก ๋ณด์.