나는 여기에있다바이낸스 숏 오버라이징 롱 오버슬럼핑 멀티통화 헤지 전략동시에 백테스팅 엔진도 출시되었습니다. 첫 번째 보고서는 1시간 K-라인 백테스트를 기반으로 전략의 효과를 검증했습니다. 하지만 퍼블릭 전략의 실제 휴면 시간은 1초로 매우 높은 빈도의 전략입니다. 시간당 K-라인으로 백테스팅을 통해 정확한 결과를 얻는 것은 분명히 불가능합니다. 나중에 추가됨분 단위 백테스트그 결과, 백테스팅 수익은 많이 증가했지만, 2차 상황에서 어떤 매개변수를 사용해야 할지 여전히 판단할 수 없으며, 전체 전략에 대한 이해가 명확하지 않습니다. 가장 큰 이유는 K-라인 기반 백테스팅의 중요한 단점 때문입니다.
우선, 역사적인 K-라인은 무엇인가요? K-라인의 데이터에는 최고 개장가와 최저 종가, 두 개의 시작 시간, 범위 거래량 등 4가지 가격이 포함됩니다. 대부분의 양적 플랫폼과 프레임워크는 K-라인 백테스팅을 기반으로 하며, FMZ 양적 플랫폼도 틱 수준 백테스팅을 제공합니다. K-라인 백테스팅은 매우 빠르고 대부분의 경우 문제가 없지만, 특히 다품종 전략과 고빈도 전략을 백테스팅하는 경우 올바른 결론을 도출하는 것이 거의 불가능하다는 심각한 단점이 있습니다.
첫 번째는 시간 문제입니다. K-line 데이터의 최고가와 최저가의 시간은 주어지지 않으므로 고려할 필요가 없습니다. 그러나 가장 중요한 시가와 종가가 시가와 종가에서 시작되지 않습니다. 마감 시간입니다. 덜 인기 있는 거래 상품의 경우에도 10초 이상 거래가 이루어지지 않는 경우가 많습니다. 여러 상품 전략을 백테스트할 때 종종 시작 가격과 마감 가격이 동시에 발생한다고 가정합니다. 이는 마감 가격을 백테스트하는 기준이기도 합니다.
분 단위의 선을 사용하여 두 종류의 차익거래를 백테스트한다고 상상해 보세요. 가격 차이는 보통 10위안입니다. 이제 10:01에 계약 A의 종가가 100이고 계약 B의 종가가 112인 것을 알 수 있습니다. 가격 차이 12위안입니다. 그래서 전략은 헤지하기 시작합니다. 이 순간, 가격 차이가 돌아왔고, 전략은 2위안의 수익률을 얻었습니다.
실제 상황은 10:00:45에 계약 A가 100위안의 거래를 생성했고 그 이후에는 거래가 없었을 수 있습니다. 10:00:58에 계약 B가 112위안의 거래를 생성했습니다. 10:01에 두 가지 가격이 모두 존재하지 않을 때, 현재 시장 가격은 얼마이며, 헤지거래를 통해 얼마나 많은 가격 차이를 얻을 수 있습니까? 알 수 있는 방법이 없습니다. 가능한 시나리오 중 하나는 10:00:58에 계약 A의 매수-매도 가격이 101.9-102.1이고, 2위안의 가격 차이가 전혀 없다는 것입니다. 이는 우리의 전략 최적화에 큰 혼란을 가져올 것입니다.
두 번째 문제는 매칭입니다. 진정한 매칭은 가격과 시간을 우선시합니다. 매수자가 매도 가격을 초과하면 거래는 일반적으로 매도 가격으로 직접 완료됩니다. 그렇지 않으면 주문장에 들어가 기다립니다. K-라인 데이터에는 매수/매도 가격이 없으며, 세부 수준에서 매칭을 시뮬레이션하는 것은 불가능합니다.
마지막으로, 전략 자체가 시장에 미치는 영향이 있습니다. 소규모 자본 백테스트라면 영향이 크지 않을 것입니다. 하지만 거래량이 큰 비중을 차지한다면 시장에 영향을 미치게 됩니다. 거래가 즉시 실행되면 가격 하락이 클 뿐만 아니라 백테스팅을 통해 매수 주문이 실행되면 원래 매수를 원했던 다른 거래자의 거래를 실제로 선점하게 되어 나비효과가 영향을 미칩니다. 시장. 이러한 영향은 정량화할 수 없으며, 경험에 근거해 고빈도 거래는 소규모 자금에만 적용 가능하다고만 말할 수 있습니다.
FMZ는 실시간 백테스팅을 제공하며 이를 통해 실제 과거 20레벨 깊이, 실시간 2차 틱, 거래별 데이터를 얻을 수 있으며 이를 기반으로 합니다.실시간 재생 기능. 백테스팅 데이터의 양은 엄청나게 많고 속도는 매우 느려서 보통 이틀 정도 걸립니다. 상대적으로 빈도가 높은 전략이나 엄격한 시간 판단이 필요한 전략의 경우, 실시간 백테스팅이 필요합니다. FMZ가 수집한 거래 쌍과 기간은 길지 않지만, 700억 개가 넘는 과거 데이터가 있습니다. 현재 매칭 메커니즘은 매수 주문이 매도 주문보다 큰 경우 거래량에 관계없이 즉시 전액 매칭되고, 매도 주문보다 작은 경우 매칭 대기열에 진입합니다. 이러한 백테스팅 메커니즘은 K-라인 백테스팅의 처음 두 가지 문제는 해결하지만, 마지막 문제는 여전히 해결할 수 없습니다. 그리고 데이터 양이 너무 많기 때문에 백테스팅 속도와 시간 범위가 제한됩니다.
K-라인 정보가 너무 적고 심도가 거짓일 수도 있지만, 시장의 진정한 거래 의도를 반영하고 가장 신뢰할 수 있는 거래 내역을 반영하는 한 가지 종류의 데이터가 있습니다. 즉, 거래별 데이터입니다. 본 논문에서는 주문 흐름에 기반한 고주파 백테스팅 시스템을 제안합니다. 이를 통해 실시간 백테스팅의 데이터 양을 대폭 줄이고 거래량이 시장에 미치는 영향을 어느 정도 시뮬레이션할 수 있습니다.
저는 지난 5일간 바이낸스 XTZ 영구 계약의 거래 기록을 다운로드했습니다(다운로드 주소: https://www.fmz.com/upload/asset/1ff487b007e1a848ead.csv). 그다지 인기 없는 상품으로 213,000건의 거래가 있습니다. 총계. 데이터, 먼저 데이터의 구성을 살펴보겠습니다.
[['XTZ', 1590981301905, 2.905, 0.4, 'False\n'],
['XTZ', 1590981303044, 2.903, 3.6, 'True\n'],
['XTZ', 1590981303309, 2.903, 3.7, 'True\n'],
['XTZ', 1590981303738, 2.903, 238.1, 'True\n'],
['XTZ', 1590981303892, 2.904, 0.1, 'False\n'],
['XTZ', 1590981305250, 2.904, 0.1, 'False\n'],
['XTZ', 1590981305643, 2.903, 197.3, 'True\n'],
데이터는 거래 시간별로 정렬된 2차원 목록입니다. 구체적인 의미는 다음과 같습니다: 제품 이름, 거래 가격, 거래 타임스탬프, 거래 수량, 활성 판매 주문 거래인지 여부입니다. 매수자와 매도자가 있으며, 각 거래에는 매수자와 매도자가 포함됩니다. 매수자가 마켓 메이커이고 매도자가 테이커인 경우 마지막 데이터는 True입니다.
첫째, 거래 방향에 따라 시장에서의 매수 및 매도 가격을 매우 정확하게 유추할 수 있습니다. 활성 매도 주문인 경우 이때의 매수 가격이 거래 가격입니다. 활성 매수 주문인 경우 판매 가격은 거래 가격입니다. 새로운 거래가 있는 경우 새로운 견적이 업데이트됩니다. 업데이트되지 않은 경우 이전 결과가 유지됩니다. 위 데이터의 마지막 순간에 매수 가격은 2.903이고 매도 가격은 2.904였음을 쉽게 알 수 있습니다.
주문 흐름에 따르면 매칭은 다음과 같이 이루어질 수 있습니다. 매수 주문을 예로 들면, 가격은 price, 주문 수량은 amount, 매수 및 매도 주문은 각각 bid 및 ask입니다. 가격이 매도보다 낮고 매수보다 높으면 먼저 메이커로 결정되어 주문과 먼저 매칭될 수 있습니다. 그런 다음 주문의 존재 시간 내에 거래 가격이 매도보다 낮거나 같은 모든 거래는 가격과 동일한 가격이 이 주문과 매칭됩니다(가격이 매도보다 낮으면 주문은 매수와 매칭됩니다). 매수 가격이 매수 가격과 같거나 높으면 주문을 먼저 거래할 수 없습니다. . 매수 가격보다 거래 가격이 낮은 모든 주문은 이 주문과 매칭됩니다. 매칭 가격은 매수 가격이고, 거래량은 주문이 완전히 실행되거나 취소될 때까지 각 거래의 거래량입니다. 가격이 매도 가격보다 높으면 매수자로 간주됩니다. 그 후 주문의 존재 시간 내에 가격보다 낮거나 같은 거래 가격을 가진 모든 거래는 이 주문과 일치되고 일치 가격은 거래의 거래 가격이 됩니다. 메이커와 테이커의 구분은 거래소가 기본적으로 주문을 장려하고 우대 거래 수수료를 제공하기 때문입니다. 고빈도 전략의 경우 이 구분을 고려해야 합니다.
이런 유형의 매칭에는 문제가 있다는 것을 쉽게 알 수 있습니다. 주문이 테이커인 경우, 실제 상황은 새로운 주문이 매칭되기를 기다리지 않고도 즉시 실행될 수 있다는 것입니다. 우선, 우리는 보류 주문의 양을 고려하지 않았습니다. 데이터가 있더라도 거래를 직접 판단하면 깊이가 바뀌고 시장에 영향을 미칠 것입니다. 새로운 주문에 따른 매칭은 과거 실제 주문을 귀하의 주문으로 대체하는 것과 같습니다. 어떤 경우에도 시장 자체 거래량의 한계를 초과하지 않으며 최종 이익은 시장에서 발생한 최대 이익을 초과하지 않습니다. 일부 매칭 메커니즘은 주문의 거래량에도 영향을 미치며, 이는 다시 전략의 수익에 영향을 미치고 전략 역량을 정량적으로 반영합니다. 자금 양이 두 배가 되면 이익도 두 배가 되는 전통적인 백테스트는 없을 것입니다.
몇 가지 작은 세부 사항이 있습니다. 주문 매수 가격이 매수 1 가격과 같으면 실제로 매수 1 가격으로 매칭될 확률이 여전히 있습니다. 보류 주문의 우선순위와 거래의 확률 등이 있습니다. 이는 비교적 복잡하므로 여기서는 고려하지 않습니다.
교환 대상은 기본적으로 변경되지 않은 시작 부분의 소개를 참조할 수 있습니다. 메이커와 테이커 수수료의 차이만 추가되고 백테스팅 속도가 최적화됩니다. 이하에서는 주로 매칭 코드를 소개합니다.
symbol = 'XTZ'
loop_time = 0
intervel = 1000 #策略的休眠时间为1000ms
init_price = data[0][2] #初始价格
e = Exchange([symbol],initial_balance=1000000,maker_fee=maker_fee,taker_fee=taker_fee,log='') #初始化交易所
depth = {'ask':data[0][2], 'bid':data[0][2]} #深度
order = {'buy':{'price':0,'amount':0,'maker':False,'priority':False,'id':0},
'sell':{'price':0,'amount':0,'maker':False,'priority':False,'id':0}} #订单
for tick in data:
price = int(tick[2]/tick_sizes[symbol])*tick_sizes[symbol] #成交价格
trade_amount = tick[3] #成交数量
time_stamp = tick[1] #成交时间戳
if tick[4] == 'False\n':
depth['ask'] = price
else:
depth['bid'] = price
if depth['bid'] < order['buy']['price']:
order['buy']['priority'] = True
if depth['ask'] > order['sell']['price']:
order['sell']['priority'] = True
if price > order['buy']['price']:
order['buy']['maker'] = True
if price < order['sell']['price']:
order['sell']['maker'] = True
#订单网络延时也可以作为撮合条件之一,这里没考虑
cond1 = order['buy']['priority'] and order['buy']['price'] >= price and order['buy']['amount'] > 0
cond2 = not order['buy']['priority'] and order['buy']['price'] > price and order['buy']['amount'] > 0
cond3 = order['sell']['priority'] and order['sell']['price'] <= price and order['sell']['amount'] > 0
cond4 = not order['sell']['priority'] and order['sell']['price'] < price and order['sell']['amount'] > 0
if cond1 or cond2:
buy_price = order['buy']['price'] if order['buy']['maker'] else price
e.Buy(symbol, buy_price, min(order['buy']['amount'],trade_amount), order['buy']['id'], order['buy']['maker'])
order['buy']['amount'] -= min(order['buy']['amount'],trade_amount)
e.Update(time_stamp,[symbol],{symbol:price})
if cond3 or cond4:
sell_price = order['sell']['price'] if order['sell']['maker'] else price
e.Sell(symbol, sell_price, min(order['sell']['amount'],trade_amount), order['sell']['id'], order['sell']['maker'])
order['sell']['amount'] -= min(order['sell']['amount'],trade_amount)
e.Update(time_stamp,[symbol],{symbol:price})
if time_stamp - loop_time > intervel:
order = get_order(e,depth,order) #交易逻辑,这里未给出
loop_time += int((time_stamp - loop_time)/intervel)*intervel
주의할 몇 가지 세부 사항:
마침내 실제 백테스팅 단계에 도달했습니다. 가장 고전적인 그리드 전략 중 하나를 백테스팅하여 예상 결과를 달성하는지 확인해보겠습니다. 이 전략의 원칙은 가격이 1% 상승할 때마다 특정 가치의 숏 주문을 보유하고(또는 그 반대로 롱 주문을 보유하고) 매수 및 매도 주문을 계산하여 사전에 배치하는 것입니다. 코드는 공개되지 않습니다. 모든 코드를 캡슐화합니다.Grid('XTZ',100,0.3,1000,maker_fee=-0.00002,taker_fee=0.0003)
해당 함수에서 매개변수는 다음과 같습니다: 거래 쌍, 보유 가치의 1% 가격 편차, 0.3%의 주문 밀도, ms 단위의 슬립 간격, 주문 작성자 수수료, 주문 수신자 수수료.
지난 5일간 XTZ 시장은 변동성이 큰 단계에 있었으며, 이는 그리드에 매우 적합한 상황입니다. /업로드/자산/1e235fa08ed9dce82a3.png
우리는 먼저 다양한 포지션 크기가 수익에 미치는 영향을 백테스트합니다. 전통적인 백테스트 메커니즘으로 측정한 수익은 포지션 증가에 따라 확실히 비례하여 증가할 것입니다.
e1 = Grid('XTZ',100,0.3,1000,maker_fee=-0.00002,taker_fee=0.0003)
print(e1.account['USDT'])
e2 = Grid('XTZ',1000,0.3,1000,maker_fee=-0.00002,taker_fee=0.0003)
print(e2.account['USDT'])
e3 = Grid('XTZ',10000,0.3,1000,maker_fee=-0.00002,taker_fee=0.0003)
print(e3.account['USDT'])
e4 = Grid('XTZ',100000,0.3,1000,maker_fee=-0.00002,taker_fee=0.0003)
print(e4.account['USDT'])
총 4개의 그룹에 대해 백테스트를 실시하였으며, 보유값은 각각 100, 1000, 10000, 100000으로 설정하였고, 총 백테스트 시간은 1.3초였습니다. 결과는 다음과 같습니다.
{'realised_profit': 28.470993031132966, 'margin': 0.7982662957624465, 'unrealised_profit': 0.0104554474048441, 'total': 10000028.481448, 'leverage': 0.0, 'fee': -0.3430967859046398, 'maker_fee': -0.36980249726699727, 'taker_fee': 0.026705711362357405}
{'realised_profit': 275.63148945320177, 'margin': 14.346335829979132, 'unrealised_profit': 4.4382117331794045e-14, 'total': 10000275.631489, 'leverage': 0.0, 'fee': -3.3102045933457784, 'maker_fee': -3.5800688964477048, 'taker_fee': 0.2698643031019274}
{'realised_profit': 2693.8701498889504, 'margin': 67.70120400534114, 'unrealised_profit': 0.5735269329348516, 'total': 10002694.443677, 'leverage': 0.0001, 'fee': -33.984021415250744, 'maker_fee': -34.879233866850974, 'taker_fee': 0.8952124516001403}
{'realised_profit': 22610.231198585603, 'margin': 983.3853688758861, 'unrealised_profit': -20.529965947304365, 'total': 10022589.701233, 'leverage': 0.002, 'fee': -200.87094000385412, 'maker_fee': -261.5849078470078, 'taker_fee': 60.71396784315319}
최종 실현 이익은 각각 포지션 가치의 28.4%, 27.5%, 26.9%, 22.6%인 것을 알 수 있습니다. 이는 실제 상황과도 일치합니다. 포지션의 가치가 클수록 보류 주문의 가치가 커지고 부분 거래가 발생할 가능성이 높아지며 최종 실현 이익은 보류 중인 주문량. 다음 그림은 각각 100과 10,000의 값을 갖는 보유 자산의 상대 수익률을 비교한 것입니다.
또한 주문 밀도, 휴면 시간, 처리 수수료 등과 같은 다양한 매개변수가 백테스팅 수익에 미치는 영향을 백테스팅할 수도 있습니다. 예를 들어 수면 시간을 100ms로 바꾸고 수면 시간 1000ms와 비교해 보면 어떤 이점이 있는지 알 수 있습니다. 백테스트 결과는 다음과 같습니다.
{'realised_profit': 29.079440803790423, 'margin': 0.7982662957624695, 'unrealised_profit': 0.0104554474048441, 'total': 10000029.089896, 'leverage': 0.0, 'fee': -0.3703702128662524, 'maker_fee': -0.37938946377435134, 'taker_fee': 0.009019250908098965}
이익이 약간 증가했습니다. 이는 전략이 한 세트의 주문만 하기 때문입니다. 일부 주문은 시간 내에 변경할 수 없기 때문에 가격 변동의 혜택을 받을 수 없습니다. 휴면 시간이 단축되어 이 문제가 개선되었습니다. 이는 또한 그리드 전략에서 여러 그룹의 주문을 배치하는 것이 중요하다는 것을 보여줍니다.
본 논문은 주문 흐름에 기반한 새로운 백테스팅 시스템을 혁신적으로 제안하는데, 이는 보류 주문, 주문 수락, 부분 거래, 지연 등의 매칭 조건을 부분적으로 시뮬레이션하고, 전략 자금이 수익에 미치는 영향을 부분적으로 반영할 수 있다. 이는 중요한 참고 자료가 있다. 헤지 전략에 대한 가치와 고정밀 백테스팅은 전략 매개변수를 최적화하는 방향을 제시합니다. 이는 장기간의 실제 거래를 통해서도 검증되었습니다. 또한 백테스팅에 필요한 데이터 양을 보다 잘 제어할 수 있으며 백테스팅 속도도 매우 빠릅니다.