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
  1. Go to Data source editor.
  2. Click CSV DATA IMPORT.
  3. Click Open CSV editor.
  4. Copy the following lines and paste them in the CSV Editor
dealStamp:PK;NPV;counterparty;currency;typeOfDeals
string;double;string;string;string
  1. Enter the Cube Name: PortfolioValuation, and then click Import. You have just created an empty cube that is waiting to be populated with data.
  2. 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
  1. Switch the UI to Flow editor mode.
  2. Create a new flow and name it Portfolio Valuation.
  3. From the Flow Menu select Import > Clipboard.
  4. 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": []
    }
]
  1. 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.
Fig. 99: The flow in Flow editor.

Fig. 99: The flow in Flow editor.

  1. 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
  1. Switch the UI to Design mode.
  2. Add a one Button to the board and configure it as follows:
    • Title: Calculate
    • Label: Calculate
    • Font-size: 4
  3. Add a new Button to the board and configure it as follows:
    • Title: Reset
    • Label: Reset
    • Font-size: 4
Fig. 100: Two buttons to connect the UI with the flow.

Fig. 100: Two buttons to connect the UI with the flow.

  1. Switch the UI to Link editor mode.
  2. On the Components bar click Reuse.
  3. 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.
  4. Click on an empty area on the board, then on the Components bar, click New.
  5. 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.
  6. 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.
  7. Repeat the steps 6 to 9 for the Reset button.
Fig. 101: Two links to connect the UI with the flow.

Fig. 101: Two links to connect the UI with the flow.

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
  1. Switch the UI to Design mode.
  2. 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
Fig. 102: Table showing all the results.

Fig. 102: Table showing all the results.

To create a chart showing the portfolio composition
  1. Switch the UI to Design mode.
  2. 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 and Show in percentage
Fig. 103: Portfolio Composition.

Fig. 103: Portfolio Composition.

To create a chart showing the counterparty participation by type of deal
  1. Switch the UI to Design mode.
  2. 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
Fig. 104: Portfolio counterparties.

Fig. 104: Portfolio counterparties.

Run the Portfolio Valuation App

To run the Portfolio Valuation App
  1. Deploy your libraries in the Financial Model Builder.
  2. 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.
  3. Click on the Reset button to delete the content of the PortfolioValuation cube.
Fig. 105: Complete view of the Portfolio Valuation App.

Fig. 105: Complete view of the Portfolio Valuation App.