First-party bank fraud involves fraudsters who apply for credit cards, loans, overdrafts and unsecured banking credit lines, with no intention of paying them back. It is a serious problem for banking institutions.

The surprising magnifitude of these losses is likely the result of two factors. The first is that first-party bank fraud is very difficult to detect. Fraudsters behave very similarly to legitimate customers, until the moment they "bust out", cleaning out all their accounts and promptly disappearing.

A second factor - which will also be explored later in greater detail—is the exponential nature of the relationship between the number of participants in the fraud ring and the overall dollar value controlled by the operation. This connected explosion is a feature often exploited by organized crime.

However while this characteristic makes these schemes potentially very damaging, it also renders them particularly susceptible to graph-based methods of fraud detection.

Common Types of First-Party Bank Fraud:

  • Sleeper fraud occurs when a fraudster acquires a form of credit and, over time, builds up what appears to be normal customer behaviour. As the customer builds trust with the service provider over months or even years, they eventually ask for more credit and then cash in, taking the maximum amount of cash and any goods with them, never to be seen again.
  • Bust-out fraud, also known as hit and run, can happen on many types of financial services. It's quick and sometimes easy, with credit cards and loans being the easiest prey today. In some countries where cheques are in use or have slower clearing cycles, fraudsters can exploit these inefficiencies to inflate a credit balance by up to 10 times the limit and cash out before getting caught.

Scenario

While the exact details behind each first-party bank fraud collusion vary from operation to operation, the pattern below illustrates how fraud rings commonly operate:

  • A group of two or more people organize into a fraud ring.
  • The ring shares a subset of legitimate contact information, for example phone numbers and addresses, combining them to create a number of synthetic identities.
  • Ring members open accounts using these synthetic identities.
  • New accounts are added to the original ones: unsecured credit lines, credit cards, overdraft protection, personal loans, etc.
  • The accounts are used normally, with regular purchases and timely payments.
  • Banks increase the revolving credit lines over time, due to the observed responsible credit behavior.
  • One day the ring “busts out”, coordinating their activity, maxing out all of their credit lines, and disappearing.
  • Sometimes fraudsters will go a step further and bring all of their balances to zero using fake checks immediately before the prior step, doubling the damage.
  • Collections processes ensue, but agents are never able to reach the fraudster.
  • The uncollectible debt is written off.

Solution

We can run appropriate graph queries using graph and run checks during key stages in the customer and account life cycles such as:

  • At the time the account is created.
  • During an investigation.
  • As soon as a credit balance threshold is hit.
  • When a check is bounced.

Graph Structure

The graph data model below represents how the data is linked and illustrates how one can find rings by simply walking the graph.

graph structure

Steps to Implement

Step 1

Sample data:

Insert data from CLI

CREATE GRAPH Bank_Fraud
USE GRAPH Bank_Fraud
CREATE (UID:101 {"FirstName":"John","LastName":"Doe"})-[HAS_ADDRESS {"info":"Address"}]->(Address:address1 {"Street":"123 NW 1st Street","City":"San Francisco","State":"California","ZipCode":"94101" })

CREATE (UID:102 {"FirstName":"Jane","LastName":"Appleseed"})-[HAS_ADDRESS {"info":"Address"}]->(Address:address1 {"Street":"123 NW 1st Street","City":"San Francisco","State":"California","ZipCode":"94101" })

CREATE (UID:103 {"FirstName":"Matt","LastName":"Smith"})-[HAS_ADDRESS {"info":"Address"}]->(Address:address1 {"Street":"123 NW 1st Street","City":"San Francisco","State":"California","ZipCode":"94101" })

CREATE (UID:104 {"FirstName":"Adam","LastName":"Well"})-[HAS_ADDRESS {"info":"Address"}]->(Address:address4 {"Street":"11 4st Street","City":"San Francisco","State":"California","ZipCode":"94105" })

CREATE (UID:105 {"FirstName":"Emily","LastName":"Green"})-[HAS_ADDRESS {"info":"Address"}]->(Address:address5 {"Street":"1445/3278 box street","City":"San Francisco","State":"California","ZipCode":"94103"})

CREATE (UID:106 {"FirstName":"Rose","LastName":"Breey"})-[HAS_ADDRESS {"info":"Address"}]->(Address:address5 {"Street":"1445/3278 box street","City":"San Francisco","State":"California","ZipCode":"94103"})

CREATE (Address:address1)-[ADDRESS_OF {"info":"Address"}]->(UID:101)

CREATE (Address:address1)-[ADDRESS_OF {"info":"Address"}]->(UID:102)

CREATE (Address:address1)-[ADDRESS_OF {"info":"Address"}]->(UID:103)

CREATE (Address:address4)-[ADDRESS_OF {"info":"Address"}]->(UID:104)

CREATE (UID:101)-[HAS_PHONENUMBER {"info":"Phone_Number"}]->(PhoneNumber:555-555-5555)

CREATE (UID:102)-[HAS_PHONENUMBER {"info":"Phone_Number"}]->(PhoneNumber:555-555-5555)

CREATE (UID:104)-[HAS_PHONENUMBER {"info":"Phone_Number"}]->(PhoneNumber:555-555-5357)

CREATE (UID:103)-[HAS_PHONENUMBER {"info":"Phone_Number"}]->(PhoneNumber:555-555-1234)

CREATE (UID:105)-[HAS_PHONENUMBER {"info":"Phone_Number"}]->(PhoneNumber:555-555-5345)

CREATE (UID:106)-[HAS_PHONENUMBER {"info":"Phone_Number"}]->(PhoneNumber:555-555-5555)

CREATE (UID:102)-[HAS_SSN {"info":"IdentificationID"}]->(SSN:241-23-1234)

CREATE (UID:103)-[HAS_SSN {"info":"IdentificationID"}]->(SSN:241-23-1234)

CREATE (UID:104)-[HAS_SSN {"info":"IdentificationID"}]->(SSN:241-23-6875)

CREATE (UID:101)-[HAS_SSN {"info":"IdentificationID"}]->(SSN:241-23-4567)

CREATE (UID:105)-[HAS_SSN {"info":"IdentificationID"}]->(SSN:241-23-7893)

CREATE (UID:106)-[HAS_SSN {"info":"IdentificationID"}]->(SSN:241-23-4567)

CREATE (UID:101)-[HAS_ACCOUNT]->(AccountNumber:1234567890123456 {"HasCreditCard":1,"HasLoan":0,"Limit":5000,"Balance":1442.23,"ExpirationDate":"01-20","SecurityCode":"123"})

CREATE (UID:101)-[HAS_ACCOUNT]->(AccountNumber:2345678901234567 {"HasCreditCard":0,"HasLoan":0,"Limit":0,"Balance":7054.43})

CREATE (UID:102)-[HAS_ACCOUNT]->(AccountNumber:1234467890123456 {"HasCreditCard":1,"HasLoan":0,"Limit":4000,"Balance":2345.56,"ExpirationDate":"02-20","SecurityCode":"456"})

CREATE (UID:102)-[HAS_ACCOUNT]->(AccountNumber:3456789012345678 {"HasCreditCard":0,"HasLoan":0,"Limit":0,"Balance":4231.12 })

CREATE (UID:102)-[HAS_ACCOUNT]->(AccountNumber:4567890123456789-0 {"HasCreditCard":0,"HasLoan":1,"Limit":0,"LoanAmt": 9045.53,"APR": 0.0541})

CREATE (UID:103)-[HAS_ACCOUNT]->(AccountNumber:4567890123456789 {"HasCreditCard":0,"HasLoan":0,"Limit":0,"Balance":12345.45})

CREATE (UID:103)-[HAS_ACCOUNT]->(AccountNumber:56789012345678900 {"HasCreditCard":0,"HasLoan":1,"Limit":0,"LoanAmt":16341.95,"APR":0.0341} 

CREATE (UID:104)-[HAS_ACCOUNT]->(AccountNumber:67890123456789010 {"HasLoan":1,"HasCreditCard":0,"Limit":0,"LoanAmt":11233.4,"APR":0.0567})

CREATE (UID:105)-[HAS_ACCOUNT]->(AccountNumber:7890123456789012 {"HasLoan":0,"HasCreditCard":1,"Limit":8000,"Balance":12345.67,"ExpirationDate":"02-20","SecurityCode":"786"})

Step 2

Performing Graph Queries

Find account holders who share more than one piece of legitimate contact information and Determine the financial risk of a possible fraud ring.

Checking for people sharing same address

S=>(@u UID:*)-[@d HAS_ADDRESS]->(@q Address:*);RETURN q.name AS AddressID,COUNT(*) AS AddressRingSize WHERE AddressRingSize > 2

Checking the risk for "address 1". Below query display all customers sharing id "address 1"

S2=>[S1=>(@u UID:*)-[@h HAS_ADDRESS]->(Address:address1)]-[@l HAS_ACCOUNT]->(@a AccountNumber:*);RETURN u.name AS UserID, SUM(a.Limit) AS CreditLimit, SUM(a.LoanAmt) AS LoanAmtBal, MATH_EXP("($CreditLimit+$LoanAmtBal)") AS TotalRisk

Checking total risk for each address

S2=>[S1=>(@u UID:*)-[@d HAS_ADDRESS]->(@q Address:*)]-[@h HAS_ACCOUNT]->(@a AccountNumber:*);RETURN COUNT(a.name) AS NumberOFAccounts, q.name AS AddressID,SUM(a.Limit) AS CreditLimit, SUM(a.LoanAmt) AS LoanAmtBal, MATH_EXP("($CreditLimit+$LoanAmtBal)") AS TotalRisk WHERE NumberOFAccounts > 6

Checking for people sharing phone number

S=>(@p PhoneNumber:*)<-[@n HAS_PHONENUMBER]-(UID:*);RETURN p.name AS phonenumber, COUNT(*) AS PhoneRingSize WHERE PhoneRingSize > 2

Checking the risk of all phone number risks

S2=>[S1=>(@u UID:*)-[@n HAS_PHONENUMBER]->(@p PhoneNumber:*)]-[@H HAS_ACCOUNT]->(@a AccountNumber:*);RETURN UCOUNT(u.name) AS PhoneNumberRingSize, p.name AS PhoneNumbers, UCOUNT(a.name) AS NumberOFAccounts, SUM(a.Limit) AS CreditLimit, SUM(a.LoanAmt) AS LoanAmtBal, MATH_EXP("($CreditLimit+$LoanAmtBal)") AS TotalRisk

Checking for people sharing identification number

S=>(@s SSN:*)<-[@l HAS_SSN]-(UID:*);RETURN s.name AS IdentificationNumber, COUNT(*) AS SSNRingSize WHERE SSNRingSize > 1

Checking the risk for "241-23-4567". Below query will display all customers sharing id "241-23-4567".

S2=>[S1=>(@u UID:*)-[@l HAS_SSN]->(SSN:241-23-4567)]-[@H HAS_ACCOUNT]->(@a AccountNumber:*);RETURN u.name AS CustomerID, COUNT(a.name) AS NumberOFAccounts, SUM(a.Limit) AS CreditLimit, SUM(a.LoanAmt) AS LoanAmtBal, MATH_EXP("($CreditLimit+$LoanAmtBal)") AS TotalRisk

Real-time graph traversals tied to the right kinds of events can help banks identify probable fraud rings: during or even before the bust-out occurs.