Hochfrequenz-Backtesting-System auf Basis von Transaktion für Transaktion und Defekte von K-Line-Backtesting

Schriftsteller:Lydia., Erstellt: 2022-11-30 12:38:50, Aktualisiert: 2023-09-11 20:01:01

img

Hochfrequenz-Backtesting-System auf Basis von Transaktion für Transaktion und Defekte von K-Line-Backtesting

Ich veröffentlichte eine Backtesting-Engine im Artikel Studie on Multi-Currency Hedging Strategy of Binance Futures (https://www.fmz.com/digest-topic/5584) und der erste Bericht basiert auf dem einstündigen K-Line-Backtesting, das die Wirksamkeit der Strategie überprüft. In der Tat beträgt die Schlafzeit der öffentlichen Strategie jedoch 1s, was eine ziemlich hohe Frequenzstrategie ist. Es ist offensichtlich unmöglich, genaue Ergebnisse mit dem einstündigen K-Line-Backtesting zu erzielen. Später wurden die Ergebnisse des Minute-Line-Backtests hinzugefügt (https://www.fmz.com/digest-topic/5621Die Ergebnisse des Backtests haben sich erheblich verbessert, aber es ist immer noch unmöglich zu bestimmen, welche Parameter im Fall der zweiten Stufe verwendet werden sollten, und das Verständnis der gesamten Strategie ist nicht sehr klar.

Probleme auf der Grundlage von K-Line-Backtesting

Zunächst einmal, was ist die historische K-Linie? Eine K-Linie Daten umfasst vier Preise: der höchste Preis, der Eröffnungspreis, der niedrigste Preis und den Schlusskurs, Startzeit, Endzeit und Intervallhandel Menge. Die meisten quantitativen Plattformen und Rahmen werden auf der Grundlage der K-Linie backtested, und FMZ Quant-Plattform bietet auch Tick-Level-Backtesting. Die Geschwindigkeit des K-Line-Backtesting ist sehr schnell, und es ist kein Problem in den meisten Fällen, aber es gibt auch sehr ernste Mängel, vor allem die Multi-Variety-Strategie und die Hochfrequenz-Strategie des Backtesting, die kaum richtige Schlussfolgerungen ziehen kann.

Zunächst einmal ist es eine Frage der Zeit. Die Zeit des höchsten und niedrigsten Preises der K-Liniendaten ist nicht angegeben, so dass es unnötig ist, zu berücksichtigen, aber die wichtigsten Eröffnungs- und Schlusskosten sind nicht die Eröffnungs- und Schlusspositionszeiten. Auch wenn die Handelsvarianten unpopulär sind, werden sie oft nicht länger als zehn Sekunden gehandelt. Wenn wir mehrere Strategien zurückprüfen, stellen wir oft fest, dass ihre Eröffnungs- und Schlusskosten gleich sind, was auch die Grundlage für das Abschlusskurs-Backtesting ist.

Stellen Sie sich vor, die Minute-Linie zu verwenden, um die Arbitrage von zwei Sorten zu testen. Die Differenz zwischen ihnen beträgt normalerweise 10 Yuan. Jetzt stellt sich heraus, dass um 10:01 Uhr der Schlusskurs von Vertrag A 100 Yuan, der Schlusskurs von Vertrag B 112 Yuan und die Differenz 12 Yuan beträgt. Also beginnt die Strategie zu sichern. Zu einem bestimmten Zeitpunkt kehrt die Differenz zurück und die Strategie erzielt 2 Yuan Rendite.

Die tatsächliche Situation kann jedoch um 10:00:45 geschehen, der Vertrag A erzeugte eine Transaktion von 100 Yuan, und dann gab es keine Transaktion. Vertrag B erzeugte eine Transaktion von 112 Yuan um 10:00:58. Um 10:01 existierten beide Preise nicht. Was war der Eröffnungspreis zu diesem Zeitpunkt? Und wie viel Unterschied könnte die Absicherung erzielen? Wir wissen es nicht. Eine mögliche Situation ist, dass um 10:00:58 der Trend des Kaufs eines und Verkaufs eines Vertrags A 101,9-102,1 beträgt, und es überhaupt keinen Spread von 2 Yuan gibt, was unsere Strategieoptimierung stark irreführen wird.

Der zweite ist das Matchmaking. Das echte Matchmaking ist Preis und Zeit zuerst. Wenn der Käufer den Verkaufspreis überschreitet, schließt er/sie in der Regel die Transaktion zum Verkaufspreis ab, andernfalls wird er/sie das Auftragsbuch eingeben und warten.

Der letzte ist die Wirkung der Transaktion der Strategie selbst auf den Markt. Wenn es sich um einen kleinen Fonds-Backtest handelt, wird die Wirkung gering sein. Wenn jedoch die Handelsmenge einen großen Anteil ausmacht, wird sie Auswirkungen auf den Markt haben. Nicht nur, dass der Preis-Slip-Point groß sein wird, wenn die Transaktion sofort abgeschlossen ist, sondern wenn Ihre Kauforder im Backtest abgeschlossen ist, geht es tatsächlich der Transaktion anderer ursprünglicher Händler vor, die kaufen möchten, was eine Schmetterlingswirkung auf den Markt haben wird. Diese Wirkung kann jedoch nicht quantifiziert werden, und es kann nur aus Erfahrung gesagt werden, dass Hochfrequenzhandel nur kleine Mittel aufnehmen kann.

Backtesting auf Basis von Echtzeittiefe und Tick

FMZ bietet das reale Bot-Level-Backtesting, das die reale historische 20-Level-Tiefe, Echtzeit-Sekunden-Tick, Transaktion für Transaktion und andere Daten erhalten kann, und auf dieser Grundlage hat es die echte Bot-Wiedergabefunktion (https://www.fmz.com/m/database) Diese Art von Backtestmessung hat eine große Datenmenge und eine langsame Geschwindigkeit, die nur für zwei Tage verwendet werden kann. Für Strategien, die relativ hohe Häufigkeit haben oder ein strenges Zeiturteil erfordern, ist das echte Bot-Backtesting notwendig. Die von FMZ gesammelten Handelspare und Zeit sind nicht zu lang, aber es gibt mehr als 70 Milliarden historische Daten. Der aktuelle Matching-Mechanismus besteht darin, dass, wenn die Kauforder größer ist als die Verkaufsorder, sie sofort vollständig abgestimmt wird, ohne auf die Menge zu achten, und wenn die Kauforder kleiner ist als die Verkaufsorder, sie in die Matching-Warteschlange eintritt. Dieser Backtesting-Mechanismus löst die ersten beiden Probleme des K-Line-Backtesting, kann aber immer noch nicht das letzte Problem lösen. Und weil die Datenmenge zu groß ist, sind die Backtestgeschwindigkeit und die Zeitspanne begrenzt.

img img

Backtesting-Mechanismus auf Basis von Transaktions-für-Transaktions-Auftragsfluss

Es gibt zu wenige Informationen über die K-Line, und die Tiefe kann auch falsch sein. Eine Art von Daten ist jedoch die tatsächliche Transaktionsabsicht des Marktes, die die realste Transaktionsgeschichte widerspiegelt - d.h. Transaktion für Transaktion. In diesem Artikel werde ich ein Hochfrequenz-Backtesting-System auf der Grundlage des Auftragsflusses vorschlagen, das die Datenmenge im Backtesting auf der echten Bot-Ebene erheblich reduziert und bis zu einem gewissen Grad die Auswirkungen des Handelsvolumens auf den Markt simuliert.

Ich habe die Transaktion pro Transaktion der letzten 5 Tage heruntergeladen Binance XTZ perpetual contract (Download-Adresse:https://www.fmz.com/upload/asset/1ff487b007e1a848ead.csvEs gibt 213.000 Datenstücke, die als weniger populär angesehen werden.

[['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'],

Die Daten sind eine zweidimensionale Liste, sortiert nach Transaktionszeit. Die spezifischen Bedeutungen sind: Artenname, Transaktionspreis, Transaktionszeitstempel, Transaktionsmenge und ob der Verkaufsbefehl aktiv ausgeführt wird. Es gibt sowohl Kauf als auch Verkauf. Jede Transaktion umfasst Käufer und Verkäufer. Wenn der Käufer ein Market Maker und der Verkäufer ein aktiver Transaktionsnehmer ist, werden die letzten Daten wahr sein.

Zunächst einmal können wir nach der Transaktionsrichtung den Kauf und den Verkauf am Markt genau spekulieren. Wenn es sich um einen aktiven Verkaufsauftrag handelt, ist der Kaufpreis zu diesem Zeitpunkt der Transaktionspreis. Wenn es sich um einen aktiven Kaufsauftrag handelt, ist der Verkaufspreis der Transaktionspreis. Wenn es eine neue Transaktion gibt, aktualisieren wir die neue Eröffnungsposition. Wenn sie nicht aktualisiert wird, wird das letzte Ergebnis beibehalten. Es ist einfach, den letzten Moment der oben genannten Daten zu starten. Der Kaufpreis beträgt 2.903 und der Verkaufspreis beträgt 2.904.

Nach dem Auftragsfluss kann es auf folgende Weise abgestimmt werden: Nehmen Sie einen Kauf Auftrag als Beispiel, der Preis ist Preis, und die Auftragsmenge ist Menge. Zu diesem Zeitpunkt werden jeweils eine Kauf- und eine Verkaufsposition der Eröffnungsposition geboten und gefragt. Wenn der Preis niedriger als gebeten und höher als geboten ist, wird er zuerst als Maker beurteilt, und der Matchmaking kann Priorität erhalten. Dann werden alle Transaktionen mit einem Transaktionspreis, der während der Laufzeit des Auftrags niedriger oder gleich dem Preis ist, mit dieser Bestellung abgestimmt (wenn der Preis niedriger oder gleich dem Gebot ist, kann der Transaktion keine Priorität eingeräumt werden, und Aufträge mit einem Transaktionspreis, der niedriger als der Preis ist, werden mit dieser Bestellung abgestimmt). Der Matchmaking-Preis ist Preis, und die Transaktionsmenge ist die Transaktionsmenge pro Transaktion, bis der Auftrag vollständig geschlossen oder gleich ist. Wenn der Unterschied höher ist als der Preis, wird er als Auft

Es ist leicht, das Problem dieses Matchmaking zu sehen. Wenn der Auftrag ein Taker ist, ist die tatsächliche Situation, dass die Transaktion sofort durchgeführt werden kann, anstatt auf eine neue Bestellung zu warten, um sie zu entsprechen. Zunächst einmal haben wir die Anzahl der auf dem Markt aufgeführten Aufträge nicht berücksichtigt. Auch wenn es Daten gab, hat das direkte Urteil der Transaktion die Tiefe verändert und den Markt beeinflusst. Das Matchmaking auf der Grundlage neuer Aufträge entspricht dem Ersetzen Ihrer Aufträge durch die realen Aufträge in der Geschichte, die in keinem Fall die Transaktionsmengegrenze des Marktes selbst überschreiten werden, und der endgültige Gewinn kann den maximalen Gewinn des Marktes nicht überschreiten. Ein Teil des Matchmaking-Mechanismus beeinflusst auch die Transaktionsmenge von Aufträgen, wodurch sich die Renditen der Strategie, die die Strategie quantitativ widerspiegelt, ändern. Es wird kein traditionelles Backtesting geben, bei dem die doppelte Rendite des Fonds verdoppelt wird.

Es gibt auch einige kleine Details. Wenn der Kaufpreis einer Bestellung gleich dem Kaufpreis ist, besteht immer noch eine gewisse Wahrscheinlichkeit, dass die Bestellung zum Kaufpreis angepasst wird. Die Priorität der Bestellung und die Transaktionswahrscheinlichkeit müssen berücksichtigt werden, was komplexer ist und hier nicht berücksichtigt wird.

Code für die Absprache

Dabei wird nur der Unterschied zwischen Maker- und Taker-Provisionen addiert und die Geschwindigkeit des Backtestings optimiert.

    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

Einige Einzelheiten sind zu beachten:

-1. Wenn es eine neue Transaktion gibt, sollten wir die Bestellung zuerst anpassen, und dann die Bestellung nach dem letzten Preis platzieren. -2. Jeder Auftrag hat zwei Attribute: Maker ob er Maker ist und Priorität Matchmaking-Priorität. Nehmen wir den Kauf Auftrag als Beispiel, wenn der Kaufpreis kleiner als der Verkaufspreis ist, wird er als Maker gekennzeichnet, und wenn der Kaufpreis größer als der Kaufpreis ist, wird er als Priority-Matchmaking gekennzeichnet. Priorität bestimmt, ob der Preis dem Kaufpreis entspricht, und Maker bestimmt die Provision. -3. Der Maker und die Priorität der Bestellung werden aktualisiert. Zum Beispiel gibt es eine große Kaufbestellung, die die Eröffnungspositionen übersteigt, wenn ein Preis größer ist als der Kaufpreis, wird zu diesem Zeitpunkt die verbleibende Transaktionsmenge Maker sein. -4. Die Strategie ist in einem Intervall notwendig, der die Verzögerung des Marktes darstellen kann.

Backtesting von Netzstrategien

Schließlich erreichen wir die eigentliche Backtesting-Phase. Hier werden wir eine klassische Gitterstrategie zurücktesten, um zu sehen, ob sie den erwarteten Effekt erzielt hat. Das Strategieprinzip lautet, dass wir jedes Mal, wenn der Preis um 1% steigt, einen bestimmten Wert von Short-Positionsordern halten (andernfalls halten wir Long-Positionsordern), und wir berechnen die Kauf- und Verkaufsorder und warten sie im Voraus ab. Der Code wird nicht veröffentlicht.Grid ('XTZ ', 100,0.31000, maker_fee=-0.00002, taker_fee=0.0003)Die Parameter sind: Handelspaar, Haltungswert mit einer Preisdifferenz von 1%, Auftragsdichte von 0,3%, Schlafintervall von ms, pending order commission und Taker commission.

Der XTZ-Markt war in den letzten 5 Tagen in Schock, was für die Netzstrategie sehr geeignet ist.

img

Wir werden zunächst die Auswirkungen verschiedener Positionen auf die Rendite überprüfen.

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'])

Insgesamt vier Gruppen wurden mit Positionswerten von 100, 1000, 10000 und 100000 zurück getestet, wobei die Gesamtzeit des Rücktests 1,3 Sekunden betrug.

{'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}

Es kann gesehen werden, dass die endgültig realisierten Gewinne jeweils 28,4%, 27,5%, 26,9% und 22,6% des Positionswerts betragen. Dies entspricht auch der tatsächlichen Situation. Je größer der Wert der Position ist, desto größer wird der Wert der Bestellung sein und desto wahrscheinlicher werden Teiltransaktionen stattfinden. Die endgültig realisierten Renditen werden relativ zur Bestellmenge kleiner sein. Die folgende Abbildung zeigt den Vergleich relativer Renditen mit Positionswerten von 100 bzw. 10000:

img

Wir können auch den Einfluss verschiedener Parameter auf die Rückgabe des Backtests, wie die ausstehende Auftragsdichte, Schlafzeit und Provisionen, zurücktesten. Nehmen wir die Schlafzeit als Beispiel, ändern sie auf 100 ms, vergleichen sie mit der Schlafzeit von 1000 ms und beobachten die Rückgaben. Die Ergebnisse des Backtests sind wie folgt:

{'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}

Der Gewinn ist etwas gestiegen. Dies liegt daran, dass nur eine Gruppe von Aufträgen an der Strategie aussteht und einige Aufträge den schwankenden Preis nicht erhalten können, weil sie keine Zeit haben, sich zu ändern. Die reduzierte Schlafzeit verbessert dieses Problem. Dies zeigt auch die Bedeutung von ausstehenden Multi-Gruppen-Bestellungen in der Netzstrategie.

Zusammenfassung

Dieses Papier schlägt ein neues Backtesting-System auf Basis des Auftragsflusses innovativ vor, das teilweise die Übereinstimmungssituation wie Auftragswartung, Auftragsübernahme, teilweise Transaktion und Verzögerung simulieren kann, teilweise die Auswirkungen des strategischen Fondsvolumens auf die Rendite widerspiegelt und einen wichtigen Referenzwert für Hochfrequenzstrategien und Hedging-Strategien hat. Hochpräzisions-Backtesting zeigt die Richtung für die Optimierung von Strategieparametern. Es wurde auch durch langfristige echte Bot-Tests überprüft. Und die Menge an Daten, die für den Backtest erforderlich ist, ist gut kontrolliert und die Backtestgeschwindigkeit ist auch sehr schnell.


Verwandt

Mehr