"Verify, Don't Trust." — This principle drives the VeritasChain Protocol (VCP), an open standard for creating tamper-evident audit trails in algorithmic trading systems.
Today, I'm excited to announce the release of vcp-tradingview-rta-reference — a complete reference implementation demonstrating how to integrate VCP v1.1 with TradingView's Pine Script environment.
The Problem: Black Box Trading
When you run an algorithmic trading strategy, how do you prove:
- What decisions your algorithm actually made?
- That your trade logs haven't been modified after the fact?
- That no events were deleted or inserted?
Traditional logging is insufficient. Logs can be edited, timestamps can be forged, and there's no cryptographic guarantee of integrity. This matters for:
- Prop trading firms evaluating trader performance
- Regulatory compliance (MiFID II, EU AI Act)
- Dispute resolution between traders and brokers
- Algorithm auditing and backtesting validation
The Solution: VCP's Three-Layer Architecture
VCP v1.1 implements a three-layer integrity architecture:
┌─────────────────────────────────────────────────┐
│ Layer 3: External Verifiability │
│ ├─ OpenTimestamps / Bitcoin anchoring │
│ └─ RFC 3161 Timestamp Authority │
├─────────────────────────────────────────────────┤
│ Layer 2: Collection Integrity │
│ ├─ RFC 6962 Merkle Tree │
│ └─ Append-only log structure │
├─────────────────────────────────────────────────┤
│ Layer 1: Event Integrity │
│ ├─ SHA-256 content hash │
│ ├─ Ed25519 digital signature │
│ └─ RFC 8785 canonical JSON (JCS) │
└─────────────────────────────────────────────────┘
Each layer provides specific guarantees:
- Event Integrity: Individual events cannot be modified without detection
- Collection Integrity: Events cannot be deleted or reordered
- External Verifiability: Timestamps are anchored to external systems (Bitcoin, TSA)
Architecture: The Sidecar Pattern
Since TradingView runs in a sandboxed environment, we use a sidecar architecture:
┌─────────────────────────────────────────────────────────────────┐
│ TradingView │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Pine Script Strategy (vcp_silver_strategy.pine) │ │
│ │ - Event capture (Entry/Exit/Position Change) │ │
│ │ - VCP-compliant JSON payload generation │ │
│ └──────────────────────┬───────────────────────────────┘ │
└─────────────────────────┼───────────────────────────────────────┘
│ Webhook (HTTPS POST)
▼
┌─────────────────────────────────────────────────────────────────┐
│ VCP Sidecar (Python FastAPI) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────┐ │
│ │ Webhook │→ │ Canonical │→ │ Merkle Tree │→ │ Anchor │ │
│ │ Receiver │ │ Transform │ │ Builder │ │ Service │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Ed25519 │ │
│ │ Signature │ │
│ └─────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Implementation Deep Dive
1. Pine Script: Generating VCP Events
The Pine Script strategy captures trading events and formats them as VCP-compliant JSON:
//@version=5
strategy("VCP Silver Tier Strategy", overlay=true)
// VCP Configuration
vcpEnabled = input.bool(true, "Enable VCP Logging")
vcpSystemId = input.string("TV-STRATEGY-001", "System ID")
vcpAccountId = input.string("DEMO-ACCOUNT", "Account ID")
// Generate VCP event payload
vcpOrderNewPayload(orderId, side, qty, price) =>
str.format(
'{{' +
'"vcp_version":"1.1",' +
'"event_id":"{0}",' +
'"timestamp":"{1}",' +
'"event_type":"ORDER_NEW",' +
'"tier":"SILVER",' +
'"policy_id":"urn:vso:policy:tv-retail:v1",' +
'"clock_sync":"BEST_EFFORT",' +
'"system_id":"{2}",' +
'"account_id":"{3}",' +
'"payload":{{' +
'"order_id":"{4}",' +
'"symbol":"{5}",' +
'"side":"{6}",' +
'"quantity":{7},' +
'"price":{8}' +
'}}' +
'}}',
vcpEventId(), vcpTimestamp(),
vcpSystemId, vcpAccountId,
orderId, syminfo.tickerid, side, qty, price)
// Send via webhook on entry
if longCondition
alert(vcpOrderNewPayload("ORD-001", "BUY", 1.0, close),
alert.freq_once_per_bar)
2. Python Sidecar: Canonical Transformation
The sidecar receives webhooks and applies RFC 8785 canonical JSON transformation:
@dataclass
class VCPEvent:
event_id: str
timestamp: str
event_type: str
tier: str
policy_id: str
clock_sync: str
system_id: str
account_id: str
payload: Dict[str, Any]
vcp_version: str = "1.1"
def to_canonical_json(self) -> str:
"""RFC 8785 (JCS) canonical JSON serialization."""
canonical = {
"account_id": self.account_id,
"clock_sync": self.clock_sync,
"event_id": self.event_id,
"event_type": self.event_type,
"payload": self._sort_dict(self.payload),
"policy_id": self.policy_id,
"system_id": self.system_id,
"tier": self.tier,
"timestamp": self.timestamp,
"vcp_version": self.vcp_version,
}
return json.dumps(canonical, sort_keys=True,
separators=(',', ':'), ensure_ascii=True)
Why canonical JSON? Because the same data must always produce the same hash. Without canonicalization, {"a":1,"b":2} and {"b":2,"a":1} would produce different hashes despite being semantically identical.
3. Ed25519 Signing
We use Ed25519 for digital signatures — it's fast, secure, and produces compact 64-byte signatures:
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
class VCPSigner:
def __init__(self, private_key: Ed25519PrivateKey):
self._private_key = private_key
def sign(self, message: bytes) -> bytes:
"""Sign message with Ed25519."""
return self._private_key.sign(message)
def verify(self, message: bytes, signature: bytes) -> bool:
"""Verify Ed25519 signature."""
try:
self._private_key.public_key().verify(signature, message)
return True
except Exception:
return False
4. RFC 6962 Merkle Tree
The Merkle tree provides collection integrity with efficient inclusion proofs:
class MerkleTree:
LEAF_PREFIX = b'\x00' # Domain separation
INTERNAL_PREFIX = b'\x01'
def _leaf_hash(self, data: bytes) -> bytes:
"""RFC 6962: H(0x00 || data)"""
return hashlib.sha256(self.LEAF_PREFIX + data).digest()
def _internal_hash(self, left: bytes, right: bytes) -> bytes:
"""RFC 6962: H(0x01 || left || right)"""
return hashlib.sha256(self.INTERNAL_PREFIX + left + right).digest()
def add_leaf(self, data_hash: bytes) -> int:
"""Add leaf and return index."""
leaf_hash = self._leaf_hash(data_hash)
self._leaves.append(leaf_hash)
return len(self._leaves) - 1
@classmethod
def verify_proof(cls, data_hash: bytes, proof: List[Tuple[str, bytes]],
expected_root: bytes) -> bool:
"""Verify Merkle inclusion proof."""
current = hashlib.sha256(cls.LEAF_PREFIX + data_hash).digest()
for position, sibling_hash in proof:
if position == 'left':
current = hashlib.sha256(
cls.INTERNAL_PREFIX + sibling_hash + current).digest()
else:
current = hashlib.sha256(
cls.INTERNAL_PREFIX + current + sibling_hash).digest()
return current == expected_root
The domain separation prefixes (0x00 for leaves, 0x01 for internal nodes) prevent second-preimage attacks.
5. FastAPI Webhook Endpoint
The sidecar exposes a simple REST API:
@app.post("/vcp/event")
async def receive_event(webhook: TradingViewWebhook):
# 1. Create VCP event
vcp_event = VCPEvent(
event_id=webhook.event_id,
timestamp=webhook.timestamp,
event_type=webhook.event_type,
# ... other fields
)
# 2. Canonical transformation and hash
canonical_json = vcp_event.to_canonical_json()
event_hash = hashlib.sha256(canonical_json.encode()).digest()
# 3. Sign
signature = signer.sign(event_hash)
# 4. Add to Merkle tree
merkle_index = merkle_tree.add_leaf(event_hash)
return {
"event_id": webhook.event_id,
"event_hash": event_hash.hex(),
"signature": signature.hex(),
"merkle_index": merkle_index
}
Tamper Detection in Action
The beauty of VCP is that any tampering is immediately detectable. Here's a test from our verification suite:
def test_modification_detection():
"""Modify an event and verify detection."""
# Load events
events = load_events("vcp_tv_events.jsonl")
# Tamper with event #5
events[5]["payload"]["quantity"] = 999 # Changed!
# Verify
for event in events:
computed_hash = compute_hash(event)
stored_hash = event["event_hash"]
if computed_hash != stored_hash:
print(f"[DETECTED] Tampering at {event['event_id']}")
# Hash mismatch proves modification!
Output:
[DETECTED] Event TV-20250115102500-0005: Hash mismatch
Computed: c44fcae94fa8cde0fd15df90e43e5d7b...
Stored: 71619cea5031b6aab37e704db7411324...
Quick Start
# Clone
git clone https://github.com/veritaschain/vcp-tradingview-rta-reference.git
cd vcp-tradingview-rta-reference
# Install
pip install -r requirements.txt
# Generate keys
python -m sidecar.keygen
# Run server
python -m sidecar.main
# Verify evidence pack
python tools/verifier/vcp_verifier.py \
evidence/01_trade_logs/vcp_tv_events.jsonl \
-s evidence/04_anchor/security_object.json
VCP Compliance Tiers
VCP defines three compliance tiers for different use cases:
| Tier | Clock Sync | Anchor Interval | Use Case |
|---|---|---|---|
| Silver | Best-effort | 24 hours | Retail, MT4/MT5, TradingView |
| Gold | NTP synced | 1 hour | Prop firms, institutions |
| Platinum | PTP locked | 10 minutes | HFT, exchanges |
This reference implementation targets Silver Tier, making it accessible to individual traders while still providing cryptographic guarantees.
What's Next?
This is just the beginning. The VCP ecosystem is expanding:
- VCP Explorer: Web-based verification tool
- MT4/MT5 Bridge: Native MQL integration
- FIX Protocol Sidecar: Institutional trading support
- IETF Standardization: draft-kamimura-scitt-vcp
Get Involved
VCP is developed by the VeritasChain Standards Organization (VSO), a vendor-neutral standards body.
- GitHub: veritaschain/vcp-tradingview-rta-reference
- Spec: VCP v1.1 Specification
- Contact: info@veritaschain.org
We welcome contributions, feedback, and early adopter partnerships.
"AI needs a Flight Recorder." — The algorithmic trading industry is changing. Cryptographic audit trails aren't just nice-to-have; they're becoming essential for compliance, trust, and accountability. VCP provides the open standard to make this a reality.
Star the repo if you find this useful! ⭐
Tags: #opensource #python #trading #cryptography #fintech #audit #compliance
Top comments (0)