리소스 로딩... 로딩...

고주파 거래 전략에 대한 생각 (1)

저자:FMZ~리디아, 창작: 2023-08-04 13:47:39, 업데이트: 2024-11-10 18:54:05

img

고주파 거래 전략에 대한 생각 (1)

저는 디지털 화폐의 고주파 거래에 관한 두 개의 기사를 썼습니다.디지털 통화 고주파 전략 상세 소개5일만에 80배를 벌고, 고주파 전략의 힘. 그러나, 이 기사들은 경험 공유로만 간주될 수 있으며 일반적인 개요를 제공할 수 있다. 이번에는 초점부터 고주파 거래의 배경의 사고 과정을 소개하기 위해 일련의 기사를 작성할 계획이다. 간결하고 명확하게 유지하기를 희망하지만, 제 제한된 전문 지식으로 인해, 고주파 거래에 대한 이해가 매우 깊지 않을 수 있다. 이 기사는 토론의 출발점으로 간주되어야 하며, 전문가의 수정과 지침을 환영한다.

고주파 수익원

이전 기사에서 나는 고주파수 전략이 매우 변동성이 높은 시장에 특히 적합하다고 언급했습니다. 짧은 기간 내에 거래 도구의 가격 변화는 전반적인 추세와 변동으로 구성됩니다. 추세 변화를 정확하게 예측할 수 있다면 실제로 수익성이 있지만 이것은 가장 도전적인 측면이기도 합니다. 이 기사에서는 주로 고주파수 메이커 전략에 초점을 맞추고 추세 예측에 깊숙이 들어가지 않을 것입니다. 오스실레이션 시장에서, 사격의 빈도가 충분히 높고 수익 마진이 상당한 경우 전략적으로 주문을 배치하여 거래 트렌드에 의한 잠재적 인 손실을 커버 할 수 있습니다. 이렇게하면 시장의 움직임을 예측하지 않고 수익성을 얻을 수 있습니다. 현재 거래소는 메이커 트레이드에 대한 할인 혜택을 제공하며 이윤의 구성 요소이기도 합니다. 경쟁 요소가 높을수록 할인 혜택의 비율이 높아야합니다.

해결 해야 할 문제 들

  1. 구매 및 판매 주문을 둘 다 배치하는 전략을 구현하는 첫 번째 문제는 이러한 주문을 어디에 배치할지 결정하는 것입니다. 주문이 시장 깊이에 가까워질수록 실행 가능성은 높아집니다. 그러나 매우 변동적인 시장 조건에서 주문이 즉시 실행되는 가격은 시장 깊이에서 멀리 떨어져 있어 수익이 충분하지 않을 수 있습니다. 반면에 주문을 너무 멀리 배치하면 실행 가능성은 감소합니다. 이것은 해결해야 할 최적화 문제입니다.

  2. 포지션 컨트롤은 위험을 관리하는 데 매우 중요합니다. 전략은 장기간 과도한 포지션을 축적 할 수 없습니다. 이것은 배치 된 주문의 거리와 양을 제어하고 전체 포지션에 대한 한계를 설정함으로써 해결할 수 있습니다.

위의 목표를 달성하기 위해서는 실행 확률, 실행에서 얻는 이익 및 시장 평가와 같은 다양한 측면에 대한 모델링과 추정이 필요합니다. 이 주제에 대한 수많은 기사와 논문이 있으며, High-Frequency TradingOrderbook과 같은 키워드를 사용합니다. 많은 권장 사항은 온라인에서도 찾을 수 있지만 추가적인 설명은이 문서의 범위를 초월합니다. 또한 신뢰할 수 있고 빠른 백테스팅 시스템을 구축하는 것이 좋습니다. 높은 빈도 전략은 라이브 트레이딩을 통해 쉽게 검증 될 수 있지만 백테스팅은 추가 인사이트를 제공하며 시행착오 비용을 줄이는 데 도움이됩니다.

요구되는 데이터

바이낸스는다운로드 가능한 데이터개별 거래 및 최고의 입찰 / 요청 주문을 위해. 깊이 데이터는 WHITELIST을 통해 API를 통해 다운로드 할 수 있습니다. 또는 수동으로 수집 할 수 있습니다. 백테스팅 목적으로 집계 된 거래 데이터는 충분합니다. 이 기사에서는 HOOKUSDT-aggTrades-2023-01-27 데이터의 예를 사용합니다.

[1]에서:

from datetime import date,datetime
import time
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

개별 무역 데이터는 다음을 포함합니다:

  1. agg_trade_id: 종합 거래의 ID.
  2. 가격: 거래가 실행된 가격입니다.
  3. 양: 거래의 양.
  4. first_trade_id: 여러 거래가 집계되는 경우, 이것은 첫 번째 거래의 ID를 나타냅니다.
  5. last_trade_id: 집계된 마지막 거래의 ID.
  6. 트랜잭션_타임: 트랜잭션 실행의 시간표.
  7. is_buyer_maker: 트레이드의 방향을 나타냅니다. True은 메이커로 실행되는 구매 주문을 나타냅니다. 판매 주문은 타커로 실행됩니다.

그 날 660,000 개의 거래가 실행되었음을 볼 수 있습니다. 매우 활발한 시장을 나타냅니다. CSV 파일은 댓글 섹션에 첨부됩니다.

[4]:

trades = pd.read_csv('COMPUSDT-aggTrades-2023-07-02.csv')
trades

아웃[4]: ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

img

664475 행 × 7 열

개별 거래 금액 모델링

먼저, 데이터는 원래 트레이드를 두 그룹으로 나누는 방식으로 처리된다. 메이커로 실행된 구매 주문과 테이커로 실행된 판매 주문이다. 또한, 원래 집계된 거래 데이터는 동시에, 같은 가격으로, 같은 방향으로 실행된 트레이드를 단일 데이터 포인트로 결합한다. 예를 들어, 100의 볼륨을 가진 단일 구매 주문이 있다면, 가격이 다르면 각각 60과 40의 볼륨을 가진 두 트레이드로 나눌 수 있다. 이것은 구매 주문 볼륨의 추정에 영향을 줄 수 있다. 따라서, 트랜잭션_타임에 기초하여 데이터를 다시 집계할 필요가 있다. 이 두 번째 집계 후, 데이터 볼륨은 140,000 기록으로 감소한다.

[6]에서:

trades['date'] = pd.to_datetime(trades['transact_time'], unit='ms')
trades.index = trades['date']
buy_trades = trades[trades['is_buyer_maker']==False].copy()
sell_trades = trades[trades['is_buyer_maker']==True].copy()
buy_trades = buy_trades.groupby('transact_time').agg({
    'agg_trade_id': 'last',
    'price': 'last',
    'quantity': 'sum',
    'first_trade_id': 'first',
    'last_trade_id': 'last',
    'is_buyer_maker': 'last',
    'date': 'last',
    'transact_time':'last'
})
sell_trades = sell_trades.groupby('transact_time').agg({
    'agg_trade_id': 'last',
    'price': 'last',
    'quantity': 'sum',
    'first_trade_id': 'first',
    'last_trade_id': 'last',
    'is_buyer_maker': 'last',
    'date': 'last',
    'transact_time':'last'
})
buy_trades['interval']=buy_trades['transact_time'] - buy_trades['transact_time'].shift()
sell_trades['interval']=sell_trades['transact_time'] - sell_trades['transact_time'].shift()

[10]에서:

print(trades.shape[0] - (buy_trades.shape[0]+sell_trades.shape[0]))

외부 [10]: 146181

구매 주문을 예로 들어, 먼저 히스토그램을 그래프화 해 봅시다. 대부분의 데이터가 히스토그램의 가장 왼쪽 부분에 집중되어있는 중요한 긴 꼬리 효과가 있음을 관찰 할 수 있습니다. 그러나 꼬리 끝으로 분산 된 몇 가지 큰 거래도 있습니다.

[36]에서:

buy_trades['quantity'].plot.hist(bins=200,figsize=(10, 5));

외부 [36]:

img

더 쉽게 관찰하기 위해, 꼬리를 자르고 데이터를 분석합니다. 거래 금액이 증가함에 따라 발생 빈도가 감소하고 감소율이 빨라지는 것을 관찰 할 수 있습니다.

[37]에서:

buy_trades['quantity'][buy_trades['quantity']<200].plot.hist(bins=200,figsize=(10, 5));

외부 [37]:

img

거래 금액의 분포에 대한 수많은 연구가 이루어졌다. 거래 금액은 파레토 분포로도 알려진 전력법칙 분포를 따르는 것으로 밝혀졌습니다. 이는 통계 물리학과 사회 과학에서 일반적인 확률 분포입니다. 전력법칙 분포에서 이벤트의 크기 (또는 빈도) 의 확률은 해당 이벤트의 크기의 음수 지수와 비례합니다. 이 분포의 주요 특징은 많은 다른 분포에서 예상보다 큰 이벤트의 빈도가 높다는 것입니다. 이것은 정확히 거래 금액 분포의 특징입니다. 파레토 분포의 형태는 P ((x) = C ((x ^-α) 로 주어집니다. 이것을 경험적으로 확인해 보겠습니다.

다음 그래프는 특정 값을 초과하는 거래 금액의 확률을 나타냅니다. 파란색 선은 실제 확률을 나타냅니다. 오렌지 선은 시뮬레이션 확률을 나타냅니다. 이 시점에서 특정 매개 변수에 들어가지 않을 것을 유의하십시오. 분포가 실제로 파레토 분포를 따르는 것을 관찰 할 수 있습니다. 거래 금액이 0보다 큰 확률이 1이기 때문에 정상화를 만족시키기 위해 분포 방정식은 다음과 같습니다.

img

여기서, N는 정규화의 매개 변수이다. 우리는 평균 거래 금액, M를 선택하고, 알파를 -2.06로 설정한다. D=N 때 P-값을 계산하여 알파의 구체적인 추정치를 얻을 수 있다. 구체적으로, 알파 = log (((P(d>M)) /log ((2). 다른 점의 선택은 알파의 값에 약간의 차이를 초래할 수 있다.

[55]에서:

depths = range(0, 250, 2)
probabilities = np.array([np.mean(buy_trades['quantity'] > depth) for depth in depths])
alpha = np.log(np.mean(buy_trades['quantity'] > mean_quantity))/np.log(2)
mean_quantity = buy_trades['quantity'].mean()
probabilities_s = np.array([(1+depth/mean_quantity)**alpha for depth in depths])

plt.figure(figsize=(10, 5))
plt.plot(depths, probabilities)
plt.plot(depths, probabilities_s)
plt.xlabel('Depth')
plt.ylabel('Probability of execution')
plt.title('Execution probability at different depths')
plt.grid(True)

아웃[55]:

img

[56]에서:

plt.figure(figsize=(10, 5))
plt.grid(True)
plt.title('Diff')
plt.plot(depths, probabilities_s-probabilities);

아웃[56]:

img

그러나 이 추정치는 시뮬레이션 값과 실제 값의 차이를 그래프에서 보여주는 것처럼 대략적인 것으로 나타난다. 거래 금액이 작을 때 오차는 현저하다. 심지어는 10%에 육박한다. 매개 변수 추정 과정에서 다른 점을 선택하는 것이 그 특정 포인트의 확률의 정확성을 향상시킬 수 있지만 전체적으로 오차 문제를 해결하지는 않는다. 이 오차는 전력법률 분포와 실제 분포 사이의 차이에서 발생한다. 더 정확한 결과를 얻기 위해 전력법률 분포의 방정식을 수정해야 한다. 구체적인 과정은 여기에 정립되지 않지만 요약적으로, 잠시 통찰한 후, 실제 방정식은 다음과 같다는 것을 발견한다.

img

간소화하기 위해, r = q / M를 정상화 된 거래 금액을 나타내기 위해 사용하자. 우리는 이전과 동일한 방법을 사용하여 매개 변수를 추정 할 수 있습니다. 다음 그래프는 수정 후 최대 오차가 2% 이상 아니라는 것을 보여줍니다. 이론적으로는 추가 조정이 가능합니다. 그러나이 수준의 정확도는 이미 충분합니다.

[52]에서:

depths = range(0, 250, 2)
probabilities = np.array([np.mean(buy_trades['quantity'] > depth) for depth in depths])
mean = buy_trades['quantity'].mean()
alpha = np.log(np.mean(buy_trades['quantity'] > mean))/np.log(2.05)
probabilities_s = np.array([(((1+20**(-depth/mean))*depth+mean)/mean)**alpha for depth in depths])

plt.figure(figsize=(10, 5))
plt.plot(depths, probabilities)
plt.plot(depths, probabilities_s)
plt.xlabel('Depth')
plt.ylabel('Probability of execution')
plt.title('Execution probability at different depths')
plt.grid(True)

아웃[52]:

img

[53]에서:

plt.figure(figsize=(10, 5))
plt.grid(True)
plt.title('Diff')
plt.plot(depths, probabilities_s-probabilities);

아웃[53]:

img

거래 금액 분포에 대한 추정 방정식에서, 방정식의 확률은 실제 확률이 아니라 조건적 확률이라는 점을 유의하는 것이 중요합니다. 이 시점에서 우리는 다음 주문이 특정 값보다 커질 확률은 무엇입니까? 우리는 또한 다른 깊이에서 실행되는 주문의 확률을 결정할 수 있습니다. (이 이상적인 시나리오에서, 주문 추가, 취소 및 같은 깊이에서 대기열을 고려하지 않고).

이 점 에 있어서 본문 의 길 이 이미 꽤 길고, 아직도 대답 해야 할 질문 이 많다. 다음 기사 시리즈 는 그 대답 을 제공 하려고 노력 할 것 이다.


더 많은