|
From: Luigi B. <lui...@gm...> - 2022-06-01 20:05:17
|
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
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
|