def printModelCalibration(basket, volatility): print ("%-20s %-20s %-20s %-20s %-20s %-20s" % ("Expiry","Model sigma","ModelPrice","MarketPrice","Model impVol","Market impVol")) print ("=================================================================================================================") for i in range(0, len(basket)): expiryDate = ql.as_black_helper(basket[i]).swaptionExpiryDate() modelValue = ql.as_black_helper(basket[i]).modelValue() marketValue= ql.as_black_helper(basket[i]).marketValue() impVol = ql.as_black_helper(basket[i]).impliedVolatility(modelValue, 1e-6, 1000, 0.0, 2.0) vol = ql.as_black_helper(basket[i]).volatility().value() print ("%-20s %-20f %-20f %-20f %-20f %-20f" % (str(expiryDate), volatility[i], modelValue, marketValue, impVol, vol)) print("==================================================================================================================")
def printBasket(basket): print ("%-20s %-20s %-20s %-20s %-20s %-20s" % ("Expiry", "Maturity", "Nominal", "Rate", "MarketVol", "Pay/Rec")) print ("==================================================================================================================") for i in range(0, len(basket)): expiryDate = ql.as_black_helper(basket[i]).swaptionExpiryDate() endDate = ql.as_black_helper(basket[i]).swaptionMaturityDate() nominal = ql.as_black_helper(basket[i]).swaptionNominal() vol = ql.as_black_helper(basket[i]).volatility().value() rate = ql.as_black_helper(basket[i]).swaptionStrike() print ("%-20s %-20s %-20f %-20f %-20f" % (str(expiryDate), str(endDate), nominal, rate, vol)) print("==================================================================================================================")
def _create(self, asof_date): maturity = self.get(F.MATURITY_DATE) or \ self.get(F.MATURITY_TENOR) undl_maturity = self.get(F.UNDERLYING_MATURITY_DATE) or \ self.get(F.UNDERLYING_MATURITY_TENOR) assert maturity is not None assert undl_maturity is not None vols = self[F.VOLATILITY] vol_quote = ql.QuoteHandle(ql.SimpleQuote(vols)) index = self[F.INDEX] fixed_tenor = self.get(F.FIXED_LEG_TENOR) fixed_basis = self.get(F.FIXED_LEG_BASIS) float_basis = self.get(F.FLOAT_LEG_BASIS) or fixed_basis fixed_basis = fixed_basis or float_basis yield_curve = self[F.DISCOUNT_CURVE] yield_handle = ql.YieldTermStructureHandle(yield_curve) strike = self.get(F.STRIKE, ql.nullDouble()) notional = self.get(F.NOTIONAL, 1.0) vol_type = self.get(F.VOLATILITY_TYPE, "ShiftedLogNormal") vol_type = vol_type.upper() vol_type_enum = self._vol_type_map.get(vol_type, ql.ShiftedLognormal) vol_shift = self.get(F.VOLATILITY_SHIFT, 0.0) swaption_helper = ql.SwaptionHelper( maturity, undl_maturity, vol_quote, index, fixed_tenor, fixed_basis, float_basis, yield_handle, ql.CalibrationHelper.RelativePriceError, strike, notional, vol_type_enum, vol_shift) return swaption_helper
def test_black_formula_implied_stdev(self): """Testing implied volatility calculator""" expected = 0.2 * math.sqrt(self.expiry) black_price = 10.4506 res = ql.blackFormulaImpliedStdDev(self.option_type, self.strike, self.forward, black_price, self.df) self.assertAlmostEquals(expected, res, delta=1e-4, msg="Failed to determine Implied Vol rounded " "to a single vol bps.")
def test_blackFormula(self): """Testing blackFormula in a simple Black-Scholes World...""" #Anyone interested, feel free to provide more accurate number expected = 10.4506 res = ql.blackFormula(self.option_type, self.strike, self.forward, self.vol, self.df, self.displacement) self.assertAlmostEquals(expected, res, delta=1e-4, msg="Failed to calculate simple " "Black-Scholes-Merton price rounded to " "four decimal places.")
print("\nThe model's curve is set to the 6m forward curve. Note that " "\nthe model adapts automatically to other curves where appropriate " "\n(e.g. if an index requires a different forwarding curve) or " "\nwhere explicitly specified (e.g. in a swaption pricing engine)." ) gsr = ql.Gsr(t0_curve, stepDates, sigmas, reversion) swaptionEngine = ql.Gaussian1dSwaptionEngine(gsr, 64, 7.0, True, False, t0_Ois) nonstandardSwaptionEngine = ql.Gaussian1dNonstandardSwaptionEngine(gsr, 64, 7.0, True, False, ql.QuoteHandle(ql.SimpleQuote(0)), t0_Ois) swaption.setPricingEngine(nonstandardSwaptionEngine) swapBase = ql.EuriborSwapIsdaFixA(ql.Period('10Y'), t0_curve, t0_Ois) basket = swaption.calibrationBasket(swapBase, swaptionVol, 'Naive') for basket_i in basket: ql.as_black_helper(basket_i).setPricingEngine(swaptionEngine) method = ql.LevenbergMarquardt() ec = ql.EndCriteria(1000, 10, 1e-8, 1e-8, 1e-8) gsr.calibrateVolatilitiesIterative(basket, method, ec) print("\nThe engine can generate a calibration basket in two modes." "\nThe first one is called Naive and generates ATM swaptions adapted to" "\nthe exercise dates of the swaption and its maturity date" "\nThe resulting basket looks as follows:" ) printBasket(basket) print("\nLet's calibrate our model to this basket. We use a specialized" "\ncalibration method calibrating the sigma function one by one to" "\nthe calibrating vanilla swaptions. The result of this is as follows:" )
def normal_cap(curve_zero, curve_date, today_date, mat, notional, sigma, k): effective_date = Ql.Date(today_date.serialNumber() + 1) calendar = Ql.SouthKorea(Ql.SouthKorea.KRX) while not calendar.isBusinessDay(effective_date): effective_date = Ql.Date(effective_date.serialNumber() + 1) option_mat_d = dt.datetime( effective_date.year(), effective_date.month(), effective_date.dayOfMonth()) + dateutil.relativedelta.relativedelta( months=12 * mat) option_mat_d = Ql.Date(option_mat_d.day, option_mat_d.month, option_mat_d.year) freq = Ql.Period('3M') convention = Ql.ModifiedFollowing term_date_convention = Ql.ModifiedFollowing my_rule = Ql.DateGeneration.Backward end_month = False schedule = Ql.Schedule(effective_date, option_mat_d, freq, calendar, convention, term_date_convention, my_rule, end_month) # Unadj_couponDate == schdule.__getitem__() # Unadj_couponDate == fixRateStart # fixRateStart == schdule.__getitem__() fixing_d = np.zeros(4 * mat) fix_rates_start = np.zeros(4 * mat) fix_rate_end = np.zeros(4 * mat) for i in range(4 * mat): fixing_d[i] = (my_working_day(schedule.__getitem__(i), 'KOREA', -1) - today_date) / 365 fix_rates_start[i] = (schedule.__getitem__(i) - today_date) / 365 fix_rate_end[i] = (schedule.__getitem__(i + 1) - today_date) / 365 fix_per = fix_rate_end - fix_rates_start methods = Ql.LinearInterpolation(curve_date, curve_zero) df1 = np.zeros(4 * mat) df2 = np.zeros(4 * mat) fix_rate = np.zeros(4 * mat) payment_d = np.zeros(4 * mat) day_cont_fraction = np.zeros(4 * mat) for i in range(4 * mat): df1[i] = ma.exp(-methods(fix_rates_start[i], allowExtrapolation=True) * fix_rates_start[i]) df2[i] = ma.exp(-methods(fix_rate_end[i], allowExtrapolation=True) * fix_rate_end[i]) fix_rate[i] = ((df1[i] - df2[i]) / df2[i]) / fix_per[i] payment_d[i] = (schedule.__getitem__(i + 1) - today_date) / 365 day_cont_fraction[i] = (schedule.__getitem__(i + 1) - schedule.__getitem__(i)) / 365 normal_d = np.zeros(4 * mat) d1 = np.zeros(4 * mat) d2 = np.zeros(4 * mat) normal_caplet = np.zeros(4 * mat) df = np.zeros(4 * mat) caplet = np.zeros(4 * mat) for i in range(4 * mat): normal_d[i] = (fix_rate[i] - k) / (sigma * ma.sqrt(fixing_d[i])) normal_caplet[i] = (fix_rate[i] - k) * norm.cdf( normal_d[i]) + sigma * ma.sqrt(fixing_d[i]) * norm.pdf(normal_d[i]) df[i] = ma.exp(-methods(payment_d[i], allowExtrapolation=True) * payment_d[i]) caplet[i] = notional * normal_caplet[i] * day_cont_fraction[i] * df[i] on_df = ma.exp(-methods(curve_date[1], allowExtrapolation=True) * curve_date[1]) price = sum(caplet) / on_df return price
# QuantLib is free software: you can redistribute it and/or modify it under the # terms of the QuantLib license. You should have received a copy of the # license along with this program; if not, please email # <*****@*****.**>. The license is also available online at # <https://www.quantlib.org/license.shtml>. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the license for more details. import QuantLib as ql import pandas as pd interactive = 'get_ipython' in globals() trade_date = ql.Date(21, 5, 2009) ql.Settings.instance().setEvaluationDate(trade_date) ql.IborCoupon.createAtParCoupons() dep_tenors = [1, 2, 3, 6, 9, 12] dep_quotes = [0.003081, 0.005525, 0.007163, 0.012413, 0.014, 0.015488] isdaRateHelpers = [ ql.DepositRateHelper(dep_quotes[i], dep_tenors[i] * ql.Period(ql.Monthly), 2, ql.WeekendsOnly(), ql.ModifiedFollowing, False, ql.Actual360()) for i in range(len(dep_tenors)) ] swap_tenors = [2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 15, 20, 25, 30] swap_quotes = [ 0.011907, 0.01699, 0.021198, 0.02444, 0.026937, 0.028967, 0.030504,
maturity = i.maturity tdatdt = i.TDATDT issue_date = Quantlib_Helpers.timestamp_to_qldate(tdatdt) maturity_date = zc_fitter.obs_date_ql + maturity _, fixed_rate_bond = CRSPQuantlib._make_bond(zc_fitter.opt, price, coupon, issue_date, maturity_date) #Remember to account for coupon freq here # Delete this zc_fitter.opt.day_counter.yearFraction(zc_fitter.obs_date_ql, maturity_date) 99.455 = 100*(1+y)^(-.24) import math math.exp(-math.log(.99455)*4) zc_fitter.yieldcurve.referenceDate() fixed_rate_bond.setPricingEngine(empty_engine) zc_fitter.yieldcurve.dates() p_fitted = fixed_rate_bond.cleanPrice() p_dirty = ql.CashFlows_npv(fixed_rate_bond.cashflows(), zc_fitter.discountingTermStructure, False, zc_fitter.obs_date_ql) p_fitted = p_dirty - fixed_rate_bond.accruedAmount() fixed_rate_bond.dirtyPrice() tdatdt[current_obs]
def oas_dirty_price(self, yield_curve_timeseries, model, model_params, last, quote, date, day_counter, calendar, business_convention, compounding, frequency, settlement_days, oas_spread=None, **kwargs): """ Warning ------- This method has only been tested with ``model=QuantLib.HullWhite``. Parameters ---------- yield_curve_timeseries: :py:func:`YieldCurveTimeSeries` The yield curve object against which the z-spreads will be calculated. model: str A string representing one of QuantLib Short Rate models, for simulating evolution of rates. **Currently only tested with QuantLib.HullWhite.** model_params: tuple, dict Parameter set for the model. * tuple format: (param1, param2, ...) If a tuple is passed, assumes the model parameters are fixed for all possibly vectorized calculation dates. * dict format: {date1: (param1, param2, ...), date2: (param1, param2, ...), ... } If a dict is passed, assumes it contains a parameter set for each date of the possibly vectorized calculation dates. last: bool, optional Whether to last data. Default: see :py:func:`default_arguments`. quote: scalar, optional Bond's quote. Default: see :py:func:`default_arguments`. date: QuantLib.Date, optional Date of the calculation. Default: see :py:func:`default_arguments`. day_counter: QuantLib.DayCounter, optional Day counter for the calculation. Default: see :py:func:`default_arguments`. calendar: QuantLib.Calendar, optional The calendar used for calculation. Default: see :py:func:`default_arguments`. business_convention: QuantLib.BusinessDayConvention The business day convention used for calculation. Default: see :py:func:`default_arguments`. compounding: QuantLib.Compounding, optional Compounding convention for the calculation. Default: see :py:func:`default_arguments`. frequency: QuantLib.Frequency, optional Compounding frequency. Default: see :py:func:`default_arguments`. settlement_days: int, optional Number of days for trade settlement. Default: see :py:func:`default_arguments`. oas_spread: float, optional The spread to be used in the calculation, will self calculate the oas_spread if none is passed. Returns ------- scalar Bond's clean price from the option-adjusted spread relative to `yield_curve_timeseries`. """ bond = self.bond date = to_ql_date(date) settlement_date = self.settlement_date( date=date, calendar=calendar, business_convention=business_convention, settlement_days=settlement_days) if self.is_expired(settlement_date): return np.nan if oas_spread is None: oas_spread = self.oas( yield_curve_timeseries=yield_curve_timeseries, model=model, model_params=model_params, last=last, quote=quote, date=date, day_counter=day_counter, calendar=calendar, business_convention=business_convention, compounding=compounding, frequency=frequency, settlement_days=settlement_days, **kwargs) if yield_curve_timeseries.calendar.isHoliday(date): yield_date = yield_curve_timeseries.calendar.adjust( date, ql.Preceding) yield_curve = ql.ImpliedTermStructure( yield_curve_timeseries.yield_curve_handle(date=yield_date), date) else: yield_curve = yield_curve_timeseries.yield_curve(date=date) yield_curve_handle = ql.YieldTermStructureHandle(yield_curve) ql.Settings.instance().evaluationDate = date ql_model = to_ql_short_rate_model(model_name=model) if isinstance(model_params, dict): # Assumes model parameters are given for each date. ql_model = ql_model(yield_curve_handle, *model_params[date]) else: # Only one set of model parameters are given (calibrated for, say, a specific date). ql_model = ql_model(yield_curve_handle, *model_params) engine = ql.TreeCallableFixedRateBondEngine(ql_model, 40) bond.setPricingEngine(engine) clean_price = bond.cleanPriceOAS(oas_spread, yield_curve_handle, day_counter, compounding, frequency, settlement_date) return clean_price + self.accrued_interest(date=settlement_date)
def __call__(self, date, csv_path, yts_handle_ois): yts_handle = ql.RelinkableYieldTermStructureHandle() cv_df = pd.read_csv(csv_path, index_col='Term') cv = cv_df.drop( columns=['Shift', 'Shifted Rate', 'Zero Rate', 'Discount']) cv['Market Rate'] = cv_df['Market Rate'] * 0.01 helpers = ql.RateHelperVector() index_libor = ql.USDLibor(ql.Period('3m'), yts_handle) simple_quote = [] for term, data in cv.iterrows(): term = term.replace(' ', '') if term == '3MO': simple_quote.append(ql.SimpleQuote(float(data['Market Rate']))) helpers.append( ql.DepositRateHelper(ql.QuoteHandle(simple_quote[-1]), index_libor)) elif term[:2] == 'ED': simple_quote.append( ql.SimpleQuote((1.0 - float(data['Market Rate'])) * 100)) helpers.append( ql.FuturesRateHelper(ql.QuoteHandle(simple_quote[-1]), ql.IMM.date(term[-2:]), index_libor)) elif term[-2:] == 'YR': simple_quote.append(ql.SimpleQuote(float(data['Market Rate']))) swapIndex = ql.UsdLiborSwapIsdaFixAm( ql.Period(term.replace('YR', 'y'))) helpers.append( ql.SwapRateHelper(ql.QuoteHandle(simple_quote[-1]), swapIndex, ql.QuoteHandle(), ql.Period(), yts_handle_ois)) return ql.PiecewiseLogLinearDiscount(date, helpers, ql.Actual365Fixed())
# QuantLib is free software: you can redistribute it and/or modify it under the # terms of the QuantLib license. You should have received a copy of the # license along with this program; if not, please email # <*****@*****.**>. The license is also available online at # <https://www.quantlib.org/license.shtml>. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the license for more details. import QuantLib as ql import pandas as pd # ### Setup todaysDate = ql.Date(15, ql.February, 2002) ql.Settings.instance().evaluationDate = todaysDate calendar = ql.TARGET() settlementDate = ql.Date(19, ql.February, 2002) def calibrate(model, helpers, l, name): print("Model: %s" % name) method = ql.Simplex(l) model.calibrate(helpers, method, ql.EndCriteria(1000, 250, 1e-7, 1e-7, 1e-7)) print("Parameters: %s" % model.params()) totalError = 0.0
def Date(d, m, y): return ql.Date(d, m, y)
def quantlibprice(strike_price,optiontype,volatility): # option data maturity_date = ql.Date(15, 11, 2020) spot_price = 311.790009 dividend_rate = 0 if optiontype == "call": option_type = ql.Option.Call elif optiontype == "put": option_type = ql.Option.Put risk_free_rate = 0.0154 day_count = ql.Actual365Fixed() calendar = ql.UnitedStates() calculation_date = ql.Date(15, 11, 2019) ql.Settings.instance().evaluationDate = calculation_date payoff = ql.PlainVanillaPayoff(option_type, strike_price) settlement = calculation_date am_exercise = ql.AmericanExercise(settlement, maturity_date) american_option = ql.VanillaOption(payoff, am_exercise) spot_handle = ql.QuoteHandle( ql.SimpleQuote(spot_price) ) flat_ts = ql.YieldTermStructureHandle( ql.FlatForward(calculation_date, risk_free_rate, day_count) ) dividend_yield = ql.YieldTermStructureHandle( ql.FlatForward(calculation_date, dividend_rate, day_count) ) flat_vol_ts = ql.BlackVolTermStructureHandle( ql.BlackConstantVol(calculation_date, calendar, volatility, day_count) ) bsm_process = ql.BlackScholesMertonProcess(spot_handle, dividend_yield, flat_ts, flat_vol_ts) steps = 200 binomial_engine = ql.BinomialVanillaEngine(bsm_process, "crr", steps) american_option.setPricingEngine(binomial_engine) return american_option.NPV()
curve_zero = [ 0.019999452, 0.019999452, 0.022624443, 0.025524245, 0.028602631, 0.029838992, 0.031748738, 0.033907276, 0.039328792, 0.041775496, 0.043108492, 0.043986181, 0.044609803, 0.045252978, 0.045678818, 0.046117978, 0.046572489, 0.046810916, 0.046917368, 0.045489601 ] curve_date = [ 0, 0.002739726, 0.079452055, 0.164383562, 0.249315068, 0.498630137, 0.750684932, 1.016438356, 2.002739726, 3.010958904, 4.008219178, 5.005479452, 6.005479452, 7.008219178, 8.008219178, 9.021917808, 10.0109589, 12.0109589, 15.01643836, 20.02191781 ] today_date = Ql.Date(1, 2, 2010) Mat = 10 Notional = 100 sigma = 0.16550020 K = 0.0463552554 # ### effective_date = Ql.Date(today_date.serialNumber() + 1) calendar = Ql.SouthKorea(Ql.SouthKorea.KRX) while not calendar.isBusinessDay(effective_date): effective_date = Ql.Date(effective_date.serialNumber() + 1) optionMatD = dt.datetime( effective_date.year(), effective_date.month(), effective_date.dayOfMonth()) + dateutil.relativedelta.relativedelta( months=12 * Mat)
import QuantLib as ql payoff = ql.PlainVanillaPayoff(ql.Option.Call, 100) print(payoff(95)) from WindPy import w import datetime w.start() code = '10001755.SH' # 获取最新成交价,买一价,卖一价 data = [temp[0] for temp in w.wsq(code, "rt_latest,rt_bid1,rt_ask1").Data] print(data) latest_price, bid1_price, ask1_price = data date_now = datetime.datetime.now().strftime('%Y-%m-%d') # 获取当日的时点 option_data = w.wss( "10001546.SH", "exe_mode,exe_type,exe_price,exe_ratio,lasttradingdate,exe_enddate", "tradeDate=" + date_now).Data print(option_data) option_type = option_data[0][0] option_strike = option_data[2][0] option_volume = option_data[3][0] option_last_day = option_data[4][0].strftime('%Y-%m-%d')
def main(): # Set evaluation date... # todays_date = ql.Date(7, 4, 2015) todays_date = ql.Date(13, 8, 2015) # ql.Settings.instance().setEvaluationDate(todays_date) set_evaluation_date(todays_date) # Market data... rate = ql.SimpleQuote(0.03) flat_forward, flat_forward_handle, flat_forward_relinkable_handle = \ create_flat_forward(todays_date, rate) Euribor6M = ql.Euribor6M(flat_forward_relinkable_handle) # Create simple swap portfolio... list_of_start_dates = [ todays_date + ql.Period("2d"), todays_date + ql.Period("2d") ] list_of_maturity_dates = [ql.Period(years) for years in ["5Y", "4Y"]] list_of_nominal_amounts = [1E6, 5E5] list_of_float_indices = [Euribor6M, Euribor6M] list_of_fixed_rates = [0.03, 0.03] list_of_swap_types = [ql.VanillaSwap.Payer, ql.VanillaSwap.Receiver] simple_portfolio = make_simple_portfolio( list_of_start_dates, list_of_maturity_dates, list_of_nominal_amounts, list_of_float_indices, list_of_fixed_rates, list_of_swap_types) portfolio_npv = calculate_portfolio_npv(flat_forward_relinkable_handle, simple_portfolio) # Instantiate the Gsr model... volatility_step_dates = [todays_date + 100] volatilities = [ ql.QuoteHandle(ql.SimpleQuote(0.0075)), ql.QuoteHandle(ql.SimpleQuote(0.0075)) ] mean_reversion = [ql.QuoteHandle(ql.SimpleQuote(0.02))] gsr_model = generate_gsr_model(flat_forward_handle, volatility_step_dates, volatilities, mean_reversion, forward_measure_time=16.0) # Create evaluation grid and simulate paths (using the Gsr model)... evaluation_dates_grid, evaluation_time_grid = \ define_evaluation_grid(todays_date, simple_portfolio) inv_cumulative_gaussian_rsg = create_random_number_generator( evaluation_time_grid) number_of_paths = 1500 tenors = np.array([0.0, 0.5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) x, zero_bonds = generate_paths(number_of_paths, evaluation_time_grid, tenors, inv_cumulative_gaussian_rsg, gsr_model) # Plot paths... # for i in range(number_of_paths): # plt.plot(evaluation_time_grid, x[i, :]) # Create the discounted NPV matrix... npv_matrix = create_npv_matrix(todays_date, number_of_paths, evaluation_dates_grid, simple_portfolio, flat_forward, flat_forward_relinkable_handle, zero_bonds, Euribor6M) discount_factors = generate_discount_factors(flat_forward_handle, evaluation_time_grid) discounted_npv_cube = calculate_discounted_npv_matrix( npv_matrix, discount_factors) # Calculate the portfolio NPV for the netting set... portfolio_npv = calculate_netted_npv_matrix(npv_matrix) discounted_portfolio_npv = calculate_netted_npv_matrix(discounted_npv_cube) # # Plot the first NPV paths... # n_first, n_last = 0, 30 # plot_npv_paths(n_first, n_last, # evaluation_time_grid, # portfolio_npv, discounted_portfolio_npv) # Calculate the exposure and discounted exposure... exposure = calculate_exposure(portfolio_npv) discounted_exposure = calculate_exposure(discounted_portfolio_npv) # # Plot the first exposure paths... # n_first, n_last = 0, 30 # plot_exposure_paths(n_first, n_last, # evaluation_time_grid, # exposure, discounted_exposure) # # Calculate the "expected" and the "expected discounted" exposure... expected_exposure = calculate_expected_exposure(portfolio_npv, number_of_paths) expected_discounted_exposure = calculate_expected_exposure( discounted_portfolio_npv, number_of_paths) # # Plot the "expected" and the "expected discounted" exposure paths... # plot_expected_exposure_paths(evaluation_time_grid, # expected_exposure, expected_discounted_exposure) # # plot_expected_discounted_exposure(evaluation_time_grid, # expected_discounted_exposure) # # Calculate the PFE (corresponding to the default 95% quantile)... potential_future_exposure = \ calculate_potential_future_exposure(exposure, number_of_paths) # plot_potential_future_exposure(evaluation_time_grid, # potential_future_exposure) # calculate the maximum PFE... max_potential_future_exposure = np.max(potential_future_exposure) # Default curve default_dates = [ todays_date + ql.Period(i_year, ql.Years) for i_year in range(11) ] hazard_rates = [0.02 * i_year for i_year in range(11)] default_curve = create_default_curve(default_dates, hazard_rates) # # Plot default curves (default and survival probabilities, default densities, and hazard rates)... # # default_times = np.linspace(0, 30, 100) # plot_default_curve(default_times, default_curve) # Calculate default probabilities... default_probabilities = \ calculate_default_probability_grid(evaluation_time_grid, default_curve) # Calculation of the CVA... economic_cva = calculate_economic_cva(expected_discounted_exposure, default_probabilities, recovery_rate=0.4) print(economic_cva)
def create_pricing_engine(flat_forward_relinkable_handle): return ql.DiscountingSwapEngine(flat_forward_relinkable_handle)
def tearDown(self): ql.Settings.instance().evaluationDate = ql.Date()
def setUp(self): QuantLib.Settings.instance().setEvaluationDate( QuantLib.Date(2, 1, 2010)) self.settlement_days = 3 self.face_amount = 100.0 self.redemption = 100.0 self.issue_date = QuantLib.Date(2, 1, 2008) self.maturity_date = QuantLib.Date(2, 1, 2018) self.calendar = QuantLib.UnitedStates( QuantLib.UnitedStates.GovernmentBond) self.day_counter = QuantLib.ActualActual(QuantLib.ActualActual.Bond) self.sched = QuantLib.Schedule(self.issue_date, self.maturity_date, QuantLib.Period(QuantLib.Semiannual), self.calendar, QuantLib.Unadjusted, QuantLib.Unadjusted, QuantLib.DateGeneration.Backward, False) self.coupons = [0.05] self.bond = QuantLib.FixedRateBond(self.settlement_days, self.face_amount, self.sched, self.coupons, self.day_counter, QuantLib.Following, self.redemption, self.issue_date) self.flat_forward = QuantLib.FlatForward(self.issue_date, self.coupons[0], self.day_counter, QuantLib.Compounded, QuantLib.Semiannual) self.term_structure_handle = QuantLib.RelinkableYieldTermStructureHandle( self.flat_forward) bondEngine = QuantLib.DiscountingBondEngine(self.term_structure_handle) self.bond.setPricingEngine(bondEngine)
''' some little examples ''' import QuantLib as ql rate = ql.InterestRate(0.05, ql.Actual360(), ql.Compounded, ql.Annual) print(rate.rate()) daycount = rate.dayCounter().dayCount(ql.Date(1,1,2020), ql.Date(1,1,2021)) print(daycolittle examples
def __call__(self, date, csv_path): yts_handle_ois = ql.RelinkableYieldTermStructureHandle() cv_df = pd.read_csv(csv_path, index_col='Term') cv = cv_df.drop( columns=['Shift', 'Shifted Rate', 'Zero Rate', 'Discount']) cv['Market Rate'] = cv_df['Market Rate'] * 0.01 helpers = ql.RateHelperVector() overnight_index = ql.OvernightIndex('USD EFFR', 0, ql.USDCurrency(), ql.UnitedStates(), ql.Actual360(), yts_handle_ois) simple_quote = [] for term, data in cv.iterrows(): term = term.replace(' ', '') if term == '1D': simple_quote.append(ql.SimpleQuote(float(data['Market Rate']))) helpers.append( ql.DepositRateHelper(ql.QuoteHandle(simple_quote[-1]), overnight_index)) #index.addFixing(rev_date, float(data['Market Rate'])) else: settlementDays = 2 swapIndex = ql.OvernightIndexedSwapIndex( "EFFR", ql.Period(term), settlementDays, ql.USDCurrency(), overnight_index) simple_quote.append(ql.SimpleQuote(float(data['Market Rate']))) helpers.append( ql.OISRateHelper(2, ql.Period(term), ql.QuoteHandle(simple_quote[-1]), overnight_index, paymentLag=0, paymentCalendar=ql.UnitedStates())) #ois_curve = ql.PiecewiseLogLinearDiscount(date, helpers, ql.Actual365Fixed()) #yts_handle_ois.linkTo(ois_curve) return ql.PiecewiseLogLinearDiscount(date, helpers, ql.Actual365Fixed())
ql.EndCriteria(400, 100, 1.0e-8, 1.0e-8, 1.0e-8)) # Output the implied Black volatilities for i in range(numRows): helper = helpers[i] j = numCols - i - 1 # 1x5, 2x4, 3x3, 4x2, 5x1 k = i * numCols + j npv = helper.modelValue() implied = helper.impliedVolatility(npv, 1e-4, 1000, 0.05, 0.50) diff = implied - swaptionVols[k] print('{0}x{1}: model {2:.5%}, market {3:.5%} ({4:.5%})'.format( i + 1, swapLenghts[j], implied, swaptionVols[k], diff)) todaysDate = ql.Date(15, ql.February, 2002) calendar = ql.TARGET() settlementDate = ql.Date(19, ql.February, 2002) ql.Settings.instance().evaluationDate = todaysDate # flat yield term structure impling 1x5 swap at 5% flatRate = ql.SimpleQuote(0.04875825) rhTermStructure = ql.YieldTermStructureHandle( ql.FlatForward(settlementDate, ql.QuoteHandle(flatRate), ql.Actual365Fixed())) # Define the ATM/OTM/ITM swaps fixedLegFrequency = ql.Annual fixedLegConvention = ql.Unadjusted floatingLegConvention = ql.ModifiedFollowing fixedLegDayCounter = ql.Thirty360(ql.Thirty360.European)
def oas_convexity(self, yield_curve_timeseries, model, model_params, last, quote, date, day_counter, calendar, business_convention, compounding, frequency, settlement_days, **kwargs): """ Warning ------- This method has only been tested with ``model=QuantLib.HullWhite``. Parameters ---------- yield_curve_timeseries: :py:func:`YieldCurveTimeSeries` The yield curve object against which the z-spreads will be calculated. model: str A string representing one of QuantLib Short Rate models, for simulating evolution of rates. **Currently only tested with QuantLib.HullWhite.** model_params: tuple, dict Parameter set for the model. * tuple format: (param1, param2, ...) If a tuple is passed, assumes the model parameters are fixed for all possibly vectorized calculation dates. * dict format: {date1: (param1, param2, ...), date2: (param1, param2, ...), ... } If a dict is passed, assumes it contains a parameter set for each date of the possibly vectorized calculation dates. last: bool, optional Whether to last data. Default: see :py:func:`default_arguments`. quote: scalar, optional Bond's quote. Default: see :py:func:`default_arguments`. date: QuantLib.Date, optional Date of the calculation. Default: see :py:func:`default_arguments`. day_counter: QuantLib.DayCounter, optional Day counter for the calculation. Default: see :py:func:`default_arguments`. calendar: QuantLib.Calendar, optional The calendar used for calculation. Default: see :py:func:`default_arguments`. business_convention: QuantLib.BusinessDayConvention The business day convention used for calculation. Default: see :py:func:`default_arguments`. compounding: QuantLib.Compounding, optional Compounding convention for the calculation. Default: see :py:func:`default_arguments`. frequency: QuantLib.Frequency, optional Compounding frequency. Default: see :py:func:`default_arguments`. settlement_days: int, optional Number of days for trade settlement. Default: see :py:func:`default_arguments`. Returns ------- scalar Bond's convexity from the option-adjusted spread relative to `yield_curve_timeseries`. """ bond = self.bond date = to_ql_date(date) settlement_date = self.settlement_date( date=date, calendar=calendar, business_convention=business_convention, settlement_days=settlement_days) if self.is_expired(settlement_date): return np.nan if yield_curve_timeseries.calendar.isHoliday(date): yield_date = yield_curve_timeseries.calendar.adjust( date, ql.Preceding) yield_curve = ql.ImpliedTermStructure( yield_curve_timeseries.yield_curve_handle(date=yield_date), date) else: yield_curve = yield_curve_timeseries.yield_curve(date=date) yield_curve_handle = ql.YieldTermStructureHandle(yield_curve) oas_spread = self.oas(yield_curve_timeseries=yield_curve_timeseries, model=model, model_params=model_params, last=last, quote=quote, date=date, day_counter=day_counter, calendar=calendar, business_convention=business_convention, compounding=compounding, frequency=frequency, settlement_days=settlement_days, **kwargs) ql.Settings.instance().evaluationDate = date return bond.effectiveConvexity(float(oas_spread), yield_curve_handle, day_counter, compounding, frequency)
import os import pickle ''' ================================== Calibrate SVI Params (put option) ================================== Only use daily put option data to calibrate SVI model, and could only be used for heging put options. ''' start = timeit.default_timer() np.random.seed() w.start() begDate = ql.Date(30, 3, 2017) #begDate = ql.Date(15, 7, 2017) endDate = ql.Date(20, 7, 2017) calendar = ql.China() daycounter = ql.ActualActual() evalDate = begDate daily_params = {} daily_option_prices = {} daily_spots = {} daily_svi_dataset = {} dates = [] count = 0 while evalDate <= endDate: print('Start : ', evalDate)
# <*****@*****.**>. The license is also available online at # <https://www.quantlib.org/license.shtml>. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the license for more details. # %% import QuantLib as ql import pandas as pd # %% [markdown] # ### Global parameters # %% todaysDate = ql.Date(15, ql.May, 1998) ql.Settings.instance().evaluationDate = todaysDate # %% interactive = "get_ipython" in globals() # %% [markdown] # ### Option construction # %% exercise = ql.AmericanExercise(todaysDate, ql.Date(17, ql.May, 1999)) payoff = ql.PlainVanillaPayoff(ql.Option.Put, 40.0) # %% option = ql.VanillaOption(payoff, exercise)
def ir_vol_history_update(ws=None): """ ir_vol_his_update() From BloombergDate.xlsm, retrieve swaption and cap vol data from start_dt to end_dt. """ wb = xw.Book.caller() ws = wb.sheets("IR_VOL") # period_range = "ir_vol_period" date_range = "ir_vol_date" # To pause for collecting data from bloomberg time_to_sleep = 2 # seconds # get range of date st_dt, end_dt = ws.range(period_range).value date = utils.str2qldate(st_dt) end_dt = utils.str2qldate(end_dt) day1 = ql.Period(1, ql.Days) # change ql.Date to str str_converter = utils.qldate2str # calendar to deal with holidays cKR = custom_calendar.cKR # DB connection engine engine = utils.db_engine(database='otcora', schema='OTCUSER', password='******') Session = sessionmaker(bind=engine) session = Session() while date <= end_dt: if cKR.isBusinessDay(date): ws.range(date_range).value = str_converter(date) checking = utils.check_bloomberg_error checker = 0 swaption_vol = ws.range("SwaptionVol").value cap_vol = ws.range("CapVol").value while checking(swaption_vol, time_to_sleep): checker = checker + 1 if checker > 3: raise utils.JbException("hello") """ pythoncom.PumpWaitingMessages() time.sleep(0.01) """ # updater.updater(data=swaption_vol, table_name='ficc_swaption_atm_vol', head_nullable_data=4, date_index=0, factor=0.0001, data_name='swaption vol data', engine=engine, session=session) # updater.updater(data=cap_vol, table_name='ficc_cap_atm_vol', head_nullable_data=3, date_index=0, factor=0.0001, data_name='cap vol data', engine=engine, session=session) date = date + day1 #ms = wb.app.api() # from xlwings.constants import Calculation # xw.constants.CalculationState # # session.close() engine.dispose() utils.Mbox("", "swaption & cap vol done", 0)
import QuantLib as ql rate = ql.InterestRate(0.05, ql.Actual360(), ql.Compounded, ql.Annual) print("Rate: ", rate.rate()) print("DayCount: ", rate.dayCounter()) print("DiscountFactor: ", rate.discountFactor(1)) print("DiscountFactor: ", rate.discountFactor(ql.Date(15, 6, 2020), ql.Date(15, 6, 2021))) print("CompoundFactor: ", rate.compoundFactor(ql.Date(15, 6, 2020), ql.Date(15, 6, 2021))) print( "EquivalentRate: ", rate.equivalentRate(ql.Actual360(), ql.Compounded, ql.Semiannual, ql.Date(15, 6, 2020), ql.Date(15, 6, 2021))) factor = rate.compoundFactor(ql.Date(15, 6, 2020), ql.Date(15, 6, 2021)) print( "ImpliedRate: ", rate.impliedRate(factor, ql.Actual360(), ql.Continuous, ql.Annual, ql.Date(15, 6, 2020), ql.Date(15, 6, 2021)))
def to_ql_dates(datetime_dates): ql_dates = [] for d in datetime_dates: dt = ql.Date(d.day, d.month, d.year) ql_dates.append(dt) return ql_dates
from Utilities.utilities import * import QuantLib as ql import math import numpy as np import timeit start = timeit.default_timer() calendar = ql.China() daycounter = ql.ActualActual() def Date(d, m, y): return ql.Date(d, m, y) def get_black_variance_surface(calibrated_params, maturity_dates_c, calibrate_date, daycounter, calendar, spot, rfs): strikes = np.arange(1.0, 5.0, 0.1 / 100) data_BVS = [] for idx_mdt, mdt in enumerate(maturity_dates_c): params = calibrated_params[idx_mdt] a_star, b_star, rho_star, m_star, sigma_star = params ttm = daycounter.yearFraction(calibrate_date, mdt) rf = rfs.get(idx_mdt) Ft = spot * math.exp(rf * ttm) x_svi = np.log(strikes / Ft) vol = np.sqrt( np.maximum( 0, a_star + b_star * (rho_star * (x_svi - m_star) + np.sqrt(
def set_values(values): try: settlement_date = values["startDate"] days = ql.Actual365Fixed() calendar = ql.Japan() frequency = ql.Annual ql.Settings.instance().evaluationDate = values["startDate"] compounding = ql.Compounded payoff = ql.PlainVanillaPayoff(values["callput"], values["strikeprice"]) eu_exercise = ql.EuropeanExercise(values["expirationdate"]) european_option = ql.VanillaOption(payoff, eu_exercise) spot_handle = ql.QuoteHandle(ql.SimpleQuote(values["spotprice"])) rTS = ql.YieldTermStructureHandle( ql.FlatForward(settlement_date, values["domesticInterestrate"], days, compounding, frequency)) fTS = ql.YieldTermStructureHandle( ql.FlatForward(settlement_date, values["foreignInterestrate"], days, compounding, frequency)) flat_vol_ts = ql.BlackVolTermStructureHandle( ql.BlackConstantVol(settlement_date, calendar, values["volatility"], days)) garman_kohlagen_process = ql.GarmanKohlagenProcess( spot_handle, fTS, rTS, flat_vol_ts) engine = ql.AnalyticEuropeanEngine(garman_kohlagen_process) european_option.setPricingEngine(engine) vol = float( european_option.impliedVolatility(values["premium"], garman_kohlagen_process, 0.000000001, minVol=0.00001, maxVol=5.0) * 100) flat_vol_ts = ql.BlackVolTermStructureHandle( ql.BlackConstantVol(settlement_date, calendar, vol / 100, days)) garman_kohlagen_process = ql.GarmanKohlagenProcess( spot_handle, fTS, rTS, flat_vol_ts) engine = ql.AnalyticEuropeanEngine(garman_kohlagen_process) european_option.setPricingEngine(engine) return round(float(values["premium"]), 3), floatrounding( float(european_option.delta())), floatrounding(vol), None except Exception as e: message = 'Unkown Error Occured' if 'root not bracketed' in repr(e): message = server_responses.root_not_bracketed_error elif 'ValueError' in repr(e): message = server_responses.value_error if 'KeyError' in repr(e): message = server_responses.missing_key_error return None, None, None, message
def stringIntoQuantLib(self): year = int(self._sDate[0:4]) month = int(self._sDate[5:7]) day = int(self._sDate[8:]) ql_date = ql.Date(day, month, year) return ql_date
def tearDown(self): QuantLib.Settings.instance().setEvaluationDate(QuantLib.Date())
def to_ql_date(datetime_date): dt = ql.Date(datetime_date.day, datetime_date.month, datetime_date.year) return dt
# This file is part of QuantLib, a free-software/open-source library # for financial quantitative analysts and developers - http://quantlib.org/ # # QuantLib is free software: you can redistribute it and/or modify it under the # terms of the QuantLib license. You should have received a copy of the # license along with this program; if not, please email # <*****@*****.**>. The license is also available online at # <http://quantlib.org/license.shtml>. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the license for more details. import QuantLib as ql calendar = ql.TARGET() # set evaluation date todaysDate = ql.Date(15, ql.May, 2007) todaysDate = calendar.adjust(todaysDate) ql.Settings.instance().evaluationDate = todaysDate risk_free_rate = ql.YieldTermStructureHandle(ql.FlatForward(todaysDate, 0.01, ql.Actual365Fixed())) # CDS parameters recovery_rate = 0.5 quoted_spreads = [0.0150, 0.0150, 0.0150, 0.0150] tenors = [ql.Period(3, ql.Months), ql.Period(6, ql.Months), ql.Period(1, ql.Years), ql.Period(2, ql.Years)] maturities = [calendar.adjust(todaysDate + x, ql.Following) for x in tenors] instruments = [
def testCleanPriceFromZSpread(self): """ Testing FixedRateBond clean price derived from Z-spread. """ self.assertEqual(round(QuantLib.cleanPriceFromZSpread( self.bond, self.flat_forward, 0.01, self.day_counter, QuantLib.Compounded, QuantLib.Semiannual, self.issue_date + 1 * QuantLib.Months), 4), 92.5637)
def get_dividend_ts(evalDate, daycounter): dividend_ts = ql.YieldTermStructureHandle( ql.FlatForward(evalDate, 0.0, daycounter)) return dividend_ts