Contrary to your claims, Bloomberg bumps the swap curve AND the discount curve when computing DV01. Moreover, the principal exchange setting also has an impact.
Assuming a standard FXFL USD 3m Libor (same outcome for EUR or USD SOFR though), if you have Details – Additional Detail – principal exchange set to the default "Effective and Maturity" (or pretty much anything except Never), you get the DV01 on the fixed leg.
You can replicate DV01 in the scenario tab. Make sure you shift all curves - one scenario with -10bps, the other +10bps.
The cashflows in the screenshot can be seen by clicking on view Cashflow. We can compute this in Python like so:
down_net_PE = (-24454.83,95497.01,-58783.90,65908.58,-77714.03,52265.44,-79520.45,54765.44,-69018.65,61277.39,-71510.19,59417.18,-61798.17,66713.08,-61215.31,67744.04,-56719.93,69103.54,-55678.05,70553.77)
up_net_PE = (-24442.50,90152.58,-63632.96,60762.28,-82381.46,47178.37,-84696.57,46072.23,-73548.68,56223.43,-75730.07,54690.73,-66002.74,61679.37,-65255.04,62888.32,-60684.76,64056.32,-59536.51,65625.37)
print(f'Principal Down shift 10bps = {round(sum(down_net_PE),2)}')
print(f'Principal Up shift 10bps = {round(sum(up_net_PE),2)}')
DV01_PE = (sum(down_net_PE) - sum(up_net_PE))/20
print(f'DV01_PE = {round(DV01_PE,2)}')
The result is:
If you set principal exchange to never, you get this picture, where DV01 largely moves to the float leg:
You can get all casfhlows:
down1_pe = (
141895.94,
137882.74,
135031.58,
132253.10,
131947.95,
130129.08,
128556.34,
127029.73,
125607.28,
8976356.00
)
down2_pe = (
-24454.83,
-46398.93,
-58783.90,
-71974.16,
-77714.03,
-82766.14,
-79520.45,
-77487.65,
-69018.65,
-70670.56,
-71510.19,
-70711.90,
-61798.17,
-61843.27,
-61215.31,
-59285.69,
-56719.93,
-56503.73,
-55678.05,
-8905802.2
)
down1 = (
141895.94,
137882.74,
135031.58,
132253.10,
131947.95,
130129.08,
128556.34,
127029.73,
125607.28,
124239.47
)
down2 = (
-24454.83,
-46398.93,
-58783.90,
-71974.16,
-77714.03,
-82766.14,
-79520.45,
-77487.65,
-69018.65,
-70670.56,
-71510.19,
-70711.90,
-61798.17,
-61843.27,
-61215.31,
-59285.69,
-56719.93,
-56503.73,
-55678.05,
-53685.70
)
up1 = (141750.28,
137606.33,
134626.59,
131728.62,
131294.15,
129356.92,
127667.00,
126026.87,
124492.60,
123016.01
)
up2 = (
-24442.50,
-51597.70,
-63632.96,
-76844.06,
-82381.46,
-87448.22,
-84696.57,
-85656.39,
-73548.68,
-75070.72,
-75730.07,
-74666.20,
-66002.74,
-65987.64,
-65255.04,
-63138.56,
-60684.76,
-60436.28,
-59536.51,
-57390.63
)
up1_pe = (141750.28,
137606.33,
134626.59,
131728.62,
131294.15,
129356.92,
127667.00,
126026.87,
124492.60,
8887960.04
)
up2_pe = (
-24442.50,
-51597.70,
-63632.96,
-76844.06,
-82381.46,
-87448.22,
-84696.57,
-85656.39,
-73548.68,
-75070.72,
-75730.07,
-74666.20,
-66002.74,
-65987.64,
-65255.04,
-63138.56,
-60684.76,
-60436.28,
-59536.51,
-8822334.6
)
where _pe denotes with principal exchange (only difference is last value) and the number refers to the respective leg of the swap.
Manually computing the DV01's results in:
Which is identical to SWPM.
The help page has a fairly lengthy explanation of the setting for Libor fixing. In a nutshell, the only difference is the first cashflow.
4668.53 - 252.31 = 4416.22
It does affect the DV01 on the main tab, but not the one in the Greeks section of the Risk tab.
While stripping ICVS curves, the fixed first Libor rate is used. Hence, the choice for Libor fixing only affects sensitivity calculations.
If you are worried that the curves are designed from heterogeneous market instruments (Cash rate, Futures / FRAs, Par Swaps), you can use the Risk tab to define shifts on homogenous curves: if you shift Forwards (essentially assuming the curve is solely constructed using forward rates /FRAs), shift swaps (assuming only par swaps are used in curve construction), shift zeros.
Bottom line:
- BBG shifts also the discounting curve and does not leave it untouched
- If you want to be consistent with the way the swap curves are designed by default (and swaps are priced in BBG), you should shift the curve instruments and use constant libor. This should also be the swap defaults as defined in
SWDF DFLT
.