Inspirasi artikel ini berasal dari pengamatan saya tentang beberapa peringatan dan perangkap umum setelah mencoba menerapkan teknologi pembelajaran mesin untuk masalah transaksi selama penelitian data di platform FMZ Quant.
Jika Anda belum membaca artikel saya sebelumnya, kami sarankan Anda membaca panduan lingkungan penelitian data otomatis dan metode sistematis untuk merumuskan strategi perdagangan yang saya buat di platform FMZ Quant sebelum artikel ini.
Dua alamat artikel ini ada di sini:https://www.fmz.com/digest-topic/9862danhttps://www.fmz.com/digest-topic/9863.
Tutorial ini ditujukan untuk penggemar, insinyur dan ilmuwan data di semua tingkat keterampilan. Apakah Anda seorang pemimpin industri atau pemula pemrograman, satu-satunya keterampilan yang Anda butuhkan adalah pemahaman dasar bahasa pemrograman Python dan pengetahuan yang cukup tentang operasi baris perintah (mampu mengatur proyek ilmu data sudah cukup).
Platform FMZ QuantFMZ.COMTidak hanya menyediakan sumber data berkualitas tinggi untuk bursa utama, tetapi juga menyediakan seperangkat antarmuka API yang kaya untuk membantu kami melakukan transaksi otomatis setelah menyelesaikan analisis data. Set antarmuka ini mencakup alat praktis, seperti menanyakan informasi akun, menanyakan harga yang tinggi, terbuka, rendah, penerimaan, volume perdagangan, dan berbagai indikator analisis teknis yang umum digunakan dari berbagai bursa utama.
Semua fitur yang disebutkan di atas dikemas dalam sistem seperti Docker. Apa yang perlu kita lakukan adalah membeli atau menyewa layanan komputasi awan kita sendiri dan menyebarkan sistem Docker.
Dalam nama resmi platform FMZ Quant, sistem Docker disebut sistem Docker.
Silakan lihat artikel saya sebelumnya tentang cara mengimplementasikan docker dan robot:https://www.fmz.com/bbs-topic/9864.
Pembaca yang ingin membeli server komputasi awan mereka sendiri untuk menyebarkan dockers dapat merujuk pada artikel ini:https://www.fmz.com/digest-topic/5711.
Setelah menyebarkan server komputasi awan dan sistem docker dengan sukses, selanjutnya kita akan menginstal artefak terbesar saat ini Python: Anaconda
Untuk mewujudkan semua lingkungan program yang relevan (perpustakaan ketergantungan, manajemen versi, dll.) yang diperlukan dalam artikel ini, cara termudah adalah menggunakan Anaconda.
Karena kami menginstal Anaconda pada layanan cloud, kami merekomendasikan bahwa server cloud menginstal sistem Linux ditambah versi baris perintah Anaconda.
Untuk metode instalasi Anaconda, silakan lihat panduan resmi Anaconda:https://www.anaconda.com/distribution/.
Jika Anda seorang programmer Python yang berpengalaman dan jika Anda merasa bahwa Anda tidak perlu menggunakan Anaconda, itu tidak masalah sama sekali. Saya akan berasumsi bahwa Anda tidak memerlukan bantuan saat menginstal lingkungan dependen yang diperlukan. Anda dapat melewatkan bagian ini langsung.
Hasil akhir dari strategi perdagangan harus menjawab pertanyaan berikut:
Arah: Tentukan apakah aset itu murah, mahal atau nilai wajar.
Kondisi posisi pembukaan: Jika asetnya murah atau mahal, Anda harus pergi panjang atau pergi pendek.
Penutupan perdagangan posisi: jika aset memiliki harga yang wajar dan kita memiliki posisi dalam aset (beli atau jual sebelumnya), apakah Anda harus menutup posisi?
Rentang harga: harga (atau rentang) di mana posisi dibuka.
Jumlah: jumlah uang yang diperdagangkan (misalnya, jumlah mata uang digital atau jumlah lot berjangka komoditas).
Pembelajaran mesin dapat digunakan untuk menjawab setiap pertanyaan ini, tetapi untuk sisa artikel ini, kita akan fokus pada pertanyaan pertama, yang merupakan arah perdagangan.
Ada dua jenis pendekatan untuk membangun strategi: satu berbasis model; yang lainnya didasarkan pada penambangan data.
Dalam konstruksi strategi berbasis model, kita memulai dari model inefisiensi pasar, membangun ekspresi matematika (seperti harga dan keuntungan) dan menguji efektivitasnya dalam jangka waktu yang lama. Model ini biasanya merupakan versi disederhanakan dari model yang kompleks nyata, dan signifikansi jangka panjang dan stabilitasnya perlu diverifikasi.
Di sisi lain, kita mencari pola harga terlebih dahulu dan mencoba menggunakan algoritma dalam metode penambangan data. Alasan untuk pola ini tidak penting, karena hanya pola yang diidentifikasi yang akan terus terulang di masa depan. Ini adalah metode analisis buta, dan kita perlu memeriksa secara ketat untuk mengidentifikasi pola nyata dari pola acak.
Jelas, pembelajaran mesin sangat mudah diterapkan pada metode data mining. mari kita lihat bagaimana menggunakan pembelajaran mesin untuk membuat sinyal transaksi melalui data mining.
Contoh kode menggunakan alat backtesting berdasarkan platform FMZ Quant dan antarmuka API transaksi otomatis. Setelah menyebarkan docker dan menginstal Anaconda di bagian di atas, Anda hanya perlu menginstal perpustakaan analisis ilmu data yang kita butuhkan dan model pembelajaran mesin terkenal scikit-learn. Kami tidak akan membahas bagian ini lagi.
pip install -U scikit-learn
- Data mining Sebelum kita mulai, sistem masalah pembelajaran mesin standar ditunjukkan pada gambar berikut:
Sistem masalah pembelajaran mesin
Fitur yang akan kita buat harus memiliki kemampuan prediksi (X). Kita ingin memprediksi variabel target (Y) dan menggunakan data historis untuk melatih model ML yang dapat memprediksi Y sedekat mungkin dengan nilai aktual. Akhirnya, kita menggunakan model ini untuk membuat prediksi pada data baru di mana Y tidak diketahui. Ini membawa kita ke langkah pertama:
Artinya, dalam kerangka kerja di atas, apa Y?
Apa yang ingin kau prediksi?
Apakah Anda ingin memprediksi harga masa depan, pengembalian masa depan / Pnl, sinyal beli / jual, mengoptimalkan alokasi portofolio dan mencoba untuk melaksanakan transaksi secara efisien?
Misalkan kita mencoba memprediksi harga pada timestamp berikutnya. dalam hal ini, Y (t) = harga (t + 1). sekarang kita dapat menggunakan data historis untuk melengkapi kerangka kerja kita.
Perhatikan bahwa Y (t) hanya diketahui dalam backtest, tetapi ketika kita menggunakan model kita, kita tidak akan tahu harga (t + 1) dari waktu t. Kita menggunakan model kita untuk memprediksi Y (diprediksi, t) dan membandingkannya dengan nilai aktual hanya pada waktu t + 1. Ini berarti bahwa Anda tidak dapat menggunakan Y sebagai fitur dalam model prediksi.
Setelah kita mengetahui target Y, kita juga dapat memutuskan bagaimana mengevaluasi prediksi kita. Ini penting untuk membedakan antara model data yang berbeda yang akan kita coba. Pilih indikator untuk mengukur efisiensi model kita sesuai dengan masalah yang kita selesaikan. Misalnya, jika kita memprediksi harga, kita dapat menggunakan root mean square error sebagai indikator. Beberapa indikator yang umum digunakan (EMA, MACD, skor varians, dll.) telah di-pre-coded di kotak alat FMZ Quant. Anda dapat memanggil indikator ini secara global melalui antarmuka API.
Kerangka kerja ML untuk memprediksi harga masa depan
Untuk tujuan demonstrasi, kami akan membuat model prediksi untuk memprediksi nilai acuan (basis) masa depan yang diharapkan dari objek investasi hipotetis, di mana:
basis = Price of Stock — Price of Future
basis(t)=S(t)−F(t)
Y(t) = future expected value of basis = Average(basis(t+1),basis(t+2),basis(t+3),basis(t+4),basis(t+5))
Karena ini adalah masalah regresi, kita akan mengevaluasi model pada RMSE (kasalahan akar rata-rata kuadrat).
Catatan: Silakan lihat Baidu Encyclopedia untuk pengetahuan matematika yang relevan tentang RMSE.
Kumpulkan dan jelaskan data yang dapat membantu Anda menyelesaikan masalah yang ada.
Data apa yang perlu Anda pertimbangkan yang dapat memprediksi variabel target Y? Jika kita memprediksi harga, Anda dapat menggunakan data harga objek investasi, data kuantitas perdagangan objek investasi, data serupa dari objek investasi terkait, tingkat indeks objek investasi dan indikator pasar keseluruhan lainnya, dan harga aset terkait lainnya.
Anda perlu mengatur izin akses data untuk data ini dan memastikan bahwa data Anda akurat, dan menyelesaikan data yang hilang (masalah yang sangat umum). Pada saat yang sama, pastikan bahwa data Anda tidak memihak dan sepenuhnya mewakili semua kondisi pasar (misalnya, jumlah skenario keuntungan dan kerugian yang sama) untuk menghindari bias dalam model. Anda juga mungkin perlu membersihkan data untuk mendapatkan dividen, tujuan investasi terbagi, kelanjutan, dll.
Jika Anda menggunakan platform FMZ Quant (FMZ. COM), kita dapat mengakses data global gratis dari Google, Yahoo, NSE dan Quandl; Data kedalaman komoditas domestik berjangka seperti CTP dan Esunny; Data dari bursa mata uang digital utama seperti Binance, OKX, Huobi dan BitMex. Platform FMZ Quant juga membersihkan dan menyaring data ini, seperti pembagian target investasi dan data pasar mendalam, dan menyajikannya kepada pengembang strategi dalam format yang mudah dipahami oleh praktisi kuantitatif.
Untuk memudahkan demonstrasi artikel ini, kami menggunakan data berikut sebagai
# Load the data
from backtester.dataSource.quant_quest_data_source import QuantQuestDataSource
cachedFolderName = '/Users/chandinijain/Auquan/qq2solver-data/historicalData/'
dataSetId = 'trainingData1'
instrumentIds = ['MQK']
ds = QuantQuestDataSource(cachedFolderName=cachedFolderName,
dataSetId=dataSetId,
instrumentIds=instrumentIds)
def loadData(ds):
data = None
for key in ds.getBookDataByFeature().keys():
if data is None:
data = pd.DataFrame(np.nan, index = ds.getBookDataByFeature()[key].index, columns=[])
data[key] = ds.getBookDataByFeature()[key]
data['Stock Price'] = ds.getBookDataByFeature()['stockTopBidPrice'] + ds.getBookDataByFeature()['stockTopAskPrice'] / 2.0
data['Future Price'] = ds.getBookDataByFeature()['futureTopBidPrice'] + ds.getBookDataByFeature()['futureTopAskPrice'] / 2.0
data['Y(Target)'] = ds.getBookDataByFeature()['basis'].shift(-5)
del data['benchmark_score']
del data['FairValue']
return data
data = loadData(ds)
Dengan kode di atas, Auquan
Ini adalah langkah yang sangat penting!Sebelum kita melanjutkan, kita harus membagi data menjadi training data set untuk melatih model Anda; test data set untuk mengevaluasi kinerja model.
Pembagian data ke dalam training set dan test set
Karena data pelatihan digunakan untuk mengevaluasi parameter model, model Anda mungkin terlalu sesuai dengan data pelatihan ini, dan data pelatihan dapat menyesatkan kinerja model. Jika Anda tidak menyimpan data uji individu dan menggunakan semua data untuk pelatihan, Anda tidak akan tahu seberapa baik atau buruk kinerja model Anda pada data tak terlihat baru. Ini adalah salah satu alasan utama kegagalan model ML terlatih dalam data real-time: orang melatih semua data yang tersedia dan bersemangat dengan indikator data pelatihan, tetapi model tidak dapat membuat prediksi yang berarti pada data real-time yang tidak terlatih.
Pembagian data menjadi training set, verification set dan test set
Ada masalah dengan metode ini. Jika kita melatih data pelatihan berulang kali, mengevaluasi kinerja data pengujian dan mengoptimalkan model kita sampai kita puas dengan kinerja, kita mengambil data pengujian sebagai bagian dari data pelatihan secara implisit. Pada akhirnya, model kita mungkin berkinerja baik pada kumpulan data pelatihan dan pengujian ini, tetapi tidak dapat menjamin bahwa ia dapat memprediksi data baru dengan baik.
Untuk memecahkan masalah ini, kita dapat membuat dataset validasi terpisah. Sekarang, Anda dapat melatih data, mengevaluasi kinerja data validasi, mengoptimalkan sampai Anda puas dengan kinerja, dan akhirnya menguji data tes. Dengan cara ini, data tes tidak akan tercemar, dan kita tidak akan menggunakan informasi dalam data tes untuk meningkatkan model kita.
Ingat, setelah Anda memeriksa kinerja data tes Anda, jangan kembali dan mencoba untuk mengoptimalkan model Anda lebih lanjut. Jika Anda menemukan bahwa model Anda tidak memberikan hasil yang baik, membuang model sepenuhnya dan mulai lagi. Disarankan bahwa 60% data pelatihan, 20% data validasi dan 20% data tes dapat dibagi.
Untuk pertanyaan kami, kami memiliki tiga set data yang tersedia. kami akan menggunakan satu sebagai set pelatihan, yang kedua sebagai set verifikasi, dan yang ketiga sebagai set tes kami.
# Training Data
dataSetId = 'trainingData1'
ds_training = QuantQuestDataSource(cachedFolderName=cachedFolderName,
dataSetId=dataSetId,
instrumentIds=instrumentIds)
training_data = loadData(ds_training)
# Validation Data
dataSetId = 'trainingData2'
ds_validation = QuantQuestDataSource(cachedFolderName=cachedFolderName,
dataSetId=dataSetId,
instrumentIds=instrumentIds)
validation_data = loadData(ds_validation)
# Test Data
dataSetId = 'trainingData3'
ds_test = QuantQuestDataSource(cachedFolderName=cachedFolderName,
dataSetId=dataSetId,
instrumentIds=instrumentIds)
out_of_sample_test_data = loadData(ds_test)
Untuk masing-masing dari ini, kita menambahkan variabel target Y, yang didefinisikan sebagai rata-rata dari lima nilai dasar berikutnya.
def prepareData(data, period):
data['Y(Target)'] = data['basis'].rolling(period).mean().shift(-period)
if 'FairValue' in data.columns:
del data['FairValue']
data.dropna(inplace=True)
period = 5
prepareData(training_data, period)
prepareData(validation_data, period)
prepareData(out_of_sample_test_data, period)
Menganalisis perilaku data dan membuat fitur prediktif
Sekarang konstruksi proyek yang sebenarnya telah dimulai. Aturan emas pemilihan fitur adalah kemampuan prediksi terutama berasal dari fitur, bukan dari model. Anda akan menemukan bahwa pemilihan fitur memiliki dampak yang jauh lebih besar pada kinerja daripada pemilihan model. Beberapa pertimbangan untuk pemilihan fitur:
Jangan memilih sejumlah besar fitur secara acak tanpa mengeksplorasi hubungan dengan variabel target.
Sedikit atau tidak ada hubungan dengan variabel target dapat menyebabkan overfit.
Fitur yang Anda pilih mungkin sangat terkait satu sama lain, dalam hal ini sejumlah kecil fitur juga dapat menjelaskan target.
Saya biasanya membuat beberapa fitur intuitif, memeriksa korelasi antara variabel target dan fitur-fitur ini, dan korelasi antara mereka untuk memutuskan yang mana yang akan digunakan.
Anda juga dapat mencoba melakukan analisis komponen utama (PCA) dan metode lain untuk menyortir fitur kandidat sesuai dengan koefisien informasi maksimum (MIC).
Model ML cenderung berkinerja baik dalam hal normalisasi. Namun, normalisasi sulit ketika berurusan dengan data deret waktu, karena rentang data masa depan tidak diketahui. Data Anda mungkin berada di luar rentang normalisasi, yang menyebabkan kesalahan model. Tetapi Anda masih dapat mencoba memaksa beberapa tingkat stabilitas:
Scaling: membagi fitur dengan standar deviasi atau kisaran kuartil.
Centering: mengurangi nilai rata-rata historis dari nilai saat ini.
Normalisasi: dua periode retrospektif dari di atas (x - rata-rata) / stdev.
Normalisasi reguler: standarkan data ke dalam kisaran - 1 sampai +1 dan tentukan kembali pusat dalam periode backtracking (x-min) / ((max min).
Perhatikan bahwa karena kita menggunakan nilai rata-rata berturut-turut historis, standar deviasi, nilai maksimum atau minimum di luar periode backtracking, nilai normalisasi standar dari fitur akan mewakili nilai aktual yang berbeda pada waktu yang berbeda. Misalnya, jika nilai saat ini dari fitur adalah 5 dan nilai rata-rata untuk 30 periode berturut-turut adalah 4,5, itu akan dikonversi menjadi 0,5 setelah berpusat. Setelah itu, jika nilai rata-rata 30 periode berturut-turut menjadi 3, nilai 3,5 akan menjadi 0,5. Ini mungkin penyebab model yang salah. Oleh karena itu, normalisasi rumit, dan Anda harus mencari tahu apa yang meningkatkan kinerja model (jika benar-benar ada).
Untuk iterasi pertama dalam masalah kami, kami membuat sejumlah besar fitur dengan menggunakan parameter campuran.
def difference(dataDf, period):
return dataDf.sub(dataDf.shift(period), fill_value=0)
def ewm(dataDf, halflife):
return dataDf.ewm(halflife=halflife, ignore_na=False,
min_periods=0, adjust=True).mean()
def rsi(data, period):
data_upside = data.sub(data.shift(1), fill_value=0)
data_downside = data_upside.copy()
data_downside[data_upside > 0] = 0
data_upside[data_upside < 0] = 0
avg_upside = data_upside.rolling(period).mean()
avg_downside = - data_downside.rolling(period).mean()
rsi = 100 - (100 * avg_downside / (avg_downside + avg_upside))
rsi[avg_downside == 0] = 100
rsi[(avg_downside == 0) & (avg_upside == 0)] = 0
return rsi
def create_features(data):
basis_X = pd.DataFrame(index = data.index, columns = [])
basis_X['mom3'] = difference(data['basis'],4)
basis_X['mom5'] = difference(data['basis'],6)
basis_X['mom10'] = difference(data['basis'],11)
basis_X['rsi15'] = rsi(data['basis'],15)
basis_X['rsi10'] = rsi(data['basis'],10)
basis_X['emabasis3'] = ewm(data['basis'],3)
basis_X['emabasis5'] = ewm(data['basis'],5)
basis_X['emabasis7'] = ewm(data['basis'],7)
basis_X['emabasis10'] = ewm(data['basis'],10)
basis_X['basis'] = data['basis']
basis_X['vwapbasis'] = data['stockVWAP']-data['futureVWAP']
basis_X['swidth'] = data['stockTopAskPrice'] -
data['stockTopBidPrice']
basis_X['fwidth'] = data['futureTopAskPrice'] -
data['futureTopBidPrice']
basis_X['btopask'] = data['stockTopAskPrice'] -
data['futureTopAskPrice']
basis_X['btopbid'] = data['stockTopBidPrice'] -
data['futureTopBidPrice']
basis_X['totalaskvol'] = data['stockTotalAskVol'] -
data['futureTotalAskVol']
basis_X['totalbidvol'] = data['stockTotalBidVol'] -
data['futureTotalBidVol']
basis_X['emabasisdi7'] = basis_X['emabasis7'] -
basis_X['emabasis5'] +
basis_X['emabasis3']
basis_X = basis_X.fillna(0)
basis_y = data['Y(Target)']
basis_y.dropna(inplace=True)
print("Any null data in y: %s, X: %s"
%(basis_y.isnull().values.any(),
basis_X.isnull().values.any()))
print("Length y: %s, X: %s"
%(len(basis_y.index), len(basis_X.index)))
return basis_X, basis_y
basis_X_train, basis_y_train = create_features(training_data)
basis_X_test, basis_y_test = create_features(validation_data)
Pilih model statistik/ML yang tepat sesuai dengan pertanyaan yang dipilih
Pemilihan model tergantung pada bagaimana masalah terbentuk. Apakah Anda memecahkan diawasi (setiap titik X dalam matriks fitur dipetakan ke variabel target Y) atau pembelajaran tanpa pengawasan (tanpa pemetaan tertentu, model mencoba mempelajari pola yang tidak diketahui)?
Pembelajaran yang diawasi atau tidak diawasi
Regresi atau klasifikasi
Beberapa algoritma pembelajaran yang diawasi dapat membantu Anda memulai:
Regresi linier (parameter, regresi)
Regresi logistik (parameter, klasifikasi)
Algoritma K-Nearest Neighbor (KNN) (berbasis kasus, regresi)
SVM, SVR (parameter, klasifikasi dan regresi)
Pohon keputusan
Hutan keputusan
Saya sarankan mulai dengan model sederhana, seperti regresi linier atau logistik, dan membangun model yang lebih kompleks dari sana sesuai kebutuhan.
Gunakan pelatihan dan verifikasi data set untuk melatih dan mengoptimalkan model Anda
Sekarang Anda siap untuk akhirnya membangun model. Pada tahap ini, Anda benar-benar hanya mengulangi model dan parameter model. Latih model Anda pada data pelatihan, mengukur kinerjanya pada data verifikasi, dan kemudian kembali, mengoptimalkan, melatih kembali dan mengevaluasinya. Jika Anda tidak puas dengan kinerja model, silakan coba model lain. Anda berputar melalui fase ini berkali-kali sampai akhirnya Anda memiliki model yang Anda puas.
Hanya ketika Anda memiliki model favorit Anda, kemudian beralih ke langkah berikutnya.
Untuk masalah demonstrasi kita, mari kita mulai dengan regresi linier sederhana:
from sklearn import linear_model
from sklearn.metrics import mean_squared_error, r2_score
def linear_regression(basis_X_train, basis_y_train,
basis_X_test,basis_y_test):
regr = linear_model.LinearRegression()
# Train the model using the training sets
regr.fit(basis_X_train, basis_y_train)
# Make predictions using the testing set
basis_y_pred = regr.predict(basis_X_test)
# The coefficients
print('Coefficients: \n', regr.coef_)
# The mean squared error
print("Mean squared error: %.2f"
% mean_squared_error(basis_y_test, basis_y_pred))
# Explained variance score: 1 is perfect prediction
print('Variance score: %.2f' % r2_score(basis_y_test,
basis_y_pred))
# Plot outputs
plt.scatter(basis_y_pred, basis_y_test, color='black')
plt.plot(basis_y_test, basis_y_test, color='blue', linewidth=3)
plt.xlabel('Y(actual)')
plt.ylabel('Y(Predicted)')
plt.show()
return regr, basis_y_pred
_, basis_y_pred = linear_regression(basis_X_train, basis_y_train,
basis_X_test,basis_y_test)
Regresi linier tanpa normalisasi
('Coefficients: \n', array([ -1.0929e+08, 4.1621e+07, 1.4755e+07, 5.6988e+06, -5.656e+01, -6.18e-04, -8.2541e-05,4.3606e-02, -3.0647e-02, 1.8826e+07, 8.3561e-02, 3.723e-03, -6.2637e-03, 1.8826e+07, 1.8826e+07, 6.4277e-02, 5.7254e-02, 3.3435e-03, 1.6376e-02, -7.3588e-03, -8.1531e-04, -3.9095e-02, 3.1418e-02, 3.3321e-03, -1.3262e-06, -1.3433e+07, 3.5821e+07, 2.6764e+07, -8.0394e+06, -2.2388e+06, -1.7096e+07]))
Mean squared error: 0.02
Variance score: 0.96
Lihatlah koefisien model. kita tidak bisa membandingkannya atau mengatakan yang mana yang penting, karena mereka semua termasuk dalam skala yang berbeda. mari kita coba normalisasi untuk membuat mereka sesuai dengan proporsi yang sama dan juga menerapkan beberapa kelancaran.
def normalize(basis_X, basis_y, period):
basis_X_norm = (basis_X - basis_X.rolling(period).mean())/
basis_X.rolling(period).std()
basis_X_norm.dropna(inplace=True)
basis_y_norm = (basis_y -
basis_X['basis'].rolling(period).mean())/
basis_X['basis'].rolling(period).std()
basis_y_norm = basis_y_norm[basis_X_norm.index]
return basis_X_norm, basis_y_norm
norm_period = 375
basis_X_norm_test, basis_y_norm_test = normalize(basis_X_test,basis_y_test, norm_period)
basis_X_norm_train, basis_y_norm_train = normalize(basis_X_train, basis_y_train, norm_period)
regr_norm, basis_y_pred = linear_regression(basis_X_norm_train, basis_y_norm_train, basis_X_norm_test, basis_y_norm_test)
basis_y_pred = basis_y_pred * basis_X_test['basis'].rolling(period).std()[basis_y_norm_test.index] + basis_X_test['basis'].rolling(period).mean()[basis_y_norm_test.index]
Regresi linier dengan normalisasi
Mean squared error: 0.05
Variance score: 0.90
Model ini tidak meningkatkan model sebelumnya, tapi tidak lebih buruk. sekarang kita dapat membandingkan koefisien untuk melihat yang sebenarnya penting.
Mari kita lihat koefisien:
for i in range(len(basis_X_train.columns)):
print('%.4f, %s'%(regr_norm.coef_[i], basis_X_train.columns[i]))
Hasilnya adalah:
19.8727, emabasis4
-9.2015, emabasis5
8.8981, emabasis7
-5.5692, emabasis10
-0.0036, rsi15
-0.0146, rsi10
0.0196, mom10
-0.0035, mom5
-7.9138, basis
0.0062, swidth
0.0117, fwidth
2.0883, btopask
2.0311, btopbid
0.0974, bavgask
0.0611, bavgbid
0.0007, topaskvolratio
0.0113, topbidvolratio
-0.0220, totalaskvolratio
0.0231, totalbidvolratio
Kita dapat melihat dengan jelas bahwa beberapa fitur memiliki koefisien yang lebih tinggi daripada yang lain, dan mereka mungkin memiliki kemampuan prediksi yang lebih kuat.
Mari kita lihat korelasi antara fitur yang berbeda.
import seaborn
c = basis_X_train.corr()
plt.figure(figsize=(10,10))
seaborn.heatmap(c, cmap='RdYlGn_r', mask = (np.abs(c) <= 0.8))
plt.show()
Korélasi antara fitur
Daerah merah gelap mewakili variabel yang sangat berkorelasi. Mari kita membuat / memodifikasi beberapa fitur lagi dan mencoba untuk meningkatkan model kita.
Misalnya, saya dapat membuang fitur seperti emabasisdi7 dengan mudah, yang hanya kombinasi linier dari fitur lain.
def create_features_again(data):
basis_X = pd.DataFrame(index = data.index, columns = [])
basis_X['mom10'] = difference(data['basis'],11)
basis_X['emabasis2'] = ewm(data['basis'],2)
basis_X['emabasis5'] = ewm(data['basis'],5)
basis_X['emabasis10'] = ewm(data['basis'],10)
basis_X['basis'] = data['basis']
basis_X['totalaskvolratio'] = (data['stockTotalAskVol']
- data['futureTotalAskVol'])/
100000
basis_X['totalbidvolratio'] = (data['stockTotalBidVol']
- data['futureTotalBidVol'])/
100000
basis_X = basis_X.fillna(0)
basis_y = data['Y(Target)']
basis_y.dropna(inplace=True)
return basis_X, basis_y
basis_X_test, basis_y_test = create_features_again(validation_data)
basis_X_train, basis_y_train = create_features_again(training_data)
_, basis_y_pred = linear_regression(basis_X_train, basis_y_train, basis_X_test,basis_y_test)
basis_y_regr = basis_y_pred.copy()
('Coefficients: ', array([ 0.03246139,
0.49780982, -0.22367172, 0.20275786, 0.50758852,
-0.21510795, 0.17153884]))
Mean squared error: 0.02
Variance score: 0.96
Lihat, kinerja model kami tidak berubah. kami hanya membutuhkan beberapa karakteristik untuk menjelaskan variabel target kami. saya sarankan Anda mencoba lebih banyak fitur di atas, mencoba kombinasi baru, dll, untuk melihat apa yang dapat meningkatkan model kami.
Kita juga bisa mencoba model yang lebih kompleks untuk melihat apakah perubahan pada model dapat meningkatkan kinerja.
from sklearn import neighbors
n_neighbors = 5
model = neighbors.KNeighborsRegressor(n_neighbors, weights='distance')
model.fit(basis_X_train, basis_y_train)
basis_y_pred = model.predict(basis_X_test)
basis_y_knn = basis_y_pred.copy()
from sklearn.svm import SVR
model = SVR(kernel='rbf', C=1e3, gamma=0.1)
model.fit(basis_X_train, basis_y_train)
basis_y_pred = model.predict(basis_X_test)
basis_y_svr = basis_y_pred.copy()
model=ensemble.ExtraTreesRegressor()
model.fit(basis_X_train, basis_y_train)
basis_y_pred = model.predict(basis_X_test)
basis_y_trees = basis_y_pred.copy()
Periksa kinerja data sampel yang sebenarnya
Kinerja pengujian balik pada set data uji (tidak tersentuh)
Ini adalah momen kritis. kita menjalankan model optimasi akhir kita dari langkah terakhir dari data uji coba, kita menyisihkannya di awal dan kita belum menyentuh data sejauh ini.
Ini memberi Anda harapan yang realistis tentang bagaimana model Anda akan dijalankan pada data baru dan tidak terlihat ketika Anda memulai perdagangan real-time. Oleh karena itu, perlu untuk memastikan bahwa Anda memiliki set data yang bersih yang tidak digunakan untuk melatih atau memverifikasi model.
Jika Anda tidak menyukai hasil backtest dari data tes, silakan buang model dan mulai lagi. Jangan pernah kembali atau mengoptimalkan kembali model Anda, yang akan menyebabkan over-fit! (Selain itu disarankan untuk membuat set data tes baru, karena set data ini sekarang tercemar; ketika membuang model, kita sudah tahu isi set data secara implisit).
Di sini kita masih akan menggunakan Toolbox Auquan
import backtester
from backtester.features.feature import Feature
from backtester.trading_system import TradingSystem
from backtester.sample_scripts.fair_value_params import FairValueTradingParams
class Problem1Solver():
def getTrainingDataSet(self):
return "trainingData1"
def getSymbolsToTrade(self):
return ['MQK']
def getCustomFeatures(self):
return {'my_custom_feature': MyCustomFeature}
def getFeatureConfigDicts(self):
expma5dic = {'featureKey': 'emabasis5',
'featureId': 'exponential_moving_average',
'params': {'period': 5,
'featureName': 'basis'}}
expma10dic = {'featureKey': 'emabasis10',
'featureId': 'exponential_moving_average',
'params': {'period': 10,
'featureName': 'basis'}}
expma2dic = {'featureKey': 'emabasis3',
'featureId': 'exponential_moving_average',
'params': {'period': 3,
'featureName': 'basis'}}
mom10dic = {'featureKey': 'mom10',
'featureId': 'difference',
'params': {'period': 11,
'featureName': 'basis'}}
return [expma5dic,expma2dic,expma10dic,mom10dic]
def getFairValue(self, updateNum, time, instrumentManager):
# holder for all the instrument features
lbInstF = instrumentManager.getlookbackInstrumentFeatures()
mom10 = lbInstF.getFeatureDf('mom10').iloc[-1]
emabasis2 = lbInstF.getFeatureDf('emabasis2').iloc[-1]
emabasis5 = lbInstF.getFeatureDf('emabasis5').iloc[-1]
emabasis10 = lbInstF.getFeatureDf('emabasis10').iloc[-1]
basis = lbInstF.getFeatureDf('basis').iloc[-1]
totalaskvol = lbInstF.getFeatureDf('stockTotalAskVol').iloc[-1] - lbInstF.getFeatureDf('futureTotalAskVol').iloc[-1]
totalbidvol = lbInstF.getFeatureDf('stockTotalBidVol').iloc[-1] - lbInstF.getFeatureDf('futureTotalBidVol').iloc[-1]
coeff = [ 0.03249183, 0.49675487, -0.22289464, 0.2025182, 0.5080227, -0.21557005, 0.17128488]
newdf['MQK'] = coeff[0] * mom10['MQK'] + coeff[1] * emabasis2['MQK'] +\
coeff[2] * emabasis5['MQK'] + coeff[3] * emabasis10['MQK'] +\
coeff[4] * basis['MQK'] + coeff[5] * totalaskvol['MQK']+\
coeff[6] * totalbidvol['MQK']
newdf.fillna(emabasis5,inplace=True)
return newdf
problem1Solver = Problem1Solver()
tsParams = FairValueTradingParams(problem1Solver)
tradingSystem = TradingSystem(tsParams)
tradingSystem.startTrading(onlyAnalyze=False,
shouldPlot=True,
makeInstrumentCsvs=False)
Hasil backtesting, Pnl dihitung dalam USD (Pnl tidak termasuk dalam biaya transaksi dan biaya lainnya)
Verifikasi Rolling, belajar set, Bagging dan Boosting
Selain mengumpulkan lebih banyak data, membuat fitur yang lebih baik atau mencoba lebih banyak model, ada beberapa poin lagi yang dapat Anda coba tingkatkan.
Verifikasi Rolling
Kondisi pasar jarang tetap sama. Misalkan Anda memiliki data setahun, dan Anda menggunakan data dari Januari hingga Agustus untuk pelatihan, dan menggunakan data dari September hingga Desember untuk menguji model Anda. Anda mungkin berlatih untuk serangkaian kondisi pasar yang sangat spesifik pada akhirnya. Mungkin tidak ada fluktuasi pasar di paruh pertama tahun, dan beberapa berita ekstrem menyebabkan kenaikan tajam di pasar pada bulan September. Model Anda tidak akan dapat mempelajari model ini, dan itu akan membawa Anda hasil prediksi sampah.
Mungkin lebih baik untuk mencoba verifikasi bergulir ke depan, seperti pelatihan dari Januari hingga Februari, verifikasi pada bulan Maret, pelatihan ulang dari April hingga Mei, verifikasi pada bulan Juni, dll.
Pelajaran set
Beberapa model mungkin sangat efektif dalam memprediksi skenario tertentu, sementara model mungkin sangat overfit dalam memprediksi skenario lain atau dalam keadaan tertentu. Salah satu cara untuk mengurangi kesalahan dan overfit adalah dengan menggunakan seperangkat model yang berbeda. Prediksi Anda akan menjadi rata-rata prediksi yang dibuat oleh banyak model, dan kesalahan model yang berbeda dapat diimbangi atau dikurangi. Beberapa metode set umum adalah Bagging dan Boosting.
Pengemasan
Meningkatkan
Untuk kesingkatannya, saya akan melewatkan metode ini, tetapi Anda dapat menemukan informasi lebih lanjut secara online.
Mari kita coba metode set untuk masalah kita:
basis_y_pred_ensemble = (basis_y_trees + basis_y_svr +
basis_y_knn + basis_y_regr)/4
Mean squared error: 0.02
Variance score: 0.95
Menyelesaikan masalah Anda;
Mengumpulkan data yang dapat diandalkan dan membersihkan data;
Pembagian data ke dalam pelatihan, verifikasi dan uji;
Membuat fitur dan menganalisis perilaku mereka;
Pilih model pelatihan yang tepat sesuai dengan perilaku;
Gunakan data pelatihan untuk melatih model Anda dan membuat prediksi;
Memeriksa kinerja pada set verifikasi dan mengoptimalkan kembali;
Memverifikasi kinerja akhir dari set uji.
Apakah itu tidak masuk ke kepala Anda? Tapi itu belum berakhir. Anda hanya memiliki model prediksi yang dapat diandalkan. Ingat apa yang benar-benar kami inginkan dalam strategi kami? Jadi Anda tidak perlu:
Mengembangkan sinyal berdasarkan model prediktif untuk mengidentifikasi arah perdagangan;
Mengembangkan strategi khusus untuk mengidentifikasi posisi terbuka dan tutup;
Melakukan sistem untuk mengidentifikasi posisi dan harga.
Di atas akan menggunakan platform FMZ Quant (FMZ.COMPada platform FMZ Quant, ada antarmuka API yang sangat terkapsul dan sempurna, serta fungsi pemesanan dan perdagangan yang dapat dipanggil secara global. Anda tidak perlu menghubungkan dan menambahkan antarmuka API dari berbagai bursa satu per satu. Di kuadrat Strategi platform FMZ Quant, ada banyak strategi alternatif yang matang dan sempurna yang cocok dengan metode pembelajaran mesin dalam artikel ini, itu akan membuat strategi spesifik Anda lebih kuat.https://www.fmz.com/square.
** Catatan penting tentang biaya transaksi: ** Model Anda akan memberi tahu Anda kapan aset yang dipilih akan long atau short. Namun, tidak mempertimbangkan biaya / biaya transaksi / jumlah perdagangan yang tersedia / stop loss, dll. Biaya transaksi biasanya mengubah transaksi yang menguntungkan menjadi kerugian. Misalnya, aset dengan kenaikan harga yang diharapkan sebesar $ 0,05 adalah pembelian, tetapi jika Anda harus membayar $ 0,10 untuk transaksi ini, Anda akhirnya akan mendapatkan kerugian bersih sebesar $ 0,05. Setelah Anda memperhitungkan komisi broker, biaya pertukaran dan perbedaan poin, grafik keuntungan besar kami di atas terlihat seperti ini:
Hasil backtest setelah biaya perdagangan dan perbedaan poin, Pnl adalah USD.
Biaya transaksi dan perbedaan harga menyumbang lebih dari 90% dari PNL kami! Kami akan membahas ini secara rinci dalam artikel berikutnya.
Akhirnya, mari kita lihat beberapa perangkap umum.
Hindari terlalu cocok dengan semua kekuatan Anda!
Jangan melatih kembali setelah setiap titik data: ini adalah kesalahan umum yang dilakukan orang dalam pengembangan pembelajaran mesin. Jika model Anda perlu dilatih kembali setelah setiap titik data, itu mungkin bukan model yang sangat baik. Artinya, itu perlu dilatih kembali secara teratur, dan hanya perlu dilatih pada frekuensi yang wajar (misalnya, jika prediksi intraday dibuat, itu perlu dilatih kembali pada akhir setiap minggu).
Hindari bias, terutama bias melihat ke depan: Ini adalah alasan lain mengapa model tidak bekerja, dan pastikan bahwa Anda tidak menggunakan informasi masa depan. Dalam kebanyakan kasus, ini berarti bahwa variabel target Y tidak digunakan sebagai fitur dalam model. Anda dapat menggunakannya selama backtesting, tetapi tidak akan tersedia ketika Anda menjalankan model sebenarnya, yang akan membuat model Anda tidak dapat digunakan.
Hati-hati dengan bias penambangan data: Karena kami mencoba melakukan serangkaian pemodelan pada data kami untuk menentukan apakah itu sesuai, jika tidak ada alasan khusus, pastikan Anda menjalankan tes ketat untuk memisahkan mode acak dari mode aktual yang mungkin terjadi.
Ini sangat penting. Saya pikir perlu untuk menyebutkannya lagi.
Overfitting adalah perangkap paling berbahaya dalam strategi perdagangan;
Algoritma yang kompleks dapat berkinerja sangat baik dalam backtest, tetapi gagal parah pada data baru yang tidak terlihat. Algoritma ini tidak benar-benar mengungkapkan tren data, juga tidak memiliki kemampuan prediksi yang nyata.
Jika Anda menemukan bahwa Anda membutuhkan banyak fungsi yang kompleks untuk menafsirkan data, Anda mungkin overfit;
Pembagi data yang tersedia menjadi data pelatihan dan tes, dan selalu verifikasi kinerja data sampel nyata sebelum menggunakan model untuk transaksi real-time.