Enterprise Resource Planning Blogs by Members
Gain new perspectives and knowledge about enterprise resource planning in blog posts from community members. Share your own comments and ERP insights today!
cancel
Showing results for 
Search instead for 
Did you mean: 
grigoriy_babitskiy
Active Contributor
15,802

Using Datafeed we can upload Market data into SAP automatically from different Market data providers.

I want to show you an example how you can use Datafeed.

Input data

I have a web site of National Bank of the Republic of Belarus ( Exchange Rates, Refinancing Rate, News | National Bank of the Republic of Belarus) from where i can get information about:

Each of mentioned Market data has API which can retrieve information. API is the URL with parameters. API returns a string with information.

As a result we need to get information into SAP and parse it into the special table "Answer".

Before we can use Datafeed, we need to configure the system.

Configuration

Create Market Data Provider

IMG -> Financial Supply Chain Management -> Treasury and Risk Management -> Basic Functions -> Market Data Management -> Datafeed -> Technical Settings -> Define Datafeed Name  (tr. S_ALR_87007834)

Here we create Market Data provider in order to separate the different sources of information:

  • Data provider - name of data provider.
  • Usage log - If you need to log all data retrievals. SAP Menu -> Accounting -> Financial Supply Chain Management -> Treasury and Risk Management -> Basic Functions -> Market Data Management -> Datafeed -> Usage Log -> ...
  • Feed active? - distinguish active and inactive feeds.
  • Quotation source - Quotation source for commodity.

RFC Settings for External Partner Program

We can contact external partners in two different ways:

  • Using RFC (remote function call) and calling external funciton.
  • Web Access (URL or Web Services).

Let's start with Web Access.

In my case i will use Web Acces.

IMG -> Financial Supply Chain Management -> Treasury and Risk Management -> Basic Functions -> Market Data Management -> Datafeed -> Technical Settings -> RFC Settings for External Partner Program -> Assign Datafeed RFC Destination (tr. SM30 -> V_VTB_DFD)

  • Datafeed operating mode:
    • •'1' synchronous:  SAP waits until the external partner program has delivered all the data.
    • •'2' asynchronous: SAP does not wait until the external partner program has delivered all the data but immediately switches control back to the calling program. The data is delivered from the external partner program at a later date (possibly in separate blocks).

          For Web Access we choose Synchronous operation mode.

  • Function: There is a standard SAP function module TB_DATAFEED_INTERNET_ACCESS to get information from web. But as i described earlier my data provider has special API - so i need to modify standard FM. So i created ZTB_DATAFEED_INTERNET_ACCESS
  • RFC destination, Back-up RFC destination: For Web Access in my case i do not need RFC connection.


FUNCTION ztb_datafeed_internet_access.
*"----------------------------------------------------------------------
*"*"Локальный интерфейс:
*"  IMPORTING
*"     VALUE(FEEDNAME) LIKE  VTB_DFDEST-RFEEDNAME
*"     VALUE(HISTORY) LIKE  VTB_DFCU-RUPDHIST
*"     VALUE(UPDATE) LIKE  VTB_DFCU-RUPDHIST
*"     VALUE(BLANKSTOCRLF) TYPE  VTB_DFDEST-BLANKSTOCRLF DEFAULT 'X'
*"     VALUE(CLEAR_REQUEST_ENTITY_BODY) TYPE  BOOLEAN DEFAULT 'X'
*"  EXPORTING
*"     VALUE(E_MESSAGE_BUFFER) LIKE  VTB_MARKET-ERROR
*"  TABLES
*"      ANSWER STRUCTURE  VTB_DFANS
*"      REQUEST STRUCTURE  VTB_DFREQ
*"  EXCEPTIONS
*"      DATAFEED_FAILURE
*"----------------------------------------------------------------------
************************************************************************
* Declarations
   CONSTANTS: rworkmodus LIKE vtb_dfdest-rworkmodus VALUE '1'.
   DATA: zresponse_body             TYPE TABLE OF zchar9000 WITH HEADER LINE, " STRING TYPE
         zstr                       TYPE zchar9000,
         zsplit                     TYPE STANDARD TABLE OF char200 WITH HEADER LINE,
         zresponse_headers          TYPE TABLE OF char50 WITH HEADER LINE,
         text_to_be_scanned         TYPE char200,      " String of market data
         regular_expression_pattern TYPE char200,      " REGEXP to find data in String of market data
         res                        TYPE match_result, " Found result in String of market data
         text                       TYPE char200,      " Temporary variable to pass market data into answer table
         zuri                       TYPE tb_dfuri,     " URL from VTB_DFDEST table. We will modify URL to match requests.
         zmetal                     TYPE char15,
         zcur                       TYPE tb_key1_ex,   " External data provider currency code
         zmet                       TYPE tb_prpty.     " External data provider metal code
   TABLES: vtb_dfdest.
* Temp answer table
   DATA: BEGIN OF temp_answer OCCURS 100.
       INCLUDE STRUCTURE vtb_dfans.
   DATA: END OF temp_answer.
   DATA: hlp_message_buffer(50) TYPE c.
* Request tables
   DATA: BEGIN OF request_headers OCCURS 100,
           line LIKE tline-tdline.
   DATA: END OF request_headers.
   DATA: BEGIN OF request_entity_body OCCURS 100,
           line LIKE vtbdfin-line.
   DATA: END OF request_entity_body.
* Response tables
   DATA: BEGIN OF response_headers OCCURS 10,
           line LIKE tline-tdline.
   DATA: END OF response_headers.
   DATA: BEGIN OF response_entity_body OCCURS 10,
           line           LIKE vtb_dfans,
           newlinechar(2) TYPE c,
         END   OF response_entity_body.
* status code RFC1945
   DATA: status_code(3) TYPE c.
* length of response body
   DATA: response_entity_body_length TYPE i.
   DATA: request_entity_body_length  TYPE i.
************************************************************************
* Initialization
   CLEAR: e_message_buffer, hlp_message_buffer.
   REFRESH: request_headers, response_headers, request_entity_body,
            response_entity_body, temp_answer.
* read table vtb_dfdest for URI and PROXY Information.
   SELECT SINGLE * FROM  vtb_dfdest CLIENT SPECIFIED
          WHERE  mandt       = sy-mandt
          AND    rfeedname   = feedname
          AND    rworkmodus  = rworkmodus.
* fill HTTP request page header
   request_headers-line =               "/ HTML version 3.2
      'content-type: text/plain'.                            "#EC *
   APPEND request_headers.
   IF clear_request_entity_body IS NOT INITIAL.
     CLEAR   request_entity_body.
     REFRESH request_entity_body.
   ENDIF.
************************************************************************
* Retrieving market data from Data Provider
   " Save the initial URL. We will modify vtb_dfdest-uri for different market data classes.
   zuri = vtb_dfdest-uri.
   " Loop at 'Data source' to get data
   LOOP AT request.
     CASE request-rinid2. "'Data source'
         " Refinance rate
       WHEN 'REFINANCE'.
         " Create the right API URL for Refinance rate.
         " If we have From (zreq-dfromdate) and To (zreq-dtodate) fields initial - then we request data on curren date (tr. TBD4).
         " If we have From (zreq-dfromdate) and To (zreq-dtodate) fields NOT initial - then we requst history data (tr. TBDJ).
         CLEAR vtb_dfdest-uri.
         IF request-dfromdate IS INITIAL OR request-dtodate IS INITIAL.
           CONCATENATE  zuri '/RefinancingRate?onDate=' sy-datum+0(4) '-' sy-datum+4(2) '-' sy-datum+6(2) INTO vtb_dfdest-uri.
         ELSE.
           CONCATENATE  zuri '/RefinancingRate' INTO vtb_dfdest-uri.
         ENDIF.
         CLEAR zresponse_body.
         REFRESH zresponse_body.
         CLEAR zresponse_headers.
         REFRESH zresponse_headers.
         CLEAR zstr.
         CLEAR zsplit.
         REFRESH zsplit.
         CLEAR text_to_be_scanned.
         WAIT UP TO 2 SECONDS.
         " Requesting information.
         CALL FUNCTION 'HTTP_GET'
           EXPORTING
             absolute_uri                = vtb_dfdest-uri
             user                        = vtb_dfdest-foreign_user
             password                    = vtb_dfdest-foreign_passwd
             blankstocrlf                = blankstocrlf  "VTB_DFDEST-BLANKSTOCRLF
           IMPORTING
             status_code                 = status_code
             response_entity_body_length = response_entity_body_length
           TABLES
             request_entity_body         = request_entity_body
             request_headers             = request_headers
             response_entity_body        = zresponse_body[]
             response_headers            = zresponse_headers[]
           EXCEPTIONS
             connect_failed              = 1
             timeout                     = 2
             internal_error              = 3
             tcpip_error                 = 4
             OTHERS                      = 5.
         " error handling!!!
         IF sy-subrc <> 0. "/ no connection
           CASE sy-subrc.
             WHEN '1'.
               e_message_buffer =
                            'Сonnect_failed'(890).
             WHEN '2'.
               e_message_buffer =
                            'Timeout'(891).
             WHEN '3'.
               e_message_buffer =
                            'Internal_error'(892).
             WHEN '4'.
               e_message_buffer =
                            'TCP/IP error'(893).
             WHEN OTHERS.
               e_message_buffer =
                            'HTTP-GET error'(894).
           ENDCASE.
           EXIT.
           " error handling!!!
         ELSEIF  status_code <> '200'.        "/ connection ok, other problems
           LOOP AT response_headers.
             hlp_message_buffer = response_headers-line.
             "/ first line contains error
             EXIT.
           ENDLOOP.
           " concatenate 'Fehler: '(910) status_code hlp_message_buffer
           MOVE hlp_message_buffer TO e_message_buffer.
           CONDENSE e_message_buffer.
           EXIT.
         ELSE.
           " everything was fine...
           CLEAR answer.
           LOOP AT zresponse_body INTO zstr.
             " All data is diveded by '},{'. Let's split it into 1 string - 1 market data.
             SPLIT zstr AT '},{' INTO TABLE zsplit IN CHARACTER MODE.
             " Loop through and retrieve data that we need.
             LOOP AT zsplit INTO text_to_be_scanned.
               " Searching for date.
               regular_expression_pattern = '\d{4}-\d{2}-\d{2}'.
               FIND REGEX regular_expression_pattern IN text_to_be_scanned RESULTS res.
               IF sy-subrc = 0.
                 CLEAR text.
                 text = text_to_be_scanned+res-offset(res-length).
                 CONCATENATE text+0(4) text+5(2) text+8(2) INTO answer-ddate.
               ENDIF.
               " Searching for time.
               regular_expression_pattern = '\d{2}:\d{2}:\d{2}'.
               FIND REGEX regular_expression_pattern IN text_to_be_scanned RESULTS res.
               IF sy-subrc = 0.
                 CLEAR text.
                 text = text_to_be_scanned+res-offset(res-length).
                 CONCATENATE text+0(2) text+3(2) text+6(2) INTO answer-ttime.
               ENDIF.
               " Searching for value.
               regular_expression_pattern = '\d{1,}\.\d{1,5}'.
               FIND REGEX regular_expression_pattern IN text_to_be_scanned RESULTS res.
               IF sy-subrc = 0.
                 answer-value = text_to_be_scanned+res-offset(res-length).
               ENDIF.
               " Other parameters (tr. SM30 -> V_DFCU03)
               answer-rinid1 = 'REFINANCE'. "Instrument
               answer-rinid2 = 'REFINANCE'. "Data Source
               answer-sprpty = 'REFINANCE'. "Instrument property
               answer-uname = sy-uname.
               " Save market data into Answer table.
               APPEND answer.
             ENDLOOP.
           ENDLOOP.
         ENDIF.
         " Exchange rate
       WHEN 'CURRENCY'.
         CLEAR vtb_dfdest-uri.
         " Get external codes for currency codes.
         SELECT SINGLE rkey1 FROM mducr INTO zcur WHERE vendor = 'NBRB.by' AND source = 'F' AND waers = request-rinid1+3(3).
         IF sy-subrc <> 0.
           CONCATENATE 'Error: Convert Codes for Currency Names: ' request-rinid1+3(3) 'SM30 -> V_MDUDFCR' INTO e_message_buffer.
           EXIT.
         ENDIF.
         " Create the right API URL for Exchange rates.
         " If we have From (zreq-dfromdate) initial or ( From (zreq-dfromdate) and To (zreq-dtodate) fields initial - then we request data on curren date (tr. TBD4).
         " Otherwise - we requst history data on zreq-dfromdate (tr. TBDJ).
         IF request-dfromdate IS INITIAL OR ( request-dtodate IS INITIAL AND request-dfromdate IS INITIAL ). " tr. TBD4
           CONCATENATE zuri " http://www.nbrb.by/API
                     '/ExRates/Rates/Dynamics/'
                     zcur
                     '?startDate='
                     sy-datum+0(4) '-'
                     sy-datum+4(2) '-'
                     sy-datum+6(2)
                     '&endDate='
                     sy-datum+0(4) '-'
                     sy-datum+4(2) '-'
                     sy-datum+6(2)
                     INTO vtb_dfdest-uri.
           sy-tcode = 'TBD4'.
         ELSE. " tr. TBDJ
           CONCATENATE zuri " http://www.nbrb.by/API
                               '/ExRates/Rates/Dynamics/'
                               zcur
                               '?startDate='
                               request-dfromdate+0(4) '-'
                               request-dfromdate+4(2) '-'
                               request-dfromdate+6(2)
                               '&endDate='
                               request-dtodate+0(4) '-'
                               request-dtodate+4(2) '-'
                               request-dtodate+6(2)
                               INTO vtb_dfdest-uri.
           sy-tcode = 'TBDJ'.
         ENDIF.
         CLEAR zresponse_body.
         REFRESH zresponse_body.
         CLEAR zresponse_headers.
         REFRESH zresponse_headers.
         CLEAR zstr.
         CLEAR zsplit.
         REFRESH zsplit.
         CLEAR text_to_be_scanned.
         WAIT UP TO 2 SECONDS.
         " Requesting information.
         CALL FUNCTION 'HTTP_GET'
           EXPORTING
             absolute_uri                = vtb_dfdest-uri
             user                        = vtb_dfdest-foreign_user
             password                    = vtb_dfdest-foreign_passwd
             blankstocrlf                = blankstocrlf  "VTB_DFDEST-BLANKSTOCRLF
           IMPORTING
             status_code                 = status_code
             response_entity_body_length = response_entity_body_length
           TABLES
             request_entity_body         = request_entity_body
             request_headers             = request_headers
             response_entity_body        = zresponse_body[]
             response_headers            = zresponse_headers[]
           EXCEPTIONS
             connect_failed              = 1
             timeout                     = 2
             internal_error              = 3
             tcpip_error                 = 4
             OTHERS                      = 5.
         " error handling!!!
         IF sy-subrc <> 0. "/ no connection
           CASE sy-subrc.
             WHEN '1'.
               e_message_buffer =
                            'Сonnect_failed'(890).
             WHEN '2'.
               e_message_buffer =
                            'Timeout'(891).
             WHEN '3'.
               e_message_buffer =
                            'Internal_error'(892).
             WHEN '4'.
               e_message_buffer =
                            'TCP/IP error'(893).
             WHEN OTHERS.
               e_message_buffer =
                            'HTTP-GET error'(894).
           ENDCASE.
           EXIT.
         ELSEIF  status_code <> '200'.        "/ connection ok, other problems
           " error handling!!!
           LOOP AT response_headers.
             hlp_message_buffer = response_headers-line.
             "/ first line contains error
             EXIT.
           ENDLOOP.
           "     concatenate 'Fehler: '(910) status_code hlp_message_buffer
           MOVE hlp_message_buffer TO e_message_buffer.
           CONDENSE e_message_buffer.
           EXIT.
         ELSE.
           " everything was fine...
           CLEAR answer.
           READ TABLE zresponse_body INTO zstr INDEX 1.
           " All data is diveded by '},{'. Let's split it into 1 string - 1 market data.
           SPLIT zstr AT '},{' INTO TABLE zsplit IN CHARACTER MODE.
           " Loop through and retrieve data that we need.
           LOOP AT zsplit INTO text_to_be_scanned.
             " Searching for date.
             regular_expression_pattern = '\d{4}-\d{2}-\d{2}'.
             FIND REGEX regular_expression_pattern IN text_to_be_scanned RESULTS res.
             IF sy-subrc = 0.
               CLEAR text.
               text = text_to_be_scanned+res-offset(res-length).
               CONCATENATE text+0(4) text+5(2) text+8(2) INTO answer-ddate.
             ENDIF.
             " Searching for time.
             regular_expression_pattern = '\d{2}:\d{2}:\d{2}'.
             FIND REGEX regular_expression_pattern IN text_to_be_scanned RESULTS res.
             IF sy-subrc = 0.
               CLEAR text.
               text = text_to_be_scanned+res-offset(res-length).
               CONCATENATE text+0(2) text+3(2) text+6(2) INTO answer-ttime.
             ENDIF.
             " Searching for echange rate.
             regular_expression_pattern = '\d{1,}\.\d{1,5}'.
             FIND REGEX regular_expression_pattern IN text_to_be_scanned RESULTS res.
             IF sy-subrc = 0.
               answer-value = text_to_be_scanned+res-offset(res-length).
             ENDIF.
             " Other parameters
             answer-currency = request-rinid1+3(3).
             answer-rinid1 = request-rinid1.
             answer-rinid2 = 'CURRENCY'.
             answer-sprpty = 'M'.
             answer-uname = sy-uname.
             " Save market data into Answer table.
             APPEND answer.
           ENDLOOP.
         ENDIF.
       WHEN 'METALS'.
         CLEAR vtb_dfdest-uri.
         " Get external codes for commodities.
         SELECT SINGLE sprpty FROM mducmv INTO zmet WHERE vendor = 'NBRB.by' AND source = 'F' AND quotyp = request-rinid1.
         IF sy-subrc <> 0.
           CONCATENATE 'Error: Convert Codes for Metal: ' request-rinid1+3(3) 'SM30 -> V_MDUCMV' INTO e_message_buffer.
           EXIT.
         ENDIF.
         " URL for tr. TBD4
         IF request-dfromdate IS INITIAL OR ( request-dtodate IS INITIAL AND request-dfromdate IS INITIAL ).
           CONCATENATE zuri "http://www.nbrb.by/API
                       '/BankIngots/Prices/'
                       zmet
                       '?startDate='
                       sy-datum+0(4) '-' sy-datum+4(2) '-' sy-datum+6(2)
                       '&endDate='
                       sy-datum+0(4) '-' sy-datum+4(2) '-' sy-datum+6(2)
                       INTO vtb_dfdest-uri.
           " URL for tr. TBDJ
         ELSEIF request-dfromdate IS NOT INITIAL AND request-dtodate IS INITIAL.
           CONCATENATE zuri "http://www.nbrb.by/API
                       '/BankIngots/Prices/'
                       zmet
                       '?startDate='
                       request-dfromdate+0(4) '-' request-dfromdate+4(2) '-' request-dfromdate+6(2)
                       '&endDate='
                       request-dfromdate+0(4) '-' request-dfromdate+4(2) '-' request-dfromdate+6(2)
                       INTO vtb_dfdest-uri.
           " URL for tr. TBDJ
         ELSE.
           CONCATENATE zuri "http://www.nbrb.by/API
                       '/BankIngots/Prices/'
                       zmet
                       '?startDate='
                       request-dfromdate+0(4) '-'
                       request-dfromdate+4(2) '-'
                       request-dfromdate+6(2)
                       '&endDate='
                       request-dtodate+0(4) '-'
                       request-dtodate+4(2) '-'
                       request-dtodate+6(2)
                       INTO vtb_dfdest-uri.
         ENDIF.
         CLEAR zresponse_body.
         REFRESH zresponse_body.
         CLEAR zresponse_headers.
         REFRESH zresponse_headers.
         CLEAR zstr.
         CLEAR zsplit.
         REFRESH zsplit.
         CLEAR text_to_be_scanned.
         WAIT UP TO 2 SECONDS.
         " Requesting information.
         CALL FUNCTION 'HTTP_GET'
           EXPORTING
             absolute_uri                = vtb_dfdest-uri
             user                        = vtb_dfdest-foreign_user
             password                    = vtb_dfdest-foreign_passwd
             blankstocrlf                = blankstocrlf  "VTB_DFDEST-BLANKSTOCRLF
           IMPORTING
             status_code                 = status_code
             response_entity_body_length = response_entity_body_length
           TABLES
             request_entity_body         = request_entity_body
             request_headers             = request_headers
             response_entity_body        = zresponse_body[]
             response_headers            = zresponse_headers[]
           EXCEPTIONS
             connect_failed              = 1
             timeout                     = 2
             internal_error              = 3
             tcpip_error                 = 4
             OTHERS                      = 5.
         " error handling!!!
         IF sy-subrc <> 0.                    "/ no connection
           CASE sy-subrc.
             WHEN '1'.
               e_message_buffer =
                            'Сonnect_failed'(890).
             WHEN '2'.
               e_message_buffer =
                            'Timeout'(891).
             WHEN '3'.
               e_message_buffer =
                            'Internal_error'(892).
             WHEN '4'.
               e_message_buffer =
                            'TCP/IP error'(893).
             WHEN OTHERS.
               e_message_buffer =
                            'HTTP-GET error'(894).
           ENDCASE.
           EXIT.
         ELSEIF  status_code <> '200'.        "/ connection ok, other problems
           " error handling!!!
           LOOP AT response_headers.
             hlp_message_buffer = response_headers-line.
             "/ first line contains error
             EXIT.
           ENDLOOP.
           "     concatenate 'Fehler: '(910) status_code hlp_message_buffer
           MOVE hlp_message_buffer TO e_message_buffer.
           CONDENSE e_message_buffer.
           EXIT.
         ELSE.
           " everything was fine...
           CLEAR answer.
           READ TABLE zresponse_body INTO zstr INDEX 1.
           " All data is diveded by '},{'. Let's split it into 1 string - 1 market data.
           SPLIT zstr AT '},{' INTO TABLE zsplit IN CHARACTER MODE.
           " Loop through and retrieve data that we need.
           LOOP AT zsplit INTO text_to_be_scanned. "response_entity_body.
             " Search for date
             regular_expression_pattern = '\d{4}-\d{2}-\d{2}'.
             FIND REGEX regular_expression_pattern IN text_to_be_scanned RESULTS res.
             IF sy-subrc = 0.
               CLEAR text.
               text = text_to_be_scanned+res-offset(res-length).
               CONCATENATE text+0(4) text+5(2) text+8(2) INTO answer-ddate.
             ENDIF.
             " Search for time
             regular_expression_pattern = '\d{2}:\d{2}:\d{2}'.
             FIND REGEX regular_expression_pattern IN text_to_be_scanned RESULTS res.
             IF sy-subrc = 0.
               CLEAR text.
               text = text_to_be_scanned+res-offset(res-length).
               CONCATENATE text+0(2) text+3(2) text+6(2) INTO answer-ttime.
             ENDIF.
             " Search for commodity rate
             regular_expression_pattern = '\d{1,}\.\d{1,5}'.
             FIND REGEX regular_expression_pattern IN text_to_be_scanned RESULTS res.
             IF sy-subrc = 0.
               answer-value = text_to_be_scanned+res-offset(res-length).
             ENDIF.
             " Search for external commodity code
             regular_expression_pattern = '"MetalId":[0-9]{1}'.
             FIND REGEX regular_expression_pattern IN text_to_be_scanned RESULTS res.
             IF sy-subrc = 0.
               zmetal = text_to_be_scanned+res-offset(res-length).
             ENDIF.
             " Other parameters
             CASE zmetal+10(1).
               WHEN '0'.
                 answer-rinid1 = 'GOLD'.
               WHEN '1'.
                 answer-rinid1 = 'SILVER'.
               WHEN '2'.
                 answer-rinid1 = 'PLATINUM'.
               WHEN '3'.
                 answer-rinid1 = 'PALADIUM'.
             ENDCASE.
             answer-rinid2 = 'METALS'.
             answer-sprpty = 'METALS'.
             answer-uname = sy-uname.
             " Save market data into Answer table.
             APPEND answer.
           ENDLOOP.
         ENDIF.
       WHEN OTHERS.
     ENDCASE.
   ENDLOOP.
   " Delete empty lines
   LOOP AT answer WHERE rinid1 IS INITIAL
                    AND rinid2 IS INITIAL
                    AND sprpty IS INITIAL.
     DELETE answer.
   ENDLOOP.
   " Find missing requests and build up error answer
   LOOP AT request.
     LOOP AT answer WHERE rinid1 = request-rinid1
                      AND rinid2 = request-rinid2
                      AND sprpty = request-sprpty.
     ENDLOOP.
     IF sy-subrc NE 0.                  "/ no answer for reques
       MOVE-CORRESPONDING request TO temp_answer.
       temp_answer-sstats = '99'.
       CONCATENATE 'There is no answer from DataFeed: ' e_message_buffer INTO temp_answer-error .
       APPEND temp_answer.
     ENDIF.
   ENDLOOP.
   " add missing entries to answer
   LOOP AT temp_answer.
     MOVE-CORRESPONDING temp_answer TO answer.
     APPEND answer.
   ENDLOOP.
   " that´s it
ENDFUNCTION.


The code also attached to this article in TXT file.

Using RFC

For RFC we need to Enter our RFC destionation (tr. SM59, RFC with type T (TCP/IP) ) and indicate partner's function. For example, with RFC we connect to Data Provider and the SAP calls special partners function in order to get Market data. Usually, you can get description of RFC configuration and list of function from your partner (Reuters, Blumberg, Teletrade, etc). Using RFC we can retrieve information in Real-time if your provider allows it.

Internet settings for WEB Server Access

IMG -> Financial Supply Chain Management -> Treasury and Risk Management -> Basic Functions -> Market Data Management -> Datafeed -> Technical Settings -> Internet Settings for External Partner Program -> Define Internet Settings for WEB Server Access (tr. SM30 -> V_VTB_DFD2)

Here we define URL (required) and User name and Password (optional) if your Data Provider requeres it.

As you can see earlier in URL we have constant part (http://www.nbrb.by/API/) and variable part depending on market data class.

So in this configuration i will put constant part. Variable part is added inside of FM ZTB_DATAFEED_INTERNET_ACCESS.

Proxy Configuration

IMG -> Financial Supply Chain Management -> Treasury and Risk Management -> Basic Functions -> Market Data Management -> Datafeed -> Technical Settings -> Internet Settings for External Partner Program -> HTTP Proxy Configuration -> Define Proxy Configuration (SM30 -> THTTP)


If according to your companie's policy you use Proxy to enter to internet, then you can configure your proxy with Proxy user and Proxy password.


Define Data Sources for Datafeed

IMG -> Financial Supply Chain Management -> Treasury and Risk Management -> Basic Functions -> Market Data Management -> Datafeed -> Translation Table -> Define Data Sources for Datafeed (tr. S_ALR_87007888)

Here we define different Data Sources of our Data Provider.

Translation Table

Translation tables can be filled in two ways:

  1. Automatically. You need to configure Datafeed Conversion Codes
  2. Manually.

Translation Table: automatically

Create Tables for Code Conversion

This operation fills Converstion tables with SAP data: Exchange rate types, Currency names, etc.

IMG -> Financial Supply Chain Management -> Treasury and Risk Management -> Basic Functions -> Market Data Management -> Datafeed -> Translation Table -> Define Datafeed Conversion Codes -> Create Tables for Code Conversion (tr. TBDK)

Convert Codes for Exchange Rate Types

IMG -> Financial Supply Chain Management -> Treasury and Risk Management -> Basic Functions -> Market Data Management -> Datafeed -> Translation Table -> Define Datafeed Conversion Codes -> Convert Codes for Exchange Rate Types (tr. SM30 -> V_MDUDFCV)


Before creating tables for Code Conversion, the table was empty. After creating tables - it will be filled with SAP data. All you need to map SAP Data with External Providers' data.

In our case SAP data is equal to External data.

Adjust converstion tables to your need: IMG -> Financial Supply Chain Management -> Treasury and Risk Management -> Basic Functions -> Market Data Management -> Datafeed -> Translation Table -> Define Datafeed Conversion Codes -> ...


For my purpse i created the following talbes:


Convert Codes for Currency Names: tr. SM30 -> V_MDUDFCR

Convert Commodity Price Types: tr. SM30 -> V_MDUCMV

I will use these tables to get external codes for currencies and commodities.

Import R/3 Master Data

Now it's turn to create Translation tables Automatically.

  • First select Master data: for example Currency.
  • Then select Quantity. If you leave these fields empty then all combination of currency 1, currency 2 and rate type will be uploaded into translation tables. I will use combination of BYN-USD, BYN-EUR, BYN-RUB with rate type M. So, field "1 key definition" is filled with BYN, field "2 key definition" if filled with USD, EUR, RUB. Rate type is M. For mentioned field there is a help, data inside these fields depends on Master data: currency, security, etc.
  • Datafeed: "Name" is NBRB.by, "Data source" is Currency.
  • Test run - to test if transaction works perfect.
  • Save market data - if you want to save data into Translation tables.

Start transaction.

Now we see, that SAP selected what we requested on selection screen. If you uncheck Test field, SAP will fill translation table for Currency. Let's see this translation talbe.

Translation Table: Currency

IMG -> Financial Supply Chain Management -> Treasury and Risk Management -> Basic Functions -> Market Data Management -> Datafeed -> Translation Table -> Define Currencies (tr. S_ALR_87007920)

Select you data provider.

SAP created translation tables for currency. Make a double click on any parameters in the table.

Most of fields are entered by SAP, selected fields with red box - you have to enter yourself.

  • Save markter data permanently in system: tell your system to save data into SAP tables. For example, Exhange rates - tr. OB08, Reference Interest rates - tr. JBIRM, etc.
  • Instrument - ask you data provider about this data or create your own. I created my own Instrument - combination of currencies.
  • External data feed currency settings: according to external data.

If you didn't use Automatic creation of Translation tables then you have to fill these tables manually.

Translation Table: Interse rates

IMG -> Financial Supply Chain Management -> Treasury and Risk Management -> Basic Functions -> Market Data Management -> Datafeed -> Translation Table -> Define Reference Interest Rates (tr. S_ALR_87007812)

Translation table for Refinance rate.

Translation Table: Commodity

IMG -> Financial Supply Chain Management -> Treasury and Risk Management -> Basic Functions -> Market Data Management -> Datafeed -> Translation Table -> Define Commodities (tr. S_ALR_87007868)

Translation table for Commodity.

That's all. For configuration.

Conclusion

If your provider is Reuters (or Bloombers, or Teletrade, or similar services) - it's very good. Reuters, for example, is licensed with SAP to provide market data. All you need is to configure RFC connection, list of Reuters functions to call and translation tables.

If your data provider has Web-Services or APIs - it's also not a problem to get data. You have to retrieve simple data structures and parse them into the SAP tables.

Even if you have access to data which is presented as a web page - you can get this information also (as HTML), but you have to find out how to parse this information.

Now it's time to process datafeed market data: TRM Market Data Management: Datafeed: Processing market data.

------------------------------------------------------------------------------------

More information about Market data management - Index.

16 Comments
Former Member
0 Kudos

Hi Grigoriy ,

Thank you very much for the sharing.

Regards,

Biao

former_member198450
Active Contributor
0 Kudos

Hi Grigoriy,

Thank you very much !

Cheers,

Jain

Former Member
0 Kudos
Dear Grigoriy,

Good Job.. Comprehensive Blog  🙂

Appreciate your help on the below queries.

We are using Reuters DATA SCOPE SELECT API.. after executing TBD4 how the request is passed to Reuters.. is there any JAVA program we need to write? how to invoke that program from TBD4?

Reuters Data Scope select API is called as Reuters SSL or ReutersWeb?
grigoriy_babitskiy
Active Contributor
0 Kudos

Hello naresh.garla,

I don’t have experience to work with Reuters, so i am unable to answer your question. I think you have to request such information from Reuters.

My thoughts about it.
1. IMG -> SAP Customizing Implementation Guide -> Financial Supply Chain Management -> Treasury and Risk Management -> Basic Functions -> Market Data Management -> Datafeed -> Technical Settings -> RFC Settings for External Partner Program
a) Define RFC Destination (tr. SM59) here you have to create RFC connection to Reuters system.
b) Assign Datafeed RFC Destination – here either Reuters function to call, or to use FM TB_DATAFEED_INTERNET_ACCESS or your ZTB_DATAFEED_INTERNET_ACCESS to request info.

2. OR IMG -> SAP Customizing Implementation Guide -> Financial Supply Chain Management -> Treasury and Risk Management -> Basic Functions -> Market Data Management -> Datafeed -> Technical Settings -> Internet Settings for External Partner Program
a) Define Internet Settings for WEB Server Access

I have this file about Reuters, it might be helpfull to you. https://drive.google.com/file/d/0B6CvOxs6tAv7RUJzMVl0ZTB2bjg/view?usp=sharing

Former Member
0 Kudos
Thanks Grigority 🙂 ... for the information .. We have achieved the solution through PI.
Former Member
0 Kudos
Hi Grigoriy, very clear your post!

I have a question regarding the function ZTB_DATAFEED_INTERNET_ACCESS. When I try to set up "Internet settings for web server access" and to complet the URI,
I get the message "No entries found that match selection criteria" (Msg SV004).
When I debug, I see that this is beacuse in the code of this transaccion it is hardcoded "TB_DATAFEED_INTERNET_ACCESS". Do you know if we have to implement any note or do some modification?

Thanks in advance,
Oscar
grigoriy_babitskiy
Active Contributor
0 Kudos
Hello Oscar, i haven't met any note about this situation. If i want to add URI into this confi, i always use debug.

0 Kudos

Thanks Grigory!

For obtainig information from other countries, you can visit http://www.sap-ob08.com

grigoriy_babitskiy
Active Contributor
0 Kudos
Thank you,  adrian.wilder2.

I will try!
Former Member
0 Kudos
Hello Naresh,

Could you please give me some clue about how you solved it via PI?

Im using HTTP_AAE receiver comm channel but I´m not able to sort out the issue.

I really appreaciate your help.

Kind regards!

Carlos
0 Kudos
Very nicely described and illustrated. It was very helpful.

I had a follow up question- we have two different exchange rate types (M -average and ZB - Balance sheet rate) that we intend to update at different frequency and time of a month.by scheduling a batch job The transaction TBD4 does not have a selection field for exchange rate type. So if I schedule a batch job then it will update the rates for both the exchange rate types whereas I will want to update M rates weekly and ZB once a month only.

please recommend a solution.
Hismayilov
Participant
0 Kudos
Code link is not active.
former_member184657
Active Contributor
0 Kudos

You are my Super Hero of the Month! It’s such a detailed document that even I (an ABAP Developer) was able to import market data into our system. Double Thumbs Up for this Blog!

 

pk

grigoriy_babitskiy
Active Contributor
0 Kudos
You are welcome. I am happy this article helped you!
WeekendVampire
Participant
0 Kudos
Can you repost the ztb_datafeed_access.txt, the link is broken.  It looks like SAP has moved it.  Can you also post the changes to the function group, otherwise the code gets an error when you try to compile (e.g.. referenced objects zchar9000, etc).
grigoriy_babitskiy
Active Contributor
0 Kudos

Good Morning Aaron,

Here is the link to txt file: https://drive.google.com/file/d/1lmxyjWy0mHQPuTtMAsuJXtgtDMt0193D/view?usp=sharing

zchar9000 is Data element with domain zchar9000 – Data Type CHAR, No. Characters 9000

 

Also pay attention, that this function module was writen when i didn't have enough knowledge about ABAP and JSON. So this code can be refactored in order to read JSON file with special functions or classes like this: https://blogs.sap.com/2017/08/03/parsing-json-in-abap/

Labels in this area