POE: Ambiente de Simulação

 O POE (Portfolio Optimization Env) é um ambiente de simulação para treinar agentes otimizadores de carteira de ações utilizando aprendizado por reforço. O ambiente é fácil de usar e segue os padrões do Gymnasium e, por isso, é integrável a diversas bibliotecas de algoritmos de aprendizado por reforço (como o stable baselines 3). 

O POE faz uso da formulação estado da arte de aprendizado por reforço, tornando fácil para desenvolvedores e pesquisadores produzirem conhecimento e desenvolverem sistemas otimizadores de portfólio de alto desempenho.

Simulação

Em um ambiente de aprendizado por reforço, é necessário que a simulação seja capaz de, a cada instante de tempo, receber uma ação do agente, definir a recompensa recebida por concluir aquela ação e retornar ao agente uma recompensa, de modo que ele tente maximizá-la a longo prazo e  para aprender a melhor política de ações a se seguir. No POE, esses três parâmetros são definidos como explicado a seguir.

ões esperadas

A ação que um agente deve fazer para interagir com o ambiente é chamada de "vetor porfólio". Sendo um com N ações, o vetor portfólio possui tamanho N+1, pois representa a proporção de valor investido em cada um dos componentes da carteira. O primeiro valor do portfólio sempre se refere ao valor não investido em nada (ou seja, valor imediatamente disponível para o investidor) e os outros N elementos se referem aos outros componentes da carteira.

Dessa forma, em uma carteira com as ações PETR4, VALE3 e VIVT3, por exemplo, um vetor portfólio W = [0.1, 0.3, 0.5, 0.2] expressa que, naquele instante de tempo, a carteira possui 10% do seu valor não-investido e 30%, 50% e 20% do seu valor investido nos componentes PETR4, VALE3 e VIVT3 respectivamente.

Assim, o agente deve fazer continuamente o balanceamento da carteira de modo a aumentar o lucro a longo prazo.

Observações retornadas

Neste ambiente de simulação, há dois tipos diferentes de observação: uma que retorna somente a série temporal dos componentes da carteira e outra que inclui a última ação feita pelo agente (algo útil em alguns algoritmos).

❗É possível modificar o tipo de observação por meio do parâmetro return_last_action ao instanciar o ambiente.

Recompensas recebidas

O ambiente envia ao agente uma recompensa que é dada pelo logaritmo natural da razão entre o valor da carteira antes e depois do step de simulação. Assim, a recompensa é positiva em caso de lucro e negativa em caso de perdas financeiras. Além disso, ela possui valores próximos de zero.

Steps e episódios

No POE, o período definido por um step de simulação depende dos dados de entrada: se os dados tiverem valores diários de ações, por exemplo, um step de simulação calcula a variação do portfólio de um dia para o outro. 

Já um episódio de simulação engloba todos os steps contidos nos dados de entrada: se eles contiverem 100 dias do preço das ações, por exemplo, um episódio será composto por 100 steps menos o tamanho da janela de tempo utilizada pelo agente (já que o balanceamento somente começará quando o agente tiver uma janela de tamanho definida). 

Detalhes da simulação

Detalhes sobre a simulação implementada podem ser encontrados no artigo publicado no workshop brasileiro de IA em finanças, organizado pela Sociedade Brasileira de Computação (SBC). A imagem a seguir redireciona para a biblioteca digital da SBC.

Instalação

O ambiente faz parte da biblioteca FinRL-Meta, um repositório com diversos ambientes de simulação para aprendizado por reforço. Por isso, para instalar o POE, basta clonar o repositório e acessar o ambiente, que está na pasta FinRL-Meta/meta/env_portfolio_optimization/

Em breve, o ambiente será adicionado ao FinRL, biblioteca que contém, não só ambientes, mas agentes de aprendizado por reforço. A adição do POE ainda está em processo de revisão.

Utilizando o POE

Preparando os dados

Antes de utilizar o POE, é necessário ter em mãos os dados financeiros que serão utilizados na simulação. Esses dados devem estar em forma de Pandas Dataframe, e devem ter mais ou menos o seguinte formato:

    date        high            low             close           tic

0   2020-12-23  0.157414        0.127420        0.136394        ADA-USD

1   2020-12-23  34.381519       30.074295       31.097898       BNB-USD

2   2020-12-23  24024.490234    22802.646484    23241.345703    BTC-USD

3   2020-12-23  0.004735        0.003640        0.003768        DOGE-USD

4   2020-12-23  637.122803      560.364258      583.714600      ETH-USD

... ...         ...             ...             ...             ...

O nome das colunas é irrelevante pois, durante a instanciação do ambiente, é possível explicitar os nomes que serão utilizados. Apesar disso, é importante que o dataframe possua uma coluna de datas e outra com o nome da ação, moeda, etc. É necessário que, para todos os dias existentes no dataframe, existam dados de todas os componentes do portfólio.

Instanciando o ambiente

Uma vez tendo os dados em mãos, iniciar o ambiante é extremamente fácil. Basta utilizar a classe PortfolioOptimizationEnv e definir seus múltiplos parâmetros, como no exemplo abaixo, em que os dados estão na variável df_portfolio.

Os únicos argumentos obrigatórios são o dataframe de dados e o valor inicial do portfólio, que são necessários para que a simulação consiga ocorrer. Mas, é possível utilizar outros argumentos, como foi feito no exemplo anterior. Alguns argumentos interessantes são:

Diversos outros parâmetros encontram-se documentados no código do ambiente.

Resetando o ambiente

Antes de iniciar a simulação, é preciso resetar o ambiente. Isso é necessário pois considera-se que um episódio ocorre enquanto o ambiente percorre o período de dados do dataframe e, ao chegar ao final, o ambiente fica em estado terminal até que um reset ocorra. Para fazer um reset, basta rodar:

A variável retornada se refere à observação inicial do agente, antes de ocorrer qualquer passagem de tempo no episódio.

❗Observação

Note que esta interface é a antiga interface do Gym, predecessor do Gymnasium. Alguns algoritmos (como por exemplo, do stable baselines 3), podem utilizar a nova interface que retorna, além da obs, uma variável info, que é um dicionário com informações sobre o início da simulação. Para utilizar esse nova interface, use o parâmetro new_gym_api=True na instanciação do ambiente. Iremos, eventualmente, fazer a nova interface ser a padrão.

Para mais detalhes sobre a mudança de API, visite este site.

Executando um step de simulação

Para executar um step, basta chamar a função chamada step, passando a ação que deseja ser feita, como em todos os ambientes que uitilizam o padrão do Gymnasium.

As variáveis retornadas são a observação do novo estado do agente após a simulação, sua recompensa recebida, se o estado foi final ou não e um dicionário com informações gerais da simulação feita.

❗Observação

Note que esta interface é a antiga interface do Gym, predecessor do Gymnasium. Alguns algoritmos (como por exemplo, do stable baselines 3), podem utilizar a nova interface que retorna, além dessas 4, uma variável truncated, que define se o episódio terminou por alcançar um tempo máximo. Para utilizar esse nova interface, use o parâmetro new_gym_api=True na instanciação do ambiente. Iremos, eventualmente, fazer a nova interface ser a padrão.

Para mais detalhes sobre a mudança de API, visite este site.

Exemplos

O código a seguir implementa a estratégia uniform buy and hold (comprar ações e segurá-las indefinidamente) aplicadas ao POE. Considere que a variável df_portfolio existe e foi previamente definida.

Repare como a ação é definida: criamos um array com PORTFOLIO_SIZE+1 elementos: o primeiro valor é 0 pois não queremos nenhum dinheiro sem investimento e os outros valores são razões iguais, indicando que investiu-se igualmente nas ações.

Um outro exemplo mais complexo, fazendo uso de um agente de aprendizado por reforço profundo pode ser encontrado aqui.