performing more complex calculations on groupby objects

Viewed 41

I am currently looking to do some calculations on a large dataset of options where I want first to split the data according to the strike price and expiry, then perform a set of calculations shown below onto each subgroup. I have been able to separate the data using groupby to get the split I want, I also wrote the calculation i want to do which works when tested on a subgroup. The only problem I have is to combine the two together.

Here is the code I used to group my data:

grouped =df.groupby(['Expiry','Strike'])

I had a read online and they mentioned the use of the apply function but the examples only included simple functions such as summation or averages.

Here is the calculation that I would like to perform on each subgroup data, where x,y,z,u,R are columns that in each subset that is the same for all subgroups:

 def p(d, S, B, c):
     return d * S + B - c


 def b_t(r, b_old, S, d, d_old, t):
     return np.exp(r * t) * b_old + S * (d_old - d)


 def e_t(d_old, S, c, r, t, b_old):
     return d_old * S - c + np.exp(r * t) * b_old
 
 P_results = []
 B_results = []
 E_results = []
 
 for i,(d,S,c,t,r) in enumerate(zip(x,y,z,u,R)):
    B = b_t(r, b_old, S, d, d_old, t)
    P = p(d, S, B, c)
    E = e_t(d_old, S, c, r, t, b_old)
    print('i={},P={},B={},E={}'.format(i,P,B,E))
    B_results.append(B)
    P_results.append(P)
    E_results.append(E)
    b_old = B
    d_old = d

I thought maybe if I could save each subset as a new variable dataframe then maybe it could work but I haven't been able to do that.

I hope this is clear and I think posting some data would help but I am not sure how best to upload it here.

Much appreciate your help!

UPDATE 1: Found a solution that works

    grouped =df.groupby(['Expiry','Strike'])

    lg = list(grouped)


    P_results = []
    l_results =[]
    B_results = []
    E_results = []
    
    for l in range(len(lg)):
      df2=lg[l][1]
      d_old = df2.iloc[0, 4]
      S_old = df2.iloc[0, 8]
      c_old = df2.iloc[0, 10]
      b_old = c_old - d_old * S_old
      x = df2.iloc[1:, 4]
      y = df2.iloc[1:, 8]
      z = df2.iloc[1:, 10]
      u = df2.iloc[1:, 9]
      R = df2.iloc[1:, 7]

        for i, (d, S, c, t, r) in enumerate(zip(x, y, z, u, R)):
           B = b_t(r, b_old, S, d, d_old, t)
           P = p(d, S, B, c)
           E = e_t(d_old, S, c, r, t, b_old)
           print('i={},P={},B={},E={}'.format(i, P, B, E))
           l_results.append(l)
           B_results.append(B)
           P_results.append(P)
           E_results.append(E)
           b_old = B
           d_old = d

    BB = pd.DataFrame(np.column_stack([l_results, P_results, 
    E_results,B_results]),columns=['l','P','E','B'])

All I did was to transform grouped into a callable list and then call each of the sections out using a for loop then use another for loop to perform the calculations. It is not the prettiest output, I put l_results there to show which group the calculations were referring to but seems to be sufficient for now. If there is any better way please let me know!

0 Answers
Related