O Dataproc e o Apache Spark oferecem infraestrutura e capacidade que pode usar para executar simulações de Monte Carlo escritas em Java, Python ou Scala.
Os métodos de Monte Carlo podem ajudar a responder a uma grande variedade de perguntas em áreas como negócios, engenharia, ciência, matemática e outras. Ao usar a amostragem aleatória repetida para criar uma distribuição de probabilidade para uma variável, uma simulação de Monte Carlo pode fornecer respostas a perguntas que, de outra forma, seriam impossíveis de responder. Nas finanças, por exemplo, a definição do preço de uma opção de ações requer a análise das milhares de formas como o preço das ações pode mudar ao longo do tempo. Os métodos de Monte Carlo oferecem uma forma de simular essas alterações do preço das ações num vasto leque de resultados possíveis, ao mesmo tempo que mantêm o controlo sobre o domínio das entradas possíveis para o problema.
Anteriormente, a execução de milhares de simulações podia demorar muito tempo e acumular custos elevados. O Dataproc permite-lhe aprovisionar capacidade a pedido e pagar por minuto. O Apache Spark permite-lhe usar clusters de dezenas, centenas ou milhares de servidores para executar simulações de uma forma intuitiva e dimensionável para satisfazer as suas necessidades. Isto significa que pode executar mais simulações mais rapidamente, o que pode ajudar a sua empresa a inovar mais rapidamente e a gerir melhor o risco.
A segurança é sempre importante quando trabalha com dados financeiros. O Dataproc é executado no Google Cloud, o que ajuda a manter os seus dados seguros, protegidos e privados de várias formas. Por exemplo, todos os dados são encriptados durante a transmissão e quando estão em repouso, e Google Cloud são conformes com as normas ISO 27001, SOC3 e PCI.
Objetivos
- Crie um cluster do Dataproc gerido com o Apache Spark pré-instalado.
- Execute uma simulação de Monte Carlo com Python que estime o crescimento de uma carteira de ações ao longo do tempo.
- Executar uma simulação de Monte Carlo com o Scala que simula como um casino ganha dinheiro.
Custos
Neste documento, usa os seguintes componentes faturáveis do Google Cloud:
Para gerar uma estimativa de custos com base na sua utilização projetada,
use a calculadora de preços.
Quando terminar as tarefas descritas neste documento, pode evitar a faturação contínua eliminando os recursos que criou. Para mais informações, consulte o artigo Limpe.
Antes de começar
- Configure um Google Cloud projeto
- 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.
Roles required to select or create a project
- Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
-
Create a project: To create a project, you need the Project Creator
(
roles/resourcemanager.projectCreator
), which contains theresourcemanager.projects.create
permission. Learn how to grant roles.
-
Verify that billing is enabled for your Google Cloud project.
-
Enable the Dataproc and Compute Engine APIs.
Roles required to enable APIs
To enable APIs, you need the Service Usage Admin IAM role (
roles/serviceusage.serviceUsageAdmin
), which contains theserviceusage.services.enable
permission. Learn how to grant roles. -
Install the Google Cloud CLI.
-
Se estiver a usar um fornecedor de identidade (IdP) externo, tem primeiro de iniciar sessão na CLI gcloud com a sua identidade federada.
-
Para inicializar a CLI gcloud, execute o seguinte comando:
gcloud init
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
Roles required to select or create a project
- Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
-
Create a project: To create a project, you need the Project Creator
(
roles/resourcemanager.projectCreator
), which contains theresourcemanager.projects.create
permission. Learn how to grant roles.
-
Verify that billing is enabled for your Google Cloud project.
-
Enable the Dataproc and Compute Engine APIs.
Roles required to enable APIs
To enable APIs, you need the Service Usage Admin IAM role (
roles/serviceusage.serviceUsageAdmin
), which contains theserviceusage.services.enable
permission. Learn how to grant roles. -
Install the Google Cloud CLI.
-
Se estiver a usar um fornecedor de identidade (IdP) externo, tem primeiro de iniciar sessão na CLI gcloud com a sua identidade federada.
-
Para inicializar a CLI gcloud, execute o seguinte comando:
gcloud init
- 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.
No diretório principal do nó principal, edite
/etc/spark/conf/log4j.properties
.sudo nano /etc/spark/conf/log4j.properties
Defina
log4j.rootCategory
igual aERROR
.# 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
Guarde as alterações e saia do editor. Se quiser ativar novamente o registo verboso, inverta a alteração restaurando o valor de
.rootCategory
para o valor original (INFO
).Inicie o intérprete Python a partir do nó principal do Dataproc.
pyspark
Aguarde o comando do Spark
>>>
.Introduza o seguinte código. Certifique-se de que mantém o recuo na definição da função.
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
Prima
return
até ver novamente o comando do Spark.O código anterior define uma função que modela o que pode acontecer quando um investidor tem uma conta de reforma existente que é investida no mercado de ações, à qual adiciona dinheiro adicional todos os anos. A função gera um retorno aleatório do investimento, como percentagem, todos os anos durante um prazo especificado. A função usa um valor de semente como parâmetro. Este valor é usado para reiniciar o gerador de números aleatórios, o que garante que a função não recebe a mesma lista de números aleatórios sempre que é executada. A função
random.normalvariate
garante que os valores aleatórios ocorrem numa distribuição normal para a média e o desvio padrão especificados. A função aumenta o valor da carteira pelo valor de crescimento, que pode ser positivo ou negativo, e adiciona uma soma anual que representa um investimento adicional.Define as constantes necessárias num passo seguinte.
Crie muitas sementes para introduzir na função. No comando do Spark, introduza o seguinte código, que gera 10 000 origens:
seeds = sc.parallelize([time.time() + i for i in range(10000)])
O resultado da operação
parallelize
é um conjunto de dados distribuídos resilientes (RDD), que é uma coleção de elementos otimizados para processamento paralelo. Neste caso, o RDD contém sementes baseadas na hora atual do sistema.Quando cria o RDD, o Spark divide os dados com base no número de trabalhadores e núcleos disponíveis. Neste caso, o Spark opta por usar oito fatias, uma fatia para cada núcleo. Não há problema para esta simulação, que tem 10 000 itens de dados. Para simulações maiores, cada fatia pode ser maior do que o limite predefinido. Nesse caso, especificar um segundo parâmetro pode aumentar o número de divisões, o que pode ajudar a manter o tamanho de cada divisão gerível, enquanto o Spark continua a tirar partido de todos os oito núcleos.
parallelize
Introduza o RDD que contém as sementes na função de crescimento.
results = seeds.map(grow)
O método
map
passa cada valor inicial no RDD para a funçãogrow
e anexa cada resultado a um novo RDD, que é armazenado emresults
. Tenha em atenção que esta operação, que executa uma transformação, não produz os respetivos resultados de imediato. O Spark não realiza este trabalho até os resultados serem necessários. Esta avaliação tardia é o motivo pelo qual pode introduzir código sem que as constantes estejam definidas.Especifique alguns valores para a função.
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
Chame
reduce
para agregar os valores no RDD. Introduza o seguinte código para somar os resultados no RDD:sum = results.reduce(add)
Estimar e apresentar o retorno médio:
print (sum / 10000.)
Certifique-se de que inclui o caráter de ponto (
.
) no final. Significa aritmética de vírgula flutuante.Agora, altere uma suposição e veja como os resultados mudam. Por exemplo, pode introduzir um novo valor para o retorno médio do mercado:
MKT_AVG_RETURN = 0.07
Execute a simulação novamente.
print (sc.parallelize([time.time() + i for i in range(10000)]) \ .map(grow).reduce(add)/10000.)
Quando terminar de experimentar, prima
CTRL+D
para sair do intérprete Python.- O jogador faz uma aposta, que consiste num número de fichas de um fundo de capital.
- O jogador lança um dado de 100 lados (não seria fantástico?).
- Se o resultado do lançamento for um número entre 1 e 49, o jogador ganha.
- Para resultados entre 50 e 100, o jogador perde a aposta.
Inicie o intérprete Scala a partir do nó principal do Dataproc.
spark-shell
Copie e cole o seguinte código para criar o jogo. O Scala não tem os mesmos requisitos que o Python no que diz respeito à indentação, pelo que pode simplesmente copiar e colar este código no comando
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) }
Prima
return
até ver o comandoscala>
.Introduza o seguinte código para jogar o jogo 25 vezes, que é o valor predefinido para
NUMBER_OF_GAMES
.playSession()
A sua banca começou com um valor de 10 unidades. É mais alto ou mais baixo agora?
Agora,simule 10 000 jogadores a apostar 100 fichas por jogo. Jogue 10 000 jogos numa sessão. Esta simulação de Monte Carlo calcula a probabilidade de perder todo o seu dinheiro antes do final da sessão. Introduza o seguinte 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)
Tenha em atenção que a sintaxe
.reduce(_+_)
é uma abreviatura em Scala para agregar usando uma função de soma. É funcionalmente equivalente à sintaxe.reduce(add)
que viu no exemplo de Python.O código anterior executa os seguintes passos:
- Cria um RDD com os resultados da reprodução da sessão.
- Substitui os resultados dos jogadores em falência pelo número
1
e os resultados diferentes de zero pelo número0
. - Soma o número de jogadores que ficaram falidos.
- Divide a contagem pelo número de jogadores.
Um resultado típico pode ser:
0.998
O que representa uma garantia quase total de perder todo o seu dinheiro, apesar de o casino ter apenas uma vantagem de um por cento.
- 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.
- Para mais informações sobre o envio de tarefas do Spark para o Dataproc sem ter de usar o
ssh
para se ligar ao cluster, leia o artigo Dataproc: envie uma tarefa
Crie um cluster do Dataproc
Siga os passos para criar um cluster do Dataproc a partir da Google Cloud consola. As predefinições do cluster, que incluem dois nós de trabalho, são suficientes para este tutorial.
Desative o registo de avisos
Por predefinição, o Apache Spark imprime o registo detalhado na janela da consola. Para os fins deste tutorial, altere o nível de registo para registar apenas erros. Siga estes passos:
Use
ssh
para se ligar ao nó principal do cluster do DataprocO nó principal do cluster do Dataproc tem o sufixo
-m
no nome da respetiva VM.É aberta uma janela SSH ligada ao nó principal.
Connected, host fingerprint: ssh-rsa 2048 ... ... user@clusterName-m:~$
Altere a definição de registo
Linguagens de programação do Spark
O Spark suporta Python, Scala e Java como linguagens de programação para aplicações autónomas e oferece intérpretes interativos para Python e Scala. O idioma que escolher é uma questão de preferência pessoal. Este tutorial usa os intérpretes interativos porque pode experimentar alterar o código, tentar diferentes valores de entrada e, em seguida, ver os resultados.
Estime o crescimento do portefólio
Na área financeira, os métodos de Monte Carlo são, por vezes, usados para executar simulações que tentam prever o desempenho de um investimento. Ao produzir amostras aleatórias de resultados num intervalo de condições de mercado prováveis, uma simulação de Monte Carlo pode responder a perguntas sobre o desempenho médio de um portefólio ou em cenários de pior caso.
Siga estes passos para criar uma simulação que usa métodos de Monte Carlo para tentar estimar o crescimento de um investimento financeiro com base em alguns fatores de mercado comuns.
Programe uma simulação de Monte Carlo em Scala
Claro que Monte Carlo é famosa como destino de jogos de azar. Nesta secção, usa o Scala para criar uma simulação que modela a vantagem matemática que um casino tem num jogo de azar. A "vantagem da casa" num casino real varia muito de jogo para jogo. Por exemplo, pode ser superior a 20% no keno. Este tutorial cria um jogo simples em que a casa tem apenas uma vantagem de um por cento. Veja como funciona o jogo:
Pode ver que este jogo cria uma desvantagem de 1% para o jogador: em 51 dos 100 resultados possíveis para cada lançamento, o jogador perde.
Siga estes passos para criar e executar o jogo:
Limpar
Elimine o projeto
O que se segue?