0

I am quite new to Python and I encountered what I assume is a precision issue with the numeric operation I am doing in Python (Jupyter). I compute the Profit at maturity of a portfolio (payoff of the option - Close Price of the option). In the end I should get only one value in my dictionary but there seems to be some differences and I can not figure why.

Here is the code I use:

import pandas as pd
do = {'Underlying': ['AMZN','AMZN','AMZN','AMZN','FB','FB'], 'Qty': [-31, -42, 31, 42,92,-92], 'Type': ['Call','Call','Put','Put','Call','Put'], 'Strike': [1450,1480,1450,1480,160,160], 'Close Price': [55.4, 42.7,72.3,87.1,3,10.8]}
dfoption = pd.DataFrame(data=do)
ds = {'Symbol': ['AMZN','FB'], 'Qty': [7300, -9200], 'Close Price': [1447, 160]}
dfstock = pd.DataFrame(data=ds)


def optionpnl(row,stress) :
    stockprice = dfstock.loc[dfstock['Symbol'] == row['Underlying']]['Close Price'] 
    if row['Type'] == 'Call' :
        return 100*row['Qty'] * (max(float(stress*stockprice - row['Strike']),0) - row['Close Price'])
    if row['Type'] == 'Put' :
        return 100*row['Qty'] * (max(float(row['Strike'] - stress*stockprice),0) - row['Close Price'])

def stockpnl(row,stress) :
    return row['Qty'] * (stress*row['Close Price'] - row['Close Price'])


dicpnl = {}

for i in (pd.Series(range(70,131,5))) :
    dfoption['PnL'+str(i-100)] = dfoption.apply(lambda row: optionpnl(row,i/100), axis=1)
    dfstock['PnL'+str(i-100)] = dfstock.apply(lambda row: stockpnl(row,i/100), axis=1)
    dicpnl[str(i-100) + "%"] = sum(dfoption['PnL'+str(i-100)]) + sum(dfstock['PnL'+str(i-100)])

The ouput :

{'-10%': -19209.999999999884,
 '-15%': -19210.000000000233,
 '-20%': -19210.0,
 '-25%': -19210.0,
 '-30%': -19210.0,
 '-5%': -19210.00000000006,
 '0%': -19209.99999999997,
 '10%': -19210.0,
 '15%': -19210.0,
 '20%': -19210.0,
 '25%': -19210.0,
 '30%': -19210.0,
 '5%': -19209.999999999884}
Frostic
  • 680
  • 4
  • 11
  • Oh ok thanks. I thought I could do my computations differently to avoid the problem but I guess not. – Frostic Apr 04 '18 at 16:37
  • 1
    Yes, this is a precision issue. But there is no answer to “how can I do arbitrary real math on arbitrary values in finite time and space without any rounding errors” except “you can’t”. So you need to decide what to do about the rounding errors you will get. Often the answer is to always check them with `isclose` instead of `==`, always print them out to the end user with explicit formatting that rounds to a smaller number of digits, and then just not worry that they’re different numbers. – abarnert Apr 04 '18 at 16:38

0 Answers0