Sistem backtest frekuensi tinggi berdasarkan setiap transaksi dan kecacatan backtest K-line

Penulis:Kebaikan, Dicipta: 2020-06-16 10:30:19, Dikemas kini: 2023-11-01 20:26:21

img

Apabila saya menulisPenyelidikan mengenai Strategi Hedging Multi-mata wang Binance Futures, Saya juga mengeluarkan enjin backtest. Dan laporan pertama adalah berdasarkan backtest K-line satu jam, yang mengesahkan keberkesanan strategi. Tetapi masa tidur strategi sumber terbuka sebenar adalah 1 saat, yang merupakan strategi frekuensi yang agak tinggi. Jelas, menggunakan backtest K-line setiap jam tidak dapat menghasilkan hasil yang tepat. Kemudian, hasil backtest K-line tahap minit ditambah, dan pendapatan backtest telah bertambah baik, tetapi masih mustahil untuk menentukan parameter apa yang harus digunakan dalam kes seconds level, dan pemahaman keseluruhan strategi tidak begitu jelas. Sebab utama adalah kelemahan penting backtest berdasarkan K-line.

Masalah berdasarkan backtest K-line

Pertama sekali, apakah garis K sejarah? Data K-line mengandungi empat harga tinggi, terbuka, rendah, dekat, dua kali pertama dan jumlah selang. Kebanyakan platform dan kerangka kuantisasi berdasarkan backtest K-line, dan platform FMZ juga menyediakan backtest tahap tik. Kelajuan backtest K line sangat cepat, dan dalam kebanyakan kes ia mempunyai sedikit masalah, tetapi ia juga mempunyai kecacatan yang sangat serius, terutamanya strategi backtest pelbagai jenis dan strategi frekuensi tinggi, hampir mustahil untuk menarik kesimpulan yang betul.

Yang pertama adalah isu masa. Masa harga tertinggi dan harga terendah data K-line tidak diberikan dan tidak perlu dipertimbangkan, tetapi harga pembukaan dan penutupan yang paling penting bukanlah masa pembukaan dan penutupan. Malah varieti perdagangan yang kurang popular sering tidak mempunyai perdagangan selama lebih dari sepuluh saat, dan apabila kita menguji strategi pelbagai varieti, kita sering menganggap bahawa harga pembukaan dan harga penutupan mereka adalah sama, yang juga berdasarkan ujian belakang harga penutupan.

Bayangkan menggunakan garis K tahap minit untuk menguji semula arbitrase dua jenis. Perbezaan antara mereka biasanya 10 yuan ((atau dolar). Sekarang, pada 10:01, harga penutupan kontrak A adalah 100, kontrak B adalah 112, dan perbezaannya adalah 12 yuan. Jadi strategi mula lindung nilai. Pada saat tertentu, perbezaan harga kembali, dan strategi menghasilkan keuntungan pulangan 2 yuan.

tetapi situasi sebenar mungkin ialah pada pukul 10:00:45, kontrak A menghasilkan transaksi 100 yuan, selepas itu tidak ada transaksi, kontrak B mempunyai transaksi 112 yuan pada pukul 10:00:58, pada 10:01:00 Kedua-dua harga tidak wujud. Apakah harga pasaran pada masa ini, dan berapa banyak operasi lindung nilai dapat mendapat? Saya tidak boleh tahu. Satu situasi yang mungkin adalah: pada pukul 10:00:58, harga pesanan menunggu Beli 1 dan Jual 1 kontrak A adalah101.9kepada102.1, dan tiada perbezaan 2 yuan sama sekali. ini akan sangat mengelirukan optimasi strategi kita.

Kedua adalah masalah pencocokan. Pencocokan sebenar adalah keutamaan harga dan keutamaan masa. Jika pembeli melebihi harga Jual 1, mereka biasanya akan berurusan secara langsung dengan harga Jual 1, jika tidak mereka akan memasuki buku pesanan yang tertunda dan menunggu. Data garis K jelas tidak mempunyai Beli 1 dan Jual 1 harga, mustahil untuk mensimulasikan tahap pencocokan harga terperinci.

Yang terakhir adalah kesan strategi itu sendiri pada pasaran. Jika ia adalah backtest dana sejumlah kecil, kesannya tidak besar. Tetapi jika jumlah urus niaga besar, ia akan memberi kesan kepada pasaran. Bukan sahaja kemerosotan harga akan besar apabila anda meletakkan pesanan jumlah yang besar, jika anda membeli pesanan panjang dilaksanakan, tindakan semacam ini sebenarnya merebut pesanan pedagang lain yang pada asalnya ingin membeli, kesan butterfly akan memberi kesan kepada pasaran. Kesan ini tidak dapat diukur. Kita hanya boleh mengatakan dari pengalaman bahawa perdagangan frekuensi tinggi hanya dapat menampung dana kecil.

Ujian balik berdasarkan kedalaman masa nyata dan tanda

FMZ menyediakan backtest tahap sebenar, yang boleh mendapatkan sejarah sebenar20 layer depth price, masa nyata tahap keduaTicks, Each Individual TransactionBerdasarkan ciri-ciri ini, FMZ membuat fungsi pemutaran transaksi masa nyata.

Jumlah data backtest ini sangat besar, dan kelajuan backtest juga sangat perlahan, biasanya hanya boleh backtest selama dua hari. Untuk strategi yang agak kerap atau kritikal masa, backtest tahap pasaran sebenar diperlukan. Pasangan perdagangan dan masa perdagangan yang dikumpulkan oleh FMZ tidak terlalu lama, tetapi masih ada lebih daripada 70 bilion data sejarah.

Mekanisme pencocokan semasa adalah bahawa jika pesanan pembelian lebih besar daripada Jual 1 , ia akan dipadankan sepenuhnya dengan segera tanpa melihat jumlahnya, dan jika kurang dari Jual 1 , ia akan memasuki barisan perlawanan untuk menunggu. Mekanisme backtest seperti itu menyelesaikan dua masalah pertama backtest K-line, tetapi masih tidak dapat menyelesaikan masalah terakhir. Dan kerana jumlah data terlalu besar, kelajuan backtest dan julat masa terhad.

img

Mekanisme uji balik berdasarkan aliran urus niaga pesanan demi pesanan

Terdapat terlalu sedikit maklumat dalam garis K, dan kedalaman harga juga boleh menjadi kedalaman palsu, tetapi terdapat sejenis data yang merupakan pasarans niat transaksi sebenar, yang mencerminkan sejarah transaksi yang paling sebenar, iaitu,Each Individual TransactionArtikel ini akan mencadangkan sistem backtest kekerapan tinggi berdasarkan aliran pesanan, yang akan mengurangkan jumlah data backtest tahap pasaran sebenar, dan hingga tahap tertentu mensimulasikan kesan jumlah dagangan di pasaran.

Saya memuat turun urus niaga 5 hari terakhir Binance XTZ kontrak kekal (alamat muat turun:https://www.fmz.com/upload/asset/1ff487b007e1a848ead.csv), sebagai jenis yang tidak popular, ia mempunyai jumlah data 213000 transaksi, pertama mari kita lihat komposisi data:

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

Data adalah senarai dua dimensi, disusun mengikut urutan kronologi. Makna khusus adalah sebagai berikut: nama varieti, harga transaksi, cap waktu transaksi, kuantiti transaksi, sama ada ia adalah urus niaga pesanan jualan aktif. Terdapat membeli dan menjual sisi, dan setiap urus niaga termasuk pembeli dan penjual. Jika pembeli adalah pasaranMakerdan penjual adalah aktifTaker, data terakhir adalahTrue.

Pertama sekali, mengikut hala tuju transaksi, anda boleh membuat spekulasi dengan tepat mengenai Buy 1 dan Sell 1 di pasaran. Jika ia adalah pesanan jual aktif, maka harga Buy 1 pada masa ini adalah harga transaksi, jika ia adalah pesanan pembelian aktif, harga Sell 1 akan menjadi harga transaksi. Jika ada transaksi baru, maka semua harga akan diperbaharui dan dikemas kini. Hasil terakhir akan dikekalkan jika tidak ada pembaharuan dan kemas kini. Mudah untuk memperkenalkan saat terakhir data di atas, harga Buy 1 adalah 2.903, dan Sell 1 adalah 2.904.

Menurut aliran pesanan, ia boleh disamakan dengan cara ini: mengambil pesanan pembelian sebagai contoh, harga adalahprice, kuantiti pesanan adalahamount, kemudian membeli dan menjual 1 pada masa ini adalahbiddanaskJikapriceadalah lebih rendah daripadaaskdan lebih tinggi daripadabid, maka ia dinilai sebagaimakerpertama, dan keutamaan boleh dipadankan untuk membuat perjanjian, maka semua urus niaga dengan harga urus niaga yang lebih rendah daripada atau sama denganpricesemasa masa wujud pesanan akan sepadan dengan pesanan ini (jikapriceadalah kurang daripada atau sama denganbid, tiada keutamaan diberikan kepada urus niaga.pricedisamakan dengan urutan ini.)

Harga yang sepadan adalahprice, dan jumlah adalah jumlah transaksiEach Individual Transaction, sehingga pesanan selesai sepenuhnya atau pesanan dibatalkan.ask, ia dinilai sebagaitakerSelepas itu, semasa pesanan itu wujud, semua urus niaga dengan harga urus niaga lebih rendah daripada atau sama denganpriceadalah sepadan dengan pesanan ini, dan harga sepadan adalah harga transaksiEach Individual Transaction. Perbezaan antaramakerdantakeradalah pada dasarnya kerana bursa menggalakkan pesanan menunggu dan terdapat diskaun untuk yuran urus niaga.

Adalah mudah untuk melihat masalah dengan jenis pencocokan ini.taker, situasi sebenar adalah bahawa ia boleh dilaksanakan dengan serta-merta, dan bukannya menunggu pesanan baru untuk dipadankan dengan ia. pertama sekali, kita tidak mempertimbangkan jumlah pesanan menunggu, walaupun ada beberapa data, langsung menilai urus niaga juga telah berubah kedalaman harga, mempengaruhi pasaran.

Berdasarkan pencocokan pesanan baru, ia bersamaan dengan menggantikan pesanan yang ada dalam sejarah dengan pesanan anda. Dalam apa jua keadaan, ia tidak akan melebihi had jumlah dagangan pasaran sendiri, dan keuntungan akhir tidak boleh melebihi keuntungan maksimum yang dihasilkan oleh pasaran. Sebahagian daripada mekanisme pencocokan juga mempengaruhi jumlah pesanan, yang seterusnya mempengaruhi pendapatan strategi, secara kuantitatif mencerminkan kapasiti strategi. Tidak akan ada ujian belakang tradisional, apabila jumlah dana berlipat ganda dan keuntungan berlipat ganda.

Masih ada beberapa butiran kecil. Jika harga pembelian pesanan sama dengan Buy 1, masih ada kebarangkalian tertentu bahawa harga pembelian akan sepadan dengan Buy 1, situasi seperti ini tidak akan dipertimbangkan di sini.

Kod yang sepadan

Objek pertukaran boleh merujuk kepada pengenalan di awal, pada dasarnya tidak berubah, hanya menambah perbezaan antaramakerdantakerberikut akan terutamanya memperkenalkan kod pencocokan.

 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

Beberapa butiran untuk diperhatikan:

  • Apabila ada urus niaga baru, kita mesti mencocokkan pesanan terlebih dahulu, dan kemudian meletakkan pesanan mengikut harga terkini.

  • Setiap pesanan mempunyai dua atribut: pembuatsama ada pembuat, keutamaanmemadankan keutamaan, mengambil pesanan pembelian sebagai contoh, apabila harga beli adalah kurang daripada jual 1, ia ditandakan sebagaimaker, dan apabila harga beli lebih besar daripada Beli 1, ia ditandakan sebagaiPriority matching, prioritymenentukan sama ada harga sama dengan harga pembelian atau tidak, dan pembuat menentukan yuran transaksi.

  • PeraturanmakerdanpriorityJika pembelian besar telah diletakkan dan melebihi kapasiti pasaran. Apabila harga adalah lebih besar daripada harga pembelian, jumlah yang tersisa akan menjadimaker.

  • Strategiintervalperlu, ia boleh mewakili kelewatan pasaran.

Ujian belakang strategi grid

Akhirnya, ia adalah peringkat backtest sebenar. Mari kita backtest salah satu strategi grid yang paling klasik di sini untuk melihat sama ada kita boleh mencapai hasil yang diharapkan. Prinsip strategi adalah bahawa setiap kali harga meningkat sebanyak 1%, kita memegang pesanan pendek nilai tertentu (sebaliknya, kita memegang pesanan panjang), mengira pesanan beli dan jual terlebih dahulu. saya tidak akan menunjukkan kod sumber. mereka semua dikemas dalamGrid('XTZ', 100, 0.3, 1000, maker_fee=-0.00002, taker_fee=0.0003)fungsi, parameter adalah: pasangan dagangan, harga menyimpang dari nilai pegangan 1%, ketumpatan pesanan menunggu adalah 0.3%, selang tidurms, yuran pesanan yang belum selesai dan yuran pesanan yang dilaksanakan.

Harga pasaran XTZ telah berada dalam kejutan selama 5 hari yang lalu, yang sangat sesuai untuk grid.

img

Kita mula-mula menguji kesan kedudukan pegangan yang berbeza pada pulangan keuntungan. pulangan yang diuji dengan mekanisme backtest tradisional pasti akan meningkat berbanding dengan peningkatan kedudukan pegangan.

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

Sebanyak empat kumpulan diuji semula, nilai kedudukan memegang adalah 100, 1000, 10000, 100,000, dan jumlah masa ujian semula adalah 1.3s. Hasilnya adalah seperti berikut:

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

Ia dapat dilihat bahawa keuntungan yang diwujudkan akhir adalah masing-masing 28.4%, 27.5%, 26.9% dan 22.6% daripada nilai kedudukan pegangan. Ini juga selaras dengan keadaan sebenar. Semakin besar nilai kedudukan pegangan, semakin besar nilai pesanan yang menunggu, semakin besar kemungkinan transaksi separa akan berlaku, dan semakin kecil keuntungan yang diwujudkan akhir berbanding dengan jumlah pesanan yang menunggu. Carta berikut adalah perbandingan pulangan relatif nilai kedudukan masing-masing 100 dan 10000:

img

Kita juga boleh backtest kesan parameter yang berbeza pada pendapatan backtest, seperti ketumpatan pesanan yang menunggu, masa tidur, yuran transaksi, dll. Ambil masa tidur sebagai contoh, ubah menjadi 100ms, dan bandingkan masa tidur kepada 1000ms untuk melihat pulangan keuntungan. Hasil backtest adalah seperti berikut:

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

pendapatan telah meningkat sedikit, kerana strategi hanya menghantar satu set pesanan, beberapa pesanan tidak akan dapat melaksanakan harga turun naik kerana mereka tidak mempunyai masa untuk berubah, dan pengurangan masa tidur memperbaiki masalah ini.

Ringkasnya

Artikel ini secara inovatif mencadangkan sistem backtest baru berdasarkan aliran pesanan, yang boleh sebahagian mensimulasikan keadaan pencocokan pesanan yang tertunda, perintah pelaksanaan, pesanan pelaksanaan separa, kelewatan, dan lain-lain, dan sebahagiannya mencerminkan kesan jumlah dana strategi pada pendapatan. Untuk strategi frekuensi tinggi dan lindung nilai, Ia mempunyai nilai rujukan yang penting.


Berkaitan

Lebih lanjut