量化交易策略
如何使用 quantlib 計算拉丁美洲掉期 CLP-TNA(智利)的 NPV?
我正在嘗試評估拉丁美洲的掉期交易。但 CLP-TNA 估值與實際估值相差甚遠。請建議,我在以下計算 NPV 的方法中缺少什麼。
# construct discount curve and libor curve risk_free_rate = 0.01 libor_rate = 0.02 day_count = ql.Actual360() discount_curve = ql.YieldTermStructureHandle( ql.FlatForward(calculation_date, risk_free_rate, day_count) ) libor_curve = ql.YieldTermStructureHandle( ql.FlatForward(calculation_date, libor_rate, day_count) ) # CLP index CLP_index = ql.OvernightIndex('CLP', 0, ql.CLPCurrency(), ql.WeekendsOnly(), ql.Actual360()) calendar = ql.WeekendsOnly() settle_date = calendar.advance(calculation_date, 5, ql.Days) maturity_date = calendar.advance(settle_date, 10, ql.Years) fixed_schedule = ql.Schedule(settle_date, maturity_date, fixed_leg_tenor, calendar, ql.ModifiedFollowing, ql.ModifiedFollowing, ql.DateGeneration.Forward, False) float_schedule = ql.Schedule (settle_date, maturity_date, float_leg_tenor, calendar, ql.ModifiedFollowing, ql.ModifiedFollowing, ql.DateGeneration.Forward, False) notional = 10000000 fixed_rate = 0.025 fixed_leg_daycount = ql.Actual360() float_spread = 0.004 float_leg_daycount = ql.Actual360() ir_swap = ql.VanillaSwap(ql.VanillaSwap.Payer, notional, fixed_schedule, fixed_rate, fixed_leg_daycount, float_schedule, libor3M_index, float_spread, float_leg_daycount ) swap_engine = ql.DiscountingSwapEngine(discount_curve) ir_swap.setPricingEngine(swap_engine)
這是一個可能為您指明正確方向的範例。正如 Luigi 所說的那樣,如果你只是使用平坦的曲線,你就不能真正期望得到可比較的值。
因此,第一步是建立一條與彭博可比的曲線。我真的沒有任何 CLP 購買經驗,查看 BBG 上的資訊,看起來這些掉期在 1800 萬之前是零息票,然後支付半價。
import QuantLib as ql today = ql.Date(25,6,2021) calendar = ql.WeekendsOnly() ql.Settings.instance().evaluationDate = today spot = calendar.advance(today, 2, ql.Days) dayCount = ql.Actual360() cop_ois_quotes = [ ('3M', 0.780), ('6M', 1.140), ('9M', 1.435), ('12M', 1.770), ('18M', 2.145), ('2Y', 2.430), ('3Y', 2.745), ('4Y', 3.01), ('5Y', 3.28), ('6Y', 3.53), ('7Y', 3.715), ('8Y', 3.835), ('9Y', 3.93), ('10Y', 4.055), ('15Y', 4.365), ('20Y', 4.465), ] helpers = [] clp_ois_yts = ql.RelinkableYieldTermStructureHandle() index = ql.OvernightIndex('CLICP', 0, ql.CLPCurrency(), ql.WeekendsOnly(), dayCount, clp_ois_yts) for tenor, value in cop_ois_quotes: value /= 100 quote = ql.QuoteHandle(ql.SimpleQuote(value)) period = ql.Period(tenor) paymentFrequency = ql.Semiannual if period.units() > 2 else ql.Once helper = ql.OISRateHelper(2, period, quote, index, paymentFrequency=paymentFrequency) helpers.append(helper) clp_ois_crv = ql.PiecewiseLogLinearDiscount(spot, helpers, ql.ActualActual()) clp_ois_crv.enableExtrapolation() clp_ois_yts.linkTo(clp_ois_crv)
然後,您可以通過為一些掉期定價來測試您的曲線。在這裡,我為輸入工具定價,因此預計會產生相同的結果,但您可以使用其他日期。
swapType = ql.OvernightIndexedSwap.Payer nominal = 100 engine = ql.DiscountingSwapEngine(clp_ois_yts) for tenor, value in cop_ois_quotes: value /= 100 maturity = calendar.advance(spot, ql.Period(tenor)) freq = '18M' if ql.Period(tenor).units() == 2 else '6M' schedule = ql.MakeSchedule(spot, maturity, ql.Period(freq), calendar=calendar) ois_swap = ql.OvernightIndexedSwap(swapType, nominal, schedule, 0.0, dayCount, index) ois_swap.setPricingEngine(engine) print(f"{tenor}: {ois_swap.fairRate()*100:.4f}, {value*100:.4f}")
3M: 0.7800, 0.7800
6M: 1.1400, 1.1400
9M: 1.4350, 1.4350
12M:
1.7700, 1.7700 18M: 2.1450, 2.1450
2Y: 2.4300, 2.4300
3Y: 2.7479, 2.7450
4Y: 3.0100, 3.0100
5Y: 3.2800, 3.2800
6Y: 3.5300, 3.5300
7Y:3.7150、3.7150
8Y:3.8350、3.8350
9Y:3.9312、3.9300
10Y:4.0550、4.0550
15Y:4.3650、4.3650
20Y:4.4651、4.4650