Skip to content

is there a way to get final PnL in pips #8

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
algomaschine opened this issue Jul 4, 2019 · 9 comments
Closed

is there a way to get final PnL in pips #8

algomaschine opened this issue Jul 4, 2019 · 9 comments
Labels
API Needs API-related discussion enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed

Comments

@algomaschine
Copy link

algomaschine commented Jul 4, 2019

Expected Behavior

PnL in pips

Actual Behavior

PnL in money or percentage, which is also useful

@kernc
Copy link
Owner

kernc commented Jul 4, 2019

IIUC, the final P/L in money and percentage is already provided:

s['Equity Final [$]'] = equity[-1]

s['Return [%]'] = (equity[-1] - equity[0]) / equity[0] * 100

For the P/L in pips, you can divide the s['Equity Final [$]'] value by pip size. If you don't know it, backtesting.py uses the following heuristic formula to determine it from closing values:

self.__pip = 10**-np.median([len(s.partition('.')[-1])
for s in self.__arrays['Close'].astype(str)])

Does this work for you?

@algomaschine
Copy link
Author

algomaschine commented Jul 4, 2019 via email

@kernc
Copy link
Owner

kernc commented Jul 4, 2019

position size is the max amount, while the equity is growing or falling, where's the catch?

The equity changes along with asset price.


Indeed, result['Equity Final [$]'] / pip_size would give the performance in pips for the whole strategy run. If you need performance of individual trades, you can use:

self.position.pl / self.data.pip

within Strategy.next() (i.e. right before closing the position, if you're closing them manually), or otherwise you likely need to resort to non-public API result._trade_data as mentioned in #4. I think this should give P/L in pips for each trade:

bt = Backtest(...)
result = bt.run()

per_trade_pips = result._trade_data['P/L'].dropna() / pip_size

@kernc
Copy link
Owner

kernc commented Jul 5, 2019

Or ... if you are interested in mere price difference in pips of your individual trades, you have to additionally divide by position size in Strategy.next():

self.position.pl / self.position.size / self.data.pip

# or

(self.data.Close - self.position.open_price) / self.data.pip  # (*-1) for short positions

Or, at the end of a backtest run, using undocumented API:

td = res._trade_data
td = td.ffill().loc[td['P/L'].dropna().index]
(td['Exit Price'] - td['Entry Price']) / pip_size

@kernc
Copy link
Owner

kernc commented Jul 5, 2019

I understand the suggestion here is to amended Position with Position.pl_pips, returning price difference in pips.

@kernc kernc added enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed API Needs API-related discussion labels Jul 5, 2019
@algomaschine
Copy link
Author

algomaschine commented Jul 5, 2019

Dear Kernc,
I'm trying to get the PnL for every trade in pips by pl*pip, but getting slightly different results than I should have, would you mind having a look at my code?

Here's the screenshot of PnL calculated in Excel VS debug data from the Python class. I've attached the screenshot, data (open price/signals in sample.txt) and code. The comparison values are in google sheets here. Your help is appreciated a big time. The python.txt file contains code.

https://docs.google.com/spreadsheets/d/1HYzT7KmVEMtNmHxlgW-qU-t-W-VAmcV8W4V9uQcCdPI/edit#gid=1848616943

pic
sample.txt

python.txt

@kernc
Copy link
Owner

kernc commented Jul 6, 2019

In pnl_classic, you're computing mere difference from one Close to the next. To get this value (within rounding accuracy) within the strategy, you have to divide P/L with position size (i.e. number of units):

delta_pips = self.position.pl / self.position.size

In order to get this value in terms of number of pips, you have to, additionally, divide by pip size:

pnl_in_pips = self.position.pl / self.position.size / self.data.pip

@algomaschine
Copy link
Author

Thanks for the tip. It seems to work now.

@kernc
Copy link
Owner

kernc commented Jul 15, 2020

As PnL in pips is easily computable, Position.pl_pips deemed not needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
API Needs API-related discussion enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants