Similarity Demo

Mutual Fund Dependency Analysis Guide

In the complex financial services landscape, comprehending investment patterns and potential risks has never been more crucial. The Mutual Fund Dependency Analytics use case addresses a pressing business challenge: a comprehensive solution to analyse and interpret clients' investment behaviours, particularly their exposure to underlying stocks within a fund.

With such insights, financial organisations can identify instances of over-leverage and assess risk effectively.

Full example here: https://neo4j.com/developer/industry-use-cases/finserv/investment-banking/mutual-fund-dependency/

How Graph Databases Can Help?

  1. Unparalleled Relationship Mapping: Graph databases excel at modelling complex relationships, enabling accurate depiction of investment dependencies that traditional databases struggle to capture.

  2. Real-time Dependency Insights: Graph databases facilitate real-time querying, allowing instant identification of dependencies and their effects, which is crucial for timely decision-making.

  3. Holistic Portfolio Visualisation: Graph-based representations provide a holistic view of portfolios, revealing hidden correlations and dependencies contributing to over-leverage and risk.

  4. Adaptive Scenario Analysis: Graph databases enable scenario modelling by tracing the impact of changes across interconnected assets, helping mitigate risks and adapt strategies proactively.

  5. Efficient Regulatory Compliance: With graph databases, tracking and reporting investment dependencies becomes streamlined, ensuring compliance with evolving regulatory demands and enhancing transparency.

Clean Up Environment.

// Delete EVERYTHING
MATCH (n) DETACH DELETE n;
					

Load Demo Data.

// Create funds
MERGE (f1:Fund {name: "Fundsmith Equity I Acc", isin: "0P0000RU81"})
MERGE (f2:Fund {name: "Lindsell Train Global Funds plc", isin: "0P0000SVHP"})

// Create stocks
MERGE (novo:Stock {name: "Novo Nordisk A/S", symbol: "NOVO-B.CO", isin: "DK0060534915"})
MERGE (msft:Stock {name: "Microsoft Corporation", symbol: "MSFT", isin: "US5949181045"})
MERGE (or:Stock {name: "L'Oréal S.A.", symbol: "OR.PA", isin: "FR0000120321"})

// Create relationships to stocks for Fundsmith
MERGE (f1)-[:HOLDINGS]->(h1:Holdings)
MERGE (h1)-[:INVESTS_IN {pct: 8.3}]->(msft)
MERGE (h1)-[:INVESTS_IN {pct: 8.01}]->(novo)
MERGE (h1)-[:INVESTS_IN {pct: 6.56}]->(or)

// Create relationships to stocks for Lindsell
MERGE (f2)-[:HOLDINGS]->(h2:Holdings)
MERGE (h2)-[:INVESTS_IN {pct: 8.1}]->(msft)
MERGE (h2)-[:INVESTS_IN {pct: 8.12}]->(novo)
MERGE (h2)-[:INVESTS_IN {pct: 6.6}]->(or)
				

Data Model

Similarity Demo
View Data Model

Let's review the schema:

// Show database schema
CALL db.schema.visualization();
					

Show all Stocks nodes for a single Fund.

// Match all stocks Fundsmith has invested in
MATCH path = (:Fund {name: "Fundsmith Equity I Acc"})-[:HOLDINGS]->(:Holdings)-[:INVESTS_IN]->(:Stock)
RETURN path
				

Show single Stocks nodes with the highest percentage of investment.

// Return path showing single highest invested stock by fund
MATCH path = (:Fund {name: "Fundsmith Equity I Acc"})-[:HOLDINGS]->(:Holdings)-[rel:INVESTS_IN]->(:Stock)
RETURN path
ORDER BY rel.pct DESC
LIMIT 1
				
// Return table with single highest invested stock by fund
MATCH (f:Fund {name: "Fundsmith Equity I Acc"})-[:HOLDINGS]->(:Holdings)-[rel:INVESTS_IN]->(s:Stock)
RETURN f.name AS fundName, rel.pct AS pctInvestment, s.name AS companyName
ORDER BY rel.pct DESC
LIMIT 1
                

Show all Stocks nodes overlap with another fund

// Return paths showing all overlapping position
MATCH path = (:Fund)-[:HOLDINGS]->(:Holdings)-[:INVESTS_IN]->(:Stock)<-[:INVESTS_IN]-(:Holdings)<-[:HOLDINGS]-(:Fund)
RETURN path
				

Show all funds that have a 100% overlap in stocks

// Return fund with 100% overlap of stocks
MATCH path = (f1:Fund)-[:HOLDINGS]->(:Holdings)-[i1:INVESTS_IN]->(:Stock)<-[i2:INVESTS_IN]-(:Holdings)<-[:HOLDINGS]-(f2:Fund)
WHERE ID(f1) > ID(f2)
WITH f1, f2, COUNT(i1) AS fund1Count, COUNT(i2) AS fund2Count
WHERE fund1Count = fund2Count
RETURN f1.name AS fund1Name, fund1Count, fund2Count, f2.name AS fund2Name
				

Show all funds that have a 100% overlap in stocks and the investments are with 1% of the same value

// Return funds that have 100% overlap and have holdings within 1% of each other
MATCH path = (f1:Fund)-[:HOLDINGS]->(:Holdings)-[i1:INVESTS_IN]->(:Stock)<-[i2:INVESTS_IN]-(:Holdings)<-[:HOLDINGS]-(f2:Fund)
WHERE abs(i1.pct - i2.pct) < 1
AND ID(f1) > ID(f2)
AND HEAD(SPLIT(f1.name, " ")) <> HEAD(SPLIT(f2.name, " "))
WITH f1, f2, COUNT(i1) AS fund1Count, COUNT(i2) AS fund2Count
WHERE fund1Count = fund2Count
RETURN f1.name AS fund1Name, fund1Count, fund2Count, f2.name AS fund2Name
ORDER BY fund1Count DESC
				

Find shortest path between two funds

// Find shortest path between two funds
MATCH p=(f1:Fund)-[:HOLDINGS]->(:Holdings)-[*..2]-(:Holdings)<-[:HOLDINGS]-(f2:Fund)
WHERE f1.symbol = "0P0000SCZD.L"
AND f2.symbol = "0P00000RA4.L"
RETURN p