การประเมินราคาตราสารหนี้และการวิเคราะห์ความเสี่ยง
ตราสารหนี้เป็นหัวใจสำคัญของงาน Quantitative Finance สำหรับสถาบันการเงิน SabiQuant มอบกลไกการประเมินราคาพันธบัตรที่สร้างขึ้นบน std โดยปราศจากการพึ่งพาไลบรารีภายนอก และได้รับการตรวจสอบความถูกต้องเชิงตัวเลขเทียบเคียงกับ QuantLib
การกำหนดสูตรทางคณิตศาสตร์ (Mathematical Formulation)
1. การประเมินราคาแบบ Dirty Price
สำหรับพันธบัตรที่มีกระแสเงินสด (คูปองและการไถ่ถอนมูลค่าหน้าตั๋ว) ที่ชำระ ณ เวลา (วัดเป็นเศษส่วนของปีนับจากวันชำระราคาตามอนุสัญญาการนับวัน) ราคาเต็มหรือราคา Dirty ภายใต้อัตราผลตอบแทนทบต้นต่อปี ด้วยความถี่การทบต้น ครั้งต่อปี จะคำนวณได้จาก:
โดยตัวคูณคิดลด (Discount factor) ขึ้นอยู่กับรูปแบบการคิดทบต้น:
-
การคิดทบต้นตามงวด ( ครั้งต่อปี):
-
การคิดทบต้นต่อเนื่อง (Continuous Compounding):
2. ราคา Clean และดอกเบี้ยค้างรับ (Accrued Interest)
ในตลาดตราสารหนี้ ราคาที่เสนอซื้อขายมักจะอยู่ในรูป ราคา Clean () ซึ่งไม่รวมดอกเบี้ยค้างรับ () ที่สะสมระหว่างงวดการจ่ายคูปอง:
ดอกเบี้ยค้างรับคำนวณจากวันจ่ายคูปองครั้งก่อนหน้า , วันชำระราคา , และวันจ่ายคูปองครั้งถัดไป :
โดย คือยอดจ่ายคูปองทั้งหมดสำหรับงวดนั้น
3. ตัวชี้วัดความเสี่ยงเชิงวิเคราะห์ (Analytical Risk Measures)
แทนที่จะใช้การประมาณค่าผลต่างสืบเนื่องแบบจำกัด () ซึ่งทำให้เกิดความคลาดเคลื่อนเชิงตัวเลข SabiQuant จะคำนวณ อนุพันธ์เชิงวิเคราะห์ที่แน่นอน:
อนุพันธ์อันดับที่หนึ่ง () และ Modified Duration
อนุพันธ์อันดับที่สอง () และ Convexity
ตัวอย่างโค้ดในภาษา Rust
use sabiquant::bonds::{BondPricingPlan, BondPricingResult};use sabiquant::core::{Date, Frequency};use sabiquant::core::calendars::TargetCalendar;use sabiquant::core::daycount::ActualActualICMA;
fn main() -> Result<(), Box<dyn std::error::Error>> { // 1. กำหนดวันชำระราคาและวันครบกำหนดไถ่ถอน let settlement = Date::from_ymd(2025, 6, 15)?; let maturity = Date::from_ymd(2035, 6, 15)?;
// 2. เรียกใช้ปฏิทินตลาดและอนุสัญญาการนับวัน let calendar = TargetCalendar::default(); let day_counter = ActualActualICMA::default();
// 3. สร้าง BondPricingPlan (พันธบัตร 10 ปี, คูปอง 5.00% จ่ายปีละ 2 ครั้ง) let plan = BondPricingPlan::builder() .settlement(settlement) .maturity(maturity) .coupon_rate(0.050) .frequency(Frequency::SemiAnnual) .calendar(calendar) .day_counter(day_counter) .face_value(100.0) .build()?;
// 4. คำนวณราคาและความเสี่ยงที่อัตราผลตอบแทน 4.75% let yield_to_maturity = 0.0475; let metrics: BondPricingResult = plan.price_from_yield(yield_to_maturity)?;
println!("Dirty Price: ${:.5}", metrics.dirty_price); println!("Clean Price: ${:.5}", metrics.clean_price); println!("Accrued Interest: ${:.5}", metrics.accrued_interest); println!("Macaulay Duration: {:.4} ปี", metrics.macaulay_duration); println!("Modified Duration: {:.4}", metrics.modified_duration); println!("Convexity: {:.4}", metrics.convexity); println!("dP/dy: {:.4}", metrics.dp_dy);
// 5. Invert หาอัตราผลตอบแทนจากราคา Clean ด้วยวิธีของ Brent let market_clean_price = 101.95; let implied_ytm = plan.yield_from_clean_price(market_clean_price)?; println!("Implied Market YTM: {:.4}%", implied_ytm * 100.0);
Ok(())}