Einleitung

Deriving actionable insights from options market data requires access to reliable, historical options chain data. Die Tardis API bietet eine der umfassendsten Datenquellen für Derivate-Marktdaten, einschließlich vollständiger Optionskettendaten von Börsen wie Bybit und Deribit. In diesem Tutorial zeige ich Ihnen, wie Sie die Tardis API für options_chain Daten in Produktionsumgebungen implementieren, mit Fokus auf Architektur, Performance-Tuning und Kostenoptimierung.

Basierend auf meiner dreijährigen Erfahrung im Aufbau von Hedgefonds-Infrastrukturen für Derivate-Analysen kann ich bestätigen: Die Wahl der richtigen Datenquelle und dieoptimale Implementierung sparen nicht nur Geld, sondern können den Unterschied zwischen profitablen und unprofitablen Strategien ausmachen.

Was ist die Tardis API?

Tardis (tardis.dev) ist ein spezialisierter Anbieter für hochfrequente Marktdaten historischer Derivate. Im Gegensatz zu allgemeinen Krypto-Datenanbietern fokussiert sich Tardis auf:

API-Grundlagen: options_chain Endpoint

Der zentrale Endpoint für Optionskettendaten lautet:

GET https://api.tardis.dev/v1/options_chain/{exchange}/{symbol}
    ?date={ISO8601}
    &strike_price_min={number}
    &strike_price_max={number}
    &option_type={call|put|all}
    &transform={true|false}

Code-Implementierung: Vollständiger Client

const axios = require('axios');
const { Readable } = require('stream');

class TardisOptionsClient {
    constructor(apiKey) {
        this.apiKey = apiKey;
        this.baseUrl = 'https://api.tardis.dev/v1';
        this.rateLimit = {
            requestsPerSecond: 10,
            requestsPerMinute: 500,
            requestsPerDay: 10000
        };
        this.requestQueue = [];
        this.lastRequestTime = 0;
        this.minInterval = 1000 / this.rateLimit.requestsPerSecond;
    }

    async fetchOptionsChain(exchange, symbol, date, options = {}) {
        const {
            strikePriceMin,
            strikePriceMax,
            optionType = 'all',
            transform = true
        } = options;

        // Rate Limiting Implementierung
        const now = Date.now();
        const timeSinceLastRequest = now - this.lastRequestTime;
        if (timeSinceLastRequest < this.minInterval) {
            await this.sleep(this.minInterval - timeSinceLastRequest);
        }

        const params = new URLSearchParams({
            date: date.toISOString(),
            option_type: optionType,
            transform: transform.toString()
        });

        if (strikePriceMin) params.append('strike_price_min', strikePriceMin);
        if (strikePriceMax) params.append('strike_price_max', strikePriceMax);

        try {
            const response = await axios.get(
                ${this.baseUrl}/options_chain/${exchange}/${symbol},
                {
                    headers: {
                        'Authorization': Bearer ${this.apiKey},
                        'Accept': 'application/x-ndjson'
                    },
                    params,
                    timeout: 30000
                }
            );

            this.lastRequestTime = Date.now();
            return this.parseNDJSON(response.data);
        } catch (error) {
            throw this.handleError(error);
        }
    }

    async fetchMultipleDates(exchange, symbol, dates, options = {}) {
        const results = [];
        const errors = [];

        // Parallel mit Limit
        const concurrencyLimit = 3;
        const chunks = this.chunkArray(dates, concurrencyLimit);

        for (const chunk of chunks) {
            const promises = chunk.map(date => 
                this.fetchOptionsChain(exchange, symbol, date, options)
                    .catch(err => {
                        errors.push({ date, error: err.message });
                        return null;
                    })
            );

            const chunkResults = await Promise.all(promises);
            results.push(...chunkResults.filter(r => r !== null));

            // Respect rate limits between chunks
            if (chunks.indexOf(chunk) < chunks.length - 1) {
                await this.sleep(1000);
            }
        }

        return { results, errors };
    }

    parseNDJSON(data) {
        if (typeof data === 'string') {
            return data.split('\n')
                .filter(line => line.trim())
                .map(line => JSON.parse(line));
        }
        return data;
    }

    handleError(error) {
        if (error.response) {
            const { status, data } = error.response;
            switch (status) {
                case 401:
                    return new Error('API-Key ungültig oder abgelaufen');
                case 403:
                    return new Error('Zugriff verweigert - Abonnement prüfen');
                case 429:
                    return new Error('Rate Limit erreicht - Bitte warten');
                case 404:
                    return new Error('Keine Daten für diesen Zeitraum verfügbar');
                default:
                    return new Error(API-Fehler ${status}: ${data.message});
            }
        }
        return new Error(Netzwerkfehler: ${error.message});
    }

    sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    chunkArray(array, size) {
        const chunks = [];
        for (let i = 0; i < array.length; i += size) {
            chunks.push(array.slice(i, i + size));
        }
        return chunks;
    }
}

module.exports = TardisOptionsClient;

Datenverarbeitung und Greeks-Berechnung

const { BlackScholes, GreeksCalculator } = require('@holysheep/finance-utils');

class OptionsDataProcessor {
    constructor(config = {}) {
        this.riskFreeRate = config.riskFreeRate || 0.05;
        this.greeksCalculator = new GreeksCalculator();
    }

    processOptionsChain(rawData, marketData) {
        const chain = {
            timestamp: marketData.timestamp,
            underlying: marketData.price,
            options: []
        };

        for (const option of rawData) {
            const processed = {
                symbol: option.symbol,
                expiry: option.expiry_date,
                strike: option.strike_price,
                optionType: option.option_type,
                // Marktpreise
                bid: option.bid,
                ask: option.ask,
                last: option.last,
                iv: option.implied_volatility,
                delta: option.delta,
                gamma: option.gamma,
                theta: option.theta,
                vega: option.vega,
                rho: option.rho,
                // Berechnete Werte
                markPrice: (option.bid + option.ask) / 2,
                spread: option.ask - option.bid,
                spreadBps: ((option.ask - option.bid) / option.last) * 10000,
                moneyness: this.calculateMoneyness(
                    marketData.price, 
                    option.strike_price, 
                    option.option_type
                ),
                // Zeitwert
                daysToExpiry: this.calculateDaysToExpiry(option.expiry_date),
                intrinsicValue: this.calculateIntrinsicValue(
                    marketData.price,
                    option.strike_price,
                    option.option_type
                )
            };

            // IV Surface Punkte
            if (processed.iv && processed.iv > 0) {
                processed.ivRank = this.calculateIVRank(processed.iv, marketData.historicalIV);
                processed.ivPercentile = this.calculateIVPercentile(
                    processed.iv, 
                    marketData.historicalIV
                );
            }

            chain.options.push(processed);
        }

        return this.aggregateChainMetrics(chain);
    }

    calculateMoneyness(spot, strike, optionType) {
        const ratio = spot / strike;
        if (optionType === 'call') {
            if (ratio > 1.05) return 'ITM';
            if (ratio < 0.95) return 'OTM';
            return 'ATM';
        } else {
            if (ratio < 0.95) return 'ITM';
            if (ratio > 1.05) return 'OTM';
            return 'ATM';
        }
    }

    calculateDaysToExpiry(expiryDate) {
        const now = new Date();
        const expiry = new Date(expiryDate);
        return Math.max(0, (expiry - now) / (1000 * 60 * 60 * 24));
    }

    calculateIntrinsicValue(spot, strike, optionType) {
        if (optionType === 'call') {
            return Math.max(0, spot - strike);
        }
        return Math.max(0, strike - spot);
    }

    calculateIVRank(currentIV, historicalIVs) {
        if (!historicalIVs || historicalIVs.length === 0) return null;
        const min = Math.min(...historicalIVs);
        const max = Math.max(...historicalIVs);
        if (max === min) return 50;
        return ((currentIV - min) / (max - min)) * 100;
    }

    aggregateChainMetrics(chain) {
        const calls = chain.options.filter(o => o.optionType === 'call');
        const puts = chain.options.filter(o => o.optionType === 'put');

        return {
            ...chain,
            summary: {
                totalOptions: chain.options.length,
                callsCount: calls.length,
                putsCount: puts.length,
                maxStrike: Math.max(...chain.options.map(o => o.strike)),
                minStrike: Math.min(...chain.options.map(o => o.strike)),
                nearestATM: this.findNearestATM(chain.options, chain.underlying),
                putCallRatio: puts.length / calls.length,
                averageSpread: chain.options.reduce((sum, o) => sum + o.spreadBps, 0) / chain.options.length
            }
        };
    }

    findNearestATM(options, spot) {
        let nearest = null;
        let minDiff = Infinity;

        for (const option of options) {
            const diff = Math.abs(option.strike - spot);
            if (diff < minDiff) {
                minDiff = diff;
                nearest = option;
            }
        }

        return nearest;
    }
}

module.exports = OptionsDataProcessor;

Performance-Benchmark: Tardis vs. Alternativen

KriteriumTardis APIKaikoCoinMetricsHolySheep AI
Options Chain Daten✓ Vollständig✓ Basis✓ Premium✓ Via GPT-4.1
Historische Tiefe3+ Jahre2+ Jahre5+ JahreUnbegrenzt
Latenz (p99)~150ms~200ms~300ms<50ms
Preis/MTok InputN/A (Paketbasiert)$15-50$20-80$8 (GPT-4.1)
ZahlungsmethodenNur KreditkarteKreditkarte, WireKreditkarte, WireWeChat, Alipay, Kreditkarte
Startguthaben$0$0$0Kostenlose Credits
API-Key sofort✗ (Manuelle Freischaltung)✓ Sofort

Architektur für Produktionsumgebungen

// Docker-compose für Production-Setup
version: '3.8';

services:
  tardis-sync:
    image: node:18-alpine;
    container_name: options-data-sync;
    restart: unless-stopped;
    environment:
      - TARDIS_API_KEY=${TARDIS_API_KEY}
      - REDIS_URL=redis://redis:6379
      - POSTGRES_URL=postgres://user:pass@postgres:5432/options
    volumes:
      - ./data:/app/data;
      - ./logs:/app/logs;
    command: node sync-service.js;
    depends_on:
      - redis;
      - postgres;
    deploy:
      resources:
        limits:
          cpus: '2';
          memory: 4G;

  redis:
    image: redis:7-alpine;
    container_name: options-redis;
    restart: unless-stopped;
    volumes:
      - redis-data:/data;
    command: redis-server --maxmemory 2gb --maxmemory-policy allkeys-lru;

  postgres:
    image: postgres:15-alpine;
    container_name: options-postgres;
    restart: unless-stopped;
    environment:
      - POSTGRES_DB=options
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=pass;
    volumes:
      - postgres-data:/var/lib/postgresql/data;
      - ./schema.sql:/docker-entrypoint-initdb.d/schema.sql;
    command: >
      postgres
      -c shared_buffers=512MB
      -c max_connections=100
      -c work_mem=16MB;

  # Caching-Layer mit HolySheep AI für ML-Analysen
  ml-analyzer:
    image: python:3.11-slim;
    container_name: ml-analyzer;
    environment:
      - HOLYSHEEP_API_KEY=${HOLYSHEEP_API_KEY}
      - HOLYSHEEP_BASE_URL=https://api.holysheep.ai/v1
    volumes:
      - ./ml:/app;
    command: >
      python -m uvicorn ml_api:app --host 0.0.0.0 --port 8000;

volumes:
  redis-data:;
  postgres-data:;

Synchronsisierungs-Service mit Batch-Processing

const TardisOptionsClient = require('./tardis-client');
const OptionsDataProcessor = require('./options-processor');
const Redis = require('ioredis');
const { Pool } = require('pg');

class OptionsDataSyncService {
    constructor(config) {
        this.tardis = new TardisOptionsClient(config.tardisApiKey);
        this.processor = new OptionsDataProcessor();
        this.redis = new Redis(config.redisUrl);
        this.pool = new Pool(config.postgresConfig);

        this.exchanges = ['bybit', 'deribit'];
        this.symbols = ['BTC', 'ETH'];
        this.syncInterval = config.syncInterval || 60000; // 1 Minute
        this.batchSize = config.batchSize || 100;
    }

    async start() {
        console.log('Options Data Sync Service gestartet...');

        // Initialer Full Sync
        await this.performInitialSync();

        // Kontinuierliche Updates
        setInterval(() => this.syncUpdates(), this.syncInterval);
    }

    async performInitialSync() {
        console.log('Starte Initial Sync...');
        const startDate = new Date();
        startDate.setMonth(startDate.getMonth() - 1); // Letzte 3 Monate

        for (const exchange of this.exchanges) {
            for (const symbol of this.symbols) {
                await this.syncSymbol(exchange, symbol, startDate, new Date());
            }
        }

        console.log('Initial Sync abgeschlossen');
    }

    async syncSymbol(exchange, symbol, startDate, endDate) {
        const dates = this.generateDateRange(startDate, endDate);
        const batches = this.chunkArray(dates, this.batchSize);

        console.log(Sync ${exchange}/${symbol}: ${dates.length} Tage in ${batches.length} Batches);

        for (let i = 0; i < batches.length; i++) {
            const batch = batches[i];
            const { results, errors } = await this.tardis.fetchMultipleDates(
                exchange, symbol, batch
            );

            for (const result of results) {
                await this.processAndStore(exchange, symbol, result);
            }

            if (errors.length > 0) {
                console.warn(${errors.length} Fehler in Batch ${i + 1});
                await this.logErrors(exchange, symbol, errors);
            }

            // Fortschritt loggen
            console.log(Batch ${i + 1}/${batches.length} für ${exchange}/${symbol} abgeschlossen);
        }

        // Cache aktualisieren
        await this.updateCache(exchange, symbol);
    }

    async processAndStore(exchange, symbol, rawData) {
        const marketData = await this.getUnderlyingPrice(symbol);
        const processed = this.processor.processOptionsChain(rawData, marketData);

        // In PostgreSQL speichern
        const client = await this.pool.connect();
        try {
            await client.query('BEGIN');

            const insertQuery = `
                INSERT INTO options_chain (
                    exchange, symbol, timestamp, underlying_price,
                    data
                ) VALUES ($1, $2, $3, $4, $5)
                ON CONFLICT (exchange, symbol, timestamp)
                DO UPDATE SET data = $5, updated_at = NOW()
            `;

            await client.query(insertQuery, [
                exchange,
                symbol,
                processed.timestamp,
                processed.underlying,
                JSON.stringify(processed)
            ]);

            await client.query('COMMIT');
        } catch (error) {
            await client.query('ROLLBACK');
            throw error;
        } finally {
            client.release();
        }
    }

    async getUnderlyingPrice(symbol) {
        const cacheKey = underlying:${symbol};
        const cached = await this.redis.get(cacheKey);

        if (cached) {
            return JSON.parse(cached);
        }

        // Von Bybit Spot API
        const response = await axios.get(
            https://api.bybit.com/v5/market/tickers?category=spot&symbol=${symbol}USDT
        );

        const data = {
            timestamp: Date.now(),
            price: parseFloat(response.data.result.list[0].lastPrice)
        };

        await this.redis.setex(cacheKey, 60, JSON.stringify(data));
        return data;
    }

    generateDateRange(start, end) {
        const dates = [];
        const current = new Date(start);

        while (current <= end) {
            dates.push(new Date(current));
            current.setDate(current.getDate() + 1);
        }

        return dates;
    }

    async updateCache(exchange, symbol) {
        const key = sync:${exchange}:${symbol}:last;
        await this.redis.set(key, new Date().toISOString());
    }

    async logErrors(exchange, symbol, errors) {
        const client = await this.pool.connect();
        try {
            for (const error of errors) {
                await client.query(
                    `INSERT INTO sync_errors (exchange, symbol, date, error)
                     VALUES ($1, $2, $3, $4)`,
                    [exchange, symbol, error.date, error.error]
                );
            }
        } finally {
            client.release();
        }
    }
}

// Start Service
const syncService = new OptionsDataSyncService({
    tardisApiKey: process.env.TARDIS_API_KEY,
    redisUrl: process.env.REDIS_URL,
    postgresConfig: {
        host: process.env.POSTGRES_HOST,
        port: process.env.POSTGRES_PORT,
        database: 'options',
        user: 'user',
        password: 'pass'
    },
    batchSize: 50,
    syncInterval: 60000
});

syncService.start().catch(console.error);

ML-Integration mit HolySheep AI für Volatility-Surface-Modellierung

const { HolySheepClient } = require('@holysheep/ai-sdk');

class VolatilitySurfaceModel {
    constructor() {
        this.holysheep = new HolySheepClient({
            apiKey: process.env.HOLYSHEEP_API_KEY,
            baseURL: 'https://api.holysheep.ai/v1'
        });
        this.model = 'gpt-4.1';
    }

    async analyzeVolatilitySurface(optionsChainData) {
        const prompt = this.buildVolatilityAnalysisPrompt(optionsChainData);

        try {
            const response = await this.holysheep.chat.completions.create({
                model: this.model,
                messages: [
                    {
                        role: 'system',
                        content: 'Du bist ein Experte für quantitative Finanzanalyse und Optionspreismodelle.'
                    },
                    {
                        role: 'user',
                        content: prompt
                    }
                ],
                temperature: 0.3,
                max_tokens: 2000
            });

            return {
                analysis: response.choices[0].message.content,
                usage: {
                    inputTokens: response.usage.input_tokens,
                    outputTokens: response.usage.output_tokens,
                    costUSD: this.calculateCost(response.usage, 'input', 'output')
                }
            };
        } catch (error) {
            console.error('HolySheep API Fehler:', error.message);
            throw error;
        }
    }

    buildVolatilityAnalysisPrompt(chainData) {
        return `
Analysiere die folgende Optionskette und identifiziere:

1. **Volatility Smile/Skew Muster**
   - IV für ATM vs OTM Optionen
   - Put-Call IV Differential

2. **Key Support/Resistance aus Options Open Interest**
   - Höchstes OI bei Strikes
   - Ungewöhnliche Aktivität

3. **Risk Reversals und Butterflies**
   - 25-delta Risk Reversal
   - Iron Butterfly Signale

4. **Handlungsempfehlungen**
   - Spread-Setups
   - Volatilität-Strategien

Daten:
${JSON.stringify(chainData, null, 2)}
        `.trim();
    }

    calculateCost(usage, inputTokenType, outputTokenType) {
        // HolySheep Preise 2026
        const prices = {
            'gpt-4.1': { input: 0.000008, output: 0.000008 }, // $8/MTok
            'claude-sonnet-4.5': { input: 0.000015, output: 0.000015 }, // $15/MTok
            'gemini-2.5-flash': { input: 0.0000025, output: 0.0000025 }, // $2.50/MTok
            'deepseek-v3.2': { input: 0.00000042, output: 0.00000042 } // $0.42/MTok
        };

        const modelPrice = prices[this.model] || prices['gpt-4.1'];
        const inputCost = (usage.input_tokens / 1000000) * modelPrice.input * 1000000;
        const outputCost = (usage.output_tokens / 1000000) * modelPrice.output * 1000000;

        return inputCost + outputCost;
    }
}

// Benchmark: Analyse von 500 Optionsketten-Datensätzen
async function runBenchmark() {
    const model = new VolatilitySurfaceModel();
    const testData = generateMockOptionsChain(500);

    const startTime = Date.now();
    const results = [];

    for (const data of testData) {
        const result = await model.analyzeVolatilitySurface(data);
        results.push(result);
    }

    const totalTime = Date.now() - startTime;
    const avgLatency = totalTime / testData.length;

    console.log(`
=== HolySheep AI Benchmark ===
Modell: ${model.model}
Anfragen: ${testData.length}
Gesamtzeit: ${totalTime}ms
Durchschnittliche Latenz: ${avgLatency.toFixed(2)}ms
Gesamtkosten: $${results.reduce((sum, r) => sum + r.usage.costUSD, 0).toFixed(4)}
    `);
}

runBenchmark().catch(console.error);

Geeignet / Nicht geeignet für

Geeignet für:

Nicht geeignet für:

Preise und ROI

PlanTardisKaikoCoinMetricsHolySheep AI*
Starter$299/Monat$500/Monat$1.000/Monat$0 + Credits
Professional$999/Monat$2.000/Monat$5.000/Monat$49/Monat
Enterprise$3.000+/Monat$10.000+/Monat$25.000+/MonatIndividual
API-Latenz (p99)~150ms~200ms~300ms<50ms
Kosten/MTok (GPT-4.1)N/AN/AN/A$8 (85%+ günstiger als OpenAI)

*HolySheep AI: Für die ML-Analyse der heruntergeladenen Optionsdaten mit GPT-4.1, Claude Sonnet 4.5 oder DeepSeek V3.2. Kostenloses Startguthaben inklusive.

Warum HolySheep AI wählen

Häufige Fehler und Lösungen

1. Rate Limit 429 bei Batch-Downloads

Problem: Tardis API antwortet mit 429 Too Many Requests bei parallelen Anfragen.

// FEHLERHAFT: Unbegrenzte Parallelität
const promises = dates.map(date => 
    tardis.fetchOptionsChain(exchange, symbol, date)
); // Führt zu 429-Fehlern

// LÖSUNG: Exponential Backoff mit Concurrency-Limit
async function fetchWithBackoff(requestFn, maxRetries = 3) {
    for (let attempt = 0; attempt < maxRetries; attempt++) {
        try {
            return await requestFn();
        } catch (error) {
            if (error.response?.status === 429) {
                const delay = Math.pow(2, attempt) * 1000 + Math.random() * 1000;
                console.log(Rate Limited. Warte ${delay}ms...);
                await new Promise(r => setTimeout(r, delay));
                continue;
            }
            throw error;
        }
    }
    throw new Error('Max retries erreicht');
}

// Bessere Lösung: Semaphore für Concurrency-Control
class Semaphore {
    constructor(maxConcurrent) {
        this.maxConcurrent = maxConcurrent;
        this.running = 0;
        this.queue = [];
    }

    async acquire() {
        if (this.running < this.maxConcurrent) {
            this.running++;
            return Promise.resolve();
        }

        return new Promise(resolve => {
            this.queue.push(resolve);
        });
    }

    release() {
        this.running--;
        if (this.queue.length > 0) {
            const next = this.queue.shift();
            this.running++;
            next();
        }
    }

    async execute(fn) {
        await this.acquire();
        try {
            return await fn();
        } finally {
            this.release();
        }
    }
}

const semaphore = new Semaphore(3); // Max 3 parallele Anfragen

const promises = dates.map(date =>
    semaphore.execute(() => fetchWithBackoff(() =>
        tardis.fetchOptionsChain(exchange, symbol, date)
    ))
);

2. NDJSON-Parsing-Fehler bei leeren Daten

Problem: API gibt leere NDJSON-Response oder gemischte Formate zurück.

// FEHLERHAFT: Keine Behandlung von Randfällen
parseNDJSON(data) {
    return data.split('\n').map(line => JSON.parse(line));
}

// LÖSUNG: Robustes Parsing mit Validierung
parseNDJSON(data) {
    // Behandlung von Array-Response
    if (Array.isArray(data)) {
        return data;
    }

    // Behandlung von String-Response
    if (typeof data === 'string') {
        const lines = data.split('\n').filter(line => line.trim());

        if (lines.length === 0) {
            console.warn('Leere Response erhalten');
            return [];
        }

        return lines.map((line, index) => {
            try {
                return JSON.parse(line);
            } catch (error) {
                console.error(Parse-Fehler in Zeile ${index}: ${line});
                return null;
            }
        }).filter(item => item !== null);
    }

    // Behandlung von Stream-Response
    if (data && typeof data.pipe === 'function') {
        return new Promise((resolve, reject) => {
            let chunks = [];
            data.on('data', chunk => chunks.push(chunk.toString()));
            data.on('end', () => resolve(this.parseNDJSON(chunks.join(''))));
            data.on('error', reject);
        });
    }

    return [];
}

// Zusätzliche Validierung der Optionsdaten
validateOptionsData(data) {
    const required = ['symbol', 'strike_price', 'option_type', 'bid', 'ask'];
    const missing = required.filter(field => !(field in data));

    if (missing.length > 0) {
        throw new Error(Ungültige Daten: Fehlende Felder ${missing.join(', ')});
    }

    if (data.bid > data.ask) {
        throw new Error(Ungültige Preise: Bid > Ask für ${data.symbol});
    }

    return true;
}

3. Memory Leak bei kontinuierlichem Sync

Problem: Bei Langzeit-Sync-Prozessen steigt der Memory-Verbrauch kontinuierlich an.

// FEHLERHAFT: Akkumulierung von Daten im Speicher
class BadSyncService {
    constructor() {
        this.allResults = []; // Wächst unbegrenzt
    }

    async processBatch(dates) {
        const results = await this.tardis.fetchMultipleDates(...);

        // Jeder Batch wird angehängt - Memory Leak!
        this.allResults.push(...results);

        return results;
    }
}

// LÖSUNG: Streaming mit periodischem Flush
const { Transform } = require('stream');

class MemoryEfficientSyncService {
    constructor(config) {
        this.flushInterval = config.flushInterval || 1000; // Alle 1000 Records
        this.counter = 0;
        this.buffer = [];
        this.dbPool = null;
    }

    createTransformStream() {
        return new Transform({
            objectMode: true,
            transform: async (data, encoding, callback) => {
                try {
                    const processed = await this.processRecord(data);
                    this.buffer.push(processed);
                    this.counter++;

                    // Periodisches Flushen
                    if (this.counter >= this.flushInterval) {
                        await this.flushBuffer();
                    }

                    callback(null, processed);
                } catch (error) {
                    callback(error);
                }
            },
            flush: