DEV Community

Cover image for Building Cryptographic Audit Trails for cTrader cBots - A Sidecar Approach

Building Cryptographic Audit Trails for cTrader cBots - A Sidecar Approach

πŸ“’ Update: We've published real evidence from live cTrader trading at github.com/veritaschain/vcp-ctrader-rta-reference. All hashes are cryptographically verifiable - run python verify.py yourself.

You've built a profitable cBot. Executions are solid. Your prop firm loves the results.

Then someone asks: "Can you prove this trade history is authentic?"

Your options today:

  1. Export MT4/cTrader statement β†’ "Here's a PDF"
  2. Show broker logs β†’ "Trust me, it's real"
  3. Screen recording β†’ "I definitely didn't edit this"

None of these are cryptographically verifiable.


What If Every Trade Had a Hash Chain?

Signal β†’ Order β†’ Execution β†’ Close
  β”‚        β”‚         β”‚         β”‚
  β–Ό        β–Ό         β–Ό         β–Ό
hash₁ ← hashβ‚‚ ← hash₃ ← hashβ‚„
        β”‚         β”‚         β”‚
        PrevHash  PrevHash  PrevHash
Enter fullscreen mode Exit fullscreen mode

Each event contains the hash of the previous event. Break the chain? Instantly detectable.

This is what VeritasChain Protocol (VCP) provides - and it runs as a sidecar alongside your cBot, not inside it.


The Sidecar Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    cTrader Desktop                       β”‚
β”‚                                                          β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚   β”‚                   Your cBot                       β”‚  β”‚
β”‚   β”‚   OnStart() β†’ OnTick() β†’ OnPositionClosed()      β”‚  β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                            β”‚                             β”‚
β”‚                            β”‚ Event Tap (async)           β”‚
β”‚                            β–Ό                             β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚   β”‚              VCP Evidence Pack                    β”‚  β”‚
β”‚   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚  β”‚
β”‚   β”‚  β”‚ Events  β”‚β†’ β”‚ Merkle  β”‚β†’ β”‚ External Anchor β”‚   β”‚  β”‚
β”‚   β”‚  β”‚Generatorβ”‚  β”‚  Tree   β”‚  β”‚  (24h batches)  β”‚   β”‚  β”‚
β”‚   β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚  β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                            β”‚                             β”‚
β”‚                            β–Ό                             β”‚
β”‚              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                β”‚
β”‚              β”‚  Tamper-Evident Logs    β”‚                β”‚
β”‚              β”‚  (JSONL + Merkle Root)  β”‚                β”‚
β”‚              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Key: Your trading logic is unchanged. Zero latency impact.
Enter fullscreen mode Exit fullscreen mode

The sidecar:

  • Collects events asynchronously (non-blocking)
  • Hashes each event with SHA-256
  • Chains events via PrevHash linkage
  • Batches into Merkle trees (RFC 6962)
  • Anchors every 24 hours (Silver Tier)

Show Me The Code

1. Basic Setup

using VCP.CTrader;

public class MyTradingBot : Robot
{
    private VCPEvidencePack _vcp;

    protected override void OnStart()
    {
        // Configure VCP sidecar
        var config = new VCPEvidencePackConfig
        {
            EventConfig = new VCPEventGeneratorConfig
            {
                PolicyID = "com.yourcompany:momentum-bot-v2",
                Issuer = "Your Trading Firm",
                AlgorithmName = "Momentum Strategy",
                AlgorithmVersion = "2.1.0",
                ConformanceTier = ConformanceTier.SILVER
            },
            AutoAnchorEnabled = true,
            BatchSize = 50
        };

        _vcp = new VCPEvidencePack(config);
        _vcp.InitializeAsync().Wait();
    }
}
Enter fullscreen mode Exit fullscreen mode

That's it. VCP is now running alongside your cBot.


2. Recording Trading Events

Every trading decision gets logged with cryptographic proof:

// Signal detected
await _vcp.RecordSignalAsync(
    symbol: Symbol.Name,
    side: "BUY",
    price: Symbol.Ask,
    confidence: 0.87,
    reason: "RSI oversold + MACD crossover"
);

// Order submitted
await _vcp.RecordOrderAsync(
    symbol: Symbol.Name,
    orderId: "ORD-001",
    side: "BUY",
    volume: 10000,
    price: Symbol.Ask,
    stopLoss: Symbol.Ask - 30 * Symbol.PipSize,
    takeProfit: Symbol.Ask + 60 * Symbol.PipSize
);

// Execution
await _vcp.RecordExecutionAsync(
    symbol: Symbol.Name,
    orderId: "ORD-001",
    positionId: position.Id.ToString(),
    side: "BUY",
    volume: position.VolumeInUnits,
    price: position.EntryPrice
);
Enter fullscreen mode Exit fullscreen mode

3. Hook Into cBot Lifecycle

protected override void OnPositionsOpened(PositionOpenedEventArgs args)
{
    var pos = args.Position;

    // Record execution
    _vcp.RecordExecutionAsync(
        symbol: pos.SymbolName,
        orderId: pos.Label,
        positionId: pos.Id.ToString(),
        side: pos.TradeType.ToString(),
        volume: pos.VolumeInUnits,
        price: pos.EntryPrice
    ).Wait();
}

protected override void OnPositionsClosed(PositionClosedEventArgs args)
{
    var pos = args.Position;

    // Record close with P&L
    _vcp.RecordCloseAsync(
        symbol: pos.SymbolName,
        orderId: pos.Label,
        positionId: pos.Id.ToString(),
        side: pos.TradeType == TradeType.Buy ? "SELL" : "BUY",
        volume: pos.VolumeInUnits,
        entryPrice: pos.EntryPrice,
        closePrice: pos.CurrentPrice,
        profit: pos.NetProfit
    ).Wait();
}

protected override void OnStop()
{
    // Final anchor before shutdown
    _vcp.AnchorNowAsync().Wait();
    _vcp.ExportVerificationPackageAsync("audit_export").Wait();
    _vcp.Dispose();
}
Enter fullscreen mode Exit fullscreen mode

What Gets Recorded

Each VCP event looks like this:

{
  "Header": {
    "Version": "1.1",
    "EventID": "019b80d5-1412-73eb-b4ca-f29e4721d9af",
    "EventType": "EXE",
    "TimestampISO": "2025-01-02T08:15:24.000000Z",
    "TimestampInt": 1735805724000000,
    "HashAlgo": "SHA256",
    "PrevHash": "3d39a2150c760b4497e740bca52df874c5b62f356d9ead7146f8bf8954871579",
    "EventHash": "810a200ba0e4f67fede77ca5283b6597461f5150ee4c5e370db0e2b7627349f1",
    "ClockSyncStatus": "BEST_EFFORT",
    "TimestampPrecision": "MILLISECOND"
  },
  "Trade": {
    "Symbol": "USDJPY",
    "OrderID": "ORD-001",
    "PositionID": "POS-001",
    "Side": "BUY",
    "Volume": 10000,
    "Price": 150.125,
    "Commission": 0.50,
    "Slippage": 0.002
  }
}
Enter fullscreen mode Exit fullscreen mode

The PrevHash creates an unbreakable chain. Modify one event? Every subsequent hash becomes invalid.


Merkle Trees for Efficient Verification

VCP batches events into Merkle trees (RFC 6962):

                    Root Hash
                   β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β”
               Hash(A+B)   Hash(C+D)
               β”Œβ”€β”€β”΄β”€β”€β”     β”Œβ”€β”€β”΄β”€β”€β”
             Hash(A) Hash(B) Hash(C) Hash(D)
               β”‚       β”‚       β”‚       β”‚
             Event₁  Eventβ‚‚  Event₃  Eventβ‚„
Enter fullscreen mode Exit fullscreen mode

Benefits:

  • Efficient proof: Prove one event exists without revealing all others
  • Batch anchoring: One root hash covers thousands of events
  • Tamper detection: Any modification invalidates the root

Verification Without Trust

The killer feature: anyone can verify your audit trail independently.

cd evidence/sample_pack_2025Q1
python verify.py
Enter fullscreen mode Exit fullscreen mode

Output:

============================================================
VCP Evidence Pack Verification Report
============================================================
Event Hash Verification (SHA-256):
  βœ“ All 21 event hashes cryptographically verified

Hash Chain Verification:
  βœ“ Hash chain continuity verified

Merkle Root Verification (Tree Reconstruction):
  βœ“ Merkle root: 584bad478f76c56a61df64cfd9d421e4...

============================================================
Overall: βœ“ CRYPTOGRAPHICALLY VERIFIED
============================================================
Enter fullscreen mode Exit fullscreen mode

The auditor doesn't need to trust you. They run the verification themselves.


Real Evidence From Live Trading (Now on GitHub)

We've just published a complete reference implementation with real evidence generated from a live cTrader environment:

πŸ”— github.com/veritaschain/vcp-ctrader-rta-reference

This isn't synthetic test data. The evidence pack contains:

  • 21 real trading events from actual cTrader executions
  • Cryptographically verifiable hashes (run verify.py yourself)
  • Complete order lifecycle: Signal β†’ Order β†’ Execution β†’ Close
  • Error handling examples: Connection loss, recovery, rejections

Personal identifiers are masked for privacy, but the cryptographic proofs are 100% real.

Hash examples from actual executions:

Event Real SHA-256 Hash
INIT 66d55677398ac180177dc7599ddba05f5b0084e0b9b8227f6078acf9fd14f993
EXE 810a200ba0e4f67fede77ca5283b6597461f5150ee4c5e370db0e2b7627349f1
Merkle Root 584bad478f76c56a61df64cfd9d421e46e6ad407b5081094ffc1068aba8aa1a3

These are real SHA-256 hashes computed from actual trading data - not placeholders.


Compliance Tiers

VCP defines three tiers. cTrader bots typically target Silver:

Requirement Silver (Retail) Gold (Prop) Platinum (HFT)
Time Sync BEST_EFFORT NTP (1ms) PTP (100ΞΌs)
Anchor Frequency 24 hours 1 hour 10 minutes
Serialization JSON JSON SBE
Throughput >1K evt/s >10K evt/s >100K evt/s

Why Not Modify cTrader Directly?

The sidecar approach has key advantages:

  1. Zero latency impact: Async logging, non-blocking
  2. No cTrader modification: Works with any cBot
  3. Portable: Same VCP library works with MT4, MT5, FIX
  4. Upgradable: Update VCP without touching trading logic
  5. Auditable separation: Auditors verify the sidecar output, not your cBot code

External Anchoring Options

For higher assurance, VCP supports external timestamping:

var config = new VCPAnchorConfig
{
    PrimaryTarget = AnchorTargetType.OPENTIMESTAMPS,  // Bitcoin
    FallbackTarget = AnchorTargetType.FREE_TSA,       // RFC 3161
    AnchorIntervalHours = 24
};
Enter fullscreen mode Exit fullscreen mode
Target What It Proves
LOCAL_FILE Hash existed at creation time
OpenTimestamps Hash existed before Bitcoin block N
FreeTSA RFC 3161 timestamp authority signature

Regulatory Alignment

Regulation Requirement How VCP Helps
MiFID II RTS 25 Clock synchronization ClockSyncStatus field
MiFID II RTS 6 Algo decision records SIG→ORD→EXE chain
EU AI Act Art. 12 Automatic logging Hash chain completeness
SEC 17a-4 Tamper-evident records Merkle trees + anchoring

The EU AI Act deadline for high-risk AI (August 2027) likely includes algo trading systems. Getting audit infrastructure in place now avoids a scramble later.


Getting Started

Option 1: Clone the Live Evidence Repository

git clone https://github.com/veritaschain/vcp-ctrader-rta-reference.git
cd vcp-ctrader-rta-reference

# Verify the real evidence pack
cd evidence/sample_pack_2025Q1
python verify.py
Enter fullscreen mode Exit fullscreen mode

You'll see cryptographic verification of actual trading data.

Option 2: Integrate Into Your cBot

Copy src/VCP.CTrader.RTA/ into your cBot solution and follow the integration pattern in SampleVCPBot.cs.

Option 3: Review the Architecture

Check docs/ARCHITECTURE.md for detailed component diagrams and data flow.


The Full Specification

Everything here implements an open standard:

No vendor lock-in. No proprietary formats.


TL;DR

Question Answer
What Cryptographic audit trail for cTrader cBots
How SHA-256 hash chains + Merkle trees + external anchoring
Impact on cBot Zero. Async sidecar process.
Verification Anyone can verify without trusting you
Time to integrate ~30 minutes for basic setup
Live evidence github.com/veritaschain/vcp-ctrader-rta-reference

The next time someone asks "can you prove these trades are real?", your answer isn't "trust me" - it's python verify.py.


Questions?

Building algo trading systems on cTrader? I'd love to hear what audit challenges you're facing. Comment below. πŸ‘‡


Disclaimer: This is a reference implementation for educational purposes. No endorsement or regulatory approval is implied.

Top comments (0)