Dataproc y Apache Spark proporcionan infraestructura y capacidad que puedes usar para ejecutar las simulaciones de Monte Carlo escritas en Java, Python o Scala.
Los métodos de Monte Carlo pueden ayudar a resolver un amplio rango de cuestiones sobre comercio, ingeniería, ciencia y matemáticas, entre otros campos. A través de muestras aleatorias repetidas que crean una probabilidad de distribución para una variable, una simulación de Monte Carlo puede brindar respuestas a preguntas que, de otro modo, serían imposibles de resolver. Por ejemplo, en finanzas, poner un precio a las opciones sobre acciones implica analizar las miles de formas en las que el precio de las acciones puede cambiar en el futuro. Los métodos de Monte Carlo permiten simular los cambios de precio de las acciones con un amplio rango de resultados posibles sin perder el control del dominio de las posibles causas del problema.
Antes, la ejecución de miles de simulaciones podía tardar mucho tiempo y generar grandes costos. Dataproc permite aprovisionar capacidad a pedido y pagar por minuto. Con Apache Spark, puedes usar clústeres de decenas, cientos o miles de servidores para ejecutar simulaciones de manera intuitiva y escalable con el fin de cumplir con tus necesidades. Esto significa que puedes ejecutar más simulaciones con mayor rapidez, lo que ayuda a que tu negocio innove y administre mejor los riesgos.
La seguridad siempre es importante cuando trabajas con datos financieros. Dataproc se ejecuta en Google Cloud, lo que ayuda a mantener tus datos seguros y privados de varias maneras. Por ejemplo, todos los datos se encriptan durante la transmisión y cuando están en reposo, y Google Cloud cumple con las normas ISO 27001, SOC3 y PCI.
Crea un clúster de Dataproc
Sigue los pasos para crear un clúster de Dataproc desde la consola de Google Cloud . La configuración del clúster predeterminada, que incluye nodos de dos trabajadores, es suficiente para este instructivo.
Inhabilita el registro para advertencias
De forma predeterminada, Apache Spark muestra el registro detallado en la ventana de la consola. A los fines de este instructivo, cambia el nivel de registro para registrar solo los errores. Sigue estos pasos:
Usa ssh para conectarte al nodo principal del clúster de Dataproc
El nodo principal del clúster de Dataproc tiene el sufijo -m en el nombre de la 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.

Se abrirá una ventana SSH conectada al nodo principal.
Connected, host fingerprint: ssh-rsa 2048 ... ... user@clusterName-m:~$
Cambia la configuración de registro
En el directorio principal del nodo principal, edita
/etc/spark/conf/log4j.properties.sudo nano /etc/spark/conf/log4j.propertiesConfigura
log4j.rootCategorycomoERROR.# 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%nGuarda los cambios y cierra el editor. Si deseas volver a habilitar el registro detallado, restablece el valor de
.rootCategorya su valor original (INFO) para anular el cambio.
Lenguajes de programación de Spark
Spark admite Python, Scala y Java como lenguajes de programación de aplicaciones independientes y proporciona intérpretes interactivos para Python y Scala. El lenguaje que elijas depende de tu preferencia. En este instructivo, se usan los intérpretes interactivos, ya que puedes experimentar si cambias el código, pruebas diferentes valores de entrada y visualizas los resultados.
Estima el crecimiento de la cartera
En finanzas, los métodos de Monte Carlo a veces se usan para ejecutar simulaciones que intentan predecir el rendimiento de una inversión. Un método de Monte Carlo produce muestras aleatorias de resultados en un rango de condiciones posibles de mercado para resolver preguntas sobre el rendimiento de una cartera en promedio o en los peores casos.
Sigue estos pasos para crear una simulación que use los métodos de Monte Carlo a fin de intentar calcular el crecimiento de una inversión financiera según los factores de mercado comunes.
Inicia el intérprete de Python desde el nodo principal de Dataproc.
pysparkEspera el mensaje de Spark
>>>.Ingresa el siguiente código. Asegúrate de mantener la sangría en la definición de la función.
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_valuePresiona
returnhasta que aparezca el mensaje de Spark.En el código anterior, se define una función que modela lo que puede ocurrir cuando un inversionista tiene una cuenta de retiro existente que se invirtió en el mercado de valores y a la que se le agrega dinero todos los años. La función genera un retorno de la inversión aleatorio, como porcentaje, cada año por un período específico y toma un valor inicial como parámetro. Este valor se usa para reiniciar el generador de números aleatorios a fin de garantizar que la función no obtenga la misma lista de números cada vez que se ejecuta. La función
random.normalvariategarantiza que se produzcan valores aleatorios en una distribución normal para la media y la desviación estándar especificadas. La función aumenta el valor de la cartera según el nivel de crecimiento que puede ser positivo o negativo y agrega una suma anual que representa las inversiones adicionales.Definirás las constantes requeridas en otro paso.
Crea muchos valores iniciales para la función. En el indicador de Spark, ingresa este código que genera 10,000 valores iniciales:
seeds = sc.parallelize([time.time() + i for i in range(10000)])El resultado de la operación
parallelizees un conjunto de datos resilientes y distribuidos (RDD), que es una colección de elementos optimizados para el procesamiento paralelo. En este caso, el RDD contiene valores iniciales que se basan en la hora actual del sistema.Cuando Spark crea el RDD, divide los datos según el número de trabajadores y núcleos disponibles. En este caso, Spark usa ocho divisiones, una por cada núcleo. Es lo adecuado para esta simulación que tiene datos de 10,000 elementos. Sin embargo, en simulaciones de mayor tamaño, cada división puede superar el límite predeterminado. En ese caso, especificar un segundo parámetro en
parallelizepuede aumentar la cantidad de fragmentos, lo que puede ayudar a mantener el tamaño de cada fragmento administrable, mientras Spark aún aprovecha los ocho núcleos.Provee valores al RDD que contiene los valores iniciales de la función de crecimiento.
results = seeds.map(grow)El método
mappasa cada valor inicial en el RDD a la funcióngrowy agrega cada resultado a un nuevo RDD, que se almacena enresults. Ten en cuenta que esta operación, que realiza una transformación, no produce los resultados de inmediato. Spark no hará este trabajo hasta que se necesiten los resultados. Esta evaluación diferida es la razón por la que puedes ingresar el código sin definir las constantes.Especifica algunos valores para la función.
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 deviationLlama a
reducepara agregar los valores en el RDD. Ingresa el siguiente código para sumar los resultados en el RDD:sum = results.reduce(add)Calcula y muestra el retorno promedio:
print (sum / 10000.)Asegúrate de incluir el carácter del punto (
.) al final. Significa la aritmética de coma flotante.Ahora modifica la suposición y verás cómo cambian los resultados. Por ejemplo, puedes ingresar un valor nuevo para el resultado promedio del mercado:
MKT_AVG_RETURN = 0.07Vuelve a ejecutar la simulación.
print (sc.parallelize([time.time() + i for i in range(10000)]) \ .map(grow).reduce(add)/10000.)Cuando termines de experimentar, presiona
CTRL+Dpara salir del intérprete de Python.
Programa una simulación de Monte Carlo en Scala
Montecarlo es un destino de juego famoso. En esta sección, usarás Scala para crear una simulación que modele la ventaja matemática que podría usar un casino en un juego de azar. La “ventaja de la casa” en un casino real varía mucho según el juego; en keno, por ejemplo, puede ser de alrededor del 20%. En este instructivo, se crea un juego sencillo en el que la ventaja de la casa es solo del uno por ciento. Así es cómo funciona el juego:
- El jugador hace una apuesta que consiste de un número de fichas del fondo de dinero.
- Luego, lanza un dado de 100 lados (¿no sería estupendo?).
- Si el resultado es un número del 1 al 49, el jugador gana.
- Si está entre el 50 y el 100, pierde la apuesta.
Como se ve, en este juego se crea una desventaja del uno por ciento para el jugador: en 51 de los 100 posibles resultados pierde.
Sigue estos pasos para crear y ejecutar el juego:
Inicia el intérprete de Scala desde el nodo principal de Dataproc.
spark-shellCopia y pega este código para crear el juego. Scala no tiene los mismos requisitos que Python en lo que respecta a las sangrías, por lo que puedes solo copiar y pegar el código en el mensaje de
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) }Presiona
returnhasta que aparezca el mensajescala>.Ingresa el siguiente código para jugar 25 veces al juego, que es el número predeterminado de
NUMBER_OF_GAMES.playSession()Tus fondos comienzan con un valor de 10 unidades. ¿Ahora, es mayor o menor?
Simula 10,000 jugadores que apuestan 100 fichas por juego. Juega 10,000 juegos en una sesión. Esta simulación de Monte Carlo calcula la probabilidad de perder todo tu dinero antes de que finalice la sesión. Ingresa el siguiente código:
(sc.parallelize(1 to 10000, 500) .map(i => playSession(100000, 100, 250000)) .map(i => if (i == 0) 1 else 0) .reduce(_+_)/10000.0)Ten en cuenta que la sintaxis
.reduce(_+_)en Scala es la abreviación para agregar con una función de suma. Su función equivale a la sintaxis.reduce(add)que viste en el ejemplo de Python.El código anterior realiza las siguientes acciones:
- Crea un RDD con los resultados de juego de una sesión.
- Reemplaza los resultados de los jugadores en quiebra con el número
1y los resultados que no son cero con el número0. - Suma la cantidad de jugadores en quiebra.
- La divide por el número de jugadores.
Un resultado típico puede ser:
0.998
Este representa casi una garantía de que perderás todo tu dinero, incluso si la ventaja del casino solo era del uno por ciento.