NakedPnL

The public registry of verified investment performance. Every return sourced from SEC filings, exchange APIs, or platform data.

Registry

  • Registry
  • Market Context
  • How It Works
  • Community

Verification

  • Get Verified
  • Connect Exchange

Legal

  • Terms of Service
  • Privacy Policy
  • Refund & Cancellation
  • Support
  • GDPR Rights
  • Cookie Policy
  • Disclaimers
  • Methodology
  • Compliance
Follow

NakedPnL is a publisher of verified performance data. Nothing on this site constitutes investment advice, a recommendation, or a solicitation to buy, sell, or hold any security, commodity, or digital asset. Past performance does not indicate future results. Trading carries a high risk of total capital loss.

© 2026 NakedPnLAll performance data is verified by the NakedPnL teamcontact@nakedpnl.com
NakedPnL
RegistryPricingHow It WorksCommunitySupport
Registry/Docs/Verification
Verification Algorithm

How the hash chain works

Every daily portfolio snapshot on NakedPnL is cryptographically chained to the previous one. This makes historical records tamper-evident: changing any past snapshot breaks every subsequent hash in the chain.

1. Hash chain formula

For each daily snapshot, two hashes are computed:

contentHash = SHA-256( canonicalize(rawApiResponse) ) chainHash = SHA-256( previousChainHash + contentHash )

For the very first snapshot in a chain (genesis), previousChainHash is the literal string "genesis".

Concatenation uses no separator: the input to the chain hash is previousChainHash + contentHash (two 64-character hex strings joined directly, or "genesis" + 64 hex chars for the first entry).

2. Fetch the raw chain

The full chain for any public trader is available via a CORS-open API:

GET https://nakedpnl.com/api/v1/chain/<handle>

Returns JSON with an array of snapshots, each containing contentHash, chainHash, and previousChainHash.

3. Verify in Python (20 lines)

import hashlib, json, urllib.request def verify_chain(handle: str) -> bool: url = f"https://nakedpnl.com/api/v1/chain/{handle}" data = json.loads(urllib.request.urlopen(url).read()) for snap in data["snapshots"]: prev = snap["previousChainHash"] content = snap["contentHash"] expected = hashlib.sha256( (prev + content).encode() ).hexdigest() if expected != snap["chainHash"]: print(f"FAIL at {snap['date']}: " f"expected {expected[:16]}... " f"got {snap['chainHash'][:16]}...") return False print(f"PASS: {len(data['snapshots'])} snapshots verified") return True verify_chain("bhutrabali")

4. Verify in JavaScript (25 lines)

async function verifyChain(handle) { const res = await fetch( `https://nakedpnl.com/api/v1/chain/${handle}` ); const { snapshots } = await res.json(); for (const snap of snapshots) { const input = snap.previousChainHash + snap.contentHash; const buf = await crypto.subtle.digest( "SHA-256", new TextEncoder().encode(input) ); const hex = [...new Uint8Array(buf)] .map(b => b.toString(16).padStart(2, "0")) .join(""); if (hex !== snap.chainHash) { console.error(`FAIL at ${snap.date}`); return false; } } console.log(`PASS: ${snapshots.length} snapshots verified`); return true; } verifyChain("bhutrabali");

5. What the chain proves

No historical snapshot has been modified after recording
No snapshot has been inserted, deleted, or reordered
The raw API response at the time of ingestion is preserved exactly

The chain does not prove that the underlying exchange API returned accurate data, that the trader is who they claim to be, or that past performance will continue. See our full disclaimers.

6. Bitcoin attestation via OpenTimestamps

Each day, all entity chain heads across the registry are combined into a binary Merkle tree. The Merkle root is submitted to OpenTimestamps calendar servers, producing a cryptographic attestation that is independently verifiable against the Bitcoin network.

# How daily anchoring works: 1. Collect all chain heads (NAV, PERFORMANCE, AUDIT chain types) 2. Sort deterministically by entityId + chainType 3. Build binary Merkle tree (SHA-256) 4. Submit 32-byte root to OTS calendar server 5. After ~24h, proof upgrades with Bitcoin block height + tx ID # Verify an anchor for a specific date: GET https://nakedpnl.com/api/verify/YYYY-MM-DD # Returns: { merkleRoot, leafCount, otsProofBase64, # btcBlockHeight, btcTxId, status } # Independent CLI verification: # 1. Extract the proof from the API response: curl -s https://nakedpnl.com/api/verify/YYYY-MM-DD \ | python3 -c "import sys,json,base64; \ d=json.load(sys.stdin)['data']; \ open('anchor.ots','wb').write( \ base64.b64decode(d['otsProofBase64']))" # 2. Verify with the OTS CLI: ots verify anchor.ots

Attestations are independently verifiable using the OpenTimestamps CLI. The Merkle root cryptographically attests to the state of every entity chain in the registry at that point in time. Modifying any historical snapshot would change its chain head, which would change the Merkle root, which would no longer match the attestation anchored in a specific Bitcoin block.

7. On-chain reconciliation

For prediction market venues with on-chain settlement (Polymarket on Polygon), NakedPnL performs daily reconciliation between the venue REST API and the public subgraph. Position data from both sources is canonicalized, hashed, and compared. Mismatches are logged to an append-only reconciliation ledger and flagged for review.

On-chain trade history for Polymarket-connected traders is publicly viewable at /trader/<handle>/onchain, with direct links to transaction records on Polygonscan. This provides a second, independently verifiable data source for position history.