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.
![22.jpg]()
![47.jpg]()
![48.jpg]()
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.
![01.jpg]()
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.
![02.jpg]()
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.
![03.jpg]()
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.
![49.jpg]()
Translation Table
Translation tables can be filled in two ways:
- Automatically. You need to configure Datafeed Conversion Codes
- 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)
![60.jpg]()
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.
![61.jpg]()
In our case SAP data is equal to External data.
![62.jpg]()
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
![45.jpg]()
Convert Commodity Price Types: tr. SM30 -> V_MDUCMV
![46.jpg]()
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.
![64.jpg]()
Start transaction.
![65.jpg]()
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.
![10.jpg]()
SAP created translation tables for currency. Make a double click on any parameters in the table.
![11.jpg]()
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.
![12.jpg]()
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.
![20.jpg]()
![21.jpg]()
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.
![30.jpg]()
![31.jpg]()
![32.jpg]()
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.