Monitoring consumer bank accounts to maintain compliance
Splunk platform reports can show customer account activity that is unusual or potentially suspicious, such as having multiple accounts, some of which have zero balances, negative balances, or are dormant. These reports can be shown instantly with transaction logs by referencing other accounts in a database.
This type of just-in-time reporting allows banks to keep customers informed in a timely manner so they can take corrective action. Monitoring customer accounts in this way helps banks to adhere to compliance regulations.
Required data
- Application data for banking transactions
- A CSV or KV lookup file of customer account information
How to use Splunk software for this use case
Some commands, parameters, and field names in the searches below may need to be adjusted to match your environment. In addition, to optimize the searches shown below, you should specify an index and a time range when appropriate.
Splunk recommends that customers look into using data models, report acceleration, or summary indexing when searching across hundreds of GBs of events in a single search. The searches provided here are a good starting point, but depending on your data, search time range, and other factors, more can be done to ensure that they scale appropriately.
Customers with too many bank accounts
Customers that have too many accounts can sometimes cause a compliance issue for banks. This report provides just-in-time information so that at the time of an account transaction, you can inform the customer if they have too many accounts above a threshold (in this case, 10) so they can consolidate.
|sourcetype=<transaction data source> |eval _time=strptime(_time, "%Y/%m/%d %H:%M:%S") |sort - _time |lookup <customer account info file> customer |stats last(_time) AS _time list(accountID) AS accountID list(action) AS action list(amount) AS amount list(balance) AS balance values(other_accountID) AS other_accountID sum(other_balance) AS Total_Balance BY customer |eval count_other_accounts=mvcount(other_accountID) |where count_other_accounts>10 |eval Total_Balance=Total_Balance+balance |eval balance=tostring(round(balance, 2),"commas"), Total_Balance=tostring(round(Total_Balance, 2),"commas")
Dormant bank accounts
Customers having dormant accounts can sometimes cause a compliance issue for banks. This report provides just-in-time information so that at the time of an account transaction, you can inform the customer if they have any untouched accounts older than 6 months from their current transaction date.
|sourcetype=<transaction data source> |eval prev_epoch=strptime(last_touched, "%m/%d/%Y %H:%M:%S") |sort - last_touched |join customer [ |inputlookup <customer account info file> ] |where epoch>relative_time(prev_epoch, "+6mon") |fields - prev_epoch, balance|rename accountID AS current_accountID action AS current_action account_type AS current_account_type |eval current_balance=tostring(round(current_balance, 2),"commas"), other_balance=tostring(round(other_balance, 2),"commas") |convert timeformat="%m/%d/%Y %H:%M:%S" ctime(epoch) AS current_time |fields - epoch
Bank accounts with large balances
Customers who have accounts with a large balance can sometimes cause a compliance issue for banks. In some countries, accounts are insured only up to certain threshold. This report provides just-in-time information so that at the time of an account transaction, you can inform the customer if their total accounts balance is greater than their country's established insured threshold.
|sourcetype=<transaction data source> |eval _time=strptime(_time, "%Y/%m/%d %H:%M:%S") |sort - _time |lookup <customer account info file> customer |stats values(_time) AS _time list(balance) as current_account_balance list(account_type) AS current_account_type list(other_account_type) AS other_account_type list(other_accountID) AS other_accountID list(other_balance) AS other_balance sum(other_balance) AS Total_Balance BY customer |eval Total_Balance=Total_Balance+current_account_balance |search other_account_type="*" AND Total_Balance>250000 |eval Total_Balance=tostring(round(Total_Balance, 2),"commas"), current_account_balance=tostring(round(current_account_balance, 2),"commas")
Bank accounts with a negative balance
Customers having accounts with a negative balance can sometimes cause a compliance issue for banks. A negative balance could indicate an overdraft or account takeover. This report provides just-in-time information so that at the time of an account transaction, you can inform the customer.
|sourcetype=<transaction data source> |eval _time=strptime(_time, "%Y/%m/%d %H:%M:%S") |sort _time |lookup <customer account info file> customer |stats last(_time) AS _time last(amount) AS amount last(accountID) AS accountID last(action) AS action last(account_type) AS account_type list(other_balance) AS other_balance list(other_accountID) AS other_accountID list(other_account_type) AS other_account_type BY customer |search other_balance=* |nomv other_balance |search other_balance="-*" |makemv delim=" " other_balance |table _time, customer, amount, accountID, action, account_type, other_accountID, other_account_type, other_balance |eval amount=tostring(round(amount, 2),"commas")
Bank accounts with zero balance
Customers having accounts with a zero balance can sometimes cause a compliance issue for banks. This report provides just-in-time information so that at the time of an account transaction, you can inform the customer.
|sourcetype=<transaction data source> |eval _time=strptime(_time, "%Y/%m/%d %H:%M:%S") |sort - _time |lookup <customer account info file> customer |stats last(_time) AS _time last(amount) AS amount last(accountID) AS accountID last(action) AS action last(account_type) AS account_type list(other_balance) AS other_balance list(other_accountID) AS other_accountID list(other_account_type) AS other_account_type BY customer |eval is_match=mvfilter(match(other_balance, "0")) |search is_match=* |fields - is_match |table _time, customer, amount, accountID, action, account_type, other_accountID, other_account_type, other_balance |eval amount=tostring(round(amount, 2),"commas")
Next steps
Run reports based off these searches on a regular basis and save the results as needed for compliance reporting. Investigate as needed to ensure the activity isn't related to employee behavior, and then communicate immediately with customers regarding any results that indicate problematic accounts.
- Fraud: Credit cards, ATM usage, wire transfers, banking transactions
- Monitoring: Credit cards, ATM usage, wire transfers, banking transactions
- Banking: Logins
- Payments: Responses, mobile payments
- Markets: Bitcoin, MFID, FIX orders, trades
- Credit limit increases
Finally, these additional Splunk resources might help you understand and implement this use case: