Search code examples
pythonpandastime-seriesfinance

Trading strategy : Computing value of an Investment


I am new to Python and here is my problem :

I have this DataFrame :

pf = pd.DataFrame({'Dates':['2018-07-31','2018-07-31','2018-08-31','2018-08-31','2018-09-30','2018-09-30'],
                   "Name":["Apple",'Faceook','JP Morgan',"Boeing",'Tesla','Disney'],
                   "Monthly Return":[-0.02,0.11,-0.03, 0.02,-0.08,0.10],
                  "Total Weight":[0.7,0.2,0.1,0.5,0.3,0.2]})

My objective is to return the final value of my investment according to the stocks, weight and returns for each month.

Let's say that we started with $1.000. I'm looking for something like below, assuming that for each month the remaining capital is fully reinvested

      Dates      Name     Monthly Return    Total Weight     P&L   Remaining Investment
0   2018-07-31  Apple         -0.02            0.7           686 
1   2018-07-31  Faceook        0.11            0.3           333          1019
2   2018-08-31  JP Morgan     -0.03            0.5           494.21
3   2018-08-31  Boeing         0.02            0.5           519.69       1013.91
4   2018-09-30  Tesla         -0.08            0.1           93.28
5   2018-09-30  Disney         0.10            0.9           1003.77      1097.05

I started by doing this :

A = 1000
pf['P&L']= A * pf['Total Weight'] * (1+pf['Monthly Return'])

But the problem is that this is only true for the first month but not for the others as we don't have the same starting point ($1000 for July 31 but $1019 for August 31).

Do I have to create a loop maybe?

If you please any idea to solve this issue, please don't hesitate to share! Thanks!


Solution

  • For something like this it would be easier to track the returns using a zero dollar portfolio.

    df = pd.DataFrame({'Dates':['2018-07-31','2018-07-31','2018-08-31','2018-08-31','2018-09-30','2018-09-30'],
                       "Name":["Apple",'Faceook','JP Morgan',"Boeing",'Tesla','Disney'],
                       "Monthly Return":[-0.02,0.11,-0.03, 0.02,-0.08,0.10],
                      "Total Weight":[0.7,0.2,0.1,0.5,0.3,0.2]})
    
    df['weighted_return'] = df['Monthly Return'] * df['Total Weight']
    rets = df.groupby(['Dates'])['weighted_return'].sum()
    cumulative_rets = (rets + 1).cumprod() - 1
    cumulative_rets
    

    So your return series is:

    Dates
    2018-07-31   0.00800
    2018-08-31   0.01506
    2018-09-30   0.01100
    Name: weighted_return, dtype: float64
    

    Now you can consider how to incorporate transaction costs, slippage etc. The main issue with a zero dollar portfolio approach is that it assumes you can buy fractional shares. Typically this zero dollar approach is used in academic papers.

    You should check out pyfolio for presenting results and calculating risk metrics.