Apakah mungkin untuk melatih agen untuk perdagangan di pasar saham dengan bala bantuan? Implementasi bahasa R

Mari kita buat prototipe reinforcement learning agent (RL) yang akan menguasai keterampilan perdagangan.

Mengingat bahwa implementasi prototipe berfungsi dalam bahasa R, saya mendorong pengguna R dan programmer untuk mendekati ide-ide yang disajikan dalam artikel ini.

Ini adalah terjemahan dari artikel bahasa Inggris saya: Dapatkah Reinforcement Learning Trade Stock? Implementasi dalam R.

Saya ingin memperingatkan para pemburu kode bahwa dalam catatan ini hanya ada kode untuk jaringan saraf yang diadaptasi untuk R.

Jika saya tidak membedakan diri saya dalam bahasa Rusia yang baik, tunjukkan kesalahan (teks disiapkan dengan bantuan penerjemah otomatis).

gambar

Pengantar masalah


gambar

Saya menyarankan Anda untuk mulai menyelami topik ini dengan artikel ini: DeepMind

Dia akan memperkenalkan Anda dengan gagasan untuk menggunakan Deep Q-Network (DQN) untuk memperkirakan fungsi nilai yang sangat penting dalam proses pengambilan keputusan Markov.

Saya juga merekomendasikan untuk masuk lebih jauh ke dalam matematika menggunakan cetakan buku ini oleh Richard S. Sutton dan Andrew J. Barto: Reinforcement Learning

Di bawah ini saya akan menyajikan versi diperpanjang dari DQN asli, yang mencakup lebih banyak ide yang membantu algoritma secara cepat dan efisien menyatu, yaitu:

Deep Double Duel Noisy NN dengan pemilihan prioritas dari buffer pemutaran pengalaman.

Apa yang membuat pendekatan ini lebih baik daripada DQN klasik?

  • Ganda: ada dua jaringan, satu di antaranya dilatih, dan yang lainnya mengevaluasi nilai Q berikut
  • Duel: Ada neuron yang jelas menghargai dan menguntungkan
  • Bising: ada matriks kebisingan yang diterapkan pada bobot lapisan menengah, di mana rata-rata dan standar deviasi adalah bobot yang terlatih
  • Prioritas pengambilan sampel: kumpulan pengamatan dari buffer pemutaran berisi contoh, yang karenanya pelatihan fungsi sebelumnya menghasilkan residu besar yang dapat disimpan dalam larik bantu.

Nah, bagaimana dengan perdagangan yang dilakukan oleh agen DQN? Ini adalah topik yang menarik.


Ada alasan mengapa ini menarik:

  • Kebebasan mutlak untuk memilih representasi status, tindakan, penghargaan, dan arsitektur NN. Anda dapat memperkaya ruang masuk dengan segala sesuatu yang Anda anggap layak untuk dicoba, dari berita hingga saham dan indeks lainnya.
  • Korespondensi dari logika perdagangan dengan logika pembelajaran penguatan adalah bahwa: agen melakukan tindakan diskrit (atau berkelanjutan), jarang dihargai (setelah transaksi ditutup atau periode berakhir), lingkungan dapat diamati sebagian dan mungkin berisi informasi tentang langkah-langkah selanjutnya, perdagangan adalah permainan episodik.
  • Anda dapat membandingkan hasil DQN dengan beberapa tolok ukur, seperti indeks dan sistem perdagangan teknis.
  • Agen dapat terus mempelajari informasi baru dan, dengan demikian, beradaptasi dengan aturan permainan yang berubah.

Agar tidak merentangkan materi, lihat kode NN ini, yang ingin saya bagikan, karena ini adalah salah satu bagian misterius dari seluruh proyek.

Kode R untuk jaringan neural nilai menggunakan Keras untuk membangun agen RL kami


Kode
# configure critic NN ------------ library('keras') library('R6') learning_rate <- 1e-3 state_names_length <- 12 # just for example a_CustomLayer <- R6::R6Class( "CustomLayer" , inherit = KerasLayer , public = list( call = function(x, mask = NULL) { x - k_mean(x, axis = 2, keepdims = T) } ) ) a_normalize_layer <- function(object) { create_layer(a_CustomLayer, object, list(name = 'a_normalize_layer')) } v_CustomLayer <- R6::R6Class( "CustomLayer" , inherit = KerasLayer , public = list( call = function(x, mask = NULL) { k_concatenate(list(x, x, x), axis = 2) } , compute_output_shape = function(input_shape) { output_shape = input_shape output_shape[[2]] <- input_shape[[2]] * 3L output_shape } ) ) v_normalize_layer <- function(object) { create_layer(v_CustomLayer, object, list(name = 'v_normalize_layer')) } noise_CustomLayer <- R6::R6Class( "CustomLayer" , inherit = KerasLayer , lock_objects = FALSE , public = list( initialize = function(output_dim) { self$output_dim <- output_dim } , build = function(input_shape) { self$input_dim <- input_shape[[2]] sqr_inputs <- self$input_dim ** (1/2) self$sigma_initializer <- initializer_constant(.5 / sqr_inputs) self$mu_initializer <- initializer_random_uniform(minval = (-1 / sqr_inputs), maxval = (1 / sqr_inputs)) self$mu_weight <- self$add_weight( name = 'mu_weight', shape = list(self$input_dim, self$output_dim), initializer = self$mu_initializer, trainable = TRUE ) self$sigma_weight <- self$add_weight( name = 'sigma_weight', shape = list(self$input_dim, self$output_dim), initializer = self$sigma_initializer, trainable = TRUE ) self$mu_bias <- self$add_weight( name = 'mu_bias', shape = list(self$output_dim), initializer = self$mu_initializer, trainable = TRUE ) self$sigma_bias <- self$add_weight( name = 'sigma_bias', shape = list(self$output_dim), initializer = self$sigma_initializer, trainable = TRUE ) } , call = function(x, mask = NULL) { #sample from noise distribution e_i = k_random_normal(shape = list(self$input_dim, self$output_dim)) e_j = k_random_normal(shape = list(self$output_dim)) #We use the factorized Gaussian noise variant from Section 3 of Fortunato et al. eW = k_sign(e_i) * (k_sqrt(k_abs(e_i))) * k_sign(e_j) * (k_sqrt(k_abs(e_j))) eB = k_sign(e_j) * (k_abs(e_j) ** (1/2)) #See section 3 of Fortunato et al. noise_injected_weights = k_dot(x, self$mu_weight + (self$sigma_weight * eW)) noise_injected_bias = self$mu_bias + (self$sigma_bias * eB) output = k_bias_add(noise_injected_weights, noise_injected_bias) output } , compute_output_shape = function(input_shape) { output_shape <- input_shape output_shape[[2]] <- self$output_dim output_shape } ) ) noise_add_layer <- function(object, output_dim) { create_layer( noise_CustomLayer , object , list( name = 'noise_add_layer' , output_dim = as.integer(output_dim) , trainable = T ) ) } critic_input <- layer_input( shape = c(as.integer(state_names_length)) , name = 'critic_input' ) common_layer_dense_1 <- layer_dense( units = 20 , activation = "tanh" ) critic_layer_dense_v_1 <- layer_dense( units = 10 , activation = "tanh" ) critic_layer_dense_v_2 <- layer_dense( units = 5 , activation = "tanh" ) critic_layer_dense_v_3 <- layer_dense( units = 1 , name = 'critic_layer_dense_v_3' ) critic_layer_dense_a_1 <- layer_dense( units = 10 , activation = "tanh" ) # critic_layer_dense_a_2 <- layer_dense( # units = 5 # , activation = "tanh" # ) critic_layer_dense_a_3 <- layer_dense( units = length(acts) , name = 'critic_layer_dense_a_3' ) critic_model_v <- critic_input %>% common_layer_dense_1 %>% critic_layer_dense_v_1 %>% critic_layer_dense_v_2 %>% critic_layer_dense_v_3 %>% v_normalize_layer critic_model_a <- critic_input %>% common_layer_dense_1 %>% critic_layer_dense_a_1 %>% #critic_layer_dense_a_2 %>% noise_add_layer(output_dim = 5) %>% critic_layer_dense_a_3 %>% a_normalize_layer critic_output <- layer_add( list( critic_model_v , critic_model_a ) , name = 'critic_output' ) critic_model_1 <- keras_model( inputs = critic_input , outputs = critic_output ) critic_optimizer = optimizer_adam(lr = learning_rate) keras::compile( critic_model_1 , optimizer = critic_optimizer , loss = 'mse' , metrics = 'mse' ) train.x <- rnorm(state_names_length * 10) train.x <- array(train.x, dim = c(10, state_names_length)) predict(critic_model_1, train.x) layer_name <- 'noise_add_layer' intermediate_layer_model <- keras_model(inputs = critic_model_1$input, outputs = get_layer(critic_model_1, layer_name)$output) predict(intermediate_layer_model, train.x)[1,] critic_model_2 <- critic_model_1 


Saya menggunakan sumber ini untuk mengadaptasi kode Python untuk bagian derau jaringan: github repo

Jaringan saraf ini terlihat seperti ini:

gambar

Ingatlah bahwa dalam arsitektur duel kita menggunakan persamaan (persamaan 1):

Q = A '+ V, di mana

A '= A - rata-rata (A);

Q = nilai tindakan negara;

V = nilai negara;

A = keuntungan.

Variabel lain dalam kode berbicara sendiri. Selain itu, arsitektur ini hanya baik untuk tugas tertentu, jadi jangan anggap remeh.

Sisa kode kemungkinan besar akan cukup umum untuk dipublikasikan, dan akan menarik bagi programmer untuk menulisnya sendiri.

Dan sekarang - percobaan. Pengujian pekerjaan agen dilakukan di kotak pasir, jauh dari kenyataan perdagangan di pasar langsung, dengan broker nyata.

Fase I


Kami menjalankan agen kami terhadap dataset sintetis. Biaya transaksi kami adalah 0,5:

gambar

Hasilnya luar biasa. Rata-rata imbalan episodik maksimum dalam percobaan ini
harus 1,5.

gambar

Kita melihat: kehilangan kritik (yang disebut jaringan nilai dalam pendekatan aktor-kritik), hadiah rata-rata untuk sebuah episode, akumulasi hadiah, contoh hadiah baru-baru ini.

Fase II


Kami mengajari agen kami simbol saham yang dipilih secara sewenang-wenang yang menunjukkan perilaku menarik: awal yang datar, pertumbuhan yang cepat di tengah dan akhir yang suram. Dalam kit pelatihan kami sekitar 4300 hari. Biaya transaksi ditetapkan pada 0,1 dolar AS (sengaja rendah); Hadiahnya adalah Laba / Rugi USD setelah menutup kesepakatan untuk membeli / menjual 1,0 saham.

Sumber: finance.yahoo.com/quote/algn?ltr=1

gambar

NASDAQ: ALGN

Setelah menetapkan beberapa parameter (membiarkan arsitektur NN tetap sama), kami sampai pada hasil berikut:

gambar

Ternyata tidak buruk, karena pada akhirnya agen belajar untuk mendapat untung dengan menekan tiga tombol di konsolnya.

gambar

spidol merah = jual, spidol hijau = beli, spidol abu-abu = tidak melakukan apa-apa.

Harap dicatat bahwa pada puncaknya, hadiah rata-rata per episode melebihi nilai transaksi realistis yang dapat ditemui dalam perdagangan nyata.

Sangat disayangkan bahwa saham jatuh seperti orang gila karena berita buruk ...

Pengamatan penutup


Berdagang dengan RL tidak hanya sulit, tetapi juga bermanfaat. Ketika robot Anda melakukannya lebih baik daripada Anda, saatnya untuk menghabiskan waktu pribadi Anda untuk mendapatkan pendidikan dan kesehatan.

Saya harap ini adalah perjalanan yang menarik untuk Anda. Jika Anda menyukai cerita ini, lambaikan tangan. Jika ada banyak minat, saya dapat melanjutkan dan menunjukkan kepada Anda bagaimana metode gradien kebijakan bekerja menggunakan bahasa R dan API Keras.

Saya juga ingin mengucapkan terima kasih kepada teman-teman saya yang tertarik pada jaringan saraf untuk saran mereka.

Jika Anda masih memiliki pertanyaan, saya selalu di sini.

Source: https://habr.com/ru/post/id433182/


All Articles