Dataproc e Apache Spark forniscono l'infrastruttura e la capacità che puoi utilizzare per eseguire simulazioni Monte Carlo scritte in Java, Python o Scala.
I metodi Monte Carlo possono aiutare a rispondere a una vasta gamma di questioni in economia, ingegneria, scienze, matematica e altri campi. Utilizzando i campionamenti casuali ripetuti per creare una distribuzione di probabilità per una variabile, una simulazione Monte Carlo può fornire risposte a domande a cui altrimenti non sarebbe possibile rispondere. Nel settore finanziario, ad esempio, la determinazione del prezzo di un'opzione azionaria richiede l'analisi delle migliaia di modi in cui il prezzo dell'azione potrebbe variare nel tempo. I metodi Monte Carlo offrono un modo per simulare queste variazioni di prezzo delle azioni in un'ampia gamma di possibili risultati, mantenendo al contempo il controllo sul dominio dei possibili input per il problema.
In passato, l'esecuzione di migliaia di simulazioni richiedeva molto tempo e accumulava costi elevati. Dataproc consente di eseguire il provisioning di capacità on demand e di pagarla al minuto. Apache Spark consente di utilizzare cluster di decine, centinaia o migliaia di server per eseguire le simulazioni in modo intuitivo e scalabile in base alle tue esigenze. Ciò significa che puoi eseguire più simulazioni più rapidamente, il che può aiutare la tua azienda a innovare più rapidamente e gestire meglio i rischi.
La sicurezza è sempre importante quando si lavora con i dati finanziari. Dataproc viene eseguito su Google Cloud, il che contribuisce a mantenere i tuoi dati sicuri, protetti e privati in diversi modi. Ad esempio, tutti i dati sono criptati durante la trasmissione e quando sono at-rest e Google Cloud è conforme agli standard ISO 27001, SOC3 e PCI.
Obiettivi
- Crea un cluster Dataproc gestito con Apache Spark preinstallato.
- Eseguire una simulazione Monte Carlo utilizzando Python che stima la crescita di un portafoglio azionario nel tempo.
- Esegui una simulazione Monte Carlo con Scala, che simula il modo in cui un casinò guadagna.
Costi
In questo documento vengono utilizzati i seguenti componenti fatturabili di Google Cloud:
Per generare una stima dei costi in base all'utilizzo previsto,
utilizza il Calcolatore prezzi.
Una volta completate le attività descritte in questo documento, puoi evitare la fatturazione continua eliminando le risorse che hai creato. Per ulteriori informazioni, consulta la pagina Pulizia.
Prima di iniziare
- Configura un progetto Google Cloud
- Accedi al tuo account Google Cloud. Se non conosci Google Cloud, crea un account per valutare le prestazioni dei nostri prodotti in scenari reali. I nuovi clienti ricevono anche 300 $di crediti gratuiti per l'esecuzione, il test e il deployment dei carichi di lavoro.
-
Nella pagina del selettore di progetti della console Google Cloud, seleziona o crea un progetto Google Cloud.
-
Assicurati che la fatturazione sia attivata per il tuo progetto Google Cloud.
-
Abilita le API Dataproc and Compute Engine.
- Installa Google Cloud CLI.
-
Per initialize gcloud CLI, esegui questo comando:
gcloud init
-
Nella pagina del selettore di progetti della console Google Cloud, seleziona o crea un progetto Google Cloud.
-
Assicurati che la fatturazione sia attivata per il tuo progetto Google Cloud.
-
Abilita le API Dataproc and Compute Engine.
- Installa Google Cloud CLI.
-
Per initialize gcloud CLI, esegui questo comando:
gcloud init
Creazione di un cluster Dataproc
Segui i passaggi per creare un cluster Dataproc dalla console Google Cloud. Per questo tutorial sono sufficienti le impostazioni predefinite del cluster, che includono nodi a due worker.
Disabilitazione del logging per gli avvisi
Per impostazione predefinita, Apache Spark stampa il logging dettagliato nella finestra della console. Ai fini di questo tutorial, modifica il livello di logging in modo da registrare solo gli errori. Segui questi passaggi:
Utilizza ssh
per connetterti al nodo principale del cluster Dataproc
Il nodo principale del cluster Dataproc ha il suffisso -m
sul nome della VM.
- Nella console Google Cloud, vai alla pagina Istanze VM.
- Nell'elenco delle istanze di macchine virtuali, fai clic su SSH nella riga dell'istanza a cui vuoi connetterti.
Si apre una finestra SSH connessa al nodo primario.
Connected, host fingerprint: ssh-rsa 2048 ... ... user@clusterName-m:~$
Modifica l'impostazione di logging
Nella home directory del nodo principale, modifica
/etc/spark/conf/log4j.properties
.sudo nano /etc/spark/conf/log4j.properties
Imposta
log4j.rootCategory
suERROR
.# 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
Salva le modifiche ed esci dall'editor. Se vuoi riattivare il logging dettagliato, annulla la modifica ripristinando il valore originale di
.rootCategory
(INFO
).
Linguaggi di programmazione Spark
Spark supporta Python, Scala e Java come linguaggi di programmazione per le applicazioni autonome e fornisce interpreti interattivi per Python e Scala. La lingua scelta dipende dalle preferenze personali. Questo tutorial utilizza gli interpreti interattivi perché puoi sperimentare modificando il codice, provando diversi valori di input e visualizzando i risultati.
Stimare la crescita del portafoglio
In finanza, i metodi Monte Carlo vengono a volte usati per eseguire simulazioni volte a prevedere il potenziale rendimento di un investimento. Producendo campioni casuali di risultati in una serie di probabili condizioni di mercato, una simulazione Monte Carlo può rispondere a domande sul rendimento medio di un portafoglio o in scenari peggiori.
Segui questi passaggi per creare una simulazione che utilizzi i metodi Monte Carlo per stimare la crescita di un investimento finanziario in base ad alcuni fattori di mercato comuni.
Avvia l'interprete Python dal nodo principale di Dataproc.
pyspark
Attendi il prompt di Spark
>>>
.Inserisci il seguente codice. Assicurati di mantenere il rientro nella definizione della funzione.
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
Premi
return
finché non viene visualizzato di nuovo il messaggio di Spark.Il codice precedente definisce una funzione che modella ciò che potrebbe accadere quando un investitore ha già un conto pensionistico investito nel mercato azionario, a cui aggiunge denaro ogni anno. La funzione genera un ritorno casuale sull'investimento, in percentuale, ogni anno per la durata di un periodo specificato. La funzione prende un valore seed come parametro. Questo valore viene utilizzato per eseguire il rendering del generatore di numeri casuali, in modo che la funzione non riceva lo stesso elenco di numeri casuali ogni volta che viene eseguita. La funzione
random.normalvariate
assicura che i valori casuali avvengano in una distribuzione normale per la media e la deviazione standard specificate. La funzione aumenta il valore del portafoglio in base all'importo della crescita, che potrebbe essere positivo o negativo, e aggiunge una somma annuale che rappresenta un ulteriore investimento.Puoi definire le costanti richieste in un passaggio successivo.
Crea molti semi da fornire alla funzione. Nel messaggio Spark, inserisci il codice seguente, che genera 10.000 seed:
seeds = sc.parallelize([time.time() + i for i in range(10000)])
Il risultato dell'operazione
parallelize
è un set di dati distribuito resiliente (RDD), ovvero una raccolta di elementi ottimizzati per l'elaborazione parallela. In questo caso, l'RDD contiene seed basati sull'ora attuale del sistema.Quando crea l'RDD, Spark suddivide i dati in base al numero di worker e core disponibili. In questo caso, Spark sceglie di utilizzare otto sezioni, una per ogni core. Non è un problema per questa simulazione, che ha 10.000 elementi di dati. Per simulazioni più grandi, ogni sezione potrebbe essere superiore al limite predefinito. In questo caso, specificare un secondo parametro per
parallelize
può aumentare il numero di sezioni, il che consente di mantenere gestibile la dimensione di ogni sezione, mentre Spark utilizza comunque tutti e otto i core.Fornisci all'RDD l'RDD che contiene i semi alla funzione di crescita.
results = seeds.map(grow)
Il metodo
map
passa ogni seed dell'RDD alla funzionegrow
e aggiunge ogni risultato a un nuovo RDD, che viene archiviato inresults
. Tieni presente che questa operazione, che esegue una trasformazione, non produce i risultati immediatamente. Spark non eseguirà queste operazioni finché non saranno necessari i risultati. Questa valutazione pigra è il motivo per cui puoi inserire il codice senza che le costanti vengano definite.Specifica alcuni valori per la funzione.
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
Richiama
reduce
per aggregare i valori nell'RDD. Inserisci il seguente codice per sommare i risultati nell'RDD:sum = results.reduce(add)
Stima e visualizza il ritorno medio:
print (sum / 10000.)
Assicurati di includere il punto (
.
) alla fine. Indica aritmetica in virgola mobile.Ora cambia un'ipotesi e guarda come cambiano i risultati. Ad esempio, puoi inserire un nuovo valore per il ritorno medio del mercato:
MKT_AVG_RETURN = 0.07
Esegui di nuovo la simulazione.
print (sc.parallelize([time.time() + i for i in range(10000)]) \ .map(grow).reduce(add)/10000.)
Al termine dell'esperimento, premi
CTRL+D
per uscire dall'interprete Python.
Programmazione di una simulazione Monte Carlo in Scala
Monte Carlo, ovviamente, è una meta famosa per il gioco d'azzardo. In questa sezione, userai Scala per creare una simulazione che modella il vantaggio matematico che un casinò apprezza in un gioco di fortuna. Il "vantaggio della casa" in un vero casinò varia da gioco a gioco; ad esempio può essere superiore al 20% in keno. Questo tutorial crea un gioco semplice in cui la casa ha un vantaggio solo dell'1%. Ecco come funziona il gioco:
- Il giocatore piazza una scommessa, costituita da una serie di fiches da un fondo bancario.
- Il giocatore lancia un dado con 100 facce (non sarebbe fantastico?).
- Se il risultato del tiro è un numero compreso tra 1 e 49, il giocatore vince.
- Per i risultati da 50 a 100, il giocatore perde la scommessa.
Puoi notare che questo gioco crea uno svantaggio dell'1% per il giocatore: in 51 dei 100 risultati possibili per ogni tiro, il giocatore perde.
Per creare ed eseguire il gioco, procedi nel seguente modo:
Avvia l'interprete Scala dal nodo principale di Dataproc.
spark-shell
Copia e incolla il codice seguente per creare il gioco. Scala non ha gli stessi requisiti di Python per quanto riguarda il rientro, quindi puoi semplicemente copiare e incollare questo codice al prompt
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) }
Premi
return
finché non viene visualizzato il messaggioscala>
.Inserisci il codice seguente per giocare 25 volte. Questo è il valore predefinito per
NUMBER_OF_GAMES
.playSession()
Il tuo bankroll ha iniziato con un valore di 10 unità. È più alto o più basso, ora?
Ora simula 10.000 giocatori che scommettono 100 chip a partita. Gioca a 10.000 partite in una sessione. Questa simulazione Monte Carlo calcola la probabilità di perdere tutti i soldi prima della fine della sessione. Inserisci il seguente codice:
(sc.parallelize(1 to 10000, 500) .map(i => playSession(100000, 100, 250000)) .map(i => if (i == 0) 1 else 0) .reduce(_+_)/10000.0)
Tieni presente che la sintassi
.reduce(_+_)
è un'abbreviazione in Scala per l'aggregazione mediante una funzione di somma. È equivalente alla sintassi.reduce(add)
che hai visto nell'esempio Python.Il codice precedente esegue i seguenti passaggi:
- Crea un RDD con i risultati della riproduzione della sessione.
- Sostituisce i risultati dei giocatori in bancarotta con il numero
1
e i risultati diversi da zero con il numero0
. - Somma il numero dei giocatori in bancarotta.
- Divide il numero per il numero di giocatori.
Un risultato tipico potrebbe essere:
0.998
Il che rappresenta una garanzia quasi di perdere tutti i soldi, anche se il casinò aveva un vantaggio solo dell'1%.
Esegui la pulizia
Elimina il progetto
- Nella console Google Cloud, vai alla pagina Gestisci risorse.
- Nell'elenco dei progetti, seleziona il progetto che vuoi eliminare, quindi fai clic su Elimina.
- Nella finestra di dialogo, digita l'ID del progetto e fai clic su Chiudi per eliminare il progetto.
Passaggi successivi
- Per saperne di più sull'invio di job Spark a Dataproc senza dover utilizzare
ssh
per la connessione al cluster, consulta Dataproc - Invio di un job