Closed elijose55 closed 4 years ago
Já existe uma função chamada partialResult que calcula o resultado parcial. Ela deveria ser usada para popular uma lista a cada evento recebido do instrumento. Não usar "_" no nome da variável, seguir o padrão.
Realizei a correção. A classe Strategy utiliza a função partialResult para realizar o cálculo do P&L parcial para cada instrumento. Esses valores são armazenados no dicionário parcialResult que é composto pelas listas de cada instrumento contendo os seus respectivos P&L parciais.
def partialResult(self):
'''
P&L: position size * (sell price - buy price)
P&L for bought position: position * (mark price - entry price)
P&L for sold position: position * (entry price - mark price)
As in this case the P&L is cumulative, it is necessary to add the old P&L value:
pnl = position * sell price - position * buy price + pnl
'''
for instrument, result in self.result.items():
if (isinstance(self.last[instrument], float)):
price = self.last[instrument]
else:
price = self.last[instrument][3]
if (self.position[instrument] != 0):
pnl = result + \
self.position[instrument] * price
self.parcialResult[instrument].append(pnl)
return
Realizei outra correção e adicionei outra feature. A classe Strategy utiliza a função partialResult para realizar o cálculo do P&L parcial para cada instrumento. Esses valores são armazenados no dicionário parcialResult que é composto pelas listas de cada instrumento contendo os seus respectivos P&L parciais.
def partialResult(self):
'''
P&L: position size * (sell price - buy price)
P&L for bought position: position * (mark price - entry price)
P&L for sold position: position * (entry price - mark price)
As in this case the P&L is cumulative, it is necessary to add the old P&L value:
pnl = position * sell price - position * buy price + pnl
'''
for instrument in self.eventPrices.keys():
if instrument not in self.parcialResult:
self.parcialResult[instrument] = []
if isinstance(self.last[instrument], float):
price = self.last[instrument]
else:
price = self.last[instrument][3]
if instrument in self.position:
if self.position[instrument] != 0:
pnl = self.result[instrument] + \
self.position[instrument] * price
else:
pnl = self.parcialResult[instrument][-1]
else:
pnl = 0
self.parcialResult[instrument].append(pnl)
return
O código do commit anterior possui um bug em que a lista não era preenchida caso a estratégia não realizasse nenhum trade. Além disso, adicionei um atributo eventPrices a classe que é um dicionário com os instrumentos recebidos na simulação como chaves e a lista de todos seus preços como os valores. Dessa maneira, é possível plotar o gráfico que mostram o preço do instrumento ao longo do tempo.
Criei a função parcialPnl que recebe um objeto event e calcula de acordo com o preço do instrumento o P&L da estratégia no momento do evento recebido. A seguinte fórmula corresponde ao cálculo do P&L:
Porém como era preciso calcular o valor cumulativo do P&L a fórmula abaixo foi utilizada:
Para aplica-la no código foi utilizado o valor contido em self.result[event.instrument], já existente no programa, considerando que:
Então, chegou-se no resultado abaixo, sendo que a função é chamada dentro da função event, ou seja, ela é executada toda vez que um evento novo é recebido.
Os valores de P&L foram armazenados em um atributo da classe, sendo este um dicionário que contém as listas de P&L de cada instrumento utilizado na simulação.