Find a fund's swap counterparties in Form N-PORT
Parse the derivatives in a fund's Form N-PORT, group its swaps by counterparty, and total fair value and unrealized appreciation per bank.
Funds that use derivatives must describe each contract in Form N-PORT: the type, the reference instrument, the notional amount, the termination date, the unrealized appreciation and, for over-the-counter contracts, the counterparty. That makes N-PORT a public map of which dealers stand on the other side of fund derivatives.
This tutorial groups one fund's swaps by counterparty.
Fetch the filing and find the swaps
Derivatives live in the same holdings list as stocks and bonds. A holding is a derivative when it has derivativeInfo, and the key inside tells you the kind: swapDeriv, fwdDeriv (forwards), futrDeriv (futures) or optionSwaptionWarrantDeriv.
This example uses Principal Funds, Inc. (CIK 898745), whose Diversified Income Fund reported credit default swaps and total return swaps.
import os
from collections import defaultdict
import requests
BASE = "https://secfeedapi.com"
HEADERS = {"Authorization": f"Bearer {os.environ['SECFEED_KEY']}"}
CIK = 898745 # Principal Funds, Inc.
r = requests.get(f"{BASE}/v1/n-port", params={"cik": CIK, "startDate": "2026-09-01"}, headers=HEADERS, timeout=120)
r.raise_for_status()
for filing in r.json()["filings"]:
form = filing["data"]["primary_doc"]["formData"]
holdings = form["invstOrSecs"]["invstOrSec"]
holdings = holdings if isinstance(holdings, list) else [holdings]
swaps = [h for h in holdings if "swapDeriv" in (h.get("derivativeInfo") or {})]
if swaps:
break
print(f"{form['genInfo']['seriesName']}, period {form['genInfo']['repPdDate']}, filed {filing['filedAt']}")
print(f"Holdings: {len(holdings)} | swaps: {len(swaps)}")
by_cp = defaultdict(lambda: {"swaps": 0, "value": 0.0, "unrealized": 0.0, "types": set()})
for h in swaps:
s = h["derivativeInfo"]["swapDeriv"]
cps = s["counterparties"] if isinstance(s["counterparties"], list) else [s["counterparties"]]
for cp in cps:
row = by_cp[cp["counterpartyName"]]
row["swaps"] += 1
row["value"] += float(h["valUSD"])
row["unrealized"] += float(s.get("unrealizedAppr") or 0)
row["types"].add(h["title"][:28])
print(f"\n{'Counterparty':<34}{'Swaps':>6}{'Fair value USD':>16}{'Unrealized USD':>16}")
for name, row in sorted(by_cp.items(), key=lambda x: -x[1]["swaps"]):
print(f"{name[:33]:<34}{row['swaps']:>6}{row['value']:>16,.0f}{row['unrealized']:>16,.0f}")
print("\nSwap types:", sorted({t for row in by_cp.values() for t in row["types"]}))
Output:
Diversified Income Fund, period 2026-07-31, filed 2026-10-08
Holdings: 2779 | swaps: 41
Counterparty Swaps Fair value USD Unrealized USD
Citigroup Inc 10 110,072 110,072
Goldman Sachs & Co 9 514,110 48,993
JPMorgan Chase 7 393,325 156,593
Morgan Stanley & Co 5 122,975 19,403
ICE 5 -716,507 -155,812
Bank of America NA 4 379,019 41,674
BNP Paribas 1 430,748 -2,197
Swap types: ['Credit Default Swaps', 'Total Return Swaps']
Reading the result
- Counterparties are the dealers named on each swap. ICE is not a bank: it is ICE Clear Credit, the clearinghouse for centrally cleared credit default swaps, so those contracts carry clearinghouse rather than dealer risk.
- Fair value (
valUSD) is the contract's value in US dollars at period end. Negative values are liabilities of the fund. - Unrealized appreciation (
unrealizedAppr) is the gain or loss since the contract was entered. For contracts with an upfront payment it differs from fair value, which is why Goldman Sachs shows a fair value of $514,110 but only $48,993 of appreciation.
Other useful swap fields
Each swapDeriv also carries:
descRefInstrmnt: the reference index or security, for example an iTraxx Crossover tranche or a single bondnotionalAmtandcurCd: notional in the contract currency (convert before adding across currencies)terminationDt: maturity datefixedRecDesc,floatingPmntDesc,otherPmntDesc: the legs of the swap, including the floating rate index and spread
To measure exposure across the industry, run the same grouping over many funds and sum by counterparty name. Names are free text in N-PORT, so normalize them (for example "JPMorgan Chase" and "JPMorgan Chase Bank, N.A.") or use counterpartyLei where the filer provides it.