|
From: Luigi B. <lui...@gm...> - 2022-06-03 09:23:57
|
Version 1.27 will be out sometime in July. The changes included so far are at <https://github.com/lballabio/QuantLib/milestone/23?closed=1>. The changes in previous releases are at < https://github.com/lballabio/QuantLib/releases/>. Luigi On Thu, Jun 2, 2022 at 7:23 AM Ashish Bansal <ash...@gm...> wrote: > That is great news. I have been waiting for TW engine for a long time :) > . Special thanks to Fredrick (@gbfredrik) for adding it. > > When is v1.27 planned to be released? Hoping that it will be released on > SWIG at the same time. Where can I read about other changes in 1.27 so that > we can plan accordingly? > > Thanks > Ashish > > On Thu, 2 Jun 2022 at 01:35, Luigi Ballabio <lui...@gm...> > wrote: > >> Hello, >> it does mention it now -- the Turnbull-Wakeman engine was added to >> the repository less than a month ago and will be in release 1.27. It >> didn't exist in release 1.17. >> >> Luigi >> >> >> On Wed, Jun 1, 2022 at 7:55 PM Ashish Bansal <ash...@gm...> >> wrote: >> >>> Luigi, >>> >>> You had given me the following link sometime back. It does mention about >>> the Turnbull Wakeman model based on 2 moment matching: >>> >>> https://github.com/lballabio/QuantLib/blob/master/test-suite/asianoptions.cpp >>> <ql/pricingengines/asian/turnbullwakemanasianengine.hpp> >>> >>> [image: image.png] >>> Even the example is given in the above file. Although the asianoption is >>> part of test-suite but the Turnbull...engine is part of main QL. Is it not >>> part of SWIG? i tried in it in python but could not find it. >>> >>> How can I use this in python with QL v1.17? >>> >>> Regards, >>> Ashish >>> >>> On Mon, 30 May 2022 at 19:39, Ashish Bansal <ash...@gm...> >>> wrote: >>> >>>> Thanks for the responses. I am trying various papers to find the moment >>>> matching for the asian options. I did find the calculation based on >>>> Turnbull-Wakeman model here: >>>> >>>> https://osf.io/efq6a/download >>>> >>>> >>>> I tried this but did not get good results for options expiring in a few >>>> months. I will try some other source probably. >>>> >>>> >>>> One last question, does QL's FdBlackScholesAsianengine with DiscreteAveragingAsianOption >>>> adjust the valuation for trade which are in between the averaging period; >>>> as mentioned on slide # 9 and 10 of this deck? >>>> >>>> >>>> Regards, >>>> >>>> Ashish >>>> >>>> On Thu, 26 May 2022 at 13:24, Luigi Ballabio <lui...@gm...> >>>> wrote: >>>> >>>>> I mean that the two engines give the same price, i.e. 6.09. I don't >>>>> have info on moment matching. >>>>> >>>>> On Wed, May 25, 2022 at 6:51 PM Ashish Bansal <ash...@gm...> >>>>> wrote: >>>>> >>>>>> By same price, you mean same as exchange i.e. 4.57. or same as aRA >>>>>> parameter i.e. 6.09? >>>>>> >>>>>> Any guidance on moment matching? I could not find anything online >>>>>> about it. >>>>>> >>>>>> Regards >>>>>> Ashish >>>>>> >>>>>> On Wed, May 25, 2022, 7:02 PM Luigi Ballabio < >>>>>> lui...@gm...> wrote: >>>>>> >>>>>>> Hi, >>>>>>> no, the engine doesn't do moment matching. I don't think we >>>>>>> have something ready to use for that in the library. >>>>>>> As for the accumulator: I confirm it's the sum. If you create a >>>>>>> virtual Python environment and install the latest QuantLib in it, you can >>>>>>> try your shortened code with the other constructor for the Asian option >>>>>>> (the one taking the list of fixings). It returns the same price. >>>>>>> >>>>>>> Luigi >>>>>>> >>>>>>> >>>>>>> On Wed, May 25, 2022 at 2:46 PM Ashish Bansal < >>>>>>> ash...@gm...> wrote: >>>>>>> >>>>>>>> Hi Luigi, >>>>>>>> >>>>>>>> One question about the QL calculation: Does QL code for the Asian >>>>>>>> option include *moment matching *of the volatility or do we need >>>>>>>> to do that before passing to the DiscAvAsOption? >>>>>>>> >>>>>>>> Regarding the code, I had attached the full code from our system in >>>>>>>> my previous email, attaching here too. The shortened version of the code, >>>>>>>> containing only the QL interaction and excluding excess processing, is also >>>>>>>> attached here. It includes the trade parameters we are using to evaluate >>>>>>>> the Asian option. Strangely, the value is coming zero with short-code but >>>>>>>> with full code in our system, we are getting the values. >>>>>>>> >>>>>>>> Following is the NPV that we are getting in our system (using full >>>>>>>> code) for our trade which has averaging period from 1st March to 31st March >>>>>>>> 2022 and the market traded premium of 4.56: >>>>>>>> arithmeticRunningAccumulator NPV >>>>>>>> 0 4.5711 >>>>>>>> 1302.88 6.09 >>>>>>>> >>>>>>>> Thanks in advance for help. >>>>>>>> >>>>>>>> PS: We are using QL1.17 and the vols are sourced from Reuters could >>>>>>>> be different from implied in the market traded premium. >>>>>>>> >>>>>>>> Regards, >>>>>>>> Ashish >>>>>>>> >>>>>>>> On Mon, 23 May 2022 at 22:26, Luigi Ballabio < >>>>>>>> lui...@gm...> wrote: >>>>>>>> >>>>>>>>> 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 >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> |