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

저자:선함, 2020-06-16 10:30:19, 업데이트: 2023-11-01 20:26:21

img

제가 글을 썼을 때바이낸스 선물 다화폐 헤지 전략에 대한 연구, 나는 또한 백테스트 엔진을 출시했다. 그리고 첫 번째 보고서는 전략의 효과를 검증 한 한 시간 K-라인 백테스트를 기반으로 했다. 그러나 실제 오픈 소스 전략의 수면 시간은 1 초입니다. 이는 상당히 높은 빈도 전략입니다. 분명히, 시간별 K-라인 백테스트를 사용하면 정확한 결과를 얻을 수 없습니다. 나중에, 분 레벨 K 라인의 백테스트의 결과가 추가되었으며, 백테스트 수익은 많이 향상되었지만, 여전히 초 레벨의 경우 어떤 매개 변수를 사용해야하는지 결정하는 것이 불가능하며 전체 전략의 이해는 매우 명확하지 않습니다. 주된 이유는 K-라인 기반의 백테스트의 중요한 단점입니다.

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

먼저, 역사적인 K 라인은 무엇입니까? K 라인 데이터는 높은, 개방, 낮은, 닫는, 첫 두 및 간격의 부피의 네 가지 가격을 포함합니다. 대부분의 양자화 플랫폼 및 프레임워크는 K 라인 백테스트를 기반으로하며 FMZ 플랫폼은 또한 틱 레벨 백테스트를 제공합니다. K 라인 백테스트 속도는 매우 빠르고 대부분의 경우 거의 문제가 없지만 매우 심각한 결함이 있습니다. 특히 백테스트 다종양 전략과 고 주파수 전략, 올바른 결론을 도출하는 것은 거의 불가능합니다.

첫 번째는 시간 문제입니다. K-라인 데이터의 가장 높은 가격과 가장 낮은 가격의 시간은 주어지지 않으며 고려할 필요가 없지만 가장 중요한 개출 및 폐쇄 가격은 개출 및 폐쇄 시간이 아닙니다. 덜 인기있는 거래 품종조차도 종종 10 초 이상 거래가 없으며, 다종 다양성 전략을 백테스트 할 때 종종 개출 가격과 폐쇄 가격이 동일하다고 가정합니다. 이는 또한 폐쇄 가격의 백테스트에 기반합니다.

두 종류의 중재를 백테스트하기 위해 분 레벨 K 라인을 사용하는 것을 상상해보십시오. 그 사이의 차이는 일반적으로 10 위안 (또는 달러) 입니다. 이제 10:01에 계약 A의 폐쇄 가격은 100이며 계약 B는 112이며 차이는 12 위안입니다. 따라서 전략은 헤지하기 시작합니다. 특정 순간에 가격 차이는 돌아 왔고 전략은 2 위안의 수익을 얻었습니다.

하지만 실제 상황은 10:00:45에 계약 A가 100 위안의 거래를 생성하고, 그 후에 거래가 없었을 수도 있고, 계약 B가 10:00:58에 112 위안의 거래를 했고, 10:01:00에 두 가격 모두 존재하지 않는다. 현재 시장 가격은 얼마이며, 헤지 운영은 얼마를 얻을 수 있을까? 나는 알 수 없다. 가능한 상황 중 하나는: 10:00:58에 계약 A의 Buy 1Sell 1 대기 주문 가격은101.9102.12원 정도의 차이는 전혀 없습니다. 이것은 우리의 전략 최적화를 크게 오해할 것입니다.

두 번째는 매치 메이킹 문제입니다. 실제 매치 메이킹은 가격 우선 순위와 시간 우선 순위입니다. 구매자가 Sell 1 가격을 초과하면 일반적으로 직접 Sell 1 가격으로 거래합니다. 그렇지 않으면 대기 주문서에 입력하고 기다립니다. K 라인 데이터에는 분명히 Buy 1Sell 1 가격이 없습니다. 세부 가격 매칭 수준을 시뮬레이션하는 것은 불가능합니다.

마지막은 시장에 전략 자체의 영향입니다. 작은 금액의 자금의 백테스트라면 영향은 크지 않습니다. 그러나 거래량이 크면 시장에 영향을 미칠 것입니다. 큰 양의 주문을 할 때 가격 미끄러지는 것이 크었을뿐만 아니라, 긴 주문을 실행하는 경우, 이러한 종류의 행동이 실제로 구매하려는 다른 거래자의 주문을 포착합니다. 이 효과는 시장에 영향을 줄 것입니다. 이 효과는 수치화 할 수 없습니다. 우리는 경험으로만 알 수 있습니다. 고주파 거래는 작은 자금을 수용 할 수 있습니다.

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

FMZ는 실제 수준의 백테스트를 제공합니다.20 layer depth price, 실시간 두 번째 수준Ticks, Each Individual Transaction이러한 특징을 바탕으로 FMZ는 실시간 트랜잭션 재생 기능을 만들었습니다.

이러한 종류의 백테스트 데이터는 매우 크며 백테스트 속도는 매우 느리고 일반적으로 2 일 동안만 백테스트 할 수 있습니다. 상대적으로 높은 주파수 또는 시간적 중요 전략에 대해 실제 시장 수준의 백테스트가 필요합니다. FMZ가 수집한 거래 쌍과 거래 시간은 매우 길지 않지만 여전히 7 억 개 이상의 역사적 데이터가 있습니다.

현재 매치메이크 메커니즘은 구매 주문이 세일 1보다 크면 금액을 보지 않고 즉시 완전히 매치되고, 세일 1보다 작으면 대기 대기 대기열에 들어갈 것입니다. 이러한 백테스트 메커니즘은 K-라인 백테스트의 첫 두 가지 문제를 해결하지만 여전히 마지막 문제를 해결할 수 없습니다. 데이터 양이 너무 크기 때문에 백테스트 속도와 시간 범위가 제한됩니다.

img

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

K선에는 너무 적은 정보가 있고, 가격 깊이는 가짜 깊이가 될 수도 있습니다. 하지만 시장의 실제 거래 의지를 나타내는 데이터가 있습니다.Each Individual Transaction이 기사는 주문 흐름에 기반한 고 빈도 백테스트 시스템을 제안합니다. 이는 실제 시장 수준의 백테스트 데이터의 양을 크게 줄이고 어느 정도 시장에 거래량의 영향을 시뮬레이션합니다.

저는 지난 5일 간 거래의 거래상황을 다운로드했습니다.https://www.fmz.com/upload/asset/1ff487b007e1a848ead.csv), 인기가 없는 품종으로, 총 213000개의 거래 데이터를 가지고 있습니다. 먼저 데이터의 구성에 대해 살펴보겠습니다.

[['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 차원 목록 이다. 구체적인 의미 는 다음과 같다: 품종 이름, 거래 가격, 거래 시간표, 거래량, 판매 주문 활성 거래 여부. 구매 및 판매 측면이 있으며, 각 거래에는 구매자와 판매자가 포함됩니다. 구매자가 시장이라면Maker그리고 판매자는 적극적인Taker, 마지막 자료는True.

우선, 거래 방향에 따라 시장에서 Buy 1Sell 1에 대해 상당히 정확하게 추측할 수 있습니다. 활성 판매 주문이라면, 이 시점에서 Buy 1 가격은 거래 가격이며, 활성 구매 주문이라면, Sell 1 가격은 거래 가격입니다. 새로운 거래가 있다면, 모든 가격이 갱신되고 업데이트됩니다. 갱신 및 업데이트가 없으면 마지막 결과가 유지됩니다. 위의 데이터의 마지막 순간을 도입하는 것이 쉽습니다, Buy 1 가격은 2.903, Sell 1는 2.904입니다.

주문 흐름에 따라, 그것은 다음과 같이 일치 할 수 있습니다: 예를 들어 구매 주문을 가져, 가격은price, 주문량은amount, 다음 구매하고 판매 1 이 시간에bid그리고ask각각.price이보다 낮습니다.ask이보다 높습니다.bid, 그 다음에는maker우선, 우선 순위가 거래에 일치 할 수 있습니다.price명령어 존재 시간 동안이 명령어와 일치합니다 (만약price이보다 작거나 같거나bid, 거래에 우선 순위가 부여되지 않습니다.price이 순서와 일치합니다.)

일치하는 가격은price, 그리고 거래량은Each Individual Transaction, 주문이 완전히 완료되거나 주문이 취소 될 때까지ask, 그것은taker그 후, 주문이 존재하는 기간 동안, 거래 가격보다 낮은 또는price이 주문과 일치합니다. 그리고 일치 가격은Each Individual Transaction. 그 사이의 차이maker그리고taker기본적으로 거래소가 대기 주문을 장려하고 거래 수수료에 대한 할인도 있기 때문입니다.

이런 종류의 매칭에 문제가 있다는 것을 쉽게 알 수 있습니다.taker, 실제 상황은 즉시 실행 될 수 있다는 것입니다, 새로운 주문을 기다리기 보다는 그것과 일치. 첫째로, 우리는 대기 주문의 양을 고려하지 않습니다, 심지어 일부 데이터가 있지만, 직접 거래도 변화했다 판단 가격 깊이, 시장에 영향을 미치는.

새로운 주문의 매칭을 기반으로, 그것은 역사에 있는 주문을 당신의 주문으로 대체하는 것과 동등합니다. 어떤 경우에도, 그것은 시장의 자체 거래량의 한계를 초과하지 않을 것이며, 최종 이익은 시장에서 생성되는 최대 이익을 초과 할 수 없습니다. 매칭 메커니즘의 일부는 또한 주문의 양에 영향을 미치며, 이는 전략의 수익에 영향을 미치며, 전략의 용량을 양적으로 반영합니다. 자금의 양이 두 배되고 이익이 두 배 될 때 전통적인 백테스트가 없습니다.

아직 몇 가지 작은 세부 사항이 있습니다. 주문의 구매 가격은 Buy 1에 같다면, 여전히 구매 가격이 Buy 1에 일치 할 확률이 있습니다. 이러한 상황은 여기에서 고려되지 않습니다.

일치하는 코드

교환 객체는 초기에 도입을 참조할 수 있습니다. 기본적으로 변경되지 않습니다.maker그리고taker다음에는 주로 매칭 코드를 소개합니다.

 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] # executed price
        trade_amount = tick[3] # executed volume
        time_stamp = tick[1] # executed 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, 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보다 작을 때,maker, 구매가격이 Buy 1보다 높으면Priority matching, priority가격이 구매 가격과 같는지 아닌지를 결정하고, 메이커는 거래 수수료를 결정합니다.

  • maker그리고priority주문의 크기가 큰 경우 시장 용량을 초과합니다. 가격이 구매 가격보다 높을 때, 나머지 부피는maker.

  • 전략interval필요한 경우, 시장의 지연을 나타낼 수 있습니다.

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

마지막으로, 그것은 실제 백테스트 단계입니다. 우리가 예상 결과를 달성 할 수 있는지 확인하기 위해 가장 고전적인 그리드 전략 중 하나를 백테스트 해 봅시다. 전략의 원리는 가격이 1% 상승 할 때마다 특정 가치의 짧은 주문을 보유한다는 것입니다 (반대의 경우, 우리는 긴 주문을 보유하고 있습니다), 사전에 구매 주문과 판매 주문을 계산합니다.Grid('XTZ', 100, 0.3, 1000, 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, 100,000이며, 총 백테스트 시간은 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}

수익은 약간 증가했습니다. 전략은 단지 일련의 주문을 보내기 때문에, 일부 주문은 변경할 시간이 없기 때문에 변동 가격을 실행할 수 없습니다. 그리고 수면 시간의 감소는이 문제를 개선합니다. 이것은 또한 여러 세트의 주문을 배치하기위한 그리드 전략의 중요성을 보여줍니다.

요약하면

이 문서에서는 주문 흐름에 기반한 새로운 백테스트 시스템을 혁신적으로 제안하고 있으며, 이는 대기 중인 주문, 실행 중인 주문, 일부 실행된 주문, 지연 등의 일치 상황을 부분적으로 시뮬레이션 할 수 있으며, 전략 자금액의 수익에 미치는 영향을 부분적으로 반영합니다. 고주파 및 헤지 전략에 대해서는 중요한 참조 가치를 가지고 있습니다. 고정도 백테스트는 전략 매개 변수 최적화의 방향을 나타냅니다. 또한 오랫동안 검증되었습니다. 게다가 백테스트에 필요한 데이터의 양은 잘 제어되며 백테스트 속도는 또한 매우 빠릅니다.


관련

더 많은