Perdagangan berpasangan berdasarkan teknologi yang didorong data

Penulis:Kebaikan, Dibuat: 2019-08-21 13:50:23, Diperbarui: 2023-10-19 21:01:31

img

Pairing trading adalah contoh yang bagus untuk membuat strategi trading berdasarkan analisis matematis. Dalam artikel ini, kami akan menunjukkan bagaimana menggunakan data untuk membuat dan mengotomatisasi strategi trading pairing.

Prinsip-prinsip dasar

假设你有一对投资标的X和Y具有一些潜在的关联,例如两家公司生产相同的产品,如百事可乐和可口可乐。你希望这两者的价格比率或基差(也称为差价)随时间的变化而保持不变。然而,由于临时供需变化,如一个投资标的的大买/卖订单,对其中一家公司的重要新闻的反应等,这两对之间的价差可能会不时出现分歧。在这种情况下,一只投资标的向上移动而另一只投资标的相对于彼此向下移动。如果你希望这种分歧随着时间的推移恢复正常,你就可以发现交易机会(或套利机会)。此种套利机会在数字货币市场或者国内商品期货市场比比皆是,比如BTC与避险资产的关系;期货中豆粕,豆油与大豆品种之间的关系.

Ketika ada perbedaan harga sementara, perdagangan akan menjual indikator yang berkinerja baik dan membeli indikator yang berkinerja buruk. Anda yakin bahwa selisih antara kedua indikator akan berakhir dengan penurunan indikator yang berkinerja baik atau pemulihan indikator yang berkinerja buruk atau keduanya. Anda akan menghasilkan uang dalam semua skenario serupa ini.

Oleh karena itu, perdagangan berpasangan adalah strategi perdagangan netral pasar yang memungkinkan pedagang untuk mendapatkan keuntungan dari hampir semua kondisi pasar: tren naik, tren turun, atau penyesuaian horizontal.

Definisi konsep: dua hipotesis indikator investasi

  • Kami membangun lingkungan penelitian kami di platform inventor kuantitas.

Pertama-tama, agar pekerjaan berjalan dengan lancar, kita perlu membangun lingkungan penelitian kita, dan dalam artikel ini kita menggunakan platform kuantitatif penemu.FMZ.COMPerangkat lunak ini digunakan untuk membangun lingkungan penelitian, terutama untuk platform yang dapat digunakan di masa depan dengan antarmuka API yang mudah dan cepat dan sistem Docker yang terintegrasi.

Dalam nama resmi platform kuantitatif penemu, sistem Docker ini disebut sistem host.

Untuk informasi lebih lanjut tentang cara mengimplementasikan administrator dan robot, lihat artikel saya sebelumnya:https://www.fmz.com/bbs-topic/4140

Untuk pembaca yang ingin membeli host yang mendistribusikan server cloud mereka sendiri, baca artikel ini:https://www.fmz.com/bbs-topic/2848

Setelah berhasil menerapkan layanan cloud dan sistem administrator, selanjutnya kita akan menginstal python terbesar saat ini: Anaconda.

Untuk menerapkan semua lingkungan program yang diperlukan untuk artikel ini (dependencies, version management, dll.), cara termudah adalah dengan menggunakan Anaconda. Ini adalah ekosistem ilmu data Python yang dikemas dan manajer repositori dependen.

Untuk cara menginstal Anaconda, lihat panduan resmi Anaconda:https://www.anaconda.com/distribution/

本文还将用到numpy和pandas这两个目前在Python科学计算方面十分流行且重要的库.

Pekerjaan dasar di atas juga dapat dilihat di artikel saya sebelumnya tentang cara mengatur lingkungan Anaconda dan perpustakaan kedua, numpy dan pandas, untuk detailnya:https://www.fmz.com/digest-topic/4169

Selanjutnya, mari kita gunakan kode untuk mewujudkan "dua hipotesis investasi".

import numpy as np
import pandas as pd

import statsmodels
from statsmodels.tsa.stattools import coint
# just set the seed for the random number generator
np.random.seed(107)

import matplotlib.pyplot as plt

Ya, kita juga akan menggunakan matplotlib, sebuah perpustakaan grafik yang sangat terkenal di Python.

Mari kita menghasilkan X dari indikator investasi hipotesis dan memproyeksikan pengembalian harian dengan pembagian normal. Kemudian kita melakukan akumulasi untuk mendapatkan nilai X harian.

# Generate daily returns
Xreturns = np.random.normal(0, 1, 100) 
# sum them and shift all the prices up
X = pd.Series(np.cumsum(
    Xreturns), name='X') 
    + 50
X.plot(figsize=(15,7))
plt.show()

img

X dari indikator investasi, dengan pembagian normal untuk mensimulasikan imbasan harian

Sekarang kita menghasilkan Y dan X yang sangat terkait, sehingga harga Y harus sangat mirip dengan perubahan X. Kita memodelkannya dengan mengambil X, memindahkannya ke atas dan menambahkan beberapa kebisingan acak yang diambil dari distribusi normal.

noise = np.random.normal(0, 1, 100)
Y = X + 5 + noise
Y.name = 'Y'
pd.concat([X, Y], axis=1).plot(figsize=(15,7))
plt.show()

img

X dan Y dari indikator investasi yang ko-integratif

Koordinasi

协整非常类似于相关性,意味着两个数据系列之间的比率将在平均值附近变化.Y和X这两个系列遵循以下内容:

Y = X + e

Di mana y adalah rasio konstan, dan e adalah kebisingan.

Untuk pasangan transaksi antara dua deret waktu, rasio ini pasti akan berkumpul pada nilai yang diharapkan dari waktu ke waktu, yaitu mereka harus koheren. Deret waktu yang kita bangun di atas adalah koheren. Kita sekarang akan menggambar rasio antara keduanya sehingga kita dapat melihat penampilannya.

(Y/X).plot(figsize=(15,7)) 
plt.axhline((Y/X).mean(), color='red', linestyle='--') 
plt.xlabel('Time')
plt.legend(['Price Ratio', 'Mean'])
plt.show()

img

Rasio dan rata-rata antara harga dua indikator investasi yang ko-integrasi

Pengujian Kointegrasi

Satu cara yang mudah untuk menguji adalah dengan menggunakan statsmodels.tsa.stattools. Kita seharusnya melihat nilai p yang sangat rendah karena kita secara artifisial membuat dua rangkaian data yang sejalan mungkin.

# compute the p-value of the cointegration test
# will inform us as to whether the ratio between the 2 timeseries is stationary
# around its mean
score, pvalue, _ = coint(X,Y)
print pvalue

Hasilnya adalah: 1.81864477307e-17

Perhatikan: Relevansi dan Kointegrasi

Hubungan dan ko-integrasi meskipun mirip secara teoritis, tetapi tidak sama. Mari kita lihat contoh dari rangkaian data yang terkait tetapi tidak ko-integrasi, dan sebaliknya. Pertama mari kita periksa hubungan dari rangkaian yang baru saja kita hasilkan.

X.corr(Y)

Hasilnya adalah: 0.951.

Seperti yang kita harapkan, ini sangat tinggi. Tapi bagaimana dengan dua rangkaian yang terkait tetapi tidak koheren? Contoh sederhana adalah dua rangkaian data yang menyimpang.

ret1 = np.random.normal(1, 1, 100)
ret2 = np.random.normal(2, 1, 100)

s1 = pd.Series( np.cumsum(ret1), name='X')
s2 = pd.Series( np.cumsum(ret2), name='Y')

pd.concat([s1, s2], axis=1 ).plot(figsize=(15,7))
plt.show()
print 'Correlation: ' + str(X_diverging.corr(Y_diverging))
score, pvalue, _ = coint(X_diverging,Y_diverging)
print 'Cointegration test p-value: ' + str(pvalue)

img

Dua seri terkait (tidak terintegrasi)

Koefisien terkait: 0.998 P-nilai tes kointegrasi: 0.258

Contoh sederhana dari kointegrasi tanpa korelasi adalah deret distribusi normal dan gelombang persegi.

Y2 = pd.Series(np.random.normal(0, 1, 800), name='Y2') + 20
Y3 = Y2.copy()
Y3[0:100] = 30
Y3[100:200] = 10
Y3[200:300] = 30
Y3[300:400] = 10
Y3[400:500] = 30
Y3[500:600] = 10
Y3[600:700] = 30
Y3[700:800] = 10
Y2.plot(figsize=(15,7))
Y3.plot()
plt.ylim([0, 40])
plt.show()
# correlation is nearly zero
print 'Correlation: ' + str(Y2.corr(Y3))
score, pvalue, _ = coint(Y2,Y3)
print 'Cointegration test p-value: ' + str(pvalue)

img

Perbedaan: 0.007546 P-nilai tes kointegrasi: 0.0

Korrelasi sangat rendah, tapi nilai p menunjukkan keseragaman yang sempurna!

Bagaimana cara berpacaran?

Karena dua urutan waktu yang berkoordinasi (misalnya X dan Y di atas) saling sejajar dan saling menyimpang, maka kadang-kadang ada situasi margin tinggi dan margin rendah. Kami melakukan perdagangan yang berpasangan dengan membeli satu indikator dan menjual indikator lain. Jadi jika dua indikator turun atau naik bersama, kami tidak menghasilkan uang atau kehilangan uang, yaitu kita netral di pasar.

Kembali ke Y = X + e di atas, X dan Y, sehingga rasio (Y / X) bergerak di sekitar nilai rata-rata, kita menghasilkan uang dengan rasio yang dikembalikan rata-rata. Untuk melakukan ini, kita akan memperhatikan situasi ketika X dan Y jauh dari satu sama lain, yaitu saat ambang batas terlalu tinggi atau terlalu rendah:

  • Perbanyak rasio: ini adalah ketika rasio bergelombang sangat kecil dan kita mengharapkannya menjadi lebih besar. Dalam contoh di atas, kita membuka posisi dengan melakukan lebih banyak Y dan kosong X.

  • Rasio kosong: ini adalah ketika rasio bergetar sangat besar dan kita mengharapkannya berubah menjadi jam. Dalam contoh di atas, kita membuka posisi dengan kosong Y dan melakukan lebih X.

Perhatikan bahwa kita selalu memiliki posisi hedging yang kuat: jika nilai beli dan rugi dari indikator yang diperdagangkan, posisi kosong akan menghasilkan uang, dan sebaliknya, sehingga kita kebal terhadap pergerakan pasar secara keseluruhan.

Jika indikator X dan Y bergerak relatif satu sama lain, kita akan menghasilkan atau kehilangan.

Menggunakan data untuk mencari perilaku yang mirip dengan indikator transaksi

Cara terbaik untuk melakukan ini adalah mulai dari indikator yang Anda curiga mungkin merupakan indikator transaksi yang koheren dan melakukan pengujian statistik.Perbandingan BerbedaSaya tidak tahu apa yang akan terjadi.

Perbandingan BerbedaHal ini berarti peningkatan peluang untuk menghasilkan p-nilai penting secara salah ketika menjalankan banyak tes, karena kita perlu menjalankan banyak tes. Jika kita melakukan 100 tes terhadap data acak, kita seharusnya melihat 5 p-nilai kurang dari 0.05. Jika Anda ingin membandingkan n indikator transaksi untuk melakukan ko-koordinasi, maka Anda akan melakukan n ((n-1) / 2 perbandingan, dan Anda akan melihat banyak p-nilai yang salah, yang akan meningkat seiring bertambahnya sampel uji Anda. Untuk menghindari hal ini, pilih beberapa pasangan transaksi yang memiliki alasan untuk Anda yakin mungkin ko-koordinasi dan uji mereka secara terpisah.Perbandingan Berbeda

Jadi, mari kita coba mencari beberapa indikator yang menunjukkan koherensi. Sebagai contoh, pertimbangkan sebuah keranjang saham teknologi besar AS dalam S&P 500 yang beroperasi di segmen pasar yang serupa dan memiliki harga koheren.

Kembali kointegrasi memeriksa matriks pecahan, matriks nilai p, dan semua pasangan dengan nilai p kurang dari 0.05.Metode ini mudah terjadi beberapa perbandingan yang salah, jadi mereka benar-benar perlu melakukan verifikasi kedua.Dalam artikel ini, untuk memudahkan penjelasan kita, kita memilih untuk mengabaikan hal ini dalam contoh-contoh tersebut.

def find_cointegrated_pairs(data):
    n = data.shape[1]
    score_matrix = np.zeros((n, n))
    pvalue_matrix = np.ones((n, n))
    keys = data.keys()
    pairs = []
    for i in range(n):
        for j in range(i+1, n):
            S1 = data[keys[i]]
            S2 = data[keys[j]]
            result = coint(S1, S2)
            score = result[0]
            pvalue = result[1]
            score_matrix[i, j] = score
            pvalue_matrix[i, j] = pvalue
            if pvalue < 0.02:
                pairs.append((keys[i], keys[j]))
    return score_matrix, pvalue_matrix, pairs

Catatan: Kami memasukkan benchmark pasar (SPX) dalam data - pasar mendorong pergerakan banyak indikator perdagangan, biasanya Anda mungkin menemukan dua indikator perdagangan yang tampaknya berkolaborasi; tetapi sebenarnya mereka tidak berkolaborasi satu sama lain, tetapi berkolaborasi dengan pasar. Ini disebut variabel campuran.

from backtester.dataSource.yahoo_data_source import YahooStockDataSource
from datetime import datetime
startDateStr = '2007/12/01'
endDateStr = '2017/12/01'
cachedFolderName = 'yahooData/'
dataSetId = 'testPairsTrading'
instrumentIds = ['SPY','AAPL','ADBE','SYMC','EBAY','MSFT','QCOM',
                 'HPQ','JNPR','AMD','IBM']
ds = YahooStockDataSource(cachedFolderName=cachedFolderName,
                            dataSetId=dataSetId,
                            instrumentIds=instrumentIds,
                            startDateStr=startDateStr,
                            endDateStr=endDateStr,
                            event='history')
data = ds.getBookDataByFeature()['Adj Close']
data.head(3)

img

Sekarang mari kita coba menggunakan metode kami untuk menemukan pencocokan transaksi yang ko-integratif.

# Heatmap to show the p-values of the cointegration test
# between each pair of stocks
scores, pvalues, pairs = find_cointegrated_pairs(data)
import seaborn
m = [0,0.2,0.4,0.6,0.8,1]
seaborn.heatmap(pvalues, xticklabels=instrumentIds, 
                yticklabels=instrumentIds, cmap=’RdYlGn_r’, 
                mask = (pvalues >= 0.98))
plt.show()
print pairs
[('ADBE', 'MSFT')]

img

Tampaknya aluminium ADBE dan aluminium MSFT bekerja sama. Mari kita lihat harga untuk memastikan itu benar-benar masuk akal.

S1 = data['ADBE']
S2 = data['MSFT']
score, pvalue, _ = coint(S1, S2)
print(pvalue)
ratios = S1 / S2
ratios.plot()
plt.axhline(ratios.mean())
plt.legend([' Ratio'])
plt.show()

img

Gambar rasio harga antara MSFT dan ADBE 2008 - 2017

Rasio ini memang terlihat seperti rata-rata yang stabil. Rasio absolut tidak berguna secara statistik. Sinyal kita lebih membantu dengan menstandarisasinya sebagai skor z. Z skor didefinisikan sebagai:

Z Score (Value) = (Value Mean) / Standar Deviasi

Peringatan

Pada kenyataannya, kita biasanya akan mencoba untuk melakukan beberapa ekstensi pada data, tetapi dengan asumsi bahwa data tersebut adalah distribusi normal. Namun, banyak data keuangan yang tidak normal, jadi kita harus sangat berhati-hati untuk tidak hanya mengasumsikan normalitas atau distribusi tertentu ketika menghasilkan data statistik. Distribusi benar dari rasio dapat memiliki efek ujung tebing, dan data yang cenderung ekstrem dapat membuat model kita berantakan dan menyebabkan kerugian besar.

def zscore(series):
    return (series - series.mean()) / np.std(series)
zscore(ratios).plot()
plt.axhline(zscore(ratios).mean())
plt.axhline(1.0, color=’red’)
plt.axhline(-1.0, color=’green’)
plt.show()

img

Rasio harga Z antara MSFT dan ADBE antara 2008 - 2017

Sekarang lebih mudah untuk mengamati rasio bergerak di dekat rata-rata, tetapi kadang-kadang mudah terjadi perbedaan besar dengan rata-rata, yang dapat kita manfaatkan.

Sekarang setelah kita membahas dasar-dasar strategi perdagangan berpasangan dan menentukan indikator perdagangan yang terintegrasi bersama berdasarkan harga historis, mari kita coba mengembangkan sinyal perdagangan. Pertama, mari kita lihat kembali langkah-langkah untuk mengembangkan sinyal perdagangan menggunakan teknologi data:

  • Mengumpulkan data yang dapat diandalkan dan membersihkan data

  • Membuat fungsi dari data untuk mengenali sinyal/logika transaksi

  • Fungsi dapat berupa rata-rata bergerak atau data harga, relevansi, atau rasio sinyal yang lebih kompleks - menggabungkannya untuk menciptakan fungsi baru

  • Fungsi ini digunakan untuk menghasilkan sinyal perdagangan, yaitu sinyal yang membeli, menjual atau melihat kosong.

Untungnya, kami memiliki platform pengukuran inventor.fmz.comKami telah melakukan pekerjaan di empat aspek di atas, yang merupakan kabar baik bagi para pengembang strategi, bahwa kami dapat menghabiskan energi dan waktu untuk merancang logika strategi dan memperluas fungsionalitasnya.

Di platform inventor kuantitatif, ada berbagai antarmuka dari bursa utama yang terbungkus dengan baik, yang harus kita lakukan hanyalah memanggil antarmuka API ini, dan sisanya adalah implementasi logika di bawahnya, yang sudah memiliki tim profesional yang mengasahnya.

Untuk kelengkapan logika dan penjelasan prinsip, di sini kita akan membuat presentasi dasar dari logika ini, tetapi dalam operasi praktis, pembaca dapat melakukan empat hal ini dengan langsung memanggil antarmuka API yang diukur oleh penemu.

Mari kita mulai:

Langkah 1: Tentukan Masalah Anda

Di sini, kita mencoba untuk membuat sinyal yang memberitahu kita apakah rasio akan membeli atau menjual pada saat berikutnya, yaitu variabel Y yang kita prediksi:

Y = Rasio adalah beli (1) atau jual (-1)

Y ((t) = Sign ((Ratio ((t+1) Ratio ((t))

Perhatikan bahwa kita tidak perlu memprediksi harga indikator perdagangan yang sebenarnya, bahkan tidak perlu memprediksi nilai sebenarnya dari rasio (meskipun kita bisa), kita hanya perlu memprediksi arah rasio selanjutnya

Langkah 2: Kumpulkan data yang dapat diandalkan dan akurat

Penemu kuantifikasi adalah teman Anda! Anda hanya perlu menentukan tanda yang akan diperdagangkan dan sumber data yang akan digunakan, dan itu akan mengekstrak data yang Anda inginkan dan membersihkannya untuk melakukan pembagian dividen dan tanda. Jadi data kami di sini bersih.

Kami menggunakan data yang kami dapatkan dari Yahoo Finance untuk 10 hari perdagangan terakhir (sekitar 2500 titik data): harga buka, harga tutup, harga tertinggi, harga terendah, dan volume perdagangan.

Langkah 3: Pembagian data

Jangan lupa langkah yang sangat penting ini untuk menguji akurasi model. Kami sedang menggunakan pembagian pelatihan / validasi / pengujian data berikut:

  • Pelatihan 7 tahun ~ 70%

  • Tes ~ 3 tahun 30%

ratios = data['ADBE'] / data['MSFT']
print(len(ratios))
train = ratios[:1762]
test = ratios[1762:]

Idealnya, kita juga harus membuat verifikasi, tetapi kita tidak akan melakukannya untuk sementara waktu.

Langkah 4: Desain Fitur

Apa fungsi yang terkait? Kita ingin memprediksi arah perubahan rasio. Kita telah melihat bahwa dua indikator perdagangan kita ko-integratif, jadi rasio ini sering kali bergeser dan kembali ke rata-rata. Tampaknya karakteristik kita harus menjadi beberapa metrik rata-rata rasio, dan perbedaan antara nilai saat ini dan rata-rata dapat menghasilkan sinyal perdagangan kita.

Kami menggunakan fitur berikut:

  • Rata-rata bergerak 60 hari: pengukuran rata-rata bergerak

  • Rasio rata-rata bergerak 5 hari: pengukuran nilai rata-rata saat ini

  • 60 hari standar

  • Z skor: ((5d MA - 60d MA) / 60d SD

ratios_mavg5 = train.rolling(window=5,
                               center=False).mean()
ratios_mavg60 = train.rolling(window=60,
                               center=False).mean()
std_60 = train.rolling(window=60,
                        center=False).std()
zscore_60_5 = (ratios_mavg5 - ratios_mavg60)/std_60
plt.figure(figsize=(15,7))
plt.plot(train.index, train.values)
plt.plot(ratios_mavg5.index, ratios_mavg5.values)
plt.plot(ratios_mavg60.index, ratios_mavg60.values)
plt.legend(['Ratio','5d Ratio MA', '60d Ratio MA'])
plt.ylabel('Ratio')
plt.show()

img

Rasio harga 60d dan 5d MA

plt.figure(figsize=(15,7))
zscore_60_5.plot()
plt.axhline(0, color='black')
plt.axhline(1.0, color='red', linestyle='--')
plt.axhline(-1.0, color='green', linestyle='--')
plt.legend(['Rolling Ratio z-Score', 'Mean', '+1', '-1'])
plt.show()

img

60-5 Z skor rasio harga

Z-scoring pada rata-rata bergulir benar-benar menunjukkan sifat regression rata-rata dari rasio!

Langkah 5: Memilih model

Mari kita mulai dengan model yang sangat sederhana. Lihatlah grafik z-score, dan kita bisa melihat bahwa jika z-score terlalu tinggi atau terlalu rendah, itu akan kembali. Mari kita gunakan +1/-1 sebagai ambang batas kita untuk mendefinisikan terlalu tinggi dan terlalu rendah, dan kemudian kita dapat menggunakan model berikut untuk menghasilkan sinyal perdagangan:

  • Jika z kurang dari -1, maka rasio adalah buy (-1), karena kita mengharapkan z kembali ke 0, maka rasio meningkat.

  • Jika z lebih besar dari 1.0, rasio adalah jual (-), karena kita mengharapkan z kembali ke 0, maka rasio berkurang.

Langkah 6: Pelatihan, Verifikasi, dan Optimasi

Dan akhirnya, mari kita lihat dampak model kita pada data yang sebenarnya.

# Plot the ratios and buy and sell signals from z score
plt.figure(figsize=(15,7))
train[60:].plot()
buy = train.copy()
sell = train.copy()
buy[zscore_60_5>-1] = 0
sell[zscore_60_5<1] = 0
buy[60:].plot(color=’g’, linestyle=’None’, marker=’^’)
sell[60:].plot(color=’r’, linestyle=’None’, marker=’^’)
x1,x2,y1,y2 = plt.axis()
plt.axis((x1,x2,ratios.min(),ratios.max()))
plt.legend([‘Ratio’, ‘Buy Signal’, ‘Sell Signal’])
plt.show()

img

Sinyal rasio harga beli dan jual

Sinyal ini tampaknya masuk akal, kita tampaknya menjual rasio ketika itu tinggi atau meningkat (titik merah) dan membeli kembali ketika itu rendah (titik hijau) dan berkurang.

# Plot the prices and buy and sell signals from z score
plt.figure(figsize=(18,9))
S1 = data['ADBE'].iloc[:1762]
S2 = data['MSFT'].iloc[:1762]
S1[60:].plot(color='b')
S2[60:].plot(color='c')
buyR = 0*S1.copy()
sellR = 0*S1.copy()
# When buying the ratio, buy S1 and sell S2
buyR[buy!=0] = S1[buy!=0]
sellR[buy!=0] = S2[buy!=0]
# When selling the ratio, sell S1 and buy S2 
buyR[sell!=0] = S2[sell!=0]
sellR[sell!=0] = S1[sell!=0]
buyR[60:].plot(color='g', linestyle='None', marker='^')
sellR[60:].plot(color='r', linestyle='None', marker='^')
x1,x2,y1,y2 = plt.axis()
plt.axis((x1,x2,min(S1.min(),S2.min()),max(S1.max(),S2.max())))
plt.legend(['ADBE','MSFT', 'Buy Signal', 'Sell Signal'])
plt.show()

img

Sinyal untuk membeli dan menjual saham MSFT dan ADBE

Perhatikan bagaimana kita kadang-kadang menghasilkan uang dengan "kaki pendek", kadang-kadang menghasilkan uang dengan "kaki panjang", dan kadang-kadang keduanya.

Kami senang dengan sinyal data pelatihan. Mari kita lihat apa keuntungan yang dapat dihasilkan dari sinyal ini. Ketika rasio rendah, kita dapat membuat backmeter sederhana, membeli 1 rasio (membeli 1 saham ADBE dan menjual rasio x saham MSFT), menjual 1 rasio saat itu tinggi (menjual 1 saham ADBE dan membeli rasio x saham MSFT) dan menghitung transaksi PnL dari rasio ini.

# Trade using a simple strategy
def trade(S1, S2, window1, window2):
    
    # If window length is 0, algorithm doesn't make sense, so exit
    if (window1 == 0) or (window2 == 0):
        return 0
    
    # Compute rolling mean and rolling standard deviation
    ratios = S1/S2
    ma1 = ratios.rolling(window=window1,
                               center=False).mean()
    ma2 = ratios.rolling(window=window2,
                               center=False).mean()
    std = ratios.rolling(window=window2,
                        center=False).std()
    zscore = (ma1 - ma2)/std
    
    # Simulate trading
    # Start with no money and no positions
    money = 0
    countS1 = 0
    countS2 = 0
    for i in range(len(ratios)):
        # Sell short if the z-score is > 1
        if zscore[i] > 1:
            money += S1[i] - S2[i] * ratios[i]
            countS1 -= 1
            countS2 += ratios[i]
            print('Selling Ratio %s %s %s %s'%(money, ratios[i], countS1,countS2))
        # Buy long if the z-score is < 1
        elif zscore[i] < -1:
            money -= S1[i] - S2[i] * ratios[i]
            countS1 += 1
            countS2 -= ratios[i]
            print('Buying Ratio %s %s %s %s'%(money,ratios[i], countS1,countS2))
        # Clear positions if the z-score between -.5 and .5
        elif abs(zscore[i]) < 0.75:
            money += S1[i] * countS1 + S2[i] * countS2
            countS1 = 0
            countS2 = 0
            print('Exit pos %s %s %s %s'%(money,ratios[i], countS1,countS2))
            
            
    return money
trade(data['ADBE'].iloc[:1763], data['MSFT'].iloc[:1763], 60, 5)

Hasilnya adalah: 1783.375

Jadi strategi ini tampaknya menguntungkan! Sekarang, kita dapat mengoptimalkannya lebih lanjut dengan mengubah jendela waktu rata-rata bergerak, dengan mengubah ambang batas posisi jual beli dan lain-lain, dan memeriksa peningkatan kinerja data verifikasi.

Kita juga dapat mencoba model yang lebih kompleks, seperti logistic regression, SVM, dll, untuk melakukan prediksi 1/-1.

Sekarang, mari kita lanjutkan dengan model ini, yang membawa kita ke

Langkah 7: Uji ulang data tes

Di sini juga disebutkan platform kuantifikasi inventor, yang menggunakan mesin backtesting QPS/TPS yang berkinerja tinggi, reproduksi nyata dari lingkungan sejarah, menghilangkan perangkap backtesting kuantifikasi yang umum, dan menemukan kekurangan strategi pada waktu yang tepat, sehingga lebih membantu investasi real-time.

Artikel ini menjelaskan prinsipnya, atau memilih untuk menunjukkan logika yang mendasari, dalam aplikasi praktis, atau merekomendasikan kepada pembaca untuk menggunakan platform kuantifikasi penemu, selain menghemat waktu, penting untuk meningkatkan tingkat kesalahan.

PnL dari hasil tes ini sangat sederhana, kita bisa menggunakan fungsi di atas untuk melihat PnL dari hasil tes.

trade(data[‘ADBE’].iloc[1762:], data[‘MSFT’].iloc[1762:], 60, 5)

Hasilnya adalah: 5262.868

Model ini bekerja dengan baik! Ini menjadi model pertama kami yang sederhana untuk berpasangan.

Hindari ketergantungan yang berlebihan

Sebelum mengakhiri diskusi, saya ingin membahas secara khusus tentang overfiting. Overfiting adalah perangkap paling berbahaya dalam strategi trading. Overfiting algoritma mungkin sangat baik dalam retrospeksi tetapi gagal pada data baru yang tidak terlihat - yang berarti tidak benar-benar mengungkapkan tren data dan tidak memiliki kemampuan prediktif yang benar.

Dalam model kami, kami menggunakan perkiraan parameter gulung dan berharap untuk mengoptimalkan panjang jendela waktu. Kami mungkin memutuskan untuk hanya mengulang semua kemungkinan, panjang jendela waktu yang masuk akal, dan memilih panjang waktu sesuai dengan kinerja terbaik model kami. Di bawah ini kami menulis loop sederhana untuk menilai panjang jendela waktu pNL berdasarkan data pelatihan dan menemukan loop yang optimal.

# Find the window length 0-254 
# that gives the highest returns using this strategy
length_scores = [trade(data['ADBE'].iloc[:1762], 
                data['MSFT'].iloc[:1762], l, 5) 
                for l in range(255)]
best_length = np.argmax(length_scores)
print ('Best window length:', best_length)
('Best window length:', 40)

Sekarang kita memeriksa kinerja model pada data pengujian, dan kita menemukan bahwa panjang jendela waktu ini jauh tidak optimal!

# Find the returns for test data
# using what we think is the best window length
length_scores2 = [trade(data['ADBE'].iloc[1762:], 
                  data['MSFT'].iloc[1762:],l,5) 
                  for l in range(255)]
print (best_length, 'day window:', length_scores2[best_length])
# Find the best window length based on this dataset, 
# and the returns using this window length
best_length2 = np.argmax(length_scores2)
print (best_length2, 'day window:', length_scores2[best_length2])
(40, 'day window:', 1252233.1395)
(15, 'day window:', 1449116.4522)

Jelas data sampel yang cocok untuk kita tidak selalu menghasilkan hasil yang baik di masa depan. Hanya untuk pengujian, mari kita gambar pecahan panjang yang dihitung dari dua dataset.

plt.figure(figsize=(15,7))
plt.plot(length_scores)
plt.plot(length_scores2)
plt.xlabel('Window length')
plt.ylabel('Score')
plt.legend(['Training', 'Test'])
plt.show()

img

Kita dapat melihat bahwa apa pun antara 20-50 adalah pilihan yang baik untuk jendela waktu.

Untuk menghindari overfitting, kita dapat menggunakan sifat penalaran ekonomi atau algoritma untuk memilih panjang jendela waktu. Kita juga dapat menggunakan penyaring Karman, yang tidak memerlukan kita untuk menentukan panjangnya; metode ini akan dijelaskan di artikel lain nanti.

Langkah selanjutnya

Dalam artikel ini, kami menawarkan beberapa cara sederhana untuk menunjukkan proses pengembangan strategi perdagangan. Dalam prakteknya, jika Anda ingin menggunakan statistik yang lebih kompleks, Anda dapat mempertimbangkan pilihan berikut:

  • Indeks Hurst

  • Periode paruh dari regression rata-rata yang didapat dari proses Ornstein-Uhlenbeck

  • Filter Karman


Berkaitan

Lebih banyak

bk_fundPaket ini tidak ditemukan

bk_fundDi mana saya bisa menginstal backtester.dataSource.yahoo_data_source