Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added SecurityCompareConnector #69

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
12 changes: 12 additions & 0 deletions demos/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,18 @@ <h3>Demos</h3>
<img src="assets/chevron.svg" alt="Logo" class="logo" />
</button>
</li>
<li>
<button onclick="selectDemo('stock-security-compare/demo.html', this)">
Security Compare
<img src="assets/chevron.svg" alt="Logo" class="logo" />
</button>
</li>
<li>
<button onclick="selectDemo('security-compare-asset-allocations/demo.html', this)">
Security Compare Assets Allocations
<img src="assets/chevron.svg" alt="Logo" class="logo" />
</button>
</li>
</ul>
</div>
<div class="sidebar-footer">
Expand Down
3 changes: 3 additions & 0 deletions demos/security-compare-asset-allocations/demo.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@import url("https://code.highcharts.com/dashboards/css/datagrid.css");
@import url("https://code.highcharts.com/css/highcharts.css");
@import url("https://code.highcharts.com/dashboards/css/dashboards.css");
28 changes: 28 additions & 0 deletions demos/security-compare-asset-allocations/demo.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<link rel="stylesheet" href="demo.css" />
<script src="https://code.highcharts.com/dashboards/datagrid.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/dashboards/dashboards.js"></script>
<script src="https://code.highcharts.com/dashboards/modules/layout.js"></script>
<script src="https://code.highcharts.com/connectors/morningstar/connectors-morningstar.js"></script>
<title>Highcharts Dashboards + Morningstar Compare Asset Allocations</title>
<style>
body {
font-family: sans-serif;
}
</style>
</head>
<body>
<h1>Highcharts Dashboards + Morningstar Compare Asset Allocations</h1>
<p>
Add your Postman environment file from Morningstar to start the demo:
<input type="file" id="postman-json" accept=".json,application/json" />
</p>
<p id="loading-label" style="display: none;">Loading data…</p>
<div id="container"></div>
<script src="./demo.js"></script>
</body>
</html>
122 changes: 122 additions & 0 deletions demos/security-compare-asset-allocations/demo.js
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Directory name:
Let's follow the convention, and since we use Dash here, the directory name should be dashboards-...

Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@

async function displaySecurityDetails (postmanJSON) {
const ids = ['F000015CH2', 'F0000143IP'],
idNames = {
'F000015CH2':
'Schroder International Selection Fund Global Emerging Market Opportunities',
'F0000143IP': 'Fidelity Funds - Asia Pacific Opportunities Fund I-Acc-USD'
}


const connector = new HighchartsConnectors.Morningstar.SecurityCompareConnector({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move the connector config under Dash ataPool's config

postman: {
environmentJSON: postmanJSON
},
security: {
ids,
idType: 'MSID'
},
converter: {
type: 'AssetAllocations'
}
});

await connector.load();

const typeMapping = {
'1': 'Stocks',
'2': 'Bonds',
'3': 'Cash',
'4': 'Other Instruments',
'99': 'Unclassified'
};

const result = ids.map(id =>
connector.table.getRowObjects()
.map(item => ({
name: typeMapping[item['AssetAllocations_Type_' + id]],
y: item['AssetAllocations_MorningstarEUR3_N_' + id]
}))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can resign from this. Use dataLabels.format to apply the translation and columnAssignment to choose the right columns for charts

.filter(entry => entry.y !== 0) // Filter out entries where y is 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we have to keep all values, otherwise we have mismatching colors in series (compare cash):

Zrzut ekranu 2025-02-18 o 13 07 16

);

Dashboards.board('container', {
gui: {
layouts: [{
id: 'layout-1',
rows: [{
cells: [{
id: 'dashboard-col-0'
}, {
id: 'dashboard-col-1'
}]
}]
}]
},
components: [
{
renderTo: 'dashboard-col-0',
type: 'Highcharts',
chartOptions: {
chart: {
animation: false,
type: 'pie'
},
title: {
text: idNames[ids[0]]
},
series: [{
data: result[0]
}]
}
},
{
renderTo: 'dashboard-col-1',
type: 'Highcharts',
chartOptions: {
chart: {
animation: false,
type: 'pie'
},
title: {
text: idNames[ids[1]]
},
series: [{
data: result[1]
}]
}
}
]
});

}

async function handleSelectEnvironment (evt) {
const target = evt.target;
const postmanJSON = await getPostmanJSON(target);

target.parentNode.style.display = 'none';

displaySecurityDetails(postmanJSON);
}

document.getElementById('postman-json')
.addEventListener('change', handleSelectEnvironment);

async function getPostmanJSON (htmlInputFile) {
let file;
let fileJSON;

for (file of htmlInputFile.files) {
try {
fileJSON = JSON.parse(await file.text());
if (HighchartsConnectors.Morningstar.Shared.isPostmanEnvironmentJSON(fileJSON)) {
break;
}
} catch (error) {
// fail silently
}
}

return fileJSON;
}
23 changes: 23 additions & 0 deletions demos/stock-security-compare/demo.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<script src="https://code.highcharts.com/stock/highstock.js"></script>
<script src="https://code.highcharts.com/connectors/morningstar/connectors-morningstar.js"></script>
<title>Highcharts Stock + Morningstar Security Compare</title>
<style>
body {
font-family: sans-serif;
}
</style>
</head>
<body>
<h1>Highcharts Stock + Morningstar Security Compare</h1>
<p>
Add your Postman environment file from Morningstar to start the demo:
<input type="file" id="postman-json" accept=".json,application/json" />
</p>
<div id="container"></div>
<script src="./demo.js"></script>
</body>
</html>
82 changes: 82 additions & 0 deletions demos/stock-security-compare/demo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@

async function displaySecurityDetails (postmanJSON) {
const ids = ['F0GBR050DD', 'F00000Q5PZ'],
idNames = {
'F0GBR050DD': 'Aviva Investors UK Listed Equity Unconstrained Fund 2 GBP Acc',
'F00000Q5PZ': 'Mirae Asset Global Discovery Fund - ' +
'ESG Asia Great Consumer Equity Fund A EUR Capitalization'
}


const connector = new HighchartsConnectors.Morningstar.SecurityCompareConnector({
postman: {
environmentJSON: postmanJSON
},
security: {
ids,
idType: 'MSID'
}
});

await connector.load();

Highcharts.chart('container', {
title: {
text: 'Comparing multiple securities (Trailing performance)'
},
series: ids.map(id => ({
type: 'column',
name: idNames[id],
data: connector.table.getRowObjects().map(obj => [
obj['TrailingPerformance_TimePeriod_' + id],
obj['TrailingPerformance_Value_' + id]
])
})),
xAxis: {
type: 'category'
},
yAxis: {
title: {
text: 'Performance'
},
labels: {
format: '{value}%'
}
},

tooltip: {
valueDecimals: 2,
valueSuffix: '%'
}
});
}

async function handleSelectEnvironment (evt) {
const target = evt.target;
const postmanJSON = await getPostmanJSON(target);

target.parentNode.style.display = 'none';

displaySecurityDetails(postmanJSON);
}

document.getElementById('postman-json')
.addEventListener('change', handleSelectEnvironment);

async function getPostmanJSON (htmlInputFile) {
let file;
let fileJSON;

for (file of htmlInputFile.files) {
try {
fileJSON = JSON.parse(await file.text());
if (HighchartsConnectors.Morningstar.Shared.isPostmanEnvironmentJSON(fileJSON)) {
break;
}
} catch (error) {
// fail silently
}
}

return fileJSON;
}
92 changes: 92 additions & 0 deletions docs/connectors/morningstar/security-compare.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Security Compare

This type retrieves investment data for multiple securities, making it ideal for comparison.

## How to use SecurityCompare

Use the `SecurityCompareConnector` to load the connector.

Specify the securities in the options along with a Postman environment file for authentication and other parameters such as `currency`.

### Securities

Securities are the investments whose details are retrieved. They can be specified using various ID types. Unlike in SecurityDetails, the IDs must be stored in an array.

Supported id-types are: `CUSIP`, `FundCode`, `ISIN`, `MSID`, `PerformanceId`, `SecurityID`, `TradingSymbol`.

If any securities are invalid, the connector will still yield results. The invalid securities will appear in the connector's `metadata` after load.


### Column Names

Columns are named based on the values they represent, followed by their respective security ID (MSID), for example: `TrailingPerformance_TimePeriod_F0GBR050DD`. This naming convention distinguishes the columns and enables quick comparison when inspecting the table. Below is an example of how the columns may be used in practice.

#### Security Compare Types

You can specify the type of data to retrieve by using the `type` option in the connector. The following types are available:

- **TrailingPerformance** (default)
- **AssetAllocations**
- **RegionalExposure**
- **GlobalStockSectorBreakdown**
- **CountryExposure**

Example usage:

```js
const connector = new HighchartsConnectors.Morningstar.SecurityCompareConnector({
postman: {
environmentJSON: postmanJSON
},
security: {
ids: ['F0GBR050DD', 'F00000Q5PZ'],
idType: 'MSID'
},
converter: {
type: 'AssetAllocations' // Specify the type
}
});
```

For more details, see [Morningstar’s Investment Compare API].

### Security Compare with Morningstar standalone for Highcharts:

```js
const ids = ['F0GBR050DD', 'F00000Q5PZ'];

const connector = new HighchartsConnectors.Morningstar.SecurityCompareConnector({
postman: {
environmentJSON: postmanJSON
},
security: {
ids,
idType: 'MSID'
}
});

await connector.load();

Highcharts.chart('container', {
title: {
text: 'Comparing multiple securities (Trailing performance)'
},
series: ids.map(id => ({
type: 'column',
name: id,
data: connector.table.getRowObjects().map(obj => [
obj['TrailingPerformance_TimePeriod_' + id],
obj['TrailingPerformance_Value_' + id]
])
})),
xAxis: {
type: 'category'
}
});
```

## Relevant demo

You will find examples of how to use SecurityCompareConnector in our demos.

[Morningstar’s Investment Compare API]: https://developer.morningstar.com/direct-web-services/documentation/direct-web-services/security-details/investment-compare
Loading
Loading