대규모 거래자들은 order book을 전부 휩쓸어 가거나 소위 물타기(iceberg) 주문, 혹은 분할 주문을 하는 방법 등으로 거래를 실행하는데 이는 sequence 안에 거래 흔적을 남긴다. 이러한 이유로 전체 거래량 안에서의 매수 시퀀스를 조사해 보는 것이 유용하며, 이 매수 시퀀스가 기대에서 벗어날 경우에 표본 추출을 한다
시장상황을 하나 가정해 보자. 기업 A의 1분기 실적 발표 이전에 내부 정보의 유출로 실적의 개선 혹은 부진이라는 정보를 가진 증권 시장 참여자가 뉴스 보도 이전에 거래를 하려고 한다. 이때, 전자의 경우는 추가 매수 주문을 넣을 것이고, 후자의 경우 매도 주문을 넣을 것이다. 이러한 정보 기반 거래자의 참여자가 적절한 수준으로 많을 때, order book에서는 기업 A의 거래량이 증가할 것이다. imbalance bar는 매도와 매수의 방향과 관게 없이 거래량 자체가 기대값을 벗어날 경우에 샘플링을 한다. run bar는 여기에서 더 나아가, 틱이 매수인지 혹은 매도인지까지 고려하여, 매수 시퀀스가 기대값에서 벗어났을 경우에 샘플링을 한다는 아이디어다. 이 경우, 어느 방향에서 정보 기반 거래자가 주문을 요청하는지 추적이 가능하다는 점에서 장점을 가지고 있다.
현재 run의 길이는 다음과 같이 정의할 수 있다
다음으로, 바의 시작 지점에서의 기대값 를 계산한다
경험적으로 는 이전 바들의 window = 인 지수 가중 이동 평균(EWMA)으로 계산할 수 있고, 은 이전 바들의 매수 tick 비율의 지수 가중 이동 평균으로 계산할 수 있다.
셋째, Tick run bar를 다음 조건을 만족하는 tick의 연접 부분 집합으로 정의한다.
여기서 run의 기대 틱 횟수는 으로 추정된다. 가 기대값보다 더 많은 런을 보여문다면, 작은 가 조건을 만족할 것이다.
이런식으로 정의하면 각 side별 틱 개수를 저장할 수 있는데, 이는 시퀀스의 길이를 측정하는 것보다 더 유용하다. 아래는 tick run bar를 정의하는 하나의 파이썬 함수 코드이다.
def tick_run_bars(file_path_or_df: Union[str, Iterable[str], pd.DataFrame],
num_prev_bars: int,
expected_imbalance_window: int = 10000,
exp_num_ticks_init: int = 20000,
batch_size: int = 2e7,
analyse_thresholds: bool = False,
verbose: bool = True):
bars = RunBars(metric='tick_run', num_prev_bars=num_prev_bars,
expected_imbalance_window=expected_imbalance_window,
exp_num_ticks_init=exp_num_ticks_init,
batch_size=batch_size, analyse_thresholds=analyse_thresholds)
run_bars = bars.batch_run(file_path_or_df=file_path_or_df, verbose=verbose)
return run_bars, pd.DataFrame(bars.bars_thresholds)
아래 예시는 동일한 데이터셋에 대하여 기대 틱의 값 300, EWMA 계산을 위한 look back기간을 300으로 지정한 tick run bar sampling의 결과이다.
volume run bar, dollar run bar는 앞서 언급한 tick run bar의 개념을 확장한 것이다. tick run bar에서 각 방향별 틱의 개수가 기대를 벗어날 때마다 샘플링을 한다면, VRB와 DRB는 각각 거래량과 달러 가치가 기대치를 벗어날 때마다 샘플링을 하는 것이다. 틱 규칙에 대한 관행적 명칭에 따라 바의 최종 관측값 인덱스인 를 결정해야 한다.
우선, 런에 관련된 거래량 혹은 달러 가치는 다음과 같이 정의할 수 있다.
여기서 는 바의 타입에 따라서 거래량이 될 수도 있고 달러 가치가 될 수도 있다. 다음으로, 바의 시작 지점에서 기대값 를 계산한다.
사실 는 이전 바들로부터 값의 지수 가중 이동 평균으로 계산할 수 있고, 은 이전 바들의 매수 틱 비율의 지수 가중 이동 평균으로 계산할 수 있다. 또한, 은 이전 매수 거래량 혹은 달러 가치 바들의 EWMA값으로, 은 이전 매도 거래량 혹은 달러 가치 바들의 EWMA값으로 추정할 수 있다.
마지막으로, VRB혹은 DRB를 다음 조건을 만족하는 틱의 연접 부분 집합으로 정의한다.
여기서 런의 기대 거래량 혹은 달러 가치는 으로 추정된다. 이 기대값보다 많은 런을 보이거나, 런으로부터의 거래량이 기대값보다 크다면 작은 가 이 조건을 만족할 것이다.
다음은 python을 이용해 VRB와 DRB를 구현하는 코드 예제이다.
def volume_run_bars(file_path_or_df: Union[str, Iterable[str], pd.DataFrame],
num_prev_bars: int,
expected_imbalance_window: int = 10000,
exp_num_ticks_init: int = 20000,
batch_size: int = 2e7,
analyse_thresholds: bool = False,
verbose: bool = True):
bars = RunBars(metric='volume_run', num_prev_bars=num_prev_bars,
expected_imbalance_window=expected_imbalance_window,
exp_num_ticks_init=exp_num_ticks_init,
batch_size=batch_size, analyse_thresholds=analyse_thresholds)
run_bars = bars.batch_run(file_path_or_df=file_path_or_df, verbose=verbose)
return run_bars, pd.DataFrame(bars.bars_thresholds)
def dollar_run_bars(file_path_or_df: Union[str, Iterable[str], pd.DataFrame],
num_prev_bars: int,
expected_imbalance_window: int = 10000,
exp_num_ticks_init: int = 20000,
batch_size: int = 2e7,
analyse_thresholds: bool = False,
verbose: bool = True):
bars = RunBars(metric='dollar_run', num_prev_bars=num_prev_bars,
expected_imbalance_window=expected_imbalance_window,
exp_num_ticks_init=exp_num_ticks_init,
batch_size=batch_size, analyse_thresholds=analyse_thresholds)
run_bars = bars.batch_run(file_path_or_df=file_path_or_df, verbose=verbose)
return run_bars, pd.DataFrame(bars.bars_thresholds)
다음은 각 표본추출법에 대한 샘플링 결과이다. 두 경우 모두 기대 틱을 100단위로 지정하였으며, EWMA 계산을 위한 look back 기간을 300으로 지정하였다.