|
From: Luigi B. <lui...@gm...> - 2022-05-23 16:56:16
|
May you send sample code and the value of the fixings for one of those options? Thanks! Luigi On Mon, May 23, 2022 at 8:32 AM Ashish Bansal <ash...@gm...> wrote: > Luigi, > > We ran the asian code, which i sent earlier for a couple of asian options > traded on exchange. We got prices very close to traded prices when we used > the value of running accumulator as 1 for march option being valued on 17th > with past fixing count as 12. But when we used the sum of past fixing > prices i.e. 1302.88 we got a very different number like 6.09 against 4.57 > earlier and 14.11 against 12.39 earlier. > > Just want to confirm if i am missing something about running accumulator > and should it be really the sum of all past fixings? > > Thanks for help in advance. > Ashish > > On Fri, 20 May 2022 at 14:58, Ashish Bansal <ash...@gm...> > wrote: > >> Ok understood. thanks. >> >> On Fri, 20 May 2022 at 14:46, Luigi Ballabio <lui...@gm...> >> wrote: >> >>> It would be the sum of past fixings; for three past fixings of 100.2, >>> 101.3 and 94.6 it would be 296.1. >>> >>> Luigi >>> >>> >>> On Thu, May 19, 2022 at 12:37 PM Ashish Bansal <ash...@gm...> >>> wrote: >>> >>>> Thanks, Luigi for the suggestion. After taking the running accumulator, >>>> we are able to generate the numbers. What exactly should be passed here? >>>> The average price of past fixings or just 1 when the trade is priced during >>>> averaging period? >>>> >>>> Thanks for help. >>>> >>>> Ashish >>>> >>>> On Wed, 18 May 2022 at 21:17, Luigi Ballabio <lui...@gm...> >>>> wrote: >>>> >>>>> I don't have a 1.7 version to try it, but the check is the one at < >>>>> https://github.com/lballabio/QuantLib/blob/QuantLib-v1.7/ql/pricingengines/asian/fdblackscholesasianengine.cpp#L51-L53>, >>>>> suggesting that your running accumulator should be 0 (which makes sense, >>>>> because you're using arithmetic average, i.e., a sum, and if you don't have >>>>> any fixings yet the sum should be 0.) >>>>> Your default seems to be 1 instead. >>>>> >>>>> Luigi >>>>> >>>>> >>>>> On Wed, May 18, 2022 at 5:17 PM Ashish Bansal <ash...@gm...> >>>>> wrote: >>>>> >>>>>> Luigi, >>>>>> >>>>>> Our code is not too much but we are using deprecated functions like >>>>>> FDEuropeanEngine and FDAmericanEngine. Not sure if using new >>>>>> function called FdBlackScholesVanillaEngine has any change in the >>>>>> calculation that our code will have an impact. >>>>>> >>>>>> Can we use the DiscreteAveragingAsianOption without the overloaded >>>>>> parameter of pastfixings under 1.7? >>>>>> >>>>>> Ashish >>>>>> >>>>>> On Wed, 18 May 2022 at 20:00, Luigi Ballabio < >>>>>> lui...@gm...> wrote: >>>>>> >>>>>>> Hi — it could be. Any particular reason you're still using a >>>>>>> version from 4 years ago? If you have a substantial amount of code that >>>>>>> depends on QuantLib, it might require some work to update because some >>>>>>> methods were deprecated and then removed in the meantime; and of course >>>>>>> you'll probably have some validation process in place when updating, so >>>>>>> that's work too. But on the other hand, you're missing 4 years worth of >>>>>>> bug fixings... >>>>>>> >>>>>>> Luigi >>>>>>> >>>>>>> >>>>>>> On Wed, May 18, 2022 at 4:19 PM Ashish Bansal < >>>>>>> ash...@gm...> wrote: >>>>>>> >>>>>>>> We tried again and got the same error. >>>>>>>> >>>>>>>> Could it be due to the old version (1.7) we are using? I see in the >>>>>>>> release notes of Apr-2021 that the overload for past fixing was added: >>>>>>>> >>>>>>>> - Added an overloaded constructor for Asian options that takes >>>>>>>> all past fixings and thus allows to reprice them correctly when the >>>>>>>> evaluation date changes (thanks to Jack Gillett). >>>>>>>> >>>>>>>> Ashish >>>>>>>> >>>>>>>> On Wed, 18 May 2022 at 19:14, Jack G <jac...@gm...> >>>>>>>> wrote: >>>>>>>> >>>>>>>>> Hi Ashish, >>>>>>>>> >>>>>>>>> I have a better answer for you with a screenshot awaiting >>>>>>>>> moderation as it's quite large, but in the meantime, I was able to run your >>>>>>>>> code without problems using the python at the bottom of this email >>>>>>>>> (although I didn't check the numbers). >>>>>>>>> >>>>>>>>> If there is something you're doing specifically to generate the >>>>>>>>> error, could you please attach a minimal reproduction of it? >>>>>>>>> >>>>>>>>> Best, >>>>>>>>> Jack >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> import QuantLib as ql >>>>>>>>> from copy import deepcopy >>>>>>>>> from datetime import datetime >>>>>>>>> from datetime import timedelta >>>>>>>>> >>>>>>>>> >>>>>>>>> # DEFAULT_PERIODS = [ql.Period(f"{i}d") for i in range(0,31)] >>>>>>>>> DEFAULT_PERIODS = [ql.Period("6M"), ql.Period("12M"), >>>>>>>>> ql.Period("18M"), ql.Period("24M")] >>>>>>>>> DEFAULT_tGRID = 100 >>>>>>>>> DEFAULT_xGRID = 100 >>>>>>>>> DEFAULT_aGRID = 50 >>>>>>>>> DEFAULT_aRA = 1 # arithmeticRunningAccumulator >>>>>>>>> DEFAULT_PASTFIXINGS = 1 >>>>>>>>> >>>>>>>>> >>>>>>>>> class AsianOptionPrice: >>>>>>>>> def __init__(self, **x): >>>>>>>>> for k, v in x.items(): >>>>>>>>> setattr(self, k, v) >>>>>>>>> self.tGrid = x.get("tGrid", DEFAULT_tGRID) >>>>>>>>> self.xGrid = x.get("xGrid", DEFAULT_xGRID) >>>>>>>>> self.aGrid = x.get("aGrid", DEFAULT_aGRID) >>>>>>>>> self.periods = x.get("periods", DEFAULT_PERIODS) >>>>>>>>> self.pastFixings = x.get("pastFixings", >>>>>>>>> DEFAULT_PASTFIXINGS) >>>>>>>>> self.aRA = x.get("arithmeticRunningAccumulator", >>>>>>>>> DEFAULT_aRA) >>>>>>>>> self.keyList = [k for k, v in x.items()] >>>>>>>>> self.dist = 10**(-2) >>>>>>>>> self.date_format = "%d-%m-%Y" >>>>>>>>> self.value_date = ql.DateParser.parseFormatted( >>>>>>>>> self.valueDate, '%d-%m-%Y') >>>>>>>>> self.expiry_date = ql.DateParser.parseFormatted( >>>>>>>>> self.expiryDate, '%d-%m-%Y') >>>>>>>>> ql.Settings.instance().evaluationDate = self.value_date >>>>>>>>> self.exDay = ql.DateParser.parseFormatted(self.expiryDate, >>>>>>>>> '%d-%m-%Y') >>>>>>>>> # Volatility input is required for running the computing >>>>>>>>> implied volatility function. This volatility is NOT used in the implied >>>>>>>>> volatility calculation. >>>>>>>>> self.vol_for_iv_calc = 0.10 >>>>>>>>> self.IV = None >>>>>>>>> >>>>>>>>> def generate_fixture_dates(self,start_date,end_date,period): >>>>>>>>> schedule = ql.MakeSchedule(start_date, end_date, period) >>>>>>>>> fixture_dates = [_date for _date in schedule if >>>>>>>>> _date.weekday() not in [1,7]] >>>>>>>>> return fixture_dates >>>>>>>>> def asian(self): >>>>>>>>> """ >>>>>>>>> arithmeticRunningAccumulator(aRA) >>>>>>>>> """ >>>>>>>>> arithmeticRunningAccumulator = self.aRA >>>>>>>>> pastFixings = self.pastFixings >>>>>>>>> print(pastFixings) >>>>>>>>> option_type = self.optionType.lower() >>>>>>>>> if option_type not in ["call", "put"]: >>>>>>>>> raise Exception( >>>>>>>>> f"Option Type is Neither Call nor Put, Option type >>>>>>>>> is {option_type}") >>>>>>>>> option_type = ql.Option.Call if option_type == "call" else >>>>>>>>> ql.Option.Put >>>>>>>>> strike = self.strikePrice >>>>>>>>> today = self.value_date >>>>>>>>> print(today) >>>>>>>>> fixingStartDate >>>>>>>>> =ql.DateParser.parseFormatted(self.fixingStartDate, '%d-%m-%Y') >>>>>>>>> print("#"*40,fixingStartDate) >>>>>>>>> periods = self.periods >>>>>>>>> asianFutureFixingDates = >>>>>>>>> self.generate_fixture_dates(fixingStartDate,self.expiry_date,ql.Period("1d")) >>>>>>>>> print("#"*40,asianFutureFixingDates) >>>>>>>>> asianExpiryDate = self.expiry_date >>>>>>>>> vanillaPayoff = ql.PlainVanillaPayoff(option_type, strike) >>>>>>>>> europeanExercise = ql.EuropeanExercise(asianExpiryDate) >>>>>>>>> arithmeticAverage = ql.Average().Arithmetic >>>>>>>>> discreteArithmeticAsianOption = >>>>>>>>> ql.DiscreteAveragingAsianOption( >>>>>>>>> arithmeticAverage, arithmeticRunningAccumulator, >>>>>>>>> pastFixings, asianFutureFixingDates, vanillaPayoff, europeanExercise) >>>>>>>>> return discreteArithmeticAsianOption >>>>>>>>> >>>>>>>>> def create_arg_list(self, Option=None, >>>>>>>>> compute_implied_vol=None, implied_vol_am_put=None): >>>>>>>>> ''' >>>>>>>>> The arguments with disturbances added. Will be used >>>>>>>>> for calculation of Greeks >>>>>>>>> using numerical differentiation. >>>>>>>>> Creating a dictionary of arguments that will be used >>>>>>>>> for option price and greeks calculation. >>>>>>>>> ''' >>>>>>>>> self.riskFreeRate = self.riskFreeRate/100 >>>>>>>>> originalDict_ = {k: getattr(self, k) for k in self.keyList} >>>>>>>>> ListDict = [] >>>>>>>>> for i in range(4): >>>>>>>>> ListDict.append(deepcopy(originalDict_)) >>>>>>>>> ListDict[1]['riskFreeRate'] = self.riskFreeRate + self.dist >>>>>>>>> ListDict[2]['volatility'] = self.volatility + self.dist >>>>>>>>> ListDict[3]['expiryDate'] = (datetime.strptime( >>>>>>>>> self.expiryDate, self.date_format) - >>>>>>>>> timedelta(days=1)).strftime(self.date_format) >>>>>>>>> print(ListDict) >>>>>>>>> return(ListDict) >>>>>>>>> >>>>>>>>> def bs_process(self, create_process_for_iv=None, use_IV=None): >>>>>>>>> """ >>>>>>>>> Creating the Black-Scholes process for option valuation. >>>>>>>>> """ >>>>>>>>> riskFreeTS = ql.YieldTermStructureHandle( >>>>>>>>> ql.FlatForward(self.value_date, self.riskFreeRate, >>>>>>>>> ql.Actual365Fixed())) >>>>>>>>> dividendTS = ql.YieldTermStructureHandle( >>>>>>>>> ql.FlatForward(self.value_date, 0, >>>>>>>>> ql.Actual365Fixed())) >>>>>>>>> volatility = >>>>>>>>> ql.BlackVolTermStructureHandle(ql.BlackConstantVol( >>>>>>>>> self.value_date, ql.NullCalendar(), self.volatility, >>>>>>>>> ql.Actual365Fixed())) >>>>>>>>> initialValue = >>>>>>>>> ql.QuoteHandle(ql.SimpleQuote(self.underlyingPrice)) >>>>>>>>> process = ql.BlackScholesMertonProcess( >>>>>>>>> initialValue, dividendTS, riskFreeTS, volatility) >>>>>>>>> return(process) >>>>>>>>> >>>>>>>>> def evaluate(self, Option=None, compute_implied_vol=None): >>>>>>>>> """ >>>>>>>>> Call the relevant option based on the input. >>>>>>>>> """ >>>>>>>>> self.riskFreeRate = self.riskFreeRate/100 >>>>>>>>> res = None >>>>>>>>> option = AsianOptionPrice.asian(self) >>>>>>>>> if compute_implied_vol == True: >>>>>>>>> # create Black Scholes process using IV. >>>>>>>>> process = AsianOptionPrice.bs_process( >>>>>>>>> self, create_process_for_iv=False, use_IV=True) >>>>>>>>> engine = ql.FdBlackScholesAsianEngine( >>>>>>>>> process, tGrid=self.tGrid, xGrid=self.xGrid, >>>>>>>>> aGrid=self.aGrid) >>>>>>>>> option.setPricingEngine(engine) >>>>>>>>> res = {'value': option.NPV(), 'impliedVolatility': >>>>>>>>> self.IV} >>>>>>>>> else: >>>>>>>>> # Create Black Scholes process using HV. >>>>>>>>> process = AsianOptionPrice.bs_process( >>>>>>>>> self, create_process_for_iv=False, use_IV=False) >>>>>>>>> engine = ql.FdBlackScholesAsianEngine( >>>>>>>>> process, tGrid=self.tGrid, xGrid=self.xGrid, >>>>>>>>> aGrid=self.aGrid) >>>>>>>>> option.setPricingEngine(engine) >>>>>>>>> res = {'value': option.NPV()} >>>>>>>>> return res >>>>>>>>> >>>>>>>>> def evaluate_asian_npv(self): >>>>>>>>> Option = AsianOptionPrice.asian(self) >>>>>>>>> process = AsianOptionPrice.bs_process( >>>>>>>>> self, create_process_for_iv=False, use_IV=False) >>>>>>>>> engine = ql.FdBlackScholesAsianEngine( >>>>>>>>> process, tGrid=self.tGrid, xGrid=self.xGrid, >>>>>>>>> aGrid=self.aGrid) >>>>>>>>> Option.setPricingEngine(engine) >>>>>>>>> res = Option.NPV() >>>>>>>>> return(res) >>>>>>>>> >>>>>>>>> def calculate_greeks(self, Option=None, >>>>>>>>> compute_implied_vol=None): >>>>>>>>> today = self.value_date >>>>>>>>> Option = AsianOptionPrice.asian(self) >>>>>>>>> if compute_implied_vol == True: >>>>>>>>> process = AsianOptionPrice.bs_process( >>>>>>>>> self, create_process_for_iv=False, use_IV=True) >>>>>>>>> else: >>>>>>>>> process = AsianOptionPrice.bs_process( >>>>>>>>> self, create_process_for_iv=False, use_IV=False) >>>>>>>>> engine = ql.FdBlackScholesAsianEngine( >>>>>>>>> process, tGrid=self.tGrid, xGrid=self.xGrid, >>>>>>>>> aGrid=self.aGrid) >>>>>>>>> Option.setPricingEngine(engine) >>>>>>>>> option_greeks_ = {"delta": Option.delta(), "gamma": >>>>>>>>> Option.gamma( >>>>>>>>> )} >>>>>>>>> ArgmntList = AsianOptionPrice.create_arg_list( >>>>>>>>> self, Option, compute_implied_vol=True, >>>>>>>>> implied_vol_am_put=self.volatility) >>>>>>>>> DisturbedPrices = [] >>>>>>>>> arg_keys = ['Price', 'PRup', 'PVup', 'PTup'] >>>>>>>>> for i in range(4): >>>>>>>>> DisturbedPrices.append(eval( >>>>>>>>> >>>>>>>>> "AsianOptionPrice(**ArgmntList[i]).evaluate_asian_npv()")) >>>>>>>>> print(DisturbedPrices) >>>>>>>>> PricesDistrbd = dict(zip(arg_keys, DisturbedPrices)) >>>>>>>>> Rho = (PricesDistrbd['PRup'] - >>>>>>>>> PricesDistrbd['Price'])/(self.dist*100) >>>>>>>>> vega = (PricesDistrbd['PVup'] - >>>>>>>>> PricesDistrbd['Price'])/(self.dist*100) >>>>>>>>> thetaDay = (PricesDistrbd['PTup'] - PricesDistrbd['Price']) >>>>>>>>> option_greeks_.update({'rho': Rho, 'vega': vega, 'theta': >>>>>>>>> thetaDay}) >>>>>>>>> return option_greeks_ >>>>>>>>> >>>>>>>>> >>>>>>>>> settings = { >>>>>>>>> "computeHistoricalVolatiltiy": False, >>>>>>>>> "tenantId": "380", >>>>>>>>> "gridPoints": 149, >>>>>>>>> "computeImpliedVolatiltiy": False, >>>>>>>>> "runId": 3735, >>>>>>>>> "timeSteps": 150, >>>>>>>>> "optionTrades": [ >>>>>>>>> { >>>>>>>>> "underlyingPrice": 98.69, >>>>>>>>> "refNo": "OPT-1135-GVA", >>>>>>>>> "underlyingPriceUnit": "US cents/LB", >>>>>>>>> "valueDate": "17-03-2022", >>>>>>>>> "fixingStartDate":"01-05-2022", >>>>>>>>> "pastFixings":0, >>>>>>>>> "volatility": 0.6015, >>>>>>>>> "openQuantity": 1, >>>>>>>>> "strikePriceUnit": "US cents/LB", >>>>>>>>> "optionType": "Call", >>>>>>>>> "expiryDate": "31-05-2022", >>>>>>>>> "exType": "asian", >>>>>>>>> "riskFreeRate": 0.8080374999999999, >>>>>>>>> "premium": 1, >>>>>>>>> "portfolioId": 18209, >>>>>>>>> "marketPremium": 11.42, >>>>>>>>> "longShort": "Long", >>>>>>>>> "optionInstrument": "EURO USD 1.105 Call", >>>>>>>>> "asset": "EURO USD 1.105 Call", >>>>>>>>> "portfolioName": "Option Trades", >>>>>>>>> "scenarioId": 8356, >>>>>>>>> "scenarioName": "Option Valuation - Greeks", >>>>>>>>> "strikePrice": 95, >>>>>>>>> "maturityInYears": 0.205479452 >>>>>>>>> } >>>>>>>>> ], >>>>>>>>> "userId": "5263", >>>>>>>>> "americanOptionsEngine": "CrankNicolson" >>>>>>>>> } >>>>>>>>> >>>>>>>>> opt = AsianOptionPrice(**settings["optionTrades"][0]) >>>>>>>>> opt.evaluate_asian_npv() >>>>>>>>> >>>>>>>>> On Wed, May 18, 2022 at 9:25 PM Ashish Bansal < >>>>>>>>> ash...@gm...> wrote: >>>>>>>>> >>>>>>>>>> Hi Jack, >>>>>>>>>> >>>>>>>>>> Please find attached the Asian option python code and the option >>>>>>>>>> trade payload. >>>>>>>>>> >>>>>>>>>> Thanks for your help, >>>>>>>>>> Regards, >>>>>>>>>> Ashish >>>>>>>>>> >>>>>>>>>> On Wed, 18 May 2022 at 12:12, Jack G <jac...@gm...> >>>>>>>>>> wrote: >>>>>>>>>> >>>>>>>>>>> Hi Ashish, >>>>>>>>>>> >>>>>>>>>>> I've just lifted the examples from your references directly for >>>>>>>>>>> a discrete arithmetic Asian using the FD Asian engine and it is working for >>>>>>>>>>> me - can you share the code you are using that breaks please? >>>>>>>>>>> >>>>>>>>>>> Best, >>>>>>>>>>> Jack >>>>>>>>>>> >>>>>>>>>>> On Wed, 18 May 2022, 13:55 Ashish Bansal, < >>>>>>>>>>> ash...@gm...> wrote: >>>>>>>>>>> >>>>>>>>>>>> Hi all, >>>>>>>>>>>> >>>>>>>>>>>> Could somebody help with the asian options? We are using >>>>>>>>>>>> FdBlackScholesAsianengine with DiscreteAveragingAsianOption. Online >>>>>>>>>>>> references are given below. In DiscreteAveragingAsianOption, we need to >>>>>>>>>>>> pass the past fixing which is suggested to be 0 for new trade. Whereas when >>>>>>>>>>>> we are passing it as 0, we are getting the following error: >>>>>>>>>>>> "QuantLib Error - Running average requires at least one past >>>>>>>>>>>> fixing" >>>>>>>>>>>> ref: >>>>>>>>>>>> >>>>>>>>>>>> https://quantlib-python-docs.readthedocs.io/en/latest/pricing_engines.html#fdblackscholesasianengine >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> https://quantlib-python-docs.readthedocs.io/en/latest/instruments/options.html?highlight=DiscreteAveragingAsianOption#ql.DiscreteAveragingAsianOption >>>>>>>>>>>> >>>>>>>>>>>> Queries: >>>>>>>>>>>> 1. What is to be passed here for new trade if not 0? >>>>>>>>>>>> 2. For trade which is mid of averaging and has few past >>>>>>>>>>>> fixings, do we need to pass the count of past fixing or the actual rates of >>>>>>>>>>>> the pastfixing as an array? >>>>>>>>>>>> >>>>>>>>>>>> Any help will be appreciated. >>>>>>>>>>>> >>>>>>>>>>>> Thanks in advance >>>>>>>>>>>> Ashish >>>>>>>>>>>> _______________________________________________ >>>>>>>>>>>> QuantLib-users mailing list >>>>>>>>>>>> Qua...@li... >>>>>>>>>>>> https://lists.sourceforge.net/lists/listinfo/quantlib-users >>>>>>>>>>>> >>>>>>>>>>> _______________________________________________ >>>>>>>> QuantLib-users mailing list >>>>>>>> Qua...@li... >>>>>>>> https://lists.sourceforge.net/lists/listinfo/quantlib-users >>>>>>>> >>>>>>> |