1. Home
  2. Article Catalog
  3. How to Calculate Forward Outright Price with RDP Library for Python

Ariticle

How to Calculate Forward Outright Price with RDP Library for Python

Pimchaya Wongrukun
Developer Advocate Developer Advocate

This article will demonstrate how to use Refinitiv Data Platform (RDP) library for Python to calculate Forward Outright Price. Forward Outright Price is the predicted metal price based on the current price and forward rate.

Introduction to the RDP Library for Python

Refinitiv Data Platform or RDP is our cloud-enabled, open platform, that brings together all the contents, including the analytics, customer, and third-party data in one service. Getting data is never been this simple. Even that, it would be ideal if a single library could be used to access all the contents in one place as well. That’s why we have created Refinitiv Data Platform Libraries that has been built to simplify the integration into ALL delivery platforms like our new flagship desktop Refinitiv Workspace that beautifully display the data in all aspects, or directly to RDP interface on cloud or even the real-time streaming called Elektron services. With this RDP Python library, they will provide a consistent API experience. You can just learn once and apply across the wealth of Refinitiv contents.  And Also, Python provides a large standard library including libraries to analyze data, create beautiful visualizations. It is also easy to learn which we will show you what a few lines of code can do. For more details, please refer to Refinitiv Data Platform Libraries - An Introduction

Prerequisite

1. Access Credentials. To be able to access data used to calculate Forward Outright Price, you need to have the access credentials for Platform - Refinitiv Data Platform endpoint. Please refer to Access Credentials Quick Start for process and details on how to obtain the access credentials for this endpoint. Moreover, you need to have the permission to access the following service endpoints which provided info used in Forward Outright Price calculation:

  • data/pricing/<version>/views/chains
  • data/quantitative-analytics-dates-and-calendars/<version>/date-schedule

Please contact the Refinitiv Account team who can help you to grant permission to access the service endpoints above.

2. Python environment and package installer. Anaconda is the easiest way to perform Python data science and machine learning on Linux, Windows, and Mac OS X. It consists of Jupyter Notebook and the packages that we will require e.g. numpy, pandas. You can download and install Anaconda from here.

3. RDP Library for Python. To install the library:

  • Open Anaconda Prompt:
  • Run the following command:
    	
            pip install refinitiv.dataplatform
        
        
    

Forward Outright Price Calculation

To calculate Forward Outright Price, you need to know:

  • The metal RIC
  • The forward offer rate RIC of the metal RIC

You can reach out to Refinitiv Helpdesk who can provide you with the proper RICs. Then, you can retrieve/calculate the following data which is required to calculate Forward Outright Price:

1. Spot Price is snapshot real-time price fields i.e. Bid and Ask of a metal RIC.

We will use RDP library for python to get the snapshot real-time Bid and Ask of a metal RIC using the get_rt function below: 

    	
            

def get_rt(instrument, fids):

    logger.info(f'Real-time data of {instrument} retrieving')

    # get snapshot real-time data using RDP library function

    instrument_rt = rdp.get_snapshot(instrument, fids)

    get_snapshot_dt_utc = datetime.now(tz=timezone.utc).strftime('%Y-%m-%d %H:%M:%S')

    # if getting data fails

    if instrument_rt is None: 

        if rdp.get_last_status()['error']: 

            logger.error(f'Getting real-time data failed with the error: ' + str(rdp.get_last_status()['error'])) 

        else:

            logger.error(f'Getting real-time data failed') 

        sys.exit(1)

    # if getting data succeeds

    else:

        instrument_rt.insert(loc=0, column='DATE', value=datetime.now(tz=timezone.utc).date())

        instrument_rt.loc[:, 'DATE'] = pd.to_datetime(instrument_rt.loc[:, 'DATE'], format='%Y-%m-%d')

        return instrument_rt, get_snapshot_dt_utc

2. Forward Rate is calculated based on snapshot real-time GV4_TEXT and PRIMACT_1 field of underlying RICs of forward offer rate RIC. The underlying RICs can be retrieved from data/pricing/beta3/views/chains service endpoint using RDP library by sending a REST request to the service endpoint like the rdp_url_request function below:  

    	
            

def rdp_url_request(session, url, method, query_parameters=None, body_parameters=None, err_detail=None):

    if query_parameters:

        logger.info(f'RDP calling with {url}: {query_parameters} ')

    if body_parameters:

        logger.info(f'RDP calling with {url}: {body_parameters}')

    #create end point to RDP service with the session 

    endpoint = rdp.DeliveryFactory.create_end_point(session=session, url=url)

    #send the request to RDP service and wait for response

    response = endpoint.send_request(method=method, query_parameters=query_parameters, body_parameters=body_parameters)

    #print if request is successful

    logger.info(f'RDP response is success: {response.is_success}')

    error = False

    #if request is unsuccessful

    if response.error_code:

        logger.error(f'RDP response error code: {response.error_code}')

        error = True

    if response.error_message:

        logger.error(f'RDP response error message: {response.error_message}')

        error = True

    strRaw = str(response.data.raw)

    if strRaw.find("Error") >= 0:

        logger.error(f"The RDP response contains the error:" + strRaw)

        error = True

    #if request is not successful, exit

    if error:

        if err_detail is not None:

            logger.error(err_detail)

        sys.exit(1)

    #if request is successful, return response

    return response

The example output:

GV4_TEXT field is TENOR which refers to the length of time remaining before a financial contract expires[1]. PRIMACT_1 field is the lending rate. We will use the get_rt function above to get real-time snapshot of both fields.

Next, we will find out the periods, start and end transaction dates, according to TENOR and Transaction date which is a date upon which a trade takes place for security or other financial instruments [2]. We will send a REST request to data/quantitative-analytics-dates-and-calendars/<version>/date-schedule service API endpoint using rdp_url_request function above.  For more details of this service API endpoint, please refer to Quantitative Analytics - Dates and Calendars in API Playground. Then, we will calculate Forward Rate of each period. 

The source code  according to the explanation above is below:

    	
            

def rate_update(session, calendar_ref, transaction_date, tenor_list, rate, lending_rate_field, rate_chain, lending_rate_ref_af=None):

    logger.info('Lending rate updating')

    rate_fids = ['GV4_TEXT', lending_rate_field]

    #request GV4_TEXT(TENOR) and lending rate(PRIMACT_1) of underlying RICs

    rate_rt, rate_dt_utc = get_rt(rate_chain, rate_fids)

    rate_rt.rename(columns={'GV4_TEXT': 'TENOR',

                            lending_rate_field: 'RATE'}, inplace=True)

    

    # calculate start dates and end dates of each period

    df_startdate = cal_startdate(rate_rt, transaction_date, calendar_ref, session)

    df_startenddate = qps_cal_enddate(df_startdate, calendar_ref, session)

    interp_frame = create_df_interp(tenor_list)

    date_interp_start = cal_startdate(interp_frame, transaction_date, calendar_ref, session)

    if lending_rate_ref_af is not None:

        date_interp_end = lending_rate_ref_af

    else:

        date_interp_end = qps_cal_enddate(date_interp_start, calendar_ref, session)

    #calculate Forward Rate of each period

    rate_interp = cal_interp(df_startenddate, date_interp_end)

    return rate_interp, date_interp_end

The example output:

3. Forward Swap Point is calculated from the formula below:

Forward Swap Point  = (Spot Price * (Forward Rate * days)) / Yearly basis

4. Forward Swap Price is calculated from Forward Swap Point according to the formula below:

Forward Swap Price = Forward Swap Point / 100

The source code below shows how to calculate Forward Swap Point and Forward Swap Price:

    	
            

def cal_swppoint(df_afterinterp, bid, ask):

    try:

        logger.info('Swap point calculating')

        df_afterinterp = df_afterinterp.rename(columns={'RATE': 'BID_RATE'})

        df_afterinterp.loc[:, 'ASK_RATE'] = df_afterinterp['BID_RATE']

        df_afterinterp.loc[:, 'ASK_RATE'] += proxy_price_spread

        df_afterinterp.loc[:, 'DAYS'] = (df_afterinterp['END'] - df_afterinterp['START']) / timedelta(days=1)

        df_afterinterp.loc[:, 'BID_SWAP_POINT'] = ((df_afterinterp['BID_RATE'].mul(df_afterinterp['DAYS'])).mul(bid)).div(365)

        df_afterinterp.loc[:, 'ASK_SWAP_POINT'] = ((df_afterinterp['ASK_RATE'].mul(df_afterinterp['DAYS'])).mul(ask)).div(365)

        #calculate Forward swap price from Forward swap point

        df_afterinterp.loc[:,'BID_SWAP_PRICE'] = df_afterinterp['BID_SWAP_POINT'].div(100)

        df_afterinterp.loc[:,'ASK_SWAP_PRICE'] = df_afterinterp['ASK_SWAP_POINT'].div(100)

        return df_afterinterp

    except Exception as e:

        logger.exception('The function cannot calculate the swap point. The exception is:')

        logger.exception(e)

        sys.exit(1)

The example output:

Next, we can calculate Forward Outright Price using the following formula:

Forward Outright Price = Spot Price + Forward Swap Price

Special case on Overnight (ON) and Tomorrow Next (TN) Forward Outright Price, switch Bid/Ask and change sign of Forward Swap Price:

  • ON Forward Outright Bid Price = Bid Spot Price -TN Forward Ask Swap Price - ON Forward Ask Swap Price)
  • ON Forward Outright Ask Price = Ask Spot Price -TN Forward Bid Swap Price - ON Forward Bid Swap Price)
  • TN Forward Outright Bid Price = Bid Spot Price -TN Forward Ask Swap Price
  • TN Forward Outright Ask Price = Ask Spot Price -TN Forward Bid Swap Price

The source code below shows how to calculate Forward Outright Price:

    	
            

def cal_fwdoutright(df, bid, ask):

    try:

        df.loc[(df['TENOR'] != 'ON') & (df['TENOR'] != 'TN'),'BID_FWDOUTRIGHT'] = bid + df['BID_SWAP_PRICE'] 

        df.loc[(df['TENOR'] != 'ON') & (df['TENOR'] != 'TN'),'ASK_FWDOUTRIGHT'] = ask + df['ASK_SWAP_PRICE'] 

        bid_on = df.loc[(df['TENOR'] == 'ON'), 'BID_SWAP_PRICE']

        bid_on = bid_on[0]

        bid_on *= -1

        ask_on = df.loc[(df['TENOR'] == 'ON'), 'ASK_SWAP_PRICE']

        ask_on = ask_on[0]

        ask_on *= -1

        bid_tn = df.loc[(df['TENOR'] == 'TN'), 'BID_SWAP_PRICE']

        bid_tn = bid_tn[1]

        bid_tn *= -1

        ask_tn = df.loc[(df['TENOR'] == 'TN'), 'ASK_SWAP_PRICE']

        ask_tn = ask_tn[1]

        ask_tn *= -1

        df.loc[(df['TENOR'] == 'ON'), 'BID_FWDOUTRIGHT'] = bid + ask_tn + ask_on

        df.loc[(df['TENOR'] == 'ON'), 'ASK_FWDOUTRIGHT'] = ask + bid_tn + bid_on

        df.loc[(df['TENOR'] == 'TN'), 'BID_FWDOUTRIGHT'] = bid + ask_tn

        df.loc[(df['TENOR'] == 'TN'), 'ASK_FWDOUTRIGHT'] = ask + bid_tn

        return df

    except Exception as e:

        logger.exception('The function cannot calculate the forward outright. The exception is:')

        logger.exception(e)

        sys.exit(1)

The example output:

For the complete source code, please refer to Article.RDPLibrary.Python.ForwardOutrightPrice.

Summary

In this article, we have demonstrated how to calculate Forward Outright Price which its input can be retrieved using RDP library for python. The article also shows how to use Cufflinks which makes financial data visualization convenient. The RDP library can be used to retrieve data for calculation of any other models to serve more accurate or specific use cases.

References

  1. "What Is Tenor?", in Tenor. Retrieved Jul 3, 2020 from https://www.investopedia.com/terms/t/tenor.asp
  2. "What Is a Transaction Date?", in Transaction Date. Retrieved Jul 3, 2020, from https://www.investopedia.com/terms/t/transaction-date.asp
  3. Refinitiv Data Platform Libraries, Refinitiv Developer Community, https://developers.refinitiv.com/refinitiv-data-platform/refinitiv-data-platform-libraries
  4. Quantitative Analytics - Dates and Calendars in API Playground, https://apidocs.refinitiv.com/Apps/ApiDocs#/details/L2RhdGEvcXVhbnRpdGF0aXZlLWFuYWx5dGljcy1kYXRlcy1hbmQtY2FsZW5kYXJzL2JldGEx/L2RhdGUtc2NoZWR1bGU=/POST/SWAGGER