def __init__(self, cx, rundate, input_path, outputdir, netting_set, stats, log): self.rundate = rundate self.input_path = input_path self.outputdir = outputdir self.netting_set = os.path.splitext(netting_set)[0] + '.json' self.stats = stats self.logger = log self.params = { 'calc_name': ('cmc', 'calc1'), 'Time_grid': '0d 2d 1w(1w) 1m(1m) 3m(3m) 1y(1y)', 'Run_Date': rundate, 'Currency': 'ZAR', 'Random_Seed': 5126, 'Calc_Scenarios': 'No', 'Dynamic_Scenario_Dates': 'Yes', 'Debug': 'No', 'NoModel': 'Constant', 'Partition': 'None', 'Generate_Slideshow': 'No', 'PFE_Recon_File': '' } from riskflow.adaptiv import AdaptivContext self.cx = AdaptivContext() old_cx = AdaptivContext() # load marketdata old_cx.parse_json( os.path.join(self.input_path, rundate, 'MarketData.json')) # load up the CVA marketdata file self.cx.parse_json( os.path.join(self.input_path, rundate, 'MarketDataCVA.json')) # update the cva data with the arena data self.cx.params['Price Factors'].update(old_cx.params['Price Factors']) # load trade self.cx.parse_json( os.path.join(self.input_path, self.rundate, self.netting_set)) # get the netting set self.ns = self.cx.deals['Deals']['Children'][0]['instrument'].field # get the agreement currency self.agreement_currency = self.ns.get('Agreement_Currency', 'ZAR') # get the balance currency self.balance_currency = self.ns.get('Balance_Currency', self.agreement_currency) # set the OIS cashflow flag to speed up prime linked swaps self.cx.params['Valuation Configuration'][ 'CFFloatingInterestListDeal']['OIS_Cashflow_Group_Size'] = 1 from riskflow.utils import Curve # set the survival curve to a default value self.crb_default = self.cx.deals['Attributes']['Reference'] self.cx.params['Price Factors'].setdefault( 'SurvivalProb.' + self.crb_default, { 'Recovery_Rate': 0.5, 'Curve': Curve([], [[0.0, 0.0], [.5, .01], [1, .02], [3, .07], [5, .15], [10, .35], [20, .71]]), 'Property_Aliases': None })
def load_market_data(rundate, path, json_name='MarketData.json', cva_default=True): """ Loads a json marketdata file and corresponding calendar (assumed to be named 'calendars.cal') :param rundate: folder inside path where the marketdata file resides :param path: root folder for the marketdata, calendar and trades :param json_name: name of the marketdata json file (default MarketData.json) :param cva_default: loads a survival curve with recovery 50% (useful for testing) :return: a context object with the data and calendars loaded """ from riskflow.adaptiv import AdaptivContext as Context context = Context() context.parse_json(os.path.join(path, rundate, json_name)) context.parse_calendar_file(os.path.join(path, 'calendars.cal')) context.params['System Parameters']['Base_Date'] = pd.Timestamp(rundate) if cva_default: context.params['Price Factors']['SurvivalProb.DEFAULT'] = { 'Recovery_Rate': 0.5, 'Curve': utils.Curve([], [[0.0, 0.0], [.5, .01], [1, .02], [3, .07], [5, .15], [10, .35], [20, .71], [30, 1.0]]), 'Property_Aliases': None } return context
def start(self, rundate, input_path, calendar, outfile='CVAMarketDataCal'): # disable gpus os.environ['CUDA_VISIBLE_DEVICES'] = "-1" # set the log level for the parent os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' # set the logger logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)-8s %(message)s', datefmt='%m-%d %H:%M') from riskflow.adaptiv import AdaptivContext # create the context self.cx = AdaptivContext() # load calendars self.cx.parse_calendar_file(calendar) # store the path self.path = input_path # load marketdata if rundate is None: self.daily = True self.path = os.path.split(input_path)[0] self.outfile = outfile self.cx.parse_json(input_path) # load up the old file if present old_output_name = os.path.join(self.path, outfile + '.json') if os.path.isfile(old_output_name): self.ref = AdaptivContext() self.ref.parse_json(old_output_name) params_to_bootstrap = self.cx.params[ 'Bootstrapper Configuration'].keys() for factor in [ x for x in self.ref.params['Price Factors'].keys() if x.split('.', 1)[0] in params_to_bootstrap ]: # override it self.cx.params['Price Factors'][factor] = self.ref.params[ 'Price Factors'][factor] rundate = pd.Timestamp.now().strftime('%Y-%m-%d') elif os.path.isfile( os.path.join(self.path, rundate, 'MarketDataCal.json')): self.cx.parse_json( os.path.join(self.path, rundate, 'MarketDataCal.json')) elif os.path.isfile(os.path.join(self.path, rundate, 'MarketData.json')): self.cx.parse_json( os.path.join(self.path, rundate, 'MarketData.json')) else: logging.error( 'Cannot find market data for rundate {}'.format(rundate)) return # update the rundate if necessary if self.cx.params['System Parameters']['Base_Date'] is None: logging.info('Setting rundate {}'.format(rundate)) self.cx.params['System Parameters']['Base_Date'] = pd.Timestamp( rundate) # load the params price_factors = self.manager.dict(self.cx.params['Price Factors']) price_models = self.manager.dict(self.cx.params['Price Models']) sys_params = self.manager.dict(self.cx.params['System Parameters']) holidays = self.manager.dict(self.cx.holidays) logging.info("starting {0} workers in {1}".format( self.NUMBER_OF_PROCESSES, input_path)) self.workers = [ Process(target=work, args=(i, self.queue, self.result, price_factors, price_models, sys_params, holidays)) for i in range(self.NUMBER_OF_PROCESSES) ] for w in self.workers: w.start() # load the bootstrapper on to the queue - note - order is important here - hence python 3.6 for bootstrapper_name, params in self.cx.params[ 'Bootstrapper Configuration'].items(): # get the market price id and any options for bootstrapping market_price, _, *options = params.split(',', 2) # get the market prices for this bootstrapper market_prices = { k: v for k, v in self.cx.params['Market Prices'].items() if k.startswith(market_price) } # number of return statuses needed status_required = 0 for market_price in market_prices.keys(): status_required += 1 self.queue.put((bootstrapper_name, options, { market_price: market_prices[market_price] })) for i in range(status_required): logging.info(self.result.get()) # tell the children it's over self.queue.put(None) # store the results back in the parent context self.cx.params['Price Factors'] = price_factors.copy() self.cx.params['Price Models'] = price_models.copy() # finish up # close the queues self.queue.close() self.result.close() # join the children to this process for i in range(self.NUMBER_OF_PROCESSES): self.workers[i].join() # write out the data logging.info('Parent: All done - saving data') if self.daily: # write out the calibrated data self.cx.write_marketdata_json( os.path.join(self.path, self.outfile + '.json')) self.cx.write_market_file( os.path.join(self.path, self.outfile + '.dat')) logfilename = os.path.join(self.path, self.outfile + '.log') else: self.cx.write_marketdata_json( os.path.join(self.path, rundate, 'MarketDataCal.json')) self.cx.write_market_file( os.path.join(self.path, rundate, 'MarketDataCal.dat')) logfilename = os.path.join(self.path, rundate, 'MarketDataCal.log') # copy the logs across with open(logfilename, 'wb') as wfd: for f in glob.glob('bootstrap*.log'): with open(f, 'rb') as fd: shutil.copyfileobj(fd, wfd)
def bootstrap(path, rundate, reuse_cal=True): from riskflow.adaptiv import AdaptivContext context = AdaptivContext() if reuse_cal and os.path.isfile( os.path.join(path, rundate, 'CVAMarketData.json')): context.parse_json(os.path.join(path, rundate, 'CVAMarketData.json')) else: context.parse_json(os.path.join(path, rundate, 'MarketData.json')) context.params['System Parameters']['Base_Date'] = pd.Timestamp(rundate) context.parse_calendar_file(os.path.join(path, 'calendars.cal')) logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)-8s %(message)s', datefmt='%m-%d %H:%M') context.bootstrap() context.write_marketdata_json( os.path.join(path, rundate, 'MarketDataCal.json')) context.write_market_file(os.path.join(path, rundate, 'MarketDataCal.dat'))
class CVAVega(JOB): def __init__(self, cx, rundate, input_path, outputdir, netting_set, stats, log): self.rundate = rundate self.input_path = input_path self.outputdir = outputdir self.netting_set = os.path.splitext(netting_set)[0] + '.json' self.stats = stats self.logger = log self.params = { 'calc_name': ('cmc', 'calc1'), 'Time_grid': '0d 2d 1w(1w) 3m(1m) 2y(3m)', 'Run_Date': rundate, 'Currency': 'ZAR', 'Random_Seed': 5126, 'Calc_Scenarios': 'No', 'Dynamic_Scenario_Dates': 'Yes', 'Debug': 'No', 'NoModel': 'Constant', 'Partition': 'None', 'Generate_Slideshow': 'No', 'PFE_Recon_File': '' } from riskflow.adaptiv import AdaptivContext self.cx = AdaptivContext() self.cx.parse_json( os.path.join(self.input_path, rundate, 'MarketDataCVA.json')) self.noshift = AdaptivContext() self.noshift.parse_json( os.path.join(self.input_path, rundate, 'MarketDataNoShift.json')) self.shift = AdaptivContext() self.shift.parse_json( os.path.join(self.input_path, rundate, 'MarketDataShift.json')) # update the cva data with the arena data self.cx.params['Price Factors'].update( self.noshift.params['Price Factors']) self.cx.parse_json( os.path.join(self.input_path, rundate, self.netting_set)) # get the netting set self.ns = self.cx.deals['Deals']['Children'][0]['instrument'].field # get the agreement currency self.agreement_currency = self.ns.get('Agreement_Currency', 'ZAR') # get the balance currency self.balance_currency = self.ns.get('Balance_Currency', self.agreement_currency) # set the OIS cashflow flag to speed up prime linked swaps self.cx.params['Valuation Configuration'][ 'CFFloatingInterestListDeal']['OIS_Cashflow_Group_Size'] = 1 from riskflow.utils import Curve # set the survival curve to a default value self.crb_default = self.cx.deals['Attributes']['Reference'] self.cx.params['Price Factors'].setdefault( 'SurvivalProb.' + self.crb_default, { 'Recovery_Rate': 0.5, 'Curve': Curve([], [[0.0, 0.0], [.5, .01], [1, .02], [3, .07], [5, .15], [10, .35], [20, .71]]), 'Property_Aliases': None }) def valid(self): if not self.cx.deals['Deals']['Children'][0]['Children']: return False else: return True def run_calc(self, calc): from riskflow.calculation import construct_calculation self.params['CVA'] = { 'Deflation': self.cx.deals['Calculation'].get('Deflation_Interest_Rate', 'ZAR-SWAP'), 'Gradient': 'No' } if self.cx.deals['Deals']['Children'][0]['instrument'].field.get( 'Collateralized') == 'True': self.logger(self.netting_set, 'is collateralized') self.params['Simulation_Batches'] = 20 self.params['Batch_Size'] = 256 else: self.params['Simulation_Batches'] = 10 self.params['Batch_Size'] = 512 self.logger(self.netting_set, 'is uncollateralized') # get the calculation parameters for CVA default_cva = { 'Deflate_Stochastically': 'Yes', 'Stochastic_Hazard_Rates': 'No', 'Counterparty': self.crb_default } cva_sect = self.cx.deals.get('Calculation', { 'Credit_Valuation_Adjustment': default_cva }).get('Credit_Valuation_Adjustment', default_cva) # update the params self.params['CVA']['Counterparty'] = cva_sect['Counterparty'] self.params['CVA']['Deflate_Stochastically'] = cva_sect[ 'Deflate_Stochastically'] self.params['CVA']['Stochastic_Hazard'] = cva_sect[ 'Stochastic_Hazard_Rates'] try: out = calc.execute(self.params) self.cx.params['Price Factors'].update( self.shift.params['Price Factors']) calcshift = construct_calculation('Credit_Monte_Carlo', self.cx) outshift = calcshift.execute(self.params) except Exception as e: exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback, limit=2, file=sys.stdout) self.logger(self.netting_set, 'Exception: ' + str(e.args)) else: stats = out['Stats'] stats.update({ 'CVA': out['Results']['cva'], 'CVA_Shift': outshift['Results']['cva'], 'Currency': self.params['Currency'] }) self.stats.setdefault('Stats', {})[self.netting_set] = stats # log the netting set self.logger( self.netting_set, 'CVA calc complete NoShift:{}, Shift:{}'.format( out['Results']['cva'], outshift['Results']['cva']))
class FVADEFAULT(JOB): def __init__(self, cx, rundate, input_path, outputdir, netting_set, stats, log): self.rundate = rundate self.input_path = input_path self.outputdir = outputdir self.netting_set = os.path.splitext(netting_set)[0] + '.json' self.stats = stats self.logger = log self.params = { 'calc_name': ('cmc', 'calc1'), 'Time_grid': '0d 2d 1w(1w) 1m(1m) 3m(3m) 1y(1y)', 'Run_Date': rundate, 'Currency': 'USD', 'Random_Seed': 5126, 'Calc_Scenarios': 'No', 'Dynamic_Scenario_Dates': 'Yes', 'Debug': 'No', 'NoModel': 'Constant', 'Partition': 'None', 'Generate_Slideshow': 'No', 'PFE_Recon_File': '' } from riskflow.adaptiv import AdaptivContext self.cx = AdaptivContext() old_cx = AdaptivContext() # load marketdata old_cx.parse_json( os.path.join(self.input_path, rundate, 'MarketData.json')) # load up the CVA marketdata file self.cx.parse_json( os.path.join(self.input_path, rundate, 'MarketDataCVA.json')) # update the cva data with the arena data self.cx.params['Price Factors'].update(old_cx.params['Price Factors']) # load trade self.cx.parse_json( os.path.join(self.input_path, self.rundate, self.netting_set)) # get the netting set self.ns = self.cx.deals['Deals']['Children'][0]['instrument'].field # get the agreement currency self.agreement_currency = self.ns.get('Agreement_Currency', 'USD') # get the balance currency self.balance_currency = self.ns.get('Balance_Currency', self.agreement_currency) # set the OIS cashflow flag to speed up prime linked swaps self.cx.params['Valuation Configuration'][ 'CFFloatingInterestListDeal']['OIS_Cashflow_Group_Size'] = 1 from riskflow.utils import Curve def makeflatcurve(curr, bps, tenor=30): return { 'Currency': curr, 'Curve': Curve([], [[0, bps * 0.01 * 0.01], [tenor, bps * 0.01 * 0.01]]), 'Day_Count': 'ACT_365', 'Property_Aliases': None, 'Sub_Type': 'None' } # set the survival curve to a default value self.crb_default = self.cx.deals['Attributes']['Reference'] # set up funding curves - ??? # self.cx.params['Price Factors']['InterestRate.ZAR-SWAP.OIS'] = makeflatcurve('ZAR',-15) # self.cx.params['Price Factors']['InterestRate.ZAR-SWAP.FUNDING'] = makeflatcurve('ZAR', 10) self.cx.params['Price Factors'][ 'InterestRate.USD-LIBOR-3M.FUNDING'] = makeflatcurve('USD', 65) self.cx.params['Price Factors'].setdefault( 'SurvivalProb.' + self.crb_default, { 'Recovery_Rate': 0.5, 'Curve': Curve([], [[0.0, 0.0], [.5, .01], [1, .02], [3, .07], [5, .15], [10, .35], [20, .71], [30, 1.0]]), 'Property_Aliases': None }) def valid(self): if not self.cx.deals['Deals']['Children'][0]['Children']: return False else: return True def run_calc(self, calc): filename = 'FVA_' + self.params[ 'Run_Date'] + '_' + self.crb_default + '.csv' if os.path.isfile(os.path.join(self.outputdir, 'Greeks', filename)): self.logger(self.netting_set, 'Warning: skipping FVA calc as file already exists') else: self.params['FVA'] = { 'Funding_Interest_Curve': 'USD-LIBOR-3M.FUNDING', 'Risk_Free_Curve': 'USD-OIS', 'Stochastic_Funding': 'Yes', 'Counterparty': self.crb_default, 'Gradient': 'Yes' } if self.cx.deals['Deals']['Children'][0]['instrument'].field.get( 'Collateralized', 'False') != 'True': # only calc FVA for uncollateralized counterparties self.params['Simulation_Batches'] = 10 self.params['Batch_Size'] = 512 self.logger(self.netting_set, 'is uncollateralized') try: out = calc.execute(self.params) except Exception as e: exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback, limit=2, file=sys.stdout) self.logger(self.netting_set, 'Exception: ' + str(e.args)) else: stats = out['Stats'] if 'grad_fva' in out['Results']: grad_fva = calc.gradients_as_df( out['Results']['grad_fva']).rename(columns={ 'Gradient': self.cx.deals['Attributes']['Reference'] }) grad_fva.to_csv( os.path.join(self.outputdir, 'Greeks', filename)) # store the FVA as part of the stats out['Stats'].update({ 'FVA': out['Results']['fva'], 'Currency': self.params['Currency'] }) self.stats.setdefault('Stats', {})[self.netting_set] = out['Stats'] # log the netting set self.logger(self.netting_set, 'FVA calc complete')
class CVADEFAULT(JOB): def __init__(self, cx, rundate, input_path, outputdir, netting_set, stats, log): self.rundate = rundate self.input_path = input_path self.outputdir = outputdir self.netting_set = os.path.splitext(netting_set)[0] + '.json' self.stats = stats self.logger = log self.params = { 'calc_name': ('cmc', 'calc1'), 'Time_grid': '0d 2d 1w(1w) 1m(1m) 3m(3m) 1y(1y)', 'Run_Date': rundate, 'Currency': 'ZAR', 'Random_Seed': 5126, 'Calc_Scenarios': 'No', 'Dynamic_Scenario_Dates': 'Yes', 'Debug': 'No', 'NoModel': 'Constant', 'Partition': 'None', 'Generate_Slideshow': 'No', 'PFE_Recon_File': '' } from riskflow.adaptiv import AdaptivContext self.cx = AdaptivContext() old_cx = AdaptivContext() # load marketdata old_cx.parse_json( os.path.join(self.input_path, rundate, 'MarketData.json')) # load up the CVA marketdata file self.cx.parse_json( os.path.join(self.input_path, rundate, 'MarketDataCVA.json')) # update the cva data with the arena data self.cx.params['Price Factors'].update(old_cx.params['Price Factors']) # load trade self.cx.parse_json( os.path.join(self.input_path, self.rundate, self.netting_set)) # get the netting set self.ns = self.cx.deals['Deals']['Children'][0]['instrument'].field # get the agreement currency self.agreement_currency = self.ns.get('Agreement_Currency', 'ZAR') # get the balance currency self.balance_currency = self.ns.get('Balance_Currency', self.agreement_currency) # set the OIS cashflow flag to speed up prime linked swaps self.cx.params['Valuation Configuration'][ 'CFFloatingInterestListDeal']['OIS_Cashflow_Group_Size'] = 1 from riskflow.utils import Curve # set the survival curve to a default value self.crb_default = self.cx.deals['Attributes']['Reference'] self.cx.params['Price Factors'].setdefault( 'SurvivalProb.' + self.crb_default, { 'Recovery_Rate': 0.5, 'Curve': Curve([], [[0.0, 0.0], [.5, .01], [1, .02], [3, .07], [5, .15], [10, .35], [20, .71]]), 'Property_Aliases': None }) def valid(self): if not self.cx.deals['Deals']['Children'][0]['Children']: return False else: return True def run_calc(self, calc): filename = 'CVA_' + self.params[ 'Run_Date'] + '_' + self.crb_default + '.csv' if os.path.isfile(os.path.join(self.outputdir, 'Greeks', filename)): self.logger(self.netting_set, 'Warning: skipping CVA calc as file already exists') else: self.params['CVA'] = { 'Deflation': self.cx.deals['Calculation'].get('Deflation_Interest_Rate', 'ZAR-SWAP'), 'Gradient': 'Yes' } if self.cx.deals['Deals']['Children'][0]['instrument'].field.get( 'Collateralized') == 'True': self.logger(self.netting_set, 'is collateralized') # make sure the margin period of risk is 10 business days (approx 12 calendar days) self.cx.deals['Deals']['Children'][0]['instrument'].field[ 'Liquidation_Period'] = 12.0 self.params['Simulation_Batches'] = 20 self.params['Batch_Size'] = 256 else: self.params['Simulation_Batches'] = 10 self.params['Batch_Size'] = 512 self.logger(self.netting_set, 'is uncollateralized') # get the calculation parameters for CVA default_cva = { 'Deflate_Stochastically': 'Yes', 'Stochastic_Hazard_Rates': 'No', 'Counterparty': self.crb_default } cva_sect = self.cx.deals.get( 'Calculation', { 'Credit_Valuation_Adjustment': default_cva }).get('Credit_Valuation_Adjustment', default_cva) # update the params self.params['CVA']['Counterparty'] = cva_sect['Counterparty'] self.params['CVA']['Deflate_Stochastically'] = cva_sect[ 'Deflate_Stochastically'] self.params['CVA']['Stochastic_Hazard'] = cva_sect[ 'Stochastic_Hazard_Rates'] # now adjust the survival curve - need intervals of .25 years sc = self.cx.params['Price Factors'][ 'SurvivalProb.' + cva_sect['Counterparty']]['Curve'].array.copy() tenors = np.arange(0, sc[-1][0], .25) self.cx.params['Price Factors'][ 'SurvivalProb.' + cva_sect['Counterparty']]['Curve'].array = np.array( list(zip(tenors, np.interp(tenors, sc[:, 0], sc[:, 1])))) try: out = calc.execute(self.params) except Exception as e: exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback, limit=2, file=sys.stdout) self.logger(self.netting_set, 'Exception: ' + str(e.args)) else: stats = out['Stats'] grad_cva = calc.gradients_as_df( out['Results']['grad_cva']).rename(columns={ 'Gradient': self.cx.deals['Attributes']['Reference'] }) # store the CVA as part of the stats out['Stats'].update({ 'CVA': out['Results']['cva'], 'Currency': self.params['Currency'] }) grad_cva.to_csv( os.path.join(self.outputdir, 'Greeks', filename)) self.stats.setdefault('Stats', {})[self.netting_set] = out['Stats'] # log the netting set self.logger(self.netting_set, 'CVA calc complete')
def __init__(self, cx, rundate, input_path, outputdir, netting_set, stats, log): self.rundate = rundate self.input_path = input_path self.outputdir = outputdir self.netting_set = os.path.splitext(netting_set)[0] + '.json' self.stats = stats self.logger = log self.params = { 'calc_name': ('cmc', 'calc1'), 'Time_grid': '0d 2d 1w(1w) 1m(1m) 3m(3m) 1y(1y)', 'Run_Date': rundate, 'Currency': 'ZAR', 'Random_Seed': 5126, 'Calc_Scenarios': 'No', 'Dynamic_Scenario_Dates': 'Yes', 'Debug': 'No', 'NoModel': 'Constant', 'Partition': 'None', 'Generate_Slideshow': 'No', 'PFE_Recon_File': '' } from riskflow.adaptiv import AdaptivContext self.cx = AdaptivContext() old_cx = AdaptivContext() # load marketdata old_cx.parse_json( os.path.join(self.input_path, rundate, 'MarketData.json')) # load up the CVA marketdata file self.cx.parse_json( os.path.join(self.input_path, rundate, 'MarketDataCVA.json')) # update the cva data with the arena data self.cx.params['Price Factors'].update(old_cx.params['Price Factors']) # load trade self.cx.parse_json( os.path.join(self.input_path, self.rundate, self.netting_set)) # get the netting set self.ns = self.cx.deals['Deals']['Children'][0]['instrument'].field # get the agreement currency self.agreement_currency = self.ns.get('Agreement_Currency', 'ZAR') # get the balance currency self.balance_currency = self.ns.get('Balance_Currency', self.agreement_currency) # set the OIS cashflow flag to speed up prime linked swaps self.cx.params['Valuation Configuration'][ 'CFFloatingInterestListDeal']['OIS_Cashflow_Group_Size'] = 1 from riskflow.utils import Curve # change the currency self.params['Currency'] = self.agreement_currency def makeflatcurve(curr, bps, tenor=30): return { 'Currency': curr, 'Curve': Curve([], [[0, bps * 0.01 * 0.01], [tenor, bps * 0.01 * 0.01]]), 'Day_Count': 'ACT_365', 'Property_Aliases': None, 'Sub_Type': 'None' } if self.agreement_currency == 'ZAR': self.cx.params['Price Factors'][ 'InterestRate.ZAR-SWAP.OIS'] = makeflatcurve('ZAR', -15) self.cx.params['Price Factors'][ 'InterestRate.ZAR-SWAP.FUNDING'] = makeflatcurve('ZAR', 10) self.cx.deals['Deals']['Children'][0]['instrument'].field[ 'Collateral_Assets']['Cash_Collateral'][0][ 'Collateral_Rate'] = 'ZAR-SWAP.OIS' self.cx.deals['Deals']['Children'][0]['instrument'].field[ 'Collateral_Assets']['Cash_Collateral'][0][ 'Funding_Rate'] = 'ZAR-SWAP.FUNDING' else: self.cx.params['Price Factors'][ 'InterestRate.USD-LIBOR-3M.FUNDING'] = makeflatcurve( 'USD', 65) self.cx.deals['Deals']['Children'][0]['instrument'].field[ 'Collateral_Assets']['Cash_Collateral'][0][ 'Collateral_Rate'] = 'USD-OIS' self.cx.deals['Deals']['Children'][0]['instrument'].field[ 'Collateral_Assets']['Cash_Collateral'][0][ 'Funding_Rate'] = 'USD-LIBOR-3M.FUNDING'
class COLLVA(JOB): def __init__(self, cx, rundate, input_path, outputdir, netting_set, stats, log): self.rundate = rundate self.input_path = input_path self.outputdir = outputdir self.netting_set = os.path.splitext(netting_set)[0] + '.json' self.stats = stats self.logger = log self.params = { 'calc_name': ('cmc', 'calc1'), 'Time_grid': '0d 2d 1w(1w) 1m(1m) 3m(3m) 1y(1y)', 'Run_Date': rundate, 'Currency': 'ZAR', 'Random_Seed': 5126, 'Calc_Scenarios': 'No', 'Dynamic_Scenario_Dates': 'Yes', 'Debug': 'No', 'NoModel': 'Constant', 'Partition': 'None', 'Generate_Slideshow': 'No', 'PFE_Recon_File': '' } from riskflow.adaptiv import AdaptivContext self.cx = AdaptivContext() old_cx = AdaptivContext() # load marketdata old_cx.parse_json( os.path.join(self.input_path, rundate, 'MarketData.json')) # load up the CVA marketdata file self.cx.parse_json( os.path.join(self.input_path, rundate, 'MarketDataCVA.json')) # update the cva data with the arena data self.cx.params['Price Factors'].update(old_cx.params['Price Factors']) # load trade self.cx.parse_json( os.path.join(self.input_path, self.rundate, self.netting_set)) # get the netting set self.ns = self.cx.deals['Deals']['Children'][0]['instrument'].field # get the agreement currency self.agreement_currency = self.ns.get('Agreement_Currency', 'ZAR') # get the balance currency self.balance_currency = self.ns.get('Balance_Currency', self.agreement_currency) # set the OIS cashflow flag to speed up prime linked swaps self.cx.params['Valuation Configuration'][ 'CFFloatingInterestListDeal']['OIS_Cashflow_Group_Size'] = 1 from riskflow.utils import Curve # change the currency self.params['Currency'] = self.agreement_currency def makeflatcurve(curr, bps, tenor=30): return { 'Currency': curr, 'Curve': Curve([], [[0, bps * 0.01 * 0.01], [tenor, bps * 0.01 * 0.01]]), 'Day_Count': 'ACT_365', 'Property_Aliases': None, 'Sub_Type': 'None' } if self.agreement_currency == 'ZAR': self.cx.params['Price Factors'][ 'InterestRate.ZAR-SWAP.OIS'] = makeflatcurve('ZAR', -15) self.cx.params['Price Factors'][ 'InterestRate.ZAR-SWAP.FUNDING'] = makeflatcurve('ZAR', 10) self.cx.deals['Deals']['Children'][0]['instrument'].field[ 'Collateral_Assets']['Cash_Collateral'][0][ 'Collateral_Rate'] = 'ZAR-SWAP.OIS' self.cx.deals['Deals']['Children'][0]['instrument'].field[ 'Collateral_Assets']['Cash_Collateral'][0][ 'Funding_Rate'] = 'ZAR-SWAP.FUNDING' else: self.cx.params['Price Factors'][ 'InterestRate.USD-LIBOR-3M.FUNDING'] = makeflatcurve( 'USD', 65) self.cx.deals['Deals']['Children'][0]['instrument'].field[ 'Collateral_Assets']['Cash_Collateral'][0][ 'Collateral_Rate'] = 'USD-OIS' self.cx.deals['Deals']['Children'][0]['instrument'].field[ 'Collateral_Assets']['Cash_Collateral'][0][ 'Funding_Rate'] = 'USD-LIBOR-3M.FUNDING' def valid(self): if not self.cx.deals['Deals']['Children'][0][ 'Children'] or self.cx.deals['Deals'][ 'Children'][0]['instrument'].field.get( 'Collateralized', 'False') == 'False': return False else: return True def run_calc(self, calc): filename = 'COLLVA_' + self.params[ 'Run_Date'] + '_' + self.crb_default + '.csv' if os.path.isfile(os.path.join(self.outputdir, 'Greeks', filename)): self.logger( self.netting_set, 'Warning: skipping COLLVA calc as file already exists') else: self.params['CollVA'] = {'Gradient': 'Yes'} # make sure the margin period of risk is 10 business days (approx 12 calendar days) self.cx.deals['Deals']['Children'][0]['instrument'].field[ 'Liquidation_Period'] = 12.0 self.params['Simulation_Batches'] = 20 self.params['Batch_Size'] = 256 try: out = calc.execute(self.params) except Exception as e: exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback, limit=2, file=sys.stdout) self.logger(self.netting_set, 'Exception: ' + str(e.args)) else: stats = out['Stats'] grad_collva = calc.gradients_as_df( out['Results']['grad_collva']).rename(columns={ 'Gradient': self.cx.deals['Attributes']['Reference'] }) # store the CollVA as part of the stats out['Stats'].update({ 'CollVA': out['Results']['collva'], 'Currency': self.params['Currency'] }) grad_collva.to_csv( os.path.join(self.outputdir, 'Greeks', filename)) self.stats.setdefault('Stats', {})[self.netting_set] = out['Stats'] # log the netting set self.logger(self.netting_set, 'CollVA calc complete')
def work(id, lock, queue, results, job, rundate, input_path, calendar, outputdir): def log(netting_set, msg): lock.acquire() print('JOB %s: ' % id) print('Netting set {0}: {1}'.format(netting_set, msg)) lock.release() # set the visible GPU os.environ['CUDA_VISIBLE_DEVICES'] = str(id) # set the log level os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' # now load the cuda context from riskflow.adaptiv import AdaptivContext # create the crstal context cx = AdaptivContext() # load calendars cx.parse_calendar_file(calendar) # load marketdata cx.parse_json(os.path.join(input_path, rundate, 'MarketData.json')) if os.path.isfile( os.path.join(input_path, rundate, 'CVAMarketData_Calibrated_New.json')): cx_new = AdaptivContext() cx_new.parse_json( os.path.join(input_path, rundate, 'CVAMarketData_Calibrated_New.json')) log("Parent", "Overriding Calibration") for factor in [ x for x in cx_new.params['Price Factors'].keys() if x.startswith('HullWhite2FactorModelParameters') ]: # override it cx.params['Price Factors'][factor] = cx_new.params[ 'Price Factors'][factor] # log results logs = {} while True: # get the task task = queue.get() if task is None: break obj = globals().get(job)(cx, rundate, input_path, outputdir, task, logs, log) obj.perform_calc() # empty the queue queue.put(None) # get ready to send the results result = [] # write out the logs if 'Stats' in logs: stats_file = os.path.join( outputdir, 'Stats', '{0}_Stats_{1}_JOB_{2}.csv'.format(job, rundate, id)) pd.DataFrame(data=logs['Stats']).T.to_csv(stats_file) result.append(('Stats', stats_file)) if 'CSA' in logs: csa_file = os.path.join( outputdir, 'CSA', '{0}_{1}_CSA_JOB_{2}.csv'.format(job, rundate, id)) pd.DataFrame(logs['CSA']).T.to_csv(csa_file) result.append(('CSA', csa_file)) results.put(result)