Bangkitnya Perdagangan Otomatis: Mesin Memperdagangkan S&P 500

Diterbitkan: 2022-03-11

Saat ini, lebih dari 60 persen aktivitas perdagangan dengan aset yang berbeda (seperti saham, indeks berjangka, komoditas) tidak lagi dilakukan oleh pedagang “manusia”, melainkan mengandalkan perdagangan otomatis. Ada program khusus berdasarkan algoritme tertentu yang secara otomatis membeli dan menjual aset di pasar yang berbeda, yang dimaksudkan untuk mencapai pengembalian positif dalam jangka panjang.

Dalam artikel ini, saya akan menunjukkan kepada Anda bagaimana memprediksi, dengan akurasi yang baik, bagaimana perdagangan berikutnya harus ditempatkan untuk mendapatkan keuntungan positif. Untuk contoh ini, sebagai aset dasar untuk diperdagangkan, saya memilih indeks S&P 500, rata-rata tertimbang dari 500 perusahaan AS dengan kapitalisasi lebih besar. Strategi yang sangat sederhana untuk diterapkan adalah dengan membeli indeks S&P 500 saat Wall Street Exchange memulai perdagangannya, pada pukul 09:30, dan menjualnya pada sesi penutupan pada pukul 16:00 Waktu Bagian Timur. Jika harga penutupan indeks lebih tinggi dari harga pembukaan, ada keuntungan positif, sedangkan keuntungan negatif akan dicapai jika harga penutupan lebih rendah dari harga pembukaan. Jadi pertanyaannya adalah: bagaimana kita tahu jika sesi perdagangan akan berakhir dengan harga penutupan lebih tinggi dari harga pembukaan? Machine Learning adalah alat yang ampuh untuk mencapai tugas yang begitu kompleks, dan dapat menjadi alat yang berguna untuk mendukung kami dengan keputusan perdagangan.

Pembelajaran Mesin adalah batas baru dari banyak aplikasi kehidupan nyata yang berguna. Perdagangan finansial adalah salah satunya, dan sangat sering digunakan di sektor ini. Konsep penting tentang Machine Learning adalah kita tidak perlu menulis kode untuk setiap jenis aturan yang mungkin, seperti pengenalan pola. Ini karena setiap model yang terkait dengan Machine Learning belajar dari data itu sendiri, dan kemudian dapat digunakan untuk memprediksi data baru yang tidak terlihat.

Penafian : Tujuan artikel ini adalah untuk menunjukkan cara melatih metode Pembelajaran Mesin, dan dalam contoh kode yang diberikan tidak semua fungsi dijelaskan. Artikel ini tidak dimaksudkan untuk membiarkan satu salinan dan tempel semua kode dan menjalankan tes yang disediakan sama, karena beberapa detail hilang yang berada di luar cakupan artikel. Juga, pengetahuan dasar tentang Python diperlukan. Tujuan utama artikel ini adalah untuk menunjukkan contoh bagaimana pembelajaran mesin mungkin efektif untuk memprediksi pembelian dan penjualan di sektor keuangan. Namun, berdagang dengan uang sungguhan berarti memiliki banyak keterampilan lain, seperti pengelolaan uang dan manajemen risiko. Artikel ini hanyalah sebagian kecil dari “gambaran besar”.

Membangun Program Perdagangan Otomatis Data Keuangan Pertama Anda

Jadi, Anda ingin membuat program pertama Anda untuk menganalisis data keuangan dan memprediksi perdagangan yang tepat? Mari saya tunjukkan bagaimana caranya. Saya akan menggunakan kode Python untuk Pembelajaran Mesin, dan kami akan menggunakan data historis dari layanan Yahoo Finance. Seperti disebutkan sebelumnya, data historis diperlukan untuk melatih model sebelum membuat prediksi kami.

Untuk memulai, kita perlu menginstal:

  • Python, dan khususnya saya sarankan menggunakan notebook IPython.
  • Paket Yahoo Finance Python (nama persisnya adalah yahoo-finance ) melalui perintah terminal: pip install yahoo-finance .
  • Versi uji coba gratis dari paket Pembelajaran Mesin yang disebut GraphLab. Jangan ragu untuk memeriksa dokumentasi berguna dari perpustakaan itu.

Perhatikan bahwa hanya sebagian dari GraphLab yang bersifat open source, yaitu SFrame, jadi untuk menggunakan seluruh pustaka kita memerlukan lisensi. Ada lisensi gratis 30 hari dan lisensi non-komersial untuk siswa atau mereka yang berpartisipasi dalam kompetisi Kaggle. Dari sudut pandang saya, GraphLab Create adalah library yang sangat intuitif dan mudah digunakan untuk menganalisis data dan melatih model Machine Learning.

Menggali dalam Kode Python

Mari gali dengan beberapa kode Python untuk melihat cara mengunduh data keuangan dari Internet. Saya sarankan menggunakan notebook IPython untuk menguji kode berikut, karena IPython memiliki banyak keunggulan dibandingkan dengan IDE tradisional, terutama ketika kita perlu menggabungkan kode sumber, kode eksekusi, data tabel dan grafik bersama-sama pada dokumen yang sama. Untuk penjelasan singkat tentang penggunaan notebook IPython, silakan lihat artikel Pengantar Notebook IPython.

Jadi, mari buat notebook IPython baru dan tulis beberapa kode untuk mengunduh harga historis indeks S&P 500. Catatan, jika Anda lebih suka menggunakan alat lain, Anda dapat memulai dengan proyek Python baru di IDE pilihan Anda.

 import graphlab as gl from __future__ import division from datetime import datetime from yahoo_finance import Share # download historical prices of S&P 500 index today = datetime.strftime(datetime.today(), "%Y-%m-%d") stock = Share('^GSPC') # ^GSPC is the Yahoo finance symbol to refer S&P 500 index # we gather historical quotes from 2001-01-01 up to today hist_quotes = stock.get_historical('2001-01-01', today) # here is how a row looks like hist_quotes[0] {'Adj_Close': '2091.580078', 'Close': '2091.580078', 'Date': '2016-04-22', 'High': '2094.320068', 'Low': '2081.199951', 'Open': '2091.48999', 'Symbol': '%5eGSPC', 'Volume': '3790580000'}

Di sini, hist_quotes adalah daftar kamus, dan setiap objek kamus adalah hari perdagangan dengan nilai Open , High , Low , Close , Adj_close , Volume , Symbol dan Date . Selama setiap hari perdagangan, harga biasanya berubah mulai dari harga pembukaan Open sampai harga penutupan Close , dan mencapai nilai maksimum dan minimum High dan Low . Kita perlu membacanya dan membuat daftar dari setiap data yang paling relevan. Selain itu, data harus diurutkan berdasarkan nilai terbaru terlebih dahulu, jadi kita perlu membaliknya:

 l_date = [] l_open = [] l_high = [] l_low = [] l_close = [] l_volume = [] # reverse the list hist_quotes.reverse() for quotes in hist_quotes: l_date.append(quotes['Date']) l_open.append(float(quotes['Open'])) l_high.append(float(quotes['High'])) l_low.append(float(quotes['Low'])) l_close.append(float(quotes['Close'])) l_volume.append(int(quotes['Volume']))

Kami dapat mengemas semua kutipan yang diunduh ke dalam objek SFrame , yang merupakan bingkai data berbasis kolom yang sangat skalabel, dan dikompresi. Salah satu kelebihannya adalah juga bisa lebih besar dari jumlah RAM karena didukung disk. Anda dapat memeriksa dokumentasi untuk mempelajari lebih lanjut tentang SFrame.

Jadi, mari kita simpan dan periksa data historisnya:

 qq = gl.SFrame({'datetime' : l_date, 'open' : l_open, 'high' : l_high, 'low' : l_low, 'close' : l_close, 'volume' : l_volume}) # datetime is a string, so convert into datetime object qq['datetime'] = qq['datetime'].apply(lambda x:datetime.strptime(x, '%Y-%m-%d')) # just to check if data is sorted in ascending mode qq.head(3)
menutup tanggal Waktu tinggi rendah membuka volume
1283,27 2001-01-02 00:00:00 1320.28 1276.05 1320.28 1129400000
1347.56 2001-01-03 00:00:00 1347,76 1274,62 1283,27 1880700000
1333.34 2001-01-04 00:00:00 1350.24 1329.14 1347.56 2131000000

Sekarang kita dapat menyimpan data ke disk dengan metode SFrame save , sebagai berikut:

 qq.save(“SP500_daily.bin”) # once data is saved, we can use the following instruction to retrieve it qq = gl.SFrame(“SP500_daily.bin/”)

Mari Kita Lihat Seperti Apa S&P 500 Itu

Untuk melihat tampilan data S&P 500 yang dimuat, kita dapat menggunakan kode berikut:

 import matplotlib.pyplot as plt %matplotlib inline # only for those who are using IPython notebook plt.plot(qq['close'])

Output dari kode tersebut adalah grafik berikut:

Grafik S&P 500, umumnya berkembang dari waktu ke waktu, seperti yang dirender oleh kode Python di atas.

Melatih Beberapa Model Pembelajaran Mesin

Menambahkan Hasil

Seperti yang saya nyatakan di bagian pengantar artikel ini, tujuan dari setiap model adalah untuk memprediksi apakah harga penutupan akan lebih tinggi dari harga pembukaan. Oleh karena itu, dalam hal ini, kita dapat mencapai pengembalian positif saat membeli aset dasar. Jadi, kita perlu menambahkan kolom outcome pada data kita yang akan menjadi target atau variabel predicted . Setiap baris kolom baru ini akan menjadi:

  • +1 untuk hari Naik dengan harga Closing lebih tinggi dari harga Opening .
  • -1 untuk hari Down dengan harga Closing lebih rendah dari harga Opening .
 # add the outcome variable, 1 if the trading session was positive (close>open), 0 otherwise qq['outcome'] = qq.apply(lambda x: 1 if x['close'] > x['open'] else -1) # we also need to add three new columns 'ho' 'lo' and 'gain' # they will be useful to backtest the model, later qq['ho'] = qq['high'] - qq['open'] # distance between Highest and Opening price qq['lo'] = qq['low'] - qq['open'] # distance between Lowest and Opening price qq['gain'] = qq['close'] - qq['open']

Karena kita perlu menilai beberapa hari sebelum hari perdagangan terakhir, kita perlu menunda data satu hari atau lebih. Untuk operasi lagging semacam itu, kita membutuhkan objek lain dari paket GraphLab bernama TimeSeries . TimeSeries memiliki shift metode yang membuat data tertinggal dengan sejumlah baris tertentu.

 ts = gl.TimeSeries(qq, index='datetime') # add the outcome variable, 1 if the bar was positive (close>open), 0 otherwise ts['outcome'] = ts.apply(lambda x: 1 if x['close'] > x['open'] else -1) # GENERATE SOME LAGGED TIMESERIES ts_1 = ts.shift(1) # by 1 day ts_2 = ts.shift(2) # by 2 days # ...etc.... # it's an arbitrary decision how many days of lag are needed to create a good forecaster, so # everyone can experiment by his own decision

Menambahkan Prediktor

Prediktor adalah seperangkat variabel fitur yang harus dipilih untuk melatih model dan memprediksi hasil kami. Jadi, pilihan faktor peramalan sangat penting, jika bukan yang paling penting, komponen peramal.

Sekedar menyebutkan beberapa contoh, faktor yang perlu dipertimbangkan mungkin jika penutupan hari ini lebih tinggi dari penutupan kemarin, dan itu mungkin diperpanjang dengan penutupan dua hari sebelumnya, dll. Pilihan serupa dapat diterjemahkan dengan kode berikut:

 ts['feat1'] = ts['close'] > ts_1['close'] ts['feat2'] = ts['close'] > ts_2['close']

Seperti yang ditunjukkan di atas, saya telah menambahkan dua kolom fitur baru, feat1 dan feat2 pada kumpulan data kami ( ts ) yang berisi 1 jika perbandingannya benar dan 0 sebaliknya.

Artikel ini dimaksudkan untuk memberikan contoh Machine Learning yang diterapkan pada sektor Keuangan. Saya lebih suka fokus pada bagaimana model Pembelajaran Mesin dapat digunakan dengan data keuangan, dan kami tidak akan membahas secara rinci tentang bagaimana memilih faktor yang tepat untuk melatih model. Terlalu lengkap untuk menjelaskan mengapa faktor-faktor tertentu digunakan sehubungan dengan yang lain, karena peningkatan yang cukup besar dalam kompleksitas. Penelitian pekerjaan saya adalah mempelajari banyak hipotesis untuk memilih faktor untuk membuat prediktor yang baik. Jadi sebagai permulaan, saya sarankan Anda bereksperimen dengan banyak kombinasi faktor yang berbeda, untuk melihat apakah mereka dapat meningkatkan akurasi model.

 # add_features is a helper function, which is out of the scope of this article, # and it returns a tuple with: # ts: a timeseries object with, in addition to the already included columns, also lagged columns # as well as some features added to train the model, as shown above with feat1 and feat2 examples # l_features: a list with all features used to train Classifier models # l_lr_features: a list all features used to train Linear Regression models ts, l_features, l_lr_features = add_features(ts) # add the gain column, for trading operations with LONG only positions. # The gain is the difference between Closing price - Opening price ts['gain'] = ts['close'] - ts['open'] ratio = 0.8 # 80% of training set and 20% of testing set training = ts.to_sframe()[0:round(len(ts)*ratio)] testing = ts.to_sframe()[round(len(ts)*ratio):]

Melatih Model Pohon Keputusan

GraphLab Create memiliki antarmuka yang sangat bersih untuk mengimplementasikan model Machine Learning. Setiap model memiliki metode create yang digunakan untuk menyesuaikan model dengan kumpulan data pelatihan. Parameter tipikal adalah:

  • training - ini adalah set pelatihan yang berisi kolom fitur dan kolom target.
  • target - itu adalah nama kolom yang berisi variabel target.
  • validation_set - ini adalah kumpulan data untuk memantau kinerja generalisasi model. Dalam kasus kami, kami tidak memiliki validation_set .
  • features - ini adalah daftar kolom nama fitur yang digunakan untuk melatih model.
  • verbose - jika true , cetak informasi kemajuan selama pelatihan.

Sedangkan parameter lain yang khas dari model itu sendiri, seperti:

  • max_depth - ini adalah kedalaman maksimum pohon.

Dengan kode berikut kami membangun pohon keputusan kami:

 max_tree_depth = 6 decision_tree = gl.decision_tree_classifier.create(training, validation_set=None, target='outcome', features=l_features, max_depth=max_tree_depth, verbose=False)

Mengukur Kinerja Model yang Dipasang

Akurasi adalah metrik penting untuk mengevaluasi kebaikan peramal. Ini adalah jumlah prediksi yang benar dibagi dengan jumlah total titik data. Karena model dilengkapi dengan data pelatihan, akurasi yang dievaluasi dengan set pelatihan lebih baik daripada yang diperoleh dengan set pengujian.

Presisi adalah fraksi dari prediksi positif yang positif. Kami membutuhkan presisi untuk menjadi angka yang mendekati 1 , untuk mencapai tingkat kemenangan yang "sempurna". decision_tree kami, sebagai pengklasifikasi lain dari paket GraphLab Create, memiliki metode yang evaluate untuk mendapatkan banyak metrik penting dari model yang dipasang.

Recall mengkuantifikasi kemampuan classifier untuk memprediksi contoh positif. Recall dapat diartikan sebagai probabilitas bahwa contoh positif yang dipilih secara acak diidentifikasi dengan benar oleh pengklasifikasi. Kami membutuhkan presisi yang akan menjadi angka yang lebih dekat ke 1 , untuk mencapai tingkat kemenangan yang "sempurna".

Kode berikut akan menunjukkan keakuratan model yang dipasang baik dengan set pelatihan dan set pengujian:

 decision_tree.evaluate(training)['accuracy'], decision_tree.evaluate(testing)['accuracy'] (0.6077348066298343, 0.577373211963589)

Seperti yang ditunjukkan di atas, akurasi model dengan set tes adalah sekitar 57 persen, yang entah bagaimana lebih baik daripada melempar koin (50 persen).

Memprediksi Data

GraphLab Create memiliki antarmuka yang sama untuk memprediksi data dari model yang berbeda. Kami akan menggunakan metode predict , yang membutuhkan satu set tes untuk memprediksi variabel target, dalam outcome kasus kami. Sekarang, kita dapat memprediksi data dari set pengujian:

 predictions = decision_tree.predict(testing) # and we add the predictions column in testing set testing['predictions'] = predictions # let's see the first 10 predictions, compared to real values (outcome column) testing[['datetime', 'outcome', 'predictions']].head(10)
tanggal Waktu hasil prediksi
05-04-2013 00:00:00 -1 -1
08-04-2013 00:00:00 1 1
2013-04-09 00:00:00 1 1
2013-04-10 00:00:00 1 -1
11-04-2013 00:00:00 1 -1
2013-04-12 00:00:00 -1 -1
15-04-2013 00:00:00 -1 1
16-04-2013 00:00:00 1 1
17-04-2013 00:00:00 -1 -1
2013-04-18 00:00:00 -1 1

Positif palsu adalah kasus di mana model memprediksi hasil positif sedangkan hasil nyata dari set pengujian negatif. Sebaliknya, negatif palsu adalah kasus di mana model memprediksi hasil negatif di mana hasil nyata dari set tes adalah positif.

Strategi perdagangan kami menunggu hasil prediksi positif untuk membeli S&P 500 pada harga Opening , dan menjualnya pada harga Closing , jadi harapan kami adalah memiliki tingkat Positif Palsu terendah untuk menghindari kerugian. Dengan kata lain, kami berharap model kami akan memiliki tingkat presisi tertinggi .

Seperti yang dapat kita lihat, ada dua negatif palsu (pada 04-04-2013 dan 04-11-2013) dan dua positif palsu (pada 2013-04-15 dan 2013-04-18) dalam sepuluh nilai prediksi pertama dari perangkat pengujian.

Dengan perhitungan sederhana, dengan mempertimbangkan kumpulan sepuluh prediksi kecil ini:

  • akurasi = 6/10 = 0,6 atau 60%
  • presisi =3/5 = 0,6 atau 60%
  • ingat = 3/5 = 0,6 atau 60%

Perhatikan bahwa biasanya angka-angka di atas berbeda satu sama lain, tetapi dalam hal ini sama.

Menguji Kembali Model

Kami sekarang mensimulasikan bagaimana model akan berdagang menggunakan nilai prediksinya. Jika hasil prediksi sama dengan +1 , itu berarti kita mengharapkan hari Naik . Dengan hari Naik, kami membeli indeks di awal sesi, dan menjual indeks di akhir sesi di hari yang sama. Sebaliknya, jika hasil yang diprediksi sama dengan -1 , kami mengharapkan hari Turun , jadi kami tidak akan berdagang selama hari itu.

Laba dan Rugi ( pnl ) untuk perdagangan harian lengkap, juga disebut putaran putaran , dalam contoh ini diberikan oleh:

  • pnl = Close - Open (untuk setiap hari perdagangan)

Dengan kode yang ditunjukkan di bawah ini, saya memanggil fungsi pembantu plot_equity_chart untuk membuat grafik dengan kurva keuntungan kumulatif (kurva ekuitas). Tanpa masuk terlalu dalam, ia hanya mendapatkan serangkaian nilai untung dan rugi dan menghitung rangkaian jumlah kumulatif untuk diplot.

 pnl = testing[testing['predictions'] == 1]['gain'] # the gain column contains (Close - Open) values # I have written a simple helper function to plot the result of all the trades applied to the # testing set and represent the total return expressed by the index basis points # (not expressed in dollars $) plot_equity_chart(pnl,'Decision tree model') 

Model pohon keputusan, umumnya naik dan ke kanan, seperti yang dirender oleh kode Python di atas.

 Mean of PnL is 1.843504 Sharpe is 1.972835 Round turns 511

Di sini, Sharpe adalah rasio Sharpe Tahunan, indikator penting dari kebaikan model perdagangan.

Rasio Sharpe sama dengan akar kuadrat dari 252, kemudian dikalikan dengan rata-rata pnl dibagi dengan standar deviasi pnl.

Mempertimbangkan perdagangan yang diungkapkan hari demi hari sedangkan mean adalah rata-rata dari daftar untung dan rugi, dan sd adalah standar deviasi. Untuk kesederhanaan dalam rumus yang digambarkan di atas, saya telah mempertimbangkan pengembalian bebas risiko sama dengan 0.

Beberapa Dasar Tentang Trading

Perdagangan indeks membutuhkan pembelian aset, yang secara langsung berasal dari indeks. Banyak broker mereplikasi indeks S&P 500 dengan produk turunan yang disebut CFD (Contract for difference), yang merupakan kesepakatan antara dua pihak untuk menukarkan selisih antara harga pembukaan dan harga penutupan kontrak.

Contoh : Beli 1 CFD S&P 500 saat Open (nilainya 2000), jual pada Close hari ini (nilainya 2020). Selisihnya, maka keuntungannya, adalah 20 poin. Jika setiap poin bernilai $25:

  • Keuntungan Kotor adalah 20 points x $25 = $500 dengan 1 kontrak CFD.

Katakanlah broker menyimpan slippage 0,6 poin untuk pendapatannya sendiri:

  • Keuntungan bersih adalah (20 - 0.6) points x $25 = $485 .

Aspek penting lainnya yang perlu dipertimbangkan adalah untuk menghindari kerugian yang signifikan dalam perdagangan. Mereka mungkin terjadi setiap kali hasil yang diprediksi adalah +1 tetapi nilai hasil yang sebenarnya adalah -1 , jadi ini adalah positif palsu . Dalam hal ini, sesi akhir ternyata adalah hari Down dengan harga penutupan lebih rendah dari pembukaan, dan kita mendapatkan kerugian.

Perintah stop loss harus ditempatkan untuk melindungi dari kerugian maksimum yang akan kami toleransi dalam perdagangan, dan perintah seperti itu dipicu setiap kali harga aset turun di bawah nilai tetap yang telah kami tetapkan sebelumnya.

Jika kita melihat time series yang diunduh dari Yahoo Finance di awal artikel ini, setiap hari memiliki harga Low yang merupakan harga terendah yang dicapai pada hari tersebut. Jika kita menetapkan level stop -3 poin jauh dari harga Opening , dan Low - Open = -5 stop order akan dipicu, dan posisi terbuka akan ditutup dengan kerugian -3 poin, bukan -5 . Ini adalah metode sederhana untuk mengurangi risiko. Kode berikut mewakili fungsi pembantu saya untuk mensimulasikan perdagangan dengan level stop:

 # This is a helper function to trade 1 bar (for example 1 day) with a Buy order at opening session # and a Sell order at closing session. To protect against adverse movements of the price, a STOP order # will limit the loss to the stop level (stop parameter must be a negative number) # each bar must contains the following attributes: # Open, High, Low, Close prices as well as gain = Close - Open and lo = Low - Open def trade_with_stop(bar, slippage = 0, stop=None): """ Given a bar, with a gain obtained by the closing price - opening price it applies a stop limit order to limit a negative loss If stop is equal to None, then it returns bar['gain'] """ bar['gain'] = bar['gain'] - slippage if stop<>None: real_stop = stop - slippage if bar['lo']<=stop: return real_stop # stop == None return bar['gain']

Biaya Perdagangan

Biaya transaksi adalah biaya yang dikeluarkan saat membeli atau menjual surat berharga. Biaya transaksi termasuk komisi dan spread broker (selisih antara harga yang dibayarkan dealer untuk sekuritas dan harga yang dibayar pembeli), dan itu perlu dipertimbangkan jika kita ingin menguji kembali strategi kita, mirip dengan skenario nyata. Slippage dalam perdagangan saham sering terjadi ketika terjadi perubahan spread. Dalam contoh ini dan untuk simulasi yang sedang berlangsung berikutnya, biaya perdagangan ditetapkan sebagai:

  • Slippage = 0,6 poin
  • Komisi = $1 untuk setiap perdagangan (satu putaran akan dikenakan biaya $2)

Hanya untuk menulis beberapa angka, jika keuntungan kotor kita adalah 10 poin, 1 poin = $25, jadi $250 termasuk biaya perdagangan, keuntungan bersih kita adalah (10 - 0.6)*$25 - 2 = $233 .

Kode berikut menunjukkan simulasi strategi trading sebelumnya dengan stop loss -3 poin. Kurva biru adalah kurva pengembalian kumulatif. Satu-satunya biaya yang diperhitungkan adalah slippage (0,6 poin), dan hasilnya dinyatakan dalam basis poin (unit dasar yang sama dari nilai S&P 500 yang diunduh dari Yahoo Finance).

 SLIPPAGE = 0.6 STOP = -3 trades = testing[testing['predictions'] == 1][('datetime', 'gain', 'ho', 'lo', 'open', 'close')] trades['pnl'] = trades.apply(lambda x: trade_with_stop(x, slippage=SLIPPAGE, stop=STOP)) plot_equity_chart(trades['pnl'],'Decision tree model') print("Slippage is %s, STOP level at %s" % (SLIPPAGE, STOP)) 

Model pohon keputusan, umumnya naik dan ke kanan, tetapi dengan lonjakan yang kurang jelas, seperti yang dirender oleh kode Python di atas.

 Mean of PnL is 2.162171 Sharpe is 3.502897 Round turns 511 Slippage is 0.6 STOP level at -3

Kode berikut digunakan untuk membuat prediksi dengan cara yang sedikit berbeda. Harap perhatikan metode predict yang dipanggil dengan parameter tambahan output_type = “probability” . Parameter ini digunakan untuk mengembalikan probabilitas nilai prediksi alih-alih prediksi kelasnya ( +1 untuk hasil yang diprediksi secara positif, -1 untuk hasil yang diprediksi secara negatif). Probabilitas lebih besar dari atau sama dengan 0.5 dikaitkan dengan nilai prediksi +1 dan nilai probabilitas kurang dari 0.5 dikaitkan dengan nilai prediksi -1 . Semakin tinggi probabilitasnya, semakin besar peluang kita untuk memprediksi Up Day yang sebenarnya.

 predictions_prob = decision_tree.predict(testing, output_type = 'probability') # predictions_prob will contain probabilities instead of the predicted class (-1 or +1)

Sekarang kita menguji kembali model dengan fungsi pembantu yang disebut backtest_ml_model yang menghitung rangkaian pengembalian kumulatif termasuk slippage dan komisi, dan memplot nilainya. Untuk singkatnya, tanpa menjelaskan fungsi backtest_ml_model secara menyeluruh, detail penting yang perlu disoroti adalah bahwa alih-alih memfilter hari-hari tersebut dengan outcome = 1 seperti yang kita lakukan pada contoh sebelumnya, sekarang kita memfilter predictions_prob yang sama dengan atau lebih besar dari threshold = 0.5 , sebagai berikut:

 trades = testing[predictions_prob>=0.5][('datetime', 'gain', 'ho', 'lo', 'open', 'close')]

Ingatlah bahwa Keuntungan bersih setiap hari perdagangan adalah: Net gain = (Gross gain - SLIPPAGE) * MULT - 2 * COMMISSION .

Metrik penting lainnya yang digunakan untuk mengevaluasi kebaikan strategi perdagangan adalah Penarikan Maksimum . Secara umum, ini mengukur penurunan tunggal terbesar dari puncak ke bawah, dalam nilai portofolio yang diinvestasikan. Dalam kasus kami, ini adalah penurunan paling signifikan dari puncak ke bawah kurva ekuitas (kami hanya memiliki satu aset dalam portofolio kami, S&P 500). Jadi mengingat SArray untung dan rugi pnl , kami menghitung penarikan sebagai:

 drawdown = pnl - pnl.cumulative_max() max_drawdown = min(drawdown)

Di dalam fungsi pembantu backtest_summary dihitung:

  • Penarikan maksimum (dalam dolar) seperti yang ditunjukkan di atas.
  • Akurasi, dengan metode Graphlab.evaluation .
  • Presisi, dengan metode Graphlab.evaluation .
  • Ingat, dengan metode Graphlab.evaluation .

Menempatkan semuanya bersama-sama, contoh berikut menunjukkan kurva ekuitas yang mewakili pengembalian kumulatif dari model strategi, dengan semua nilai dinyatakan dalam dolar.

 model = decision_tree predictions_prob = model.predict(testing, output_type="probability") THRESHOLD = 0.5 bt_1_1 = backtest_ml_model(testing, predictions_prob, target='outcome', threshold=THRESHOLD, STOP=-3, MULT=25, SLIPPAGE=0.6, COMMISSION=1, plot_title='DecisionTree') backtest_summary(bt_1_1) 

Grafik DecisionTree, dengan sumbu Y berlabel "dolar" dan naik hingga 30.000, dan sumbu X berlabel "# putaran balik" dan diperpanjang hingga 600, seperti yang dirender oleh kode Python di atas. Data grafik itu sendiri identik dengan rendering sebelumnya.

 Mean of PnL is 54.054286 Sharpe is 3.502897 Round turns 511 Name: DecisionTree Accuracy: 0.577373211964 Precision: 0.587084148728 Recall: 0.724637681159 Max Drawdown: -1769.00025

Untuk meningkatkan ketepatan nilai perkiraan, alih-alih probabilitas standar 0.5 (50 persen) kami memilih nilai ambang yang lebih tinggi, untuk lebih yakin bahwa model memprediksi hari Naik .

 THRESHOLD = 0.55 # it's the minimum threshold to predict an Up day so hopefully a good day to trade bt_1_2 = backtest_ml_model(testing, predictions_prob, target='outcome', threshold=THRESHOLD, STOP=-3, MULT=25, SLIPPAGE=0.6, COMMISSION=1, plot_title='DecisionTree') backtest_summary(bt_1_2) 

Grafik DecisionTree, dengan sumbu Y berlabel "dolar" dan naik menjadi 30.000, dan sumbu X berlabel "# putaran balik" dan kali ini hanya diperpanjang hingga 250, seperti yang dirender oleh kode Python di atas. Data grafik itu sendiri mirip dengan rendering sebelumnya, tetapi bahkan lebih dihaluskan.

 Mean of PnL is 118.244689 Sharpe is 6.523478 Round turns 234 Name: DecisionTree Accuracy: 0.560468140442 Precision: 0.662393162393 Recall: 0.374396135266 Max Drawdown: -1769.00025

Seperti yang dapat kita lihat pada grafik di atas, kurva ekuitas jauh lebih baik dari sebelumnya (Sharpe adalah 6,5 bukannya 3,5), bahkan dengan putaran putaran yang lebih sedikit.

Mulai saat ini, kami akan mempertimbangkan semua model berikutnya dengan ambang batas yang lebih tinggi dari nilai standar.

Melatih Pengklasifikasi Logistik

Kami dapat menerapkan penelitian kami, seperti yang kami lakukan sebelumnya dengan pohon keputusan, ke dalam model Pengklasifikasi Logistik. GraphLab Create memiliki antarmuka yang sama dengan objek Logistic Classifier, dan kita akan memanggil metode create untuk membangun model kita dengan daftar parameter yang sama. Selain itu, kami lebih memilih untuk memprediksi vektor probabilitas daripada vektor kelas yang diprediksi (terdiri dari +1 untuk hasil positif, dan -1 untuk hasil negatif), jadi kami akan memiliki ambang lebih besar dari 0.5 untuk mencapai presisi yang lebih baik dalam peramalan.

 model = gl.logistic_classifier.create(training, target='outcome', features=l_features, validation_set=None, verbose=False) predictions_prob = model.predict(testing, 'probability') THRESHOLD = 0.6 bt_2_2 = backtest_ml_model(testing, predictions_prob, target='outcome', threshold=THRESHOLD, STOP=-3, plot_title=model.name()) backtest_summary(bt_2_2) 

Grafik LogisticClassifier, dengan sumbu Y berlabel "dolar" dan kali ini naik hingga 50.000, dan sumbu X berlabel "# putaran balik" dan diperpanjang sekarang menjadi 450, seperti yang dirender oleh kode Python di atas. Data grafik itu sendiri mirip dengan rendering sebelumnya dalam tren keseluruhannya.

 Mean of PnL is 112.704215 Sharpe is 6.447859 Round turns 426 Name: LogisticClassifier Accuracy: 0.638491547464 Precision: 0.659624413146 Recall: 0.678743961353 Max Drawdown: -1769.00025

Dalam hal ini, ada ringkasan yang sangat mirip dengan Pohon Keputusan. Bagaimanapun, kedua model adalah pengklasifikasi, mereka hanya memprediksi kelas hasil biner ( +1 , -1 ).

Melatih Model Regresi Linier

Perbedaan utama dari model ini adalah bahwa model ini berhubungan dengan nilai kontinu alih-alih kelas biner, seperti yang disebutkan sebelumnya. Kita tidak harus melatih model dengan variabel target sama dengan +1 untuk hari Naik dan -1 untuk hari Turun , target kita harus berupa variabel kontinu. Karena kita ingin memprediksi keuntungan positif, atau dengan kata lain harga Penutupan lebih tinggi dari harga Pembukaan , sekarang target harus menjadi kolom keuntungan dari set pelatihan kita. Juga, daftar fitur harus terdiri dari nilai berkelanjutan, seperti sebelumnya Open , Close , dll.

Untuk singkatnya, saya tidak akan membahas detail tentang cara memilih fitur yang tepat, karena ini di luar cakupan artikel ini, yang lebih cenderung menunjukkan bagaimana kita harus menerapkan model Pembelajaran Mesin yang berbeda pada kumpulan data. Daftar parameter yang diteruskan ke metode create adalah:

  • training - ini adalah set pelatihan yang berisi kolom fitur dan kolom target.
  • target - itu adalah nama kolom yang berisi variabel target.
  • validation_set - ini adalah kumpulan data untuk memantau kinerja generalisasi model. Dalam kasus kami, kami tidak memiliki validation_set .
  • features - ini adalah daftar nama kolom fitur yang digunakan untuk melatih model, untuk model ini kita akan menggunakan set lain untuk model Classifier.
  • verbose - jika true , itu akan mencetak informasi kemajuan selama pelatihan.
  • max_iterations - ini adalah jumlah maksimum yang diizinkan melewati data. Lebih banyak melewati data dapat menghasilkan model yang terlatih lebih akurat.
 model = gl.linear_regression.create(training, target='gain', features = l_lr_features, validation_set=None, verbose=False, max_iterations=100) predictions = model.predict(testing) # a linear regression model, predict continuous values, so we need to make an estimation of their # probabilities of success and normalize all values in order to have a vector of probabilities predictions_max, predictions_min = max(predictions), min(predictions) predictions_prob = (predictions - predictions_min)/(predictions_max - predictions_min)

Sejauh ini, kami memiliki prediksi yang merupakan SArray dari keuntungan yang diprediksi, sedangkan predictions_prob adalah SArray dengan nilai predictions yang dinormalisasi. Untuk memiliki akurasi yang baik dan jumlah putaran tertentu, sebanding dengan model sebelumnya, saya telah memilih nilai ambang 0.4 . Untuk predictions_prob kurang dari 0.4 , fungsi pembantu backtest_linear_model tidak akan membuka perdagangan karena hari Down diharapkan. Jika tidak, perdagangan akan dibuka.

 THRESHOLD = 0.4 bt_3_2 = backtest_linear_model(testing, predictions_prob, target='gain', threshold=THRESHOLD, STOP = -3, plot_title=model.name()) backtest_summary(bt_3_2) 

Grafik LinearRegression, dengan sumbu Y berlabel "dolar" dan naik hingga 45.000, dan sumbu X berlabel "# putaran balik" dan diperpanjang hingga 350, seperti yang dirender oleh kode Python di atas. Data grafik itu sendiri sekali lagi mirip, tetapi tidak persis sama dengan, rendering sebelumnya.

 Mean of PnL is 138.868280 Sharpe is 7.650187 Round turns 319 Name: LinearRegression Accuracy: 0.631989596879 Precision: 0.705329153605 Recall: 0.54347826087 Max Drawdown: -1769.00025

Melatih Pohon yang Dikuatkan

Seperti yang sebelumnya kita lakukan untuk melatih pohon keputusan, sekarang kita akan melatih pengklasifikasi pohon yang dikuatkan dengan parameter yang sama yang digunakan untuk model pengklasifikasi lainnya. Selain itu, kami menetapkan jumlah max_iterations = 12 untuk meningkatkan jumlah maksimum iterasi untuk boosting. Setiap iterasi menghasilkan pembuatan pohon tambahan. Kami juga menetapkan nilai ambang batas yang lebih tinggi dari 0.5 untuk meningkatkan presisi.

 model = gl.boosted_trees_classifier.create(training, target='outcome', features=l_features, validation_set=None, max_iterations=12, verbose=False) predictions_prob = model.predict(testing, 'probability') THRESHOLD = 0.7 bt_4_2 = backtest_ml_model(testing, predictions_prob, target='outcome', threshold=THRESHOLD, STOP=-3, plot_title=model.name()) backtest_summary(bt_4_2) 

Grafik BoostedTreesClassifier, dengan sumbu Y berlabel "dolar" dan naik hingga 25.000, dan sumbu X berlabel "# putaran balik" dan diperpanjang hingga 250, seperti yang dirender oleh kode Python di atas. Data grafiknya sendiri kembali mirip dengan rendering sebelumnya, dengan peningkatan yang lebih tajam sekitar 175 pada sumbu X.

 Mean of PnL is 112.002338 Sharpe is 6.341981 Round turns 214 Name: BoostedTreesClassifier Accuracy: 0.563068920676 Precision: 0.682242990654 Recall: 0.352657004831 Max Drawdown: -1769.00025

Melatih Hutan Acak

Ini adalah model terlatih terakhir kami, Pengklasifikasi Hutan Acak, yang disusun oleh ansambel pohon keputusan. Jumlah maksimum pohon untuk digunakan dalam model diatur ke num_trees = 10 , untuk menghindari terlalu banyak kerumitan dan pemasangan yang berlebihan.

 model = gl.random_forest_classifier.create(training, target='outcome', features=l_features, validation_set=None, verbose=False, num_trees = 10) predictions_prob = model.predict(testing, 'probability') THRESHOLD = 0.6 bt_5_2 = backtest_ml_model(testing, predictions_prob, target='outcome', threshold=THRESHOLD, STOP=-3, plot_title=model.name()) backtest_summary(bt_5_2) 

Grafik RandomForestClassifier, dengan sumbu Y berlabel "dolar" dan naik hingga 40.000, dan sumbu X berlabel "# putaran balik" dan diperpanjang hingga 350, seperti yang dirender oleh kode Python di atas. Data grafik itu sendiri sekali lagi mirip dengan rendering sebelumnya.

 Mean of PnL is 114.786962 sharpe is 6.384243 Round turns 311 Name: RandomForestClassifier Accuracy: 0.598179453836 Precision: 0.668810289389 Recall: 0.502415458937 Max Drawdown: -1769.00025

Collecting All the Models Together

Now we can join all the strategies together and see the overall result. It's interesting to see the summary of all Machine Learning models, sorted by their precision.

nama accuracy presisi round turns sharpe
LinearRegression 0.63 0,71 319 7.65
BoostedTreesClassifier 0,56 0.68 214 6.34
RandomForestClassifier 0,60 0,67 311 6.38
DecisionTree 0,56 0,66 234 6.52
LogisticClassifier 0,64 0,66 426 6.45

If we collect all the profit and loss for each one of the previous models in the array pnl , the following chart depicts the equity curve obtained by the sum of each profit and loss, day by day.

 Mean of PnL is 119.446463 Sharpe is 6.685744 Round turns 1504 First trading day 2013-04-09 Last trading day 2016-04-22 Total return 179647

Just to give some numbers, with about 3 years of trading, all models have a total gain of about 180,000 dollars. The maximum exposition is 5 CFD contracts in the market, but to reduce the risk they all are closed at the end of each day, so overnight positions are not allowed.

Statistics of the Aggregation of All Models Together

Since each model can open a trade, but we added 5 concurrent models together, during the same day there could be from 1 contract up to 5 CFD contracts. If all models agree to open trades during the same day, there is a high chance to have an Up day predicted. Moreover, we can group by the number of models that open a trade at the same time during the opening session of the day. Then we evaluate precision as a function of the number of concurrent models.

As we can see by the chart depicted above, the precision gets better as the number of models do agree to open a trade. The more models agree, the more precision we get. For instance, with 5 models triggered the same day, the chance to predict an Up day is greater than 85%.

Kesimpulan

Even in the financial world, Machine Learning is welcomed as a powerful instrument to learn from data and give us great forecasting tools. Each model shows different values of accuracy and precision, but in general, all models can be aggregated to achieve a better result than each one of them taken singularly. GraphLab Create is a great library, easy to use, scalable and able to manage Big Data very quickly. It implements different scientific and forecasting models, and there is a free license for students and Kaggle competitions.

Terkait: Pengantar Teori Pembelajaran Mesin dan Aplikasinya: Tutorial Visual dengan Contoh

Additional disclosure: This article has been prepared solely for information purposes, and is not an offer to buy or sell or a solicitation of an offer to buy or sell any security or instrument or to participate in any particular trading strategy. Examples presented on these sites are for educational purposes only. Past results are not necessarily indicative of future results.