前言
在利率衍生性商品或債券中,現金流(Cashflow)建構是一個不可或缺的步驟。尤其是在利率交換(Interest Rate Swap, IRS)或浮動利率債券(FRN)等結構中,如何靈活地生成固定利率(Fixed)或浮動利率(Floating)的現金流,直接影響到後續的產品定價與風險管理。
在這篇文章中,我們將延續前兩篇介紹關於單一期現金流物件IborCoupon與OvernighIndexedCoupon的基本使用與特性後,繼續探討QuantLib Python裡的FixedRateLeg
、IborLeg
與OvernightLeg
三個重要產生一連串現金流工具,了解它們的設計理念、實務應用場景,並透過實際Python範例,帶你建構出完整的現金流結構。

Image created by author - Cash Flow Generation via QuantLib Python
QuantLib中的物件導向設計:Leg與現金流的關係
QuantLib在設計利率產品現金流時,採用物件導向設計原則(OOP ),以保持系統的彈性與擴充性。
以下是核心設計邏輯:
- Leg 是一個現金流集合
Leg
本質上是std::vector<boost::shared_ptr<CashFlow>>
。也就是說,一個Leg就是一堆指向CashFlow
物件的共享指標集合。 - CashFlow是所有現金流型態的基礎類別
不論是固定利率、浮動利率、本金償還,全部繼承自CashFlow
基礎類別。 - FixedRateCoupon 、IborCoupon與OvernightIndexedCoupon
- FixedRateCoupon:固定利息計算現金流,從Coupon繼承而來。
- IborCoupon:浮動利息計算現金流,從FloatingRateCoupon繼承,並且需要有Index的引用(如TAIBOR)。
- OvernightIndexedCoupon:浮動利息計算現金流,從FloatingRateCoupon繼承,並且需要有Index的引用(如SOFR)。
- FixedRateLeg、IborLeg與OvernightLeg是建構器(Builder Pattern)
它們本身不是現金流,而是根據設定的參數(如起息日、利率、名目本金等)來建造一組完整的Leg。 - FixedRateLeg:代表一連串固定金額的利息金額,底層是由FixedRateCoupon物件組成。
- IborLeg:代表一連串依據浮動利率(例如TAIBOR)變動的利息金額,底層是FloatingRateCoupon物件。
- OvernightLeg:代表一連串依據隔夜利率(例如SOFR)變動的利息金額,底層是OvernightIndexedCoupon物件。
- 金融產品合成
在QuantLib中,像Vanilla Swap這樣的產品,本質上就是把兩個Leg(通常一個Fixed,一個Ibor或是OvernightIndex)組合在一起。
這種設計的好處是:
- 高模組化:每種現金流類型都有獨立邏輯,方便擴展和重用。
- 高彈性:可以輕鬆組合出新型態的複合產品(如Callable Swap、CMS Swap等)。
- 清晰明確:CashFlow的角色、Leg的角色,以及產品(如Swap)間的關係分工明確。
- 與Schedule緊密結合:Leg的現金流生成,是根據Schedule來切分時間週期與支付日。
從學習QuantLib的角度來看,理解這套物件導向設計思路,能幫助我們更快掌握整體架構,也更容易在實務上應用。
實務應用場景:
在金融市場上,FixedRateLeg
和IborLeg
、OvernightLeg
無處不在。以下是一些常見的應用範例:

QuantLib Python 範例
接下來,我們直接用Python來操作。假設今天要模擬一個5年期的SOFR對固定利率交換,名目本金是100萬美元,交換的頻率為Annual。
基本設定
假定計算日期為2025/4/1,同時假設SOFR連結到一條flat forward的利率曲線。
import QuantLib as ql
import pandas as pd
# setup reference date
ref_date = ql.Date(1, 4, 2025)
ql.Settings.instance().evaluationDate = ref_date
# create SOFR Index and link to dummy term structure (flat curve)
sofr_curve = ql.FlatForward(ref_date, 0.045, ql.Actual365Fixed())
sofr_termStrcuture = ql.YieldTermStructureHandle(sofr_curve)
sofr_index = ql.Sofr(sofr_termStrcuture)
calendar = ql.UnitedStates(ql.UnitedStates.FederalReserve)
# <https://www.newyorkfed.org/markets/reference-rates/sofr>
sofr_rates = [(ql.Date(1,4,2025),4.39),
(ql.Date(31,3,2025),4.41),]
# add daily USD/SOFR fixing rate
for s_rate in sofr_rates:
sofr_index.addFixing(s_rate[0], s_rate[1]/100.0)
建立Schedule
# define cash flows start and end date
start_date = calendar.advance(ref_date, ql.Period("2D"))
maturity_date = calendar.advance(start_date, ql.Period("5Y"))
# assume SOFR interest payment annually.
schedule = ql.Schedule(
start_date, # effective date
maturity_date, # termination date
ql.Period(ql.Annual), # schedule frequency
calendar, # reference calendar
ql.ModifiedFollowing, # date roll convention for schedule generation
ql.ModifiedFollowing, # date roll convention for termination
ql.DateGeneration.Forward, # schedule generation direction
False # end of month flag
)
生成FixedLeg
# generate fixed rate leg
# assume rate is 5%
fixed_rate = 0.05
fixed_leg = ql.FixedRateLeg(schedule, ql.Actual360(), [1_000_000], [fixed_rate])
print("Fixed Leg Cashflows:")
fixed_ints = []
for cf in fixed_leg:
fixed_ints.append({'PaymentDate' : cf.date().ISO(),
'Interest Amount' : cf.amount()})
df_fixed_ints = pd.DataFrame(fixed_ints)
display(df_fixed_ints)

生成OvernightLeg - SOFR
# generate floating SOFR leg
sofr_leg = ql.OvernightLeg([1_000_000], schedule, sofr_index)
print("SOFR Leg Cashflows:")
sofr_ints = []
for cf in sofr_leg:
sofr_ints.append({'PaymentDate' : cf.date().ISO(),
'Interest Amount' : cf.amount()})
df_ints = pd.DataFrame(sofr_ints)
display(df_ints)

支付日調整
QuantLib允許我們使用不同的市場慣例將現金流支付日期調整為實際營業日。預設的慣例為順延(ql.Following
)。以下是市場上主要使用的營業日調整慣例:

要使用特定的營業日調整慣例,只需在leg參數中指定即可:
fixed_leg = ql.FixedRateLeg(schedule, ql.Actual360(), [1_000_000], [fixed_rate],
paymentAdjustment=ql.ModifiedFollowing)
sofr_leg = ql.OvernightLeg([1_000_000], schedule, sofr_index, ql.Actual360(),
paymentConvention=ql.ModifiedFollowing)
延遲支付日
付款延遲參數指定在計劃期間結束日期後多少天進行付款(通常為T+2)以便於結算。這解決了無風險利率以T+1延遲發佈的問題。
fixed_leg = ql.FixedRateLeg(schedule, ql.Actual360(), [1_000_000], [fixed_rate],
paymentAdjustment=ql.ModifiedFollowing, paymentLag=2)
sofr_leg = ql.OvernightLeg([1_000_000], schedule, sofr_index, ql.Actual360(),
paymentConvention=ql.ModifiedFollowing, paymentLag=2)
名目本金變化
在實務上,金融工具(如利率交換)的名目本金可能需要根據其他產品(如貸款)進行調整以達到避險效果。這就需要為每個現金流排程設定不同的名目本金。在QuantLib中,只要提供一個名目本金列表,每個數值對應其各自排程的名目本金,就能輕鬆實現這個功能。
# Notional Amortization case
# Assume the notional is amortized by 0.2 million for each schedule
notionals = [1_000_000 - 200_000 * i for i in range(len(schedule) - 1)]
fixed_leg_amt = ql.FixedRateLeg(schedule, ql.Actual360(), notionals, [fixed_rate])
print("Fixed Leg Cashflows with Notional Amortization:")
fixed_ints_amt = []
for cf in fixed_leg_amt:
fixed_ints_amt.append({'PaymentDate' : cf.date().ISO(),
'Interest Amount' : cf.amount()})
df_fixed_ints_amt = pd.DataFrame(fixed_ints_amt)
display(df_fixed_ints_amt)

上面的程式結果即展現了由於名目本金逐期遞減的緣故,計算的利息金額也跟著下降。
結語
QuantLib提供的FixedRateLeg、IborLeg
與OvernightLeg
物件,不只是簡化現金流生成過程的工具,更是進行利率產品開發與了解的重要基礎。掌握這幾個物件的設計理念與使用技巧,能讓你對QuantLib在處理現金流等方式有更入的理解,同時如果你也在進行相關的金融程式開發與學習,相信這篇文章的說明也能有助於在程式設計的學習。
如果你對更多QuantLib Python應用(如利率交換定價、現金流折現計算、PV01風險分析)感興趣,歡迎持續關注後續文章!
參考資料
- Ballabio, Luigi. Implementing QuantLib. Online resource
- Goutham Balaraman, Luigi Ballabio. QuantLib Python Cookbook. Leanpub, 2020. https://leanpub.com/quantlibpythoncookbook