0
$\begingroup$

I am trying to compute the daily P&L of the following systematic trading strategy: sell each day a 1M straddle on EUR-USD from 04th January, 1999 to today. My dataset contains the strike, the spot, the CCY1 rate and CCY2 rate, the volatility and the expiry date. The premium is computed using Garman and Kholagen formula.

The idea is to compute for each day the total premium of the portfolio of existing straddles (updated with the new market data) in order to get the P&L of the position and this, for each day. After that, I also take into account delta hedging on a daily basis.

I tried to implement this strategy with the following code (in Python) but the final outputs do not match the expected results.

for t in DataFrame.index[32:]:
StrategyNPV = 0
StrategyDelta = 0
nbOptionInPortfolio=0
Call = EuropeanFxWithStrike(OptionType='Call', Spot=DataFrame['Spot'].at[t],
                                     CCY1Rate=DataFrame['CCY1rate'].at[t], CCY2Rate=DataFrame['CCY2rate'].at[t],
                                     Sigma=DataFrame['CCY1CCY2V'].at[t], Strike=DataFrame['Strike'].at[t],
                                     EvaluationDate=DataFrame['Date'].at[t],
                                     ExpiryDate=DataFrame['ExpiryDate'].at[t],
                                     Calendar=Calendar, DayCounter=ql.ActualActual())
Put = EuropeanFxWithStrike(OptionType='Put', Spot=DataFrame['Spot'].at[t],
                                    CCY1Rate=DataFrame['CCY1rate'].at[t], CCY2Rate=DataFrame['CCY2rate'].at[t],
                                    Sigma=DataFrame['CCY1CCY2V'].at[t], Strike=DataFrame['Strike'].at[t],
                                    EvaluationDate=DataFrame['Date'].at[t],
                                    ExpiryDate=DataFrame['ExpiryDate'].at[t],
                                    Calendar=Calendar, DayCounter=ql.ActualActual())
DataFrame['Premium'].at[t]= Put[0] + Call[0]
for i in range(0,33):
    if (DataFrame['Date'].at[t] < DataFrame['ExpiryDate'].at[t-i]):
        nbOptionInPortfolio=nbOptionInPortfolio+1
        CallCondition = EuropeanFxWithStrike(OptionType='Call', Spot=DataFrame['Spot'].at[t],
                                    CCY1Rate=DataFrame['CCY1rate'].at[t], CCY2Rate=DataFrame['CCY2rate'].at[t],
                                    Sigma=DataFrame['CCY1CCY2V'].at[t], Strike=DataFrame['Strike'].at[t - i],
                                    EvaluationDate=DataFrame['Date'].at[t],
                                    ExpiryDate=DataFrame['ExpiryDate'].at[t - i],
                                    Calendar=Calendar, DayCounter=ql.ActualActual())
        PutCondition = EuropeanFxWithStrike(OptionType='Put', Spot=DataFrame['Spot'].at[t],
                                   CCY1Rate=DataFrame['CCY1rate'].at[t], CCY2Rate=DataFrame['CCY2rate'].at[t],
                                   Sigma=DataFrame['CCY1CCY2V'].at[t], Strike=DataFrame['Strike'].at[t - i],
                                   EvaluationDate=DataFrame['Date'].at[t],
                                   ExpiryDate=DataFrame['ExpiryDate'].at[t - i],
                                   Calendar=Calendar, DayCounter=ql.ActualActual())
        StrategyNPV = StrategyNPV + CallCondition[0] + PutCondition[0] 
        StrategyDelta = StrategyDelta - (CallCondition[1] + PutCondition[1])
DataFrame["nb"].at[t]=nbOptionInPortfolio
DataFrame["FullPosition"].at[t] = StrategyNPV
DataFrame['P&LNoDeltaHedge'].at[t] = DataFrame["FullPosition"].at[t-1] - DataFrame["FullPosition"].at[t] + DataFrame['Premium'].at[t]
DataFrame['P&LNoDeltaHedge'].at[32] = 0
DataFrame['PortfolioDelta'].at[t] = StrategyDelta
DataFrame['SpotToPurchase'].at[32] = - DataFrame['PortfolioDelta'].at[32]
DataFrame['SpotToPurchase'].at[t] = DataFrame['PortfolioDelta'].at[t - 1] - DataFrame['PortfolioDelta'].at[t]
DataFrame['SpotToPurchase'].at[32] = - DataFrame['PortfolioDelta'].at[32]
DataFrame['P&LHedged'].at[t] = -DataFrame['PortfolioDelta'].at[t-1] * (DataFrame['Spot'].at[t] - DataFrame['Spot'].at[t - 1])
DataFrame['TotalP&L'].at[t] = DataFrame['P&LNoDeltaHedge'].at[t] + DataFrame['P&LHedged'].at[t] here

The function called EuropeanFxWithStrike compute respectively the option premium and the option delta. This function works correctly since the premiums match with the one of data providers.

Why does the first loop start at index 32 ? I use that trick because of the second loop. The lines before index 31 contains an option that expiry before the date at line 32 so that it does not impact the results provided by the second loop.

The second loop simply a reevaluation the total premium of the strategy based on the new market data (except the strike that is kept to the initial strike of each option). On the first day (so index 32), the P&L is zero because I sell an option which worth x at price x. The same applies for the delta hedging P&L. Example: On day 2, the P&L is the premium received on day 1 (since we sell) - the updated premium. If I received 10 on day 1 and if the new premium is 9 on day 2, then the P&L is 10-9=1 because I sold at 10 something that is now only 9.

Then I compute the P&L of the option portfolio and the P&L of the delta hedge to finally sum these two to get the total P&L of the strategy.

What do you think about that ? I have a (some) mistake(s) somewhere but I do not spot it (them). Any help would be very welcomed :)!

The following picture is about my dataset (called DataFrame in my code). Purple colour is four my dataset, red colour is for the computations added by the code. enter image description here

$\endgroup$

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.