Metode Monte Carlo yang menggunakan Dataproc dan Apache Spark


Dataproc dan Apache Spark menyediakan infrastruktur dan kapasitas yang dapat Anda gunakan untuk menjalankan simulasi Monte Carlo yang ditulis dalam Java, Python, atau Scala.

Metode Monte Carlo dapat membantu menjawab berbagai pertanyaan di bidang bisnis, teknik, sains, matematika, dan bidang lainnya. Dengan menggunakan pengambilan sampel acak berulang untuk membuat distribusi probabilitas untuk suatu variabel, simulasi Monte Carlo dapat memberikan jawaban atas pertanyaan yang mungkin tidak dapat dijawab. Misalnya, dalam bidang keuangan, penetapan harga opsi ekuitas memerlukan analisis ribuan cara harga saham dapat berubah dari waktu ke waktu. Metode Monte Carlo memberikan cara untuk menyimulasikan perubahan harga saham tersebut dalam berbagai kemungkinan hasil, sambil mempertahankan kontrol atas domain kemungkinan input terhadap masalah.

Sebelumnya, menjalankan ribuan simulasi dapat memerlukan waktu yang sangat lama dan menimbulkan biaya yang tinggi. Dengan Dataproc, Anda dapat menyediakan kapasitas sesuai permintaan dan membayar per menit. Apache Spark memungkinkan Anda menggunakan cluster yang terdiri dari puluhan, ratusan, atau ribuan server untuk menjalankan simulasi dengan cara yang intuitif dan dapat diskalakan untuk memenuhi kebutuhan Anda. Artinya, Anda dapat menjalankan lebih banyak simulasi dengan lebih cepat, yang dapat membantu bisnis Anda berinovasi lebih cepat dan mengelola risiko dengan lebih baik.

Keamanan selalu penting saat bekerja dengan data keuangan. Dataproc berjalan di Google Cloud, yang membantu menjaga data Anda tetap aman, terlindungi, dan bersifat pribadi dalam beberapa cara. Misalnya, semua data dienkripsi selama transmisi dan saat dalam penyimpanan, serta Google Cloud mematuhi standar ISO 27001, SOC3, dan PCI.

Tujuan

  • Buat cluster Dataproc terkelola dengan Apache Spark yang sudah diinstal sebelumnya.
  • Jalankan simulasi Monte Carlo menggunakan Python yang memperkirakan pertumbuhan portofolio saham dari waktu ke waktu.
  • Jalankan simulasi Monte Carlo menggunakan Scala yang menyimulasikan cara kasino menghasilkan uang.

Biaya

Dalam dokumen ini, Anda akan menggunakan komponen Google Cloudyang dapat ditagih berikut:

Untuk membuat perkiraan biaya berdasarkan proyeksi penggunaan Anda, gunakan kalkulator harga.

Pengguna Google Cloud baru mungkin memenuhi syarat untuk mendapatkan uji coba gratis.

Setelah menyelesaikan tugas yang dijelaskan dalam dokumen ini, Anda dapat menghindari penagihan berkelanjutan dengan menghapus resource yang Anda buat. Untuk mengetahui informasi selengkapnya, lihat Pembersihan.

Sebelum memulai

  • Menyiapkan project Google Cloud
    1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
    2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

      Go to project selector

    3. Verify that billing is enabled for your Google Cloud project.

    4. Enable the Dataproc and Compute Engine APIs.

      Enable the APIs

    5. Install the Google Cloud CLI.

    6. Jika Anda menggunakan penyedia identitas (IdP) eksternal, Anda harus login ke gcloud CLI dengan identitas gabungan Anda terlebih dahulu.

    7. Untuk melakukan inisialisasi gcloud CLI, jalankan perintah berikut:

      gcloud init
    8. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

      Go to project selector

    9. Verify that billing is enabled for your Google Cloud project.

    10. Enable the Dataproc and Compute Engine APIs.

      Enable the APIs

    11. Install the Google Cloud CLI.

    12. Jika Anda menggunakan penyedia identitas (IdP) eksternal, Anda harus login ke gcloud CLI dengan identitas gabungan Anda terlebih dahulu.

    13. Untuk melakukan inisialisasi gcloud CLI, jalankan perintah berikut:

      gcloud init
    14. Membuat cluster Dataproc

      Ikuti langkah-langkah untuk membuat cluster Dataproc dari konsol Google Cloud . Setelan cluster default, yang mencakup dua node pekerja, sudah cukup untuk tutorial ini.

      Menonaktifkan logging untuk peringatan

      Secara default, Apache Spark mencetak logging verbose di jendela konsol. Untuk tujuan tutorial ini, ubah tingkat logging untuk mencatat hanya kesalahan. Ikuti langkah-langkah berikut:

      Gunakan ssh untuk terhubung ke node utama cluster Dataproc

      Node utama cluster Dataproc memiliki akhiran -m pada nama VM-nya.

      1. In the Google Cloud console, go to the VM instances page.

        Go to VM instances

      2. In the list of virtual machine instances, click SSH in the row of the instance that you want to connect to.

        SSH button next to instance name.

      Jendela SSH yang terhubung ke node utama akan terbuka.

      Connected, host fingerprint: ssh-rsa 2048 ...
      ...
      user@clusterName-m:~$
      

      Mengubah setelan logging

      1. Dari direktori beranda node utama, edit /etc/spark/conf/log4j.properties.

        sudo nano /etc/spark/conf/log4j.properties
        
      2. Tetapkan log4j.rootCategory sama dengan ERROR.

        # Set only errors to be logged to the console
        log4j.rootCategory=ERROR, console
        log4j.appender.console=org.apache.log4j.ConsoleAppender
        log4j.appender.console.target=System.err
        log4j.appender.console.layout=org.apache.log4j.PatternLayout
        log4j.appender.console.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} %p %c{1}: %m%n
        
      3. Simpan perubahan dan keluar dari editor. Jika Anda ingin mengaktifkan logging panjang lagi, batalkan perubahan dengan memulihkan nilai .rootCategory ke nilai aslinya (INFO).

      Bahasa pemrograman Spark

      Spark mendukung Python, Scala, dan Java sebagai bahasa pemrograman untuk aplikasi mandiri, serta menyediakan interpreter interaktif untuk Python dan Scala. Bahasa yang Anda pilih adalah preferensi pribadi. Tutorial ini menggunakan interpreter interaktif karena Anda dapat bereksperimen dengan mengubah kode, mencoba nilai input yang berbeda, lalu melihat hasilnya.

      Memperkirakan pertumbuhan portofolio

      Dalam bidang keuangan, metode Monte Carlo terkadang digunakan untuk menjalankan simulasi yang mencoba memprediksi performa investasi. Dengan menghasilkan sampel hasil secara acak dalam berbagai kondisi pasar yang mungkin terjadi, simulasi Monte Carlo dapat menjawab pertanyaan tentang performa rata-rata portofolio atau dalam skenario terburuk.

      Ikuti langkah-langkah berikut untuk membuat simulasi yang menggunakan metode Monte Carlo untuk mencoba memperkirakan pertumbuhan investasi keuangan berdasarkan beberapa faktor pasar umum.

      1. Mulai interpreter Python dari node utama Dataproc.

        pyspark
        

        Tunggu perintah Spark >>>.

      2. Masukkan kode berikut. Pastikan Anda mempertahankan indentasi dalam definisi fungsi.

        import random
        import time
        from operator import add
        
        def grow(seed):
            random.seed(seed)
            portfolio_value = INVESTMENT_INIT
            for i in range(TERM):
                growth = random.normalvariate(MKT_AVG_RETURN, MKT_STD_DEV)
                portfolio_value += portfolio_value * growth + INVESTMENT_ANN
            return portfolio_value
        
      3. Tekan return hingga Anda melihat perintah Spark lagi.

        Kode sebelumnya menentukan fungsi yang memodelkan apa yang mungkin terjadi saat investor memiliki akun pensiun yang sudah ada yang diinvestasikan di pasar saham, yang kemudian menambahkan dana tambahan setiap tahun. Fungsi menghasilkan laba atas investasi acak, sebagai persentase, setiap tahun selama jangka waktu yang ditentukan. Fungsi ini menggunakan nilai awal sebagai parameter. Nilai ini digunakan untuk menyemai ulang generator angka acak, yang memastikan bahwa fungsi tidak mendapatkan daftar angka acak yang sama setiap kali dijalankan. Fungsi random.normalvariate memastikan bahwa nilai acak terjadi di seluruh distribusi normal untuk rataan dan simpangan baku yang ditentukan. Fungsi ini meningkatkan nilai portofolio sebesar jumlah pertumbuhan, yang bisa positif atau negatif, dan menambahkan jumlah tahunan yang mewakili investasi lebih lanjut.

        Anda akan menentukan konstanta yang diperlukan pada langkah berikutnya.

      4. Buat banyak nilai awal untuk dimasukkan ke fungsi. Pada prompt Spark, masukkan kode berikut, yang menghasilkan 10.000 seed:

        seeds = sc.parallelize([time.time() + i for i in range(10000)])
        

        Hasil operasi parallelize adalah resilient distributed dataset (RDD), yang merupakan kumpulan elemen yang dioptimalkan untuk pemrosesan paralel. Dalam hal ini, RDD berisi seed yang didasarkan pada waktu sistem saat ini.

        Saat membuat RDD, Spark membagi data berdasarkan jumlah worker dan core yang tersedia. Dalam hal ini, Spark memilih untuk menggunakan delapan slice, satu slice untuk setiap inti. Tidak masalah untuk simulasi ini, yang memiliki 10.000 item data. Untuk simulasi yang lebih besar, setiap slice mungkin lebih besar dari batas default. Dalam hal ini, menentukan parameter kedua ke parallelize dapat meningkatkan jumlah slice, yang dapat membantu menjaga ukuran setiap slice tetap dapat dikelola, sementara Spark tetap memanfaatkan kedelapan core.

      5. Berikan RDD yang berisi bibit ke fungsi pertumbuhan.

        results = seeds.map(grow)
        

        Metode map meneruskan setiap nilai awal dalam RDD ke fungsi grow dan menambahkan setiap hasil ke RDD baru, yang disimpan dalam results. Perhatikan bahwa operasi ini, yang melakukan transformasi, tidak langsung menghasilkan hasilnya. Spark tidak akan melakukan pekerjaan ini hingga hasilnya diperlukan. Evaluasi lambat ini adalah alasan Anda dapat memasukkan kode tanpa konstanta yang ditentukan.

      6. Tentukan beberapa nilai untuk fungsi.

        INVESTMENT_INIT = 100000  # starting amount
        INVESTMENT_ANN = 10000  # yearly new investment
        TERM = 30  # number of years
        MKT_AVG_RETURN = 0.11 # percentage
        MKT_STD_DEV = 0.18  # standard deviation
        
      7. Panggil reduce untuk menggabungkan nilai dalam RDD. Masukkan kode berikut untuk menjumlahkan hasil dalam RDD:

        sum = results.reduce(add)
        
      8. Perkirakan dan tampilkan pengembalian rata-rata:

        print (sum / 10000.)
        

        Pastikan untuk menyertakan karakter titik (.) di akhir. Ini menandakan aritmatika floating point.

      9. Sekarang ubah asumsi dan lihat bagaimana hasilnya berubah. Misalnya, Anda dapat memasukkan nilai baru untuk rata-rata keuntungan pasar:

        MKT_AVG_RETURN = 0.07
        
      10. Jalankan simulasi lagi.

        print (sc.parallelize([time.time() + i for i in range(10000)]) \
                .map(grow).reduce(add)/10000.)
        
      11. Setelah selesai bereksperimen, tekan CTRL+D untuk keluar dari interpreter Python.

      Memprogram simulasi Monte Carlo di Scala

      Monte Carlo, tentu saja, terkenal sebagai tujuan perjudian. Di bagian ini, Anda akan menggunakan Scala untuk membuat simulasi yang memodelkan keuntungan matematika yang dinikmati kasino dalam permainan untung-untungan. "Keunggulan kasino" di kasino sungguhan sangat bervariasi dari satu game ke game lainnya; misalnya, bisa lebih dari 20% dalam game keno. Tutorial ini membuat game sederhana di mana bandar hanya memiliki keunggulan satu persen. Berikut cara kerja game ini:

      • Pemain memasang taruhan, yang terdiri dari sejumlah chip dari dana bankroll.
      • Pemain melempar dadu 100 sisi (keren, bukan?).
      • Jika hasil lemparan dadu adalah angka 1 hingga 49, pemain menang.
      • Untuk hasil 50 hingga 100, pemain kalah taruhan.

      Anda dapat melihat bahwa game ini menciptakan kerugian sebesar satu persen bagi pemain: dalam 51 dari 100 kemungkinan hasil untuk setiap lemparan, pemain kalah.

      Ikuti langkah-langkah berikut untuk membuat dan menjalankan game:

      1. Mulai interpreter Scala dari node utama Dataproc.

        spark-shell
        
      2. Salin dan tempel kode berikut untuk membuat game. Scala tidak memiliki persyaratan yang sama dengan Python dalam hal indentasi, jadi Anda cukup menyalin dan menempelkan kode ini di perintah scala>.

        val STARTING_FUND = 10
        val STAKE = 1   // the amount of the bet
        val NUMBER_OF_GAMES = 25
        
        def rollDie: Int = {
            val r = scala.util.Random
            r.nextInt(99) + 1
        }
        
        def playGame(stake: Int): (Int) = {
            val faceValue = rollDie
            if (faceValue < 50)
                (2*stake)
            else
                (0)
        }
        
        // Function to play the game multiple times
        // Returns the final fund amount
        def playSession(
           startingFund: Int = STARTING_FUND,
           stake: Int = STAKE,
           numberOfGames: Int = NUMBER_OF_GAMES):
           (Int) = {
        
            // Initialize values
            var (currentFund, currentStake, currentGame) = (startingFund, 0, 1)
        
            // Keep playing until number of games is reached or funds run out
            while (currentGame <= numberOfGames && currentFund > 0) {
        
                // Set the current bet and deduct it from the fund
                currentStake = math.min(stake, currentFund)
                currentFund -= currentStake
        
                // Play the game
                val (winnings) = playGame(currentStake)
        
                // Add any winnings
                currentFund += winnings
        
                // Increment the loop counter
                currentGame += 1
            }
            (currentFund)
        }
        
      3. Tekan return hingga Anda melihat perintah scala>.

      4. Masukkan kode berikut untuk memainkan game 25 kali, yang merupakan nilai default untuk NUMBER_OF_GAMES.

        playSession()
        

        Modal awal Anda adalah 10 unit. Apakah sekarang lebih tinggi atau lebih rendah?

      5. Sekarang simulasikan 10.000 pemain yang bertaruh 100 chip per game. Mainkan 10.000 game dalam satu sesi. Simulasi Monte Carlo ini menghitung probabilitas kehilangan semua uang Anda sebelum sesi berakhir. Masukkan kode berikut:

        (sc.parallelize(1 to 10000, 500)
          .map(i => playSession(100000, 100, 250000))
          .map(i => if (i == 0) 1 else 0)
          .reduce(_+_)/10000.0)
        

        Perhatikan bahwa sintaksis .reduce(_+_) adalah singkatan di Scala untuk menggabungkan dengan menggunakan fungsi penjumlahan. Secara fungsional, ini setara dengan sintaksis .reduce(add) yang Anda lihat dalam contoh Python.

        Kode sebelumnya melakukan langkah-langkah berikut:

        • Membuat RDD dengan hasil pemutaran sesi.
        • Mengganti hasil pemain yang bangkrut dengan angka 1 dan hasil yang tidak nol dengan angka 0.
        • Menjumlahkan jumlah pemain yang bangkrut.
        • Membagi jumlah dengan jumlah pemain.

        Hasil umumnya mungkin:

        0.998
        

        Yang hampir menjamin Anda akan kehilangan semua uang Anda, meskipun kasino hanya memiliki keunggulan satu persen.

      Pembersihan

      Menghapus project

      1. In the Google Cloud console, go to the Manage resources page.

        Go to Manage resources

      2. In the project list, select the project that you want to delete, and then click Delete.
      3. In the dialog, type the project ID, and then click Shut down to delete the project.

      Langkah berikutnya

      • Untuk mengetahui informasi selengkapnya tentang cara mengirimkan tugas Spark ke Dataproc tanpa harus menggunakan ssh untuk terhubung ke cluster, baca Dataproc—Mengirimkan tugas