Dataproc et Apache Spark fournissent l'infrastructure et la capacité nécessaires pour exécuter Monte-Carlo des simulations écrites en Java, Python ou Scala.
Les méthodes de Monte-Carlo peuvent permettre de répondre à un large éventail de questions dans les domaines des affaires, de l'ingénierie, des sciences, des mathématiques, etc. En procédant par échantillonnage aléatoire répété afin de créer une distribution de probabilité pour une variable, une simulation Monte-Carlo permet de répondre à des questions qui seraient insolubles par tout autre moyen. Ainsi, dans le domaine financier, la fixation du prix d'une option sur titres nécessite d'analyser les milliers de façons dont le cours de ce titre pourrait varier sur une certaine période. Les méthodes de Monte-Carlo offrent un moyen de simuler ces variations de cours des actions sur différents résultats possibles, tout en gardant le contrôle sur le domaine des intrants possibles du problème.
Auparavant, l'exécution de milliers de simulations pouvait prendre un temps considérable et engendrer des coûts élevés. Dataproc vous offre la possibilité de provisionner la capacité à la demande en payant à la minute. Apache Spark vous permet d'utiliser des clusters de plusieurs dizaines, centaines ou milliers de serveurs pour exécuter des simulations de manière intuitive et évolutive en fonction de vos besoins. Résultat : vous pouvez exécuter plus de simulations en moins de temps, ce qui peut aider votre entreprise à innover plus rapidement et à mieux gérer les risques.
La sécurité est toujours importante lorsque vous travaillez sur des données financières. Dataproc s'exécute sur Google Cloud, qui vous offre plusieurs moyens de gérer vos données de manière sécurisée et privée. Par exemple, toutes les données sont chiffrées pendant la transmission et au repos. En outre, Google Cloud est conforme aux normes ISO 27001, SOC3 et PCI.
Objectifs
- Créer un cluster Dataproc géré avec Apache Spark préinstallé
- Exécuter une simulation Monte-Carlo à l'aide de Python pour estimer la croissance d'un portefeuille d'actions au fil du temps
- Exécuter une simulation Monte-Carlo à l'aide de Scala pour simuler les gains d'un casino
Coûts
Dans ce document, vous utilisez les composants facturables suivants de Google Cloud :
Obtenez une estimation des coûts en fonction de votre utilisation prévue à l'aide du simulateur de coût.
Une fois que vous avez terminé les tâches décrites dans ce document, vous pouvez éviter de continuer à payer des frais en supprimant les ressources que vous avez créées. Pour en savoir plus, consultez la section Effectuer un nettoyage.
Avant de commencer
- Configurez un projet Google Cloud
- 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.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Dataproc and Compute Engine APIs.
- Install the Google Cloud CLI.
-
To initialize the gcloud CLI, run the following command:
gcloud init
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Dataproc and Compute Engine APIs.
- Install the Google Cloud CLI.
-
To initialize the gcloud CLI, run the following command:
gcloud init
Création d'un cluster Dataproc
Suivez les étapes permettant de créer un cluster Dataproc à partir de Google Cloud Console. Les paramètres de cluster par défaut prévoient deux nœuds de calcul, ce qui suffit pour ce tutoriel.
Désactiver la journalisation des avertissements
Par défaut, Apache Spark imprime une journalisation détaillée dans la fenêtre de la console. Pour les besoins de ce tutoriel, modifiez le niveau de journalisation pour ne consigner que les erreurs. Procédez comme suit :
Utiliser ssh
pour se connecter au nœud principal du cluster Dataproc
Le nœud principal du cluster Dataproc comporte le suffixe -m
sur son nom de VM.
- In the Google Cloud console, go to the VM instances page.
- In the list of virtual machine instances, click SSH in the row of the instance that you want to connect to.
Une fenêtre SSH s'ouvre, connectée au nœud principal.
Connected, host fingerprint: ssh-rsa 2048 ... ... user@clusterName-m:~$
Redéfinir le paramètre de journalisation
Dans le répertoire d'accueil du nœud principal, modifiez le fichier
/etc/spark/conf/log4j.properties
.sudo nano /etc/spark/conf/log4j.properties
Définissez
log4j.rootCategory
surERROR
.# 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
Enregistrez les modifications, puis quittez l'éditeur. Si vous souhaitez réactiver la journalisation détaillée, annulez la modification en rétablissant la valeur d'origine (
INFO
) de.rootCategory
.
Langages de programmation Spark
Spark accepte les langages de programmation Python, Scala et Java pour les applications autonomes, et fournit des interpréteurs interactifs pour Python et Scala. Le choix de tel ou tel langage est une question de préférence personnelle. Dans ce tutoriel, nous utilisons les interpréteurs interactifs, car ils vous permettent de faire des tests en modifiant le code et en essayant différentes valeurs de saisie, puis en affichant les résultats.
Estimer la croissance d'un portefeuille
Dans le domaine de la finance, les méthodes de Monte-Carlo servent parfois à effectuer des simulations visant à prédire la performance d'un investissement. En produisant des échantillons aléatoires de résultats sur une plage de conditions de marché probables, une simulation Monte-Carlo peut répondre aux questions concernant la performance d'un portefeuille pour une situation moyenne ou dans le pire cas de figure.
Suivez ces étapes pour créer une simulation basée sur les méthodes de Monte-Carlo pour essayer d'estimer la rentabilité d'un investissement financier en fonction de quelques facteurs de marché courants.
Démarrez l'interpréteur Python à partir du nœud principal Dataproc.
pyspark
Attendez l'invite Spark
>>>
.Saisissez le code ci-dessous. Veillez à conserver les retraits dans la définition de la fonction.
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
Appuyez sur
return
jusqu'à ce que l'invite Spark réapparaisse.Le code qui précède définit une fonction qui modélise ce qui pourrait se produire pour un investisseur disposant d'un compte d'épargne-retraite investi en actions, sur lequel il effectue tous les ans un versement complémentaire. La fonction génère chaque année un retour sur investissement aléatoire exprimé en pourcentage pour une durée de terme spécifiée. La fonction reçoit pour paramètre une graine. Cette valeur permet de réinitialiser le générateur de nombres aléatoires, ce qui garantit que la fonction ne reçoit pas la même liste de nombres aléatoires à chaque exécution. La fonction
random.normalvariate
garantit que les valeurs aléatoires se situent au cours d'une distribution normale pour l'écart moyen et l'écart type spécifiés. La fonction augmente la valeur du portefeuille du montant de la croissance, qui peut être positif ou négatif, et ajoute une somme annuelle représentant un investissement supplémentaire.Vous définissez les constantes requises lors d'une prochaine étape.
Créez de nombreuses valeurs initiales pour alimenter la fonction. À l'invite Spark, saisissez le code suivant, qui génère 10 000 valeurs initiales :
seeds = sc.parallelize([time.time() + i for i in range(10000)])
Le résultat de l'opération
parallelize
est un ensemble de données distribué résilient (RDD, Resilient Distributed Dataset), c'est-à-dire un ensemble d'éléments optimisés pour le traitement en parallèle. Dans notre exemple, ce RDD contient des valeurs initiales basées sur l'heure système actuelle.Lors de la création du RDD, Spark divise les données en fonction du nombre de nœuds de calcul et de cœurs disponibles. Ici, Spark choisit d'utiliser huit tranches, soit une tranche par cœur. Cette valeur convient pour la présente simulation, qui porte sur 10 000 éléments de données. Dans des simulations plus importantes, chaque tranche pourrait dépasser la limite par défaut. Dans ce cas, spécifier un second paramètre sur la valeur
parallelize
permet d'augmenter le nombre de tranches, ce qui peut aider à maintenir une taille gérable pour chaque tranche, sans empêcher Spark d'exploiter les huit cœurs.Transmettez les valeurs initiales contenues dans le RDD à la fonction grow.
results = seeds.map(grow)
La méthode
map
transmet chaque graine du RDD à la fonctiongrow
et ajoute chaque résultat à un nouveau RDD, qui est stocké dans les résultats (results
). Notez que cette opération, qui effectue une transformation, ne produit pas immédiatement ses résultats. Spark n'effectue ce travail qu'au moment où les résultats sont requis. Cette évaluation minimaliste explique pourquoi vous pouvez saisir du code sans avoir préalablement défini les constantes.Spécifiez certaines valeurs pour la fonction.
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
Appelez
reduce
pour agréger les valeurs du RDD. Saisissez le code suivant pour additionner les résultats stockés dans le RDD :sum = results.reduce(add)
Estimez et affichez le rendement moyen :
print (sum / 10000.)
Veillez à saisir le point (
.
) final, qui signifie que vous utilisez l'arithmétique en virgule flottante.Vous allez maintenant modifier une hypothèse et découvrir comment cela influe sur les résultats. Par exemple, vous pouvez saisir une nouvelle valeur pour le rendement moyen du marché :
MKT_AVG_RETURN = 0.07
Lancez à nouveau la simulation.
print (sc.parallelize([time.time() + i for i in range(10000)]) \ .map(grow).reduce(add)/10000.)
Lorsque vous avez terminé vos tests, appuyez sur
CTRL+D
pour quitter l'interpréteur Python.
Programmation d'une simulation Monte-Carlo en langage Scala
Comme chacun sait, Monte-Carlo est la destination de référence pour les jeux de hasard. Dans cette section, vous allez utiliser Scala afin de créer une simulation qui modélise l'avantage mathématique dont bénéficie un casino dans un jeu de hasard. La "marge maison" d'un véritable casino varie sensiblement d'un jeu à un autre. Par exemple, elle peut dépasser 20 % au Keno. Dans ce tutoriel, nous allons créer un jeu simple dans lequel la maison n'a qu'un avantage de 1 %. Voici comment ce jeu se déroule :
- Le joueur place une mise consistant en un certain nombre de jetons provenant de sa cagnotte.
- Le joueur lance un dé à 100 faces (amusant, non ?).
- Si le résultat du lancer est un nombre compris entre 1 et 49, le joueur gagne.
- En cas de résultat compris entre 50 et 100, le joueur perd sa mise.
À l'évidence, ce jeu crée un désavantage de 1 % pour le joueur : 51 des 100 résultats possibles pour chaque lancer lui font perdre sa mise.
Suivez ces étapes pour créer et exécuter le jeu :
Démarrez l'interpréteur Scala à partir du nœud principal Dataproc.
spark-shell
Copiez et collez le code ci-après pour créer le jeu. Scala n'a pas les mêmes exigences que Python en matière de retrait : vous pouvez donc vous contenter de copier le code et de le coller lorsque l'invite
scala>
s'affiche.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) }
Appuyez sur
return
jusqu'à ce que l'invitescala>
réapparaisse.Saisissez le code suivant pour jouer 25 fois au jeu. Il s'agit de la valeur par défaut du paramètre
NUMBER_OF_GAMES
.playSession()
Votre cagnotte contenait 10 unités au départ. Et maintenant, a-t-elle augmenté ou diminué ?
Simulez à présent 10 000 joueurs misant 100 jetons par partie. Faites 10 000 parties en une session. Cette simulation Monte-Carlo calcule la probabilité de perdre tout votre argent avant la fin de la session. Saisissez le code suivant :
(sc.parallelize(1 to 10000, 500) .map(i => playSession(100000, 100, 250000)) .map(i => if (i == 0) 1 else 0) .reduce(_+_)/10000.0)
Notez la syntaxe
.reduce(_+_)
: il s'agit d'une notation abrégée en Scala pour désigner une agrégation à l'aide d'une fonction de sommation. Elle est fonctionnellement équivalente à la notation.reduce(add)
que vous avez pu voir dans l'exemple Python.Le code ci-dessus effectue les étapes suivantes :
- Créer un RDD contenant les résultats des parties jouées au cours de la session
- Remplacer les résultats des joueurs ruinés par le nombre
1
et les résultats non nuls par le nombre0
- Calculer le nombre total de joueurs ruinés
- Diviser ce nombre par le nombre de joueurs
Voici le type de résultat que vous pouvez obtenir :
0.998
Ce résultat est la quasi-garantie de perdre tout votre argent, même si le casino n'avait qu'un avantage de 1 %.
Effectuer un nettoyage
Supprimer le projet
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
Étape suivante
- Pour savoir comment envoyer des tâches Spark à Dataproc sans avoir à vous connecter en
ssh
au cluster, consultez la section Envoyer une tâche de la documentation Cloud Dataproc.