트랜잭션별 트랜잭션 및 K-라인 백트테스팅의 결함을 기반으로 하는 고주파 백트테스팅 시스템

저자:리디아, 창작: 2022-11-30 12:38:50, 업데이트: 2023-09-11 20:01:01

img

트랜잭션별 트랜잭션 및 K-라인 백트테스팅의 결함을 기반으로 하는 고주파 백트테스팅 시스템

저는 기사에서 백테스팅 엔진을 공개했습니다.https://www.fmz.com/digest-topic/5584) 그리고 첫 번째 보고서는 전략의 효과를 확인하는 한 시간 K-라인 백테스팅을 기반으로합니다. 그러나 사실, 공공 전략의 수면 시간은 1s입니다. 이는 상당히 높은 빈도 전략입니다. 한 시간 K-라인 백테스팅을 사용하여 정확한 결과를 얻는 것은 분명히 불가능합니다. 나중에 분 줄 백테스팅의 결과가 추가되었습니다 (https://www.fmz.com/digest-topic/5621그 결과, 백테스팅의 수익은 많이 향상되었지만, 두 번째 레벨의 경우 어떤 매개 변수를 사용해야하는지 결정하는 것은 여전히 불가능하며, 전체 전략의 이해는 매우 명확하지 않습니다. 주요 이유는 K-라인에 기반한 백테스팅의 중요한 결함입니다.

K-라인 백테스팅에 기초한 문제

우선, 역사적인 K-라인이란 무엇인가? 한 K-라인 데이터에는 네 가지 가격이 포함됩니다: 최고 가격, 개시 가격, 최저 가격 및 폐쇄 가격, 시작 시간, 종료 시간 및 간격 거래 양. 대부분의 양적 플랫폼 및 프레임워크는 K-라인에 기반하여 백테스트되며 FMZ 퀀트 플랫폼은 또한 틱 레벨 백테스트를 제공합니다. K-라인 백테스트의 속도는 매우 빠르며 대부분의 경우 문제가되지 않지만, 특히 복수 다양성 전략과 고주파 백테스트의 전략, 정확한 결론을 도출 할 수 없는 매우 심각한 결함이 있습니다.

우선, 시간 문제입니다. K-라인 데이터의 가장 높고 가장 낮은 가격의 시간은 주어지지 않으므로 고려할 필요가 없지만 가장 중요한 오픈 및 클로저 가격은 오픈 및 클로저 포지션 시간이 아닙니다. 거래 품종이 인기가 없더라도 종종 10 초 이상 거래되지 않습니다. 여러 가지 전략의 백테스트를 할 때, 우리는 종종 오픈 및 클로저 가격이 동일하다는 것을 기본으로 설정합니다. 이는 또한 클로저 가격 백테스팅의 기초입니다.

분자선을 사용하여 두 가지 품종의 중재를 백테스트하는 것을 상상해보십시오. 그 사이의 차이는 일반적으로 10 위안입니다. 이제 10:01에 계약 A의 폐쇄 가격은 100 위안, 계약 B의 폐쇄 가격은 112 위안이며 차이는 12 위안입니다. 따라서 전략은 헤지하기 시작합니다. 특정 시간에 차이는 반환되며 전략은 2 위안의 수익을 얻습니다.

그러나 실제 상황은 10:00:45에 A 계약이 100 위안의 거래를 생성하고 그 후에 거래가 발생하지 않을 수 있습니다. B 계약은 10:00:58에 112 위안의 거래를 생성했습니다. 10:01에 두 가격은 존재하지 않았습니다. 이 시점에서 개시 가격은 무엇입니까? 그리고 헤지링이 얼마나 큰 차이를 얻을 수 있습니까? 우리는 모릅니다. 가능한 상황 중 하나는 10:00:58에 A 계약의 하나 구입하고 하나 판매하는 추세가 101.9-102.1이며 2 위안의 스프레드가 전혀 없으며 전략 최적화를 크게 오해 할 것입니다.

두 번째는 매치 메이킹입니다. 실제 매치 메이킹은 가격과 시간입니다. 구매자가 판매 한 가격을 초과하면 일반적으로 판매 한 가격으로 거래를 마무리합니다. 그렇지 않으면 주문록에 입력하고 기다립니다. K-라인 데이터에는 판매 한 가격이나 구매 한 가격이 없으므로 세부 수준에서 매칭을 시뮬레이션 할 수 없습니다.

마지막으로 전략 자체의 거래가 시장에 미치는 영향입니다. 작은 펀드 백테스트라면 그 영향은 작을 것입니다. 그러나 거래 양이 큰 비중을 차지하는 경우 시장에 영향을 미칠 것입니다. 거래가 즉시 완료되면 가격 슬립 포인트가 커질뿐만 아니라 백테스트에서 구매 주문이 완료되면 실제로 구매하려는 다른 원래 트레이더의 거래를 예방합니다. 이는 시장에 나비 효과 영향을 줄 것입니다. 그러나이 영향은 수치화 할 수 없으며 경험에 의해 고주파 트레이딩이 작은 자금을 수용 할 수 있다고 말할 수 있습니다.

실시간 깊이와 틱을 기반으로 백테스팅

FMZ는 실제 보트 레벨 백테스팅을 제공하며 실제 역사적인 20 레벨 깊이, 실시간 두 번째 틱, 트랜잭션별 트랜잭션 및 기타 데이터를 얻을 수 있으며 이를 기반으로 실제 보트 재생 기능을 만들었습니다 (https://www.fmz.com/m/database이 유형의 백테스트 측정은 많은 양의 데이터와 느린 속도를 가지고 있으며, 2 일 동안만 사용할 수 있습니다. 상대적으로 높은 빈도 또는 엄격한 시간 판단을 필요로하는 전략에는 실제 봇 백테스팅이 필요합니다. FMZ가 수집한 거래 쌍과 시간은 너무 길지 않지만 700억 개 이상의 역사적 데이터가 있습니다. 현재 일치 메커니즘은 구매 주문이 판매 주문보다 크면 양을 보지 않고 즉시 완전히 일치되며 구매 주문이 판매 주문보다 작으면 일치 대기열에 들어갈 것입니다. 이 백테스팅 메커니즘은 K-라인 백테스팅의 첫 두 가지 문제를 해결하지만 여전히 마지막 문제를 해결할 수 없습니다. 데이터 양이 너무 크기 때문에 백테스트 속도와 시간이 제한됩니다.

img img

거래별 주문 흐름에 기반한 백테스팅 메커니즘

K-Line에 대한 정보는 너무 적고 깊이도 거짓일 수 있습니다. 그러나 하나의 유형의 데이터는 가장 실제 거래 역사를 반영하는 시장의 실제 거래 의도로 거래됩니다. 즉, 거래마다 거래입니다. 이 논문에서는 주문 흐름에 기반한 고주파 백테스팅 시스템을 제안합니다. 이는 실제 봇 수준에서 백테스팅의 데이터 양을 크게 줄이고 어느 정도 시장에 거래량의 영향을 시뮬레이션합니다.

지난 5일 동안의 트랜잭션별 트랜잭션을 다운로드했습니다.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 이다.

우선 거래 방향에 따라 시장에서 구매를 정확하게 추측하고 판매를 할 수 있습니다. 활성 판매 주문인 경우 현재 구매 1값은 거래 가격입니다. 활성 구매 주문인 경우 판매 1값은 거래 가격입니다. 새로운 거래가 있으면 새로운 오픈 포지션을 업데이트합니다. 업데이트되지 않으면 마지막 결과가 유지됩니다. 위의 데이터의 마지막 순간을 시작하는 것이 쉽습니다. 구매 1값은 2.903이고 판매 1값은 2.904입니다.

주문 흐름에 따라 다음과 같이 매칭할 수 있다. 구매 주문을 예로 들면, 가격은 가격이고, 주문 양은 금액이다. 이 때, 오픈 포지션 중 하나를 구매하고, 하나를 판매하는 것은 각각 청약과 청약이다. 가격이 청약보다 낮고, 청약보다 높으면, 먼저 메이커로 판단되고, 매칭에 우선 순위를 부여할 수 있다. 그 다음 주문의 수명 동안 가격보다 낮은 또는 가격에 해당하는 거래 가격은 이 주문과 매칭된다. (가격이 청약보다 낮거나 같다면, 거래에 우선 순위를 부여할 수 없으며, 가격보다 낮은 거래 가격은 이 주문과 매칭된다). 매칭 가격은 가격이며, 거래 양은 거래가 완전히 종료되거나 취소될 때까지 거래마다 거래의 빈도이다. 차이가 더 높으면, 주문을 받는 사람으로서 판단된다. 이러한 전략은 거래의 가격이나 가격보다 낮은 거래 가격과 거래의 가격에 따른 거래에 따른 매칭을 권장한다.

이 매치메이킹의 문제는 쉽게 알 수 있다. 주문이 타커라면 실제 상황은 새로운 주문이 매치될 때까지 기다리지 않고 즉시 거래를 할 수 있다는 것이다. 첫째, 시장에 나열된 주문의 수를 고려하지 않았다. 데이터가 있었다 하더라도 거래의 직접적인 판단은 깊이를 변화시키고 시장에 영향을 미쳤다. 새로운 주문에 기반한 매치메이킹은 역사에서 실제 주문으로 주문을 대체하는 것과 동등하다. 이는 어떤 경우에도 시장 자체의 거래량 한계를 초과하지 않으며 최종 이익은 시장에서 생성되는 최대 이익을 초과할 수 없다. 매치메이킹 메커니즘의 일부도 거래량 주문에 영향을 미치며 전략의 수익에 영향을 미치며 전략의 양적으로 반영한다. 재원이 두 배로 증가하면 거래액이 두 배로 증가하는 전통적인 백테스팅이 없을 것이다.

또한 몇 가지 작은 세부 사항이 있습니다. 주문의 구매 가격이 구매 한 가격과 같다면, 여전히 주문이 구매 한 가격에 일치 할 확률이 있습니다. 주문의 우선 순위와 거래 확률이 고려되어야합니다. 이것은 더 복잡하며 여기에서 고려되지 않습니다.

매치 메이킹 코드

교환 객체는 기본적으로 변경되지 않은 초기 도입을 참조할 수 있습니다. 제작자와 수신자 수수료의 차이만 추가되고 백테스팅의 속도가 최적화됩니다. 매치 메이킹 코드는 주로 아래에 소개됩니다.

    symbol = 'XTZ'
    loop_time = 0
    intervel = 1000 #The sleep time of the strategy is 1000ms
    init_price = data[0][2] #Initial price
    e = Exchange([symbol],initial_balance=1000000,maker_fee=maker_fee,taker_fee=taker_fee,log='') #Initialize the exchange
    depth = {'ask':data[0][2], 'bid':data[0][2]} #depth
    order = {'buy':{'price':0,'amount':0,'maker':False,'priority':False,'id':0},
             'sell':{'price':0,'amount':0,'maker':False,'priority':False,'id':0}} #Order
    for tick in data:
        price = int(tick[2]/tick_sizes[symbol])*tick_sizes[symbol] #Transaction price
        trade_amount = tick[3] #Number of transactions
        time_stamp = tick[1] #Transaction timestamp
        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
        
        #Order network delay can also be used as one of the matching conditions, which is not considered here
        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) #Trading logic, not given here
            loop_time += int((time_stamp - loop_time)/intervel)*intervel

몇 가지 세부 사항은 주목해야 합니다.

-1. 새로운 거래가 있을 때, 먼저 주문을 맞추고, -2. 각 주문은 두 가지 속성을 가지고 있습니다: 메이커 메이커인지, 우선 순위 매치 메이킹 우선 순위. 예를 들어 구매 주문을 취하면 구매 가격이 판매 가격보다 낮으면 메이커로 표시되며 구매 가격이 구매 가격보다 높으면 우선 순위 매치 메이킹으로 표시됩니다. 우선 순위는 가격이 구매 가격과 같으면 일치하는지 여부를 결정하며 메이커는 수수료를 결정합니다. -3. 주문의 메이커와 우선 순위가 업데이트됩니다. 예를 들어, 오픈 포지션을 초과하는 큰 구매 주문이 있으며, 구매 가격보다 높은 가격이있을 때, 이 시점에서 남은 거래 양은 메이커가됩니다. -4. 전략의 간격이 필요합니다. 이는 시장의 지연을 나타낼 수 있습니다.

네트워크 전략의 백트테스팅

마지막으로, 우리는 실제 백테스팅 단계에 도달합니다. 여기서, 우리는 가장 고전적인 그리드 전략을 백테스팅하여 예상 효과를 달성했는지 확인합니다. 전략 원칙은 가격이 1% 증가할 때마다 우리는 특정 값의 쇼트 포지션 오더를 보유 할 것입니다 (그렇지 않으면, 우리는 긴 포지션 오더를 보유 할 것입니다), 그리고 우리는 구매 주문과 판매 주문을 계산하고 미리 미루어 볼 것입니다. 코드는 공개되지 않을 것입니다. 모든 코드를 함수로 캡슐화하십시오.Grid ('XTZ ', 100,0.31000, maker_fee=-0.00002, taker_fee=0.0003)매개 변수 는: 거래 쌍, 가격 오차 1%, 주문 밀도 0.3%, 수면 간격 ms, 대기 주문 수수료 및 타커 수수료입니다.

지난 5일 동안 XTZ 시장은 충격에 빠졌습니다.

img

우리는 먼저 수익에 대한 다른 포지션의 영향을 백테스트 할 것입니다. 전통적인 백테스팅 메커니즘으로 측정 된 수익은 확실히 포지션 증가에 비례하여 증가 할 것입니다.

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 및 10000의 상대적 수익을 비교하는 것을 보여줍니다:

img

우리는 또한 대기 주문 밀도, 수면 시간 및 수수료와 같은 배트 테스트의 반환에 대한 다른 매개 변수의 영향을 배트 테스트 할 수 있습니다. 예를 들어 수면 시간을 가져서 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}

이윤은 약간 증가했습니다. 이것은 전략에 미뤄진 주문의 한 그룹 만이 있기 때문에 일부 주문은 변경할 시간이 없기 때문에 변동하는 가격을 얻을 수 없습니다. 잠자리 시간이 줄어드는 것이이 문제를 개선합니다. 이것은 또한 그리드 전략에서 미뤄진 멀티 그룹 주문의 중요성을 보여줍니다.

요약

이 논문에서는 주문 흐름에 기반한 새로운 백테스팅 시스템을 혁신적으로 제안하며, 부분적으로 주문 유예, 주문 채용, 부분 거래 및 지연과 같은 매칭 상황을 시뮬레이션 할 수 있으며, 부분적으로 전략 펀드 부피가 수익에 미치는 영향을 반영하며, 고주파 전략 및 헤지 전략에 중요한 참조 가치를 가지고 있습니다. 고정도 백테스팅은 전략 매개 변수 최적화의 방향을 제시합니다. 또한 장기적인 실제 봇 테스트로 검증되었습니다. 백테스트에 필요한 데이터 양은 잘 제어되며 백테스트 속도는 또한 매우 빠릅니다.


관련

더 많은