Visualize the Data
In this section you will work with FusionCreator App Builder, to do the following:
- Create a cube to store results using the Data source editor.
- Create a flow in Flow editor, to manage the input and the results.
- Connect the flow with the UI using the Link editor.
- Run the App and see the results.
Create the Cube
To create the cube that will store the data from Financial Model Builder
- Go to Data source editor.
- Click CSV DATA IMPORT.
- Click Open CSV editor.
- Copy the following lines and paste them in the CSV Editor
dealStamp:PK;NPV;counterparty;currency;typeOfDeals
string;double;string;string;string
- Enter the Cube Name:
PortfolioValuation
, and then click Import. You have just created an empty cube that is waiting to be populated with data. - Click Generate the report. The Report Name field is automatically filled with the name of the cube. You can change it, but take a note of it as you will use it to select the data source in all the subsequent data visualization.
Create the Flow
To create the flow in the Flow editor
- Switch the UI to Flow editor mode.
- Create a new flow and name it Portfolio Valuation.
- From the Flow Menu select Import > Clipboard.
- Copy the following code, and paste it into the text area of the Import nodes window. Select the Import to current flow option.
[
{
"id": "a706cd2e.616e9",
"type": "mb-http-in",
"z": "44af8190.8d58a",
"name": "Calculate",
"method": "post",
"url": "/55ced101-c8d4-a06e-1dd2-a33c4976d6a3/Calculate",
"x": 100,
"y": 620,
"wires": [
[
"6a3dadf7.c15334"
]
]
},
{
"id": "6a3dadf7.c15334",
"type": "function",
"z": "44af8190.8d58a",
"name": "Library and APIM Settings",
"func": "msg.libraryName = \"<your_LibraryName_key>\";\nmsg.projectName = \"<your_project_name>\";\nmsg.apiKey = \"<your_API_key>\";\nmsg.host =\"{apiHost}\";\nmsg.basePath = \"{basePath}\";\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 330,
"y": 620,
"wires": [
[
"4a63027e.1b99bc"
]
]
},
{
"id": "4a63027e.1b99bc",
"type": "function",
"z": "44af8190.8d58a",
"name": "Authorization",
"func": "msg.headers = {\n\"Authorization\" : \"Bearer \" + msg.req.user.authTokens.master.access_token,\n\"Ocp-Apim-Subscription-Key\": msg.apiKey\n};\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 290,
"y": 680,
"wires": [
[
"f81f427c.3effe"
]
]
},
{
"id": "f81f427c.3effe",
"type": "function",
"z": "44af8190.8d58a",
"name": "Variables",
"func": "if(msg.req.url.includes('Calculate')){\n msg.cubeName = \"PortfolioValuation\"\n msg.shiftsIncluded = false\n msg.shifts = JSON.stringify(\"\")\n msg.device = 0\n} \nelse {\n msg.cubeName = \"PortfolioValuationScenarios\" \n msg.shiftsIncluded = true\n data = [\n {\n \"type\": \"YIELD_CURVE\",\n \"steps\": msg.payload.value.steps,\n \"min\": msg.payload.value.Min,\n \"max\": msg.payload.value.Max,\n \"param1\": msg.payload.value[\"Yield Curve\"],\n \"param2\": \"discountFactor\"\n }\n ]\n msg.shifts = JSON.stringify(data)\n switch (msg.payload.value.Device){\n case \"JAVA\":\n msg.device = -2;\n break;\n case \"GROOVY\":\n msg.device = -1;\n break;\n case \"SIMD CPU\":\n msg.device = 0;\n break;\n }\n}\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 280,
"y": 740,
"wires": [
[
"807cf259.a2e19"
]
]
},
{
"id": "807cf259.a2e19",
"type": "template",
"z": "44af8190.8d58a",
"name": "Workflow input",
"field": "payload",
"fieldType": "msg",
"format": "handlebars",
"syntax": "mustache",
"template": "{ \n \"config\": {\n \"engineConfig\": {\n \"selectedOpenclDevices\": {{device}}\n }\n },\n \"messages\": [\n {\n \"box\": \"tutorial_Portfolio\",\n \"data\": {\n \"inputIncluded\": false,\n \"pathDoc\": \"/projects/{{projectName}}/src/test/resources/documents/tutorial_Portfolio.json\",\n \"pathPricingData\": \"/projects/{{projectName}}/src/test/resources/pricingData/tutorial_Portfolio.scn\",\n \"shiftsIncluded\" : {{shiftsIncluded}},\n \"shifts\": {{{shifts}}}\n }\n }\n ]\n}",
"output": "json",
"x": 300,
"y": 800,
"wires": [
[
"f561cd10.326cc"
]
]
},
{
"id": "f561cd10.326cc",
"type": "http request",
"z": "44af8190.8d58a",
"name": "FMB Valuation",
"method": "POST",
"ret": "obj",
"url": "https://{{{apiHost}}}{{{basePath}}}/library/{{{libraryName}}}/workflow/tutorial_Portfolio/execute",
"tls": "",
"x": 580,
"y": 620,
"wires": [
[
"53d0f975.f98068"
]
]
},
{
"id": "53d0f975.f98068",
"type": "function",
"z": "44af8190.8d58a",
"name": "Processing results",
"func": "results = msg.payload.outputs[0].message\nvar Json = JSON.parse(results)\nvar resultsAsJson = Json.results\n\nif(msg.shiftsIncluded){\n msg.time = Json.timeSpent;\n var type = Json.type\n var shift = Json.shift\n var scen = resultsAsJson[0].NPV.length\n var list = []\n for (var k = 0; k < resultsAsJson.length; k++){\n for (var l = 0; l < scen; l++){\n var info = {\n dealStamp: resultsAsJson[k].dealStamp,\n type : type[l],\n shiftId: shift[l],\n shift: parseFloat(shift[l].slice(0,7)),\n NPV: resultsAsJson[k].NPV[l],\n NPVchange: resultsAsJson[k].NPV[l] - resultsAsJson[k].NPV[0],\n counterparty: resultsAsJson[k].counterparty,\n currency:resultsAsJson[k].currency,\n typeOfDeals: resultsAsJson[k].typeOfDeals\n };\n list.push(info);\n }\n }\n var data = {\n \trows: list\n }\n}else{\n msg.time = \"\";\n var list = []\n for (var k = 0; k < resultsAsJson.length; k++){\n var info = {\n dealStamp: resultsAsJson[k].dealStamp,\n NPV: resultsAsJson[k].NPV[0],\n counterparty: resultsAsJson[k].counterparty,\n currency:resultsAsJson[k].currency,\n typeOfDeals: resultsAsJson[k].typeOfDeals\n };\n list.push(info);\n }\n var data = {\n\trows: list\n }\n} \n\nmsg.payload = data;\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 590,
"y": 680,
"wires": [
[
"9a9687d5.6a3d98"
]
]
},
{
"id": "9a9687d5.6a3d98",
"type": "cube-delete",
"z": "44af8190.8d58a",
"default": true,
"deleteRowsInCube_id": "cubeName",
"deleteRowsInCube_idType": "msg",
"deleteRowsInCube_filter": "",
"deleteRowsInCube_filterType": "nof",
"name": "Reset Cube",
"x": 570,
"y": 740,
"wires": [
[
"80dd03c7.1432b"
]
]
},
{
"id": "80dd03c7.1432b",
"type": "cube-insert-update",
"z": "44af8190.8d58a",
"default": true,
"insertUpdateRowsInCube_id": "cubeName",
"insertUpdateRowsInCube_idType": "msg",
"insertUpdateRowsInCube_body": "",
"insertUpdateRowsInCube_bodyType": "pay",
"name": "Insert results",
"x": 570,
"y": 800,
"wires": [
[
"23b3e91d.6b2006"
]
]
},
{
"id": "23b3e91d.6b2006",
"type": "switch",
"z": "44af8190.8d58a",
"name": "Component output",
"property": "cubeName",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "PortfolioValuation",
"vt": "str"
},
{
"t": "neq",
"v": "PortfolioValuation",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 590,
"y": 860,
"wires": [
[
"d5062a21.afbfb8"
],
[]
]
},
{
"id": "d5062a21.afbfb8",
"type": "mb-http-out",
"z": "44af8190.8d58a",
"name": "Calculate_out",
"x": 820,
"y": 840,
"wires": []
},
{
"id": "f53c72b7.6c7ca",
"type": "comment",
"z": "44af8190.8d58a",
"name": "Portfolio Valuation Flow",
"info": "This flows calls FMB to price a portfolio",
"x": 140,
"y": 540,
"wires": []
},
{
"id": "f8b79bee.c595f8",
"type": "comment",
"z": "44af8190.8d58a",
"name": "Reset Flow",
"info": "",
"x": 110,
"y": 940,
"wires": []
},
{
"id": "9f421ecc.f38f5",
"type": "mb-http-in",
"z": "44af8190.8d58a",
"name": "Reset",
"method": "post",
"url": "/24562bdc-96a8-50b7-b5d8-99535ece590d/",
"x": 90,
"y": 1000,
"wires": [
[
"8661c4b0.443588"
]
]
},
{
"id": "8661c4b0.443588",
"type": "cube-delete",
"z": "44af8190.8d58a",
"default": true,
"deleteRowsInCube_id": "PortfolioValuation",
"deleteRowsInCube_idType": "str",
"deleteRowsInCube_filter": "",
"deleteRowsInCube_filterType": "nof",
"name": "Reset Cube",
"x": 330,
"y": 1000,
"wires": [
[
"7d16ed14.123f24"
]
]
},
{
"id": "7d16ed14.123f24",
"type": "mb-http-out",
"z": "44af8190.8d58a",
"name": "Reset_out",
"x": 530,
"y": 1000,
"wires": []
}
]
- In the Library and APIM Settings node update the variables:
- msg.libraryName: replace
<your_LibraryName_key>
with the name of your library, for example FMB. - msg.projectName: replace
<your_project_name>
with the name of your project. - msg.apiKey: replace
<your_API_key>
with your API key; - msg.host: replace
{host}
with the value that you get from the API definition. - msg.basePath: replace
{basePath}
with the value that you get from the API definition. See Get Started with Finastra Open APIs.
- Click Deploy to make your flow available in the Components list of the UI.
Connect the flow with the UI
To connect the flow with the UI
- Switch the UI to Design mode.
- Add a one Button to the board and configure it as follows:
- Title:
Calculate
- Label:
Calculate
- Font-size: 4
- Title:
- Add a new Button to the board and configure it as follows:
- Title:
Reset
- Label:
Reset
- Font-size: 4
- Title:
- Switch the UI to Link editor mode.
- On the Components bar click Reuse.
- Select the Calculate button that you just created in the Layout editor. A box listing the actions and events bound to the button is displayed on the board.
- Click on an empty area on the board, then on the Components bar, click New.
- Search and select the Portfolio Valuation component, which is linked to the Portfolio Valuation flow that you previously created. A box listing the actions and events of the flow is displayed on the board.
- Connect the
on_click
event of the Calculate button to the Calculate action of the Portfolio Valuation flow. The effect of this link is that when you click the button, you trigger the flow in Flow editor which, in turn, calls Financial Model Builder to execute the portfolio pricer workflow. - Repeat the steps 6 to 9 for the Reset button.
You can now trigger the calculation of the portfolio and get the results stored in the cube. Don’t forget to deploy your library in Financial Model Builder.
Display Results
To display the results in a table
- Switch the UI to Design mode.
- Add a new table to the board and configure it as follows:
- Title:
Portfolio Deals
- Data source: select the
Portfolio Valuation
report - Columns: Click on
Select All
- Title:
To create a chart showing the portfolio composition
- Switch the UI to Design mode.
- Add a new Pie Chart to the board and configure it as follows:
- Title:
Portfolio Composition
- Data source: select the
PortfolioValuation
report - Measures: select
NPV
- Dimensions: select
typeOfDeals
- Chart type: select
Doughnut
- Options: select
Label
andShow in percentage
- Title:
To create a chart showing the counterparty participation by type of deal
- Switch the UI to Design mode.
- Add a new Pie Chart to the board and configure it as follows:
- Title:
Portfolio counterparties
- Horizontal axis: select the
counterparty
report - Vertical axis: select
NPV
- Series: select
typeOfDeals
- Title:
Run the Portfolio Valuation App
To run the Portfolio Valuation App
- Deploy your libraries in the Financial Model Builder.
- Click on the Calculate button to call the portfolio pricer, this will:
- Store the results in the
PortfolioValuation
cube. - Display the results in the three components.
- Store the results in the
- Click on the Reset button to delete the content of the
PortfolioValuation
cube.