News & Events
[알고리즘 트레이딩/전략편] 39. API를 통한 스프레드의 성분 분해
- 2019년 1월 11일
- Posted by: 인사이트캠퍼스
- Category: 금융/AI/IT 기사
알고리즘 트레이딩 (Algorithmic Trading) – 전략 (39)
API를 통한 스프레드의 성분 분해
호가창의 Bid-Ask 스프레드를 측정하는 방법으로는, 눈에 보이는 명목 스프레드 (Quoted Spread), 현재의 체결 가격과 현재의 중간 가격을 이용한 유효 스프레드 (Effective Spread), 그리고 현재의 체결 가격과 다음 (가까운 미래의) 중간 가격을 이용한 실질 스프레드 (Realized Spread)가 있다. 이 방법들은 향후 시장미시구조론의 이론편에서 자세히 다루기로 하고, 이번 시간에는 Bid-Ask 스프레드를 구성하는 요인들을 실시간으로 측정해 보기로 한다.
Bid-Ask 스프레드는 3가지 요소로 구성되어 있다. 첫째, 마켓메이커가 기본적으로 요구하는 댓가 (Order Processing cost : OP)가 있고, 둘째, 마켓메이커가 거래를 통해 보유하게 되는 악성 재고 위험에 대한 댓가 (Inventory Holding cost : IH)가 있다. 그리고 셋째는 정보 비대칭으로 인해 마켓메이커가 잘못된 호가를 제시하게 될 위험 (역선택 위험)에 대한 댓가 (Asymmetric Information cost : AI)가 있다. 호가창의 이벤트를 관찰해서 스프레드를 측정하고, 스프레드를 요인별로 분해해 볼 수 있을까?
시장미시구조론에서 살펴본 Madhavan (1996) 모형을 이용하면 Bid-Ask 스프레드를 OP와 AI로 분해해 볼 수 있다. 아래 그림은 필자가 개발한 XingScript 프로그램에서 지수 옵션의 스프레드를 요인별로 관찰하는 모습이다. XingAPI를 이용하여 지수 옵션의 호가창 정보 (호가 + 체결 틱)를 실시간으로 받아 스프레드를 요인별로 분해하고 있는 모습이다. 지수 옵션은 2015년 8월 20일, 행사가격 235.0 인 ATM 옵션을 이용하였다. (자세한 측정 방법은 http://blog.naver.com/chunjein/100187637404 참조)
09:00:00 ~ 09:19:57 까지 관찰한 결과, 평균 스프레드는 0.005008 이었다. 이 옵션의 명목 스프레드는 0.01 인데, 이와 비교하면 절반 정도에 해당한다. 통상 유효 스프레드나 실질 스프레드는 명목 스프레드에 비해 낮게 측정된다. 이것은 실제 스프레드는 눈에 보이는 것보다 항상 낮다는 것을 의미한다.
마켓메이커의 기본적 요구 비용 (OP : Φ)은 0.001137 이었고, 정보 비대칭 비용 (AI : θ) 은 0.001368 이었다. OP + AI에 대한 AI 비중은 54.61% 로 (θ / (Φ+θ)), AI의 비중이 OP의 비중보다 높게 관측되었다. 즉, 정보의 비대칭 비용이 더 높게 관측되고 있다.
정보의 비대칭 비용의 흐름을 관찰하면 현재 시장의 효율성 (EMH)을 짐작할 수 있다. 정보 비대칭 비용이 증가하고 있으면 시장의 효율성이 떨어지고 있고, 반대로 정보 비대칭 비용이 감소하고 있으면 시장의 효율성이 높아진다고 생각할 수 있다.
정보 비대칭이 증가하면 시장의 효율성이 감소하므로 주가는 단기적 추세를 형성할 가능성이 있다. 반대로 정보 비대칭이 감소하면 시장의 효율성이 증가하므로 주가는 랜덤워크로 흐르고, 횡보하거나, 랜덤한 추세를 형성하게 된다.
알고리즘 전략 측면에서 보면, 정보 비대칭이 증가할수록 스캘핑 (Scalping)이나 단기 추세추종 (Trend following) 전략이 유용해 보인다. 이것은 정보의 비대칭으로 인해 주가에 방향이 생길 수 있기 때문이다. 반면에 정보 비대칭이 감소할수록 마켓메이킹 전략이 유용해 보인다. 이때는 정보의 대칭성이 증가하므로 시장에 유입되는 정보량이 감소하거나, 정보가 유입되더라도 모든 참여자가 이미 알고 있는 상태이므로 주가에 방향이 생기기 어렵기 때문이다.
참고로, Madhavan 논문 등, 스프레드 분해를 다룬 다수의 논문들은 체결 틱을 분석할 때 동일 주체에 의한 분할 주문은 1건의 주문으로 취급해야 한다는 것을 언급하고 있다. 그러나 거래소에서 제공하는 데이터로는 이것이 가능하지 않으므로, 근사적으로 분석할 수밖에 없다. 개별 종목이나 지수 선물의 경우는 동일 주체의 분할 주문 가능성이 높을 수 있지만 옵션은 그럴 가능성이 다소 낮을 것으로 가정해 보았다. 지수 옵션의 경우는 대량 주문을 분할해서 집행하는 주문은 많지 않을 것으로 보고, 직전 체결 주문과, 현재 체결 주문의 주체는 서로 다른 것으로 가정하여 근사적으로 스프레드를 분해해 본 것이다.
참고로, 아래 스크립트는 XingScript 프로그램에서 체결 틱 데이터를 분석해서 스프레드를 분해하는 과정으로, 위 그림의 결과를 얻을 수 있는 스크립트이다.
// Madhavan의 스프레드를 실시간으로 관찰한다. Spread = 2(φ + θ). 이 스프레드는 유효 스프레드 (Effective Spread)에 해당함.
// 또한, 스프레드 = 마켓메이커의 비용 (φ) + 정보 비대칭 비용 (θ) 이므로, 각 비용의 비중을 관찰한다. 예) 스프레드 중 정보
// 비대칭 비용은 50% 차지함. 단, 동일 주체에 의한 분할 주문은 1건의 주문으로 처리해야 하지만, 판단이 불가하므로 이전 주문과
// 현재 주문의 주체는 동일한 것으로 간주함.
//
// 옵션의 경우는 개별 종목이나 지수에 비해 분할 주문 비중이 작을 것이므로, 관찰 대상은 지수 옵션으로 한다.
// ————————————————————————————————————————
cont = 0 // 체결 방향이 연속된 체결 틱 수
ticks = 0 // 전체 체결 틱 수
// 초기값을 확인한다
bPrice = FilledInfo(_lob, _close) * 100 // 체결 가격을 가져온다
bSize = FilledInfo(_lob, _size) // 체결 수량을 가져온다
If (bSize >= 0) Then // 이전 체결 틱의 부호 (매수 주문 = +1, 매도 주문 = -1)
bt = 1
Else
bt = neg(1)
Endif
For loop = 1 to 2 step 0
// 체결 틱이 1개 발생할 때까지 대기한다
Wait(_ftick, _lob, 1)
ticks = ticks + 1
// 현재의 체결 가격과 체결 수량을 조회한다
cPrice = FilledInfo(_lob, _close) * 100 // 체결 가격을 가져온다
cSize = FilledInfo(_lob, _size) // 체결 수량을 가져온다
// 체결 수량으로 현재 매수, 매도 indicator를 구분한다
If (cSize >= 0) Then
ct = 1
Else
ct = neg(1)
Endif
// 이전 indicator와 비교해서 주문의 연속 확률과 자기상관계수를 계산한다
If (bt == ct) Then
cont = cont + 1
Else Endif
prob = cont / ticks // 체결 주문이 연속인 확률
rho = 2 * prob – 1 // indicator의 자기상관계수 (시차=1). AR(1) 모형.
// Et, Et1을 계산한다. 실시간 평균으로 계산한다.
dp = (cPrice – bPrice) * ct
dp1 = (cPrice – bPrice) * bt
If (ticks == 1) Then
Et = dp
Et1 = dp1
Else
Et = Et * (ticks – 1)/ticks + dp / ticks
Et1 = Et1 * (ticks – 1)/ticks + dp1 / ticks
Endif
// φ 와 θ를 계산하고 스프레드를 계산한다
If (rho < 0.99) & (rho > neg(0.99)) Then
phi = neg(Et1 / (1 – rho)) // Order Processsing cost (AP)
theta = (Et + Et1) / (1 – (rho ^ 2)) // Asymmetry Information cost (AI)
spread = 2 * (phi + theta) // Bid-Ask 스프레드
// 결과를 출력한다
If (phi + theta > 0) Then
Print GetTime(_krx, _time),” : φ=”,phi,” θ=”,theta,” S=”,spread,” θ(%)=”, theta/(phi+theta), ” ρ=”, rho
Else
Print GetTime(_krx, _time),” : φ=”,phi,” θ=”,theta,” S=”,spread, ” ρ=”, rho
Endif
Else Endif
// 현재 데이터를 이전 데이터에 업데이트한다
bt = ct
bPrice = cPrice
Next
End
[출처]39. API를 통한 스프레드의 성분 분해|작성자아마퀀트