Skip to content
All library documents

Pricing a Bond Portfolio from a Pandas Table with QuantLib

Article Quant Q&A · Author: Ruth

Summary

The document explains a practical way to price several fixed-rate bonds described in a pandas table. A row-wise function converts each bond’s dates and coupon into a QuantLib bond object. The bonds are assigned a shared discounting engine built from a flat yield curve, and their net present values are summed. The example also shows wrapping these operations in a DataFrame subclass with methods for bond creation, engine assignment, and portfolio valuation.

This illustrates how to process a collection of instruments even though QuantLib does not provide a general portfolio object in the described workflow. The example is schematic: it uses a particular calendar, day-count convention, schedule frequency, and curve setup. It does not discuss market-data calibration, handling differing conventions, notional treatment, or validation against independent prices, so users should adapt those assumptions to their bond data and valuation requirements.

Key ideas

  • A pandas row function can turn bond records into QuantLib fixed-rate bond objects.
  • A shared discounting engine can be assigned across the constructed bonds.
  • Individual bond NPVs can be aggregated to obtain a portfolio value.
  • A DataFrame subclass can organize construction, engine assignment, and valuation steps.
  • The example's conventions and curve assumptions may need adaptation.

Tags

Full text
# Bond portfolio valuation in Quantlib python


# Bond portfolio valuation in Quantlib python












I have a table of bonds which I imported into python using pandas.

Is there a way I can simultaneously price all of them in python using the Quantlib library. I know how to price one bond but not in a table.

## Answer by David Duarte (score 6)

https://quant.stackexchange.com/a/57334

QuantLib doesn't really have the concept of portfolio but since you're using pandas, you can play around with that to price your bonds at once. Here is an example:

```
data = [
    [ "15-06-2018", "15-06-2022", 4.75, 500 ],
    [ "21-07-2017", "21-07-2027", 0.25, 100 ],
    [ "17-02-2015", "17-02-2045", 1.50, 250 ],   
]
bonds = pd.DataFrame(data, columns=["start", "maturity", "coupon", "notional"])

def makeBond(row):
    start, maturity, coupon, notional = row
    startDate = ql.Date(start, "%d-%m-%Y")
    maturityDate = ql.Date(maturity, "%d-%m-%Y")
    return ql.FixedRateBond(2, ql.TARGET(), 100, startDate, maturityDate, ql.Period("1Y"), [coupon], ql.ActualActual())

yts = ql.YieldTermStructureHandle(
    ql.FlatForward(2, ql.TARGET(), 0.05, ql.Actual360())
)
engine = ql.DiscountingBondEngine(yts)
bonds['bond'] = bonds.apply(makeBond, axis=1)
bonds['bond'].apply(lambda x: x.setPricingEngine(engine))
bonds['bond'].apply(lambda x: x.NPV()).sum()
```

#### 3347.2767053215985

Or you could even make a bond portfolio object from a pandas DataFrame:

```
class BondPortfolio(pd.DataFrame):
    def makeBond(self, row):
        start, maturity, coupon, notional = row
        startDate = ql.Date(start, "%d-%m-%Y")
        maturityDate = ql.Date(maturity, "%d-%m-%Y")
        return ql.FixedRateBond(2, ql.TARGET(), 100, startDate, maturityDate, ql.Period("1Y"), [coupon], ql.ActualActual())
    def makeBonds(self):
        self['bond'] = self.apply(self.makeBond, axis=1)
    def setPricingEngine(self, engine):
        self['bond'].apply(lambda x: x.setPricingEngine(engine))
    def NPV(self):
        return self['bond'].apply(lambda x: x.NPV()).sum()
        
portfolio = BondPortfolio(data, columns=["start", "maturity", "coupon", "notional"])
portfolio.makeBonds()
portfolio.setPricingEngine(engine)
portfolio.NPV()
```

#### 3347.2767053215985

Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.