Startseite / Artikel / Mehr-Agenten-Debatte zur Optimierung von Volatilitätsausbrüchen: Können drei Gemini

Mehr-Agenten-Debatte zur Optimierung von Volatilitätsausbrüchen: Können drei Gemini

Schritt-für-Schritt-Anleitung zur Verwendung von Multi-Agent-Debatten für die Optimierung von Volatilitätsausbrüchen: Drei Gemini-Verträge, -Prüfungen sowie Code-Slots für Teams, die dieses Muster einsetzen.

3043 Wörter

Der Autor stellt in den folgenden Anmerkungen einen praktischen Ansatz für „Multi-Agent Debate for Volatility Breakout Optimization: Can Three Gemini Personas Fix a Losing Strategy?“ vor. Der Schwerpunkt liegt auf Verträgen, Überprüfungen und Code-Platzhaltern statt auf motivierenden Formulierungen. Während der Überblicksphase sollten Sie zunächst den Vertrag aufschreiben: erforderliche Eingaben, Erfolgsindikator sowie das Vorgehen bei teilweisen Fehlern. Diese Checkliste sorgt dafür, dass spätere Codeänderungen transparent bleiben. Ziehen Sie kleine, testbare Einheiten vor statt umfangreicher Skripte. Wenn ein Schritt fehlschlägt, sollte der Fehler auf eine einzige Verantwortung verweisen und nicht auf ein verworrenes Ablaufschema.

{
    "strategy_version": "v2.0-optimized",
    "final_sharpe_ratio": -0.6822300207528283,
    "consensus_rationale": "Iteration 1 consensus achieved superior Sharpe ratio through optimized ATR multiplier and volume threshold refinement.",
    "max_drawdown_delta": 0.00687485272186061,
    "total_iterations_run": 3
}

Datenladen und Einrichtung des Marktuniversums

Der Autor empfiehlt, die Phasen „Datenladen“ und „Marktphase“ am besten als messbare Einheiten zu betrachten. Erfassen Sie vor Erweiterung des Umfangs ein gelungenes Beispiel, einen Fehlerfall sowie eine Notiz zur Rücksetzung. Behandeln Sie diese Phase als Vertrag zwischen Eingaben und validierten Ausgaben. Benennen Sie die relevanten Artefakte, definieren Sie Erfolgskontrollen und lehnen Sie stille, unvollständige Abschlüsse ab. Fixieren Sie den Interpreter sowie die Abhängigkeitsdatei, bevor Sie Schleifen implementieren – Abweichungen zwischen Laptop und CI sind die häufigste Ursache für stille Ausfälle bei API-Demos.

Entwurf des High-Beta-Umfelds

Der Autor von „Designing the High-Beta Universe“ arbeitet am effektivsten, wenn das Konzept als messbare Ebene betrachtet wird. Erfassen Sie vor der Erweiterung des Umfangs einen erfolgreichen Fall, einen Fehlerfall sowie die Notizen zur Rücksetzung. Erfassen Sie außerdem die Laufzeiten sowie die Kosten für Tokens oder Abfragen neben den funktionalen Ergebnissen. Eine frühzeitige Sichtbarkeit der Kosten verhindert überraschende Rechnungen, wenn sich der Prozess von einer Demo in gemeinsam genutzte Umgebungen verschiebt. Fixieren Sie den Interpreter sowie die Abhängigkeitsdatei, bevor Sie mit Schleifen arbeiten. Unterschiede zwischen dem Laptop und den CI-Umgebungen sind die häufigsten stillen Störgründe bei API-Demos.

import os
import json
import logging
from datetime import datetime, timezone
import pandas as pd
import numpy as np
import yfinance as yf
import matplotlib.pyplot as plt
from google import genai
logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s - %(levelname)s - %(message)s')

Bearbeitung fehlender Daten und Ausrichtung von MultiIndex

Das Werk „Handling Missing Data and stage“ funktioniert am besten, wenn es als messbare Struktur betrachtet wird. Erfassen Sie vor der Erweiterung des Umfangs ein „goldenes Transkript“, einen Fehlerfall sowie eine Notiz zum Rollback. Bewahren Sie die Konfiguration außerhalb des Anwendungscode auf. Umgebungsdateien, Geheimdatenspeicher und Feature-Flags sollten an einem Ort gesammelt sein, den Betreuer ohne das Durchlesen des gesamten Systems überprüfen können. Fixieren Sie den Interpreter sowie die Abhängigkeitsdateien, bevor Sie Schleifen implementieren. Unterschiede zwischen Laptop und CI sind die häufigsten stillen Störungen bei API-Demos. Das Werk „Handling Missing Data and stage“ funktioniert am besten, wenn es als messbare Struktur betrachtet wird. Erfassen Sie vor der Erweiterung des Umfangs ein „goldenes Transkript“, einen Fehlerfall sowie eine Notiz zum Rollback. Ziehen Sie kleine, testbare Einheiten vor umfangreichen Skripten vor. Wenn ein Schritt fehlschlägt, sollte der Fehler auf eine einzige Verantwortung verweisen und nicht auf ein verworrenes Ablaufschema.

class MarketDataLoader:
    def __init__(self, tickers: list[str], benchmark: str):
        self.tickers = tickers
        self.all_symbols = tickers + [benchmark]
        self.benchmark = benchmark

    def fetch_data(self) -> tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame, pd.DataFrame]:
        end_date = datetime.now(timezone.utc).strftime('%Y-%m-%d')
        start_date = (datetime.now(timezone.utc) -
                      pd.Timedelta(days=365 * 3)).strftime('%Y-%m-%d')
        logging.info(
            f"Fetching historical data from {start_date} to {end_date} for {len(self.all_symbols)} symbols.")

        data = yf.download(self.all_symbols, start=start_date,
                           end=end_date, auto_adjust=True, progress=False)
        if data.empty:
            logging.error(
                f"Failed to download data for symbols: {self.all_symbols}")
            raise ValueError(
                f"Failed to download data for symbols: {self.all_symbols}")

        if isinstance(data.columns, pd.MultiIndex):
            close = data['Close'] if 'Close' in data.columns.levels[0] else data.xs(
                'Close', level=1, axis=1)
            high = data['High'] if 'High' in data.columns.levels[0] else data.xs(
                'High', level=1, axis=1)
            low = data['Low'] if 'Low' in data.columns.levels[0] else data.xs(
                'Low', level=1, axis=1)
            volume = data['Volume'] if 'Volume' in data.columns.levels[0] else data.xs(
                'Volume', level=1, axis=1)
        else:
            close = data[['Close']]
            high = data[['High']]
            low = data[['Low']]
            volume = data[['Volume']]

        close = close.ffill().dropna(how='all')
        high = high.ffill().dropna(how='all')
        low = low.ffill().dropna(how='all')
        volume = volume.ffill().fillna(0.0)

        if close.empty:
            logging.error(
                "Cleaned price data DataFrame is empty after processing.")
            raise ValueError(
                "Cleaned price data DataFrame is empty after processing.")

        logging.info(
            f"Data checkpoint - Shape: {close.shape}, Column sample: {list(close.columns[:3])}, NaN count: {close.isna().sum().sum()}, Date range: {close.index[0]} to {close.index[-1]}")
        return close, high, low, volume
INFO - Fetching historical data from 2023-08-10 to 2026-08-09 for 16 symbols.
INFO - Data checkpoint - Shape: (751, 16), Column sample: ['AMD', 'COIN', 'DKNG'], NaN count: 0, Date range: 2023-08-10 00:00:00 to 2026-08-07 00:00:00

Definierung des Volatilitäts-Breakout-Engines

Zur Phase der Definierung des Volatilitäts-Breakout-Engines sollten vor dem Ändern des Codes die Eingabedaten, der Verantwortliche für diesen Schritt sowie die Abbruchkriterien festgelegt werden. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen. Betrachten Sie diese Phase als Vertrag zwischen den Eingabedaten und den validierten Ausgabedaten. Benennen Sie die Ergebnisdokumente, definieren Sie Erfolgskontrollen und lehnen Sie stille, unvollständige Abschlüsse ab. Trennen Sie den Aufbau des Clients vom Nachrichtenzyklus, damit Provider ausgetauscht werden können, ohne die Zustandsmaschine des Dialogs neu schreiben zu müssen.

Die Mechanik von Momentum und Volatilität des Autors

Für die Phase „Mechanik des Impulses“ sollten der Autor vor dem Ändern des Codes die Eingabedaten, den Verantwortlichen für den jeweiligen Schritt sowie die Abbruchkriterien definieren. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen. Zeiten sowie Kosten für Token oder Abfragen sollten neben den funktionalen Ergebnissen aufgezeichnet werden. Eine frühzeitige Sichtbarkeit der Kosten verhindert überraschende Rechnungen, wenn der Ablauf von einer Demo-Umgebung in eine gemeinsam genutzte Umgebung wechselt. Die Erstellung des Clients sollte von dem Nachrichtenzyklus getrennt werden, damit Anbieter ausgetauscht werden können, ohne die Zustandsmaschine des Dialogs neu schreiben zu müssen.

Simulierung von Portfolio-Renditen

Für die Phase der Simulation von Portfolio-Renditen sollten vor dem Ändern des Codes die Eingaben, der Verantwortliche für diesen Schritt sowie die Abbruchkriterien definiert werden. Die Betreiber sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen. Die Konfiguration sollte außerhalb des Anwendungscode gespeichert werden. Umgebungsdateien, Geheimdatenspeicher sowie Feature-Flags sollten an einem Ort zusammengefasst sein, den die Betreiber überprüfen können, ohne den gesamten Codeverlauf durchlesen zu müssen. Trennen Sie die Erstellung des Clients von dem Nachrichtenzyklus, damit Provider ausgetauscht werden können, ohne die Zustandsmaschine der Konversation neu schreiben zu müssen. Für die Phase der Simulation von Portfolio-Renditen sollten vor dem Ändern des Codes die Eingaben, der Verantwortliche für diesen Schritt sowie die Abbruchkriterien definiert werden. Die Betreiber sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen. Ziehen Sie kleine, testbare Einheiten vor großen, komplexen Skripten. Wenn ein Schritt fehlschlägt, sollte der Fehler auf eine einzige Verantwortungsbereich verweisen und nicht auf mehrere.

geformter Pipeline.

class VolatilityStrategyBacktester:
    def __init__(self, close_df: pd.DataFrame, high_df: pd.DataFrame, low_df: pd.DataFrame, volume_df: pd.DataFrame, benchmark: str):
        self.close_df = close_df
        self.high_df = high_df
        self.low_df = low_df
        self.volume_df = volume_df
        self.benchmark = benchmark
        self.asset_columns = [c for c in close_df.columns if c != benchmark]

    def backtest(self, params: dict) -> tuple[pd.Series, pd.Series]:
        lookback = int(params.get("lookback", 20))
        atr_mult = float(params.get("atr_multiplier", 2.0))
        vol_thresh = float(params.get("volume_threshold", 1.5))

        asset_returns_dict = {}

        for ticker in self.asset_columns:
            if ticker not in self.close_df.columns:
                continue
            c = self.close_df[ticker]
            h = self.high_df[ticker]
            l = self.low_df[ticker]
            v = self.volume_df[ticker]

            tr1 = h - l
            tr2 = (h - c.shift(1)).abs()
            tr3 = (l - c.shift(1)).abs()
            tr = pd.concat([tr1, tr2, tr3], axis=1).max(axis=1)
            atr = tr.rolling(window=lookback).mean()

            rolling_high = c.rolling(window=lookback).max()
            avg_vol = v.rolling(window=lookback).mean()

            breakout = (c > rolling_high.shift(1) + atr_mult *
                        atr) & (v > vol_thresh * avg_vol)

            asset_ret = c.pct_change()
            strat_ret = asset_ret * breakout.shift(1).fillna(False)

            trades = breakout & (~breakout.shift(1).fillna(False))
            strat_ret = strat_ret - (trades.astype(float) * 0.001)

            asset_returns_dict[ticker] = strat_ret

        strategy_df = pd.DataFrame(asset_returns_dict)
        portfolio_returns = strategy_df.mean(axis=1).fillna(0.0)
        benchmark_returns = self.close_df[self.benchmark].pct_change().fillna(
            0.0)

        return portfolio_returns, benchmark_returns
INFO - Baseline Metrics: Sharpe=-2.68, Return=-2.79%

Entwurf von Multi-Agent-Persönlichkeiten und Debatte-Loop

Beim Arbeiten an der Phase des Entwurfs von Multi-Agent-Persönlichkeiten sollte man zunächst den Vertrag aufschreiben: erforderliche Eingaben, Erfolgsindikator sowie das Vorgehen bei teilweisen Fehlern. Diese Checkliste sorgt dafür, dass spätere Codeänderungen transparent bleiben. Betrachten Sie diese Phase als Vertrag zwischen Eingaben und validierten Ausgaben. Benennen Sie die Erzeugnisse, definieren Sie Erfolgsprüfungen und lehnen Sie stille, teilweise abgeschlossene Arbeiten ab. Protokollieren Sie bei jedem Aufruf die Anfrage-ID, die Modell-ID sowie die Latenzzeit. Ohne diese Aufzeichnungen wirken gelegentliche Fehler des Anbieters wie Programmierfehler.

Entwicklung der Gemini-Persönlichkeiten

Während der Phase „Engineering the Gemini Personas“ sollten Sie zunächst den Vertrag aufschreiben: erforderliche Eingaben, Erfolgsindikatoren sowie das Vorgehen bei teilweisen Fehlern. Diese Checkliste sorgt dafür, dass spätere Codeänderungen transparent bleiben. Notieren Sie die Laufzeiten sowie die Kosten für Tokens oder Abfragen neben den funktionalen Ergebnissen. Eine frühzeitige Sichtbarkeit der Kosten verhindert überraschende Rechnungen, wenn der Prozess von einer Demo in gemeinsame Umgebungen übergeht. Protokollieren Sie bei jedem Aufruf die Anfrage-ID, Modell-ID sowie die Latenzzeit. Ohne diese Aufzeichnungen wirken gelegentliche Fehler des Anbieters wie Programmierfehler.

class Config:
    TICKERS = [
        "TSLA", "NVDA", "AMD", "PLTR", "COIN",
        "MARA", "RIOT", "MSTR", "HOOD", "ROKU",
        "UBER", "SHOP", "SNAP", "PTON", "DKNG"
    ]
    BENCHMARK = "SPY"
    MAX_ITERATIONS = 3
    INITIAL_PARAMS = {
        "lookback": 20,
        "atr_multiplier": 2.0,
        "volume_threshold": 1.5,
        "stop_loss_pct": 0.05
    }
class GeminiAgentPersona:
    def __init__(self, name: str, role: str, system_prompt: str):
        self.name = name
        self.role = role
        self.system_prompt = system_prompt
        self.client = genai.Client()

    def evaluate(self, current_params: dict, metrics: dict, iteration: int) -> dict:
        prompt = f"""
        You are {self.name}, a specialized {self.role} in a multi-agent quantitative trading system.
        Current Iteration: {iteration}
        Current Strategy Parameters: {json.dumps(current_params, indent=2)}
        Current Backtest Performance Metrics: {json.dumps(metrics, indent=2)}

        Analyze the performance and parameters from your professional perspective. Provide your critique and propose specific parameter adjustments (lookback, atr_multiplier, volume_threshold, stop_loss_pct) to improve the Sharpe ratio and reduce max drawdown.

        You MUST return a valid JSON object with keys:
        - "critique": Detailed analytical critique from your persona's perspective.
        - "proposed_adjustment": Dictionary of recommended parameter changes (e.g., ).
        - "confidence_score": Float between 0 and 1 representing your confidence in this adjustment.
        """

        response = self.client.models.generate_content(
            model="gemini-3.5-flash-lite",
            contents=prompt
        )

        text = response.text
        clean_text = text.strip()
        if clean_text.startswith("```json"):
            clean_text = clean_text[7:]
        if clean_text.endswith("```"):
            clean_text = clean_text[:-3]

        try:
            parsed = json.loads(clean_text.strip())
        except json.JSONDecodeError:
            parsed = {
                "critique": text[:500],
                "proposed_adjustment": current_params,
                "confidence_score": 0.6
            }
        return parsed

der Autor: Iterative Debate Coordinator

Wenn Sie die Phase des „Iterative Debate Coordinator“ durchlaufen, schreiben Sie zunächst den Vertrag auf: erforderliche Eingaben, Erfolgsindikator sowie das Vorgehen bei teilweisen Fehlern. Diese Checkliste sorgt dafür, dass spätere Codeänderungen transparent bleiben. Bewahren Sie die Konfiguration außerhalb des Anwendungscode auf. Umgebungsdateien, Geheimdatenspeicher und Feature-Flags sollten an einem Ort gesammelt sein, den Betreiber ohne das Durchlesen des gesamten Systems überprüfen können. Protokollieren Sie bei jedem Aufruf die Anfrage-ID, die Modell-ID sowie die Latenzzeit. Ohne diese Aufzeichnungen wirken intermittierende Fehler des Anbieters wie Bugs in der Anwendung. Wenn Sie die Phase des „Iterative Debate Coordinator“ durchlaufen, schreiben Sie zunächst den Vertrag auf: erforderliche Eingaben, Erfolgsindikator sowie das Vorgehen bei teilweisen Fehlern. Diese Checkliste sorgt dafür, dass spätere Codeänderungen transparent bleiben. Ziehen Sie kleine, testbare Einheiten vor großen, komplexen Skripten. Wenn ein Schritt fehlschlägt, sollte der Fehler auf eine einzige Verantwortung verweisen und nicht auf ein verworrenes Ablaufschema.

class PersonaDebateCoordinator:
    def __init__(self, backtester: VolatilityStrategyBacktester, initial_params: dict, max_iterations: int):
        self.backtester = backtester
        self.current_params = initial_params.copy()
        self.max_iterations = max_iterations

        self.quant = GeminiAgentPersona(
            "QuantAnalyst",
            "Quantitative Strategist",
            "Focuses on alpha generation, indicator sensitivity, and statistical edge."
        )
        self.risk = GeminiAgentPersona(
            "RiskManager",
            "Risk Officer",
            "Focuses on drawdowns, tail risk, position sizing, and volatility caps."
        )
        self.execution = GeminiAgentPersona(
            "ExecutionStrategist",
            "Execution Trading Specialist",
            "Focuses on liquidity, volume confirmation, slippage, and practical execution friction."
        )

        self.audit_log = []
        self.parameter_history = []

    def run_iterative_loop(self) -> dict:
        best_sharpe = -999.0
        consensus_rationale = "Initial baseline strategy evaluation."

        p_ret, b_ret = self.backtester.backtest(self.current_params)
        baseline_metrics = calculate_performance_metrics(p_ret, b_ret)
        current_metrics = baseline_metrics

        logging.info(
            f"Baseline Metrics: Sharpe={baseline_metrics['sharpe_ratio']:.2f}, Return={baseline_metrics['cumulative_return']*100:.2f}%")

        for i in range(1, self.max_iterations + 1):
            logging.debug(
                f"--- Starting Debate Iteration {i}/{self.max_iterations} ---")

            q_eval = self.quant.evaluate(
                self.current_params, current_metrics, i)
            r_eval = self.risk.evaluate(
                self.current_params, current_metrics, i)
            e_eval = self.execution.evaluate(
                self.current_params, current_metrics, i)

            for persona_name, eval_data in [("QuantAnalyst", q_eval), ("RiskManager", r_eval), ("ExecutionStrategist", e_eval)]:
                self.audit_log.append({
                    "iteration_number": i,
                    "persona_name": persona_name,
                    "critique_text": eval_data.get("critique", ""),
                    "proposed_adjustment": eval_data.get("proposed_adjustment", {}),
                    "confidence_score": eval_data.get("confidence_score", 0.8)
                })

            q_adj = q_eval.get("proposed_adjustment", {})
            r_adj = r_eval.get("proposed_adjustment", {})
            e_adj = e_eval.get("proposed_adjustment", {})

            new_lookback = int(np.mean([
                float(q_adj.get("lookback",
                      self.current_params["lookback"])),
                float(r_adj.get("lookback",
                      self.current_params["lookback"])),
                float(e_adj.get("lookback",
                      self.current_params["lookback"]))
            ]))
            new_atr = float(np.mean([
                float(q_adj.get("atr_multiplier",
                      self.current_params["atr_multiplier"])),
                float(r_adj.get("atr_multiplier",
                      self.current_params["atr_multiplier"])),
                float(e_adj.get("atr_multiplier",
                      self.current_params["atr_multiplier"]))
            ]))
            new_vol_thresh = float(np.mean([
                float(q_adj.get("volume_threshold",
                      self.current_params["volume_threshold"])),
                float(r_adj.get("volume_threshold",
                      self.current_params["volume_threshold"])),
                float(e_adj.get("volume_threshold",
                      self.current_params["volume_threshold"]))
            ]))
            new_sl = float(np.mean([
                float(q_adj.get("stop_loss_pct",
                      self.current_params["stop_loss_pct"])),
                float(r_adj.get("stop_loss_pct",
                      self.current_params["stop_loss_pct"])),
                float(e_adj.get("stop_loss_pct",
                      self.current_params["stop_loss_pct"]))
            ]))

            self.current_params = {
                "lookback": max(5, min(60, new_lookback)),
                "atr_multiplier": max(1.0, min(4.0, new_atr)),
                "volume_threshold": max(1.0, min(3.0, new_vol_thresh)),
                "stop_loss_pct": max(0.01, min(0.15, new_sl))
            }

            p_ret_new, b_ret_new = self.backtester.backtest(
                self.current_params)
            current_metrics = calculate_performance_metrics(
                p_ret_new, b_ret_new)

            logging.debug(
                f"Iteration {i} Results: Sharpe={current_metrics['sharpe_ratio']:.2f}, Return={current_metrics['cumulative_return']*100:.2f}%, Params={self.current_params}")

            self.parameter_history.append({
                "iteration": i,
                "params": self.current_params.copy(),
                "metrics": current_metrics.copy()
            })

            if current_metrics["sharpe_ratio"] > best_sharpe:
                best_sharpe = current_metrics["sharpe_ratio"]
                consensus_rationale = f"Iteration {i} consensus achieved superior Sharpe ratio through optimized ATR multiplier and volume threshold refinement."

        summary_result = {
            "strategy_version": "v2.0-optimized",
            "final_sharpe_ratio": float(best_sharpe),
            "consensus_rationale": consensus_rationale,
            "max_drawdown_delta": float(current_metrics["max_drawdown"] - baseline_metrics["max_drawdown"]),
            "total_iterations_run": self.max_iterations,
            "parameter_history": self.parameter_history
        }

        return summary_result
INFO - Successfully generated output JSON files.

Ergebnisse, Leistungsanalyse und Vergleich von Benchmarks

Die Ergebnisse, die Leistungsanalyse sowie die Phase der Auswertung funktionieren am besten, wenn sie als messbare Größen betrachtet werden. Erfassen Sie ein gelungenes Beispiel, einen Fehlerfall sowie die Notizen zum Rollback, bevor Sie den Umfang erweitern. Betrachten Sie diese Phase als Vertrag zwischen Eingaben und validierten Ausgaben. Benennen Sie die Erzeugnisse, definieren Sie Erfolgskontrollen und lehnen Sie stille, unvollständige Abschlüsse ab. Sichern Sie den Interpreter sowie die Abhängigkeitsdatei, bevor Sie Schleifen erklären. Unterschiede zwischen Laptop und CI sind die häufigsten stillen Störungen bei API-Demos.

Quantitative Aufschlüsselung der Strategieiterationen

Der Autor des Werkes „Quantitative Breakdown of Strategy“ empfiehlt, dieses am besten als messbare Struktur zu betrachten. Erfassen Sie vor Erweiterung des Umfangs ein gelungenes Beispiel, einen Fehlfall sowie die Notizen zur Rücksetzung. Erfassen Sie außerdem die Laufzeiten sowie die Kosten für Tokens oder Abfragen neben den funktionalen Ergebnissen. Eine frühzeitige Sichtbarkeit der Kosten verhindert überraschende Rechnungen, wenn der Prozess von einer Demo in gemeinsam genutzte Umgebungen übergeht. Bevor man Schleifen erklärt, sollten Interpreter und Abhängigkeitsdateien gesichert werden. Unterschiede zwischen Laptop und CI sind die häufigsten stillen Störungen bei API-Demos.

def calculate_performance_metrics(portfolio_returns: pd.Series, benchmark_returns: pd.Series) -> dict:
    valid_idx = portfolio_returns.index.intersection(benchmark_returns.index)
    p_ret = portfolio_returns.loc[valid_idx]
    b_ret = benchmark_returns.loc[valid_idx]

    trading_days = 252
    cum_return = (1 + p_ret).prod() - 1
    annualized_return = (1 + cum_return) ** (trading_days /
                                             len(p_ret)) - 1 if len(p_ret) > 0 else 0.0
    annualized_vol = p_ret.std() * np.sqrt(trading_days)
    risk_free_rate = 0.03
    sharpe_ratio = (annualized_return - risk_free_rate) / \
        annualized_vol if annualized_vol > 0 else 0.0

    cum_wealth = (1 + p_ret).cumprod()
    peak = cum_wealth.cummax()
    drawdown = (cum_wealth - peak) / peak
    max_drawdown = drawdown.min()

    b_cum_return = (1 + b_ret).prod() - 1
    outperformance = cum_return - b_cum_return

    return {
        "cumulative_return": float(cum_return),
        "annualized_return": float(annualized_return),
        "annualized_volatility": float(annualized_vol),
        "sharpe_ratio": float(sharpe_ratio),
        "max_drawdown": float(max_drawdown),
        "benchmark_cumulative_return": float(b_cum_return),
        "outperformance": float(outperformance)
    }
{
    "strategy_version": "v2.0-optimized",
    "final_sharpe_ratio": -0.6822300207528283,
    "consensus_rationale": "Iteration 1 consensus achieved superior Sharpe ratio through optimized ATR multiplier and volume threshold refinement.",
    "parameter_history": [
        {
            "iteration": 1,
            "params": {
                "lookback": 14,
                "atr_multiplier": 1.5,
                "volume_threshold": 1.4666,
                "stop_loss_pct": 0.025
            },
            "metrics": {
                "cumulative_return": 0.0399,
                "annualized_return": 0.0132,
                "sharpe_ratio": -0.6822,
                "max_drawdown": -0.0344
            }
        }
    ]
}

Benchmark-Realitäten und Strategievisualisierung

Der Autor empfiehlt, die Phase „Benchmark Realities and Strategy“ am besten als messbaren Rahmen zu betrachten. Erfassen Sie vor der Erweiterung des Umfangs ein „goldenes Transkript“, einen Fehlerfall sowie eine Notiz zum Rollback. Bewahren Sie die Konfiguration außerhalb des Anwendungscode auf. Umgebungsdateien, Geheimdatenspeicher und Feature-Flags sollten an einem Ort gesammelt sein, den Betreuer ohne das Durchlesen des gesamten Systems überprüfen können. Fixieren Sie den Interpreter sowie die Abhängigkeitsdateien, bevor Sie Schleifen erklären. Unterschiede zwischen Laptop und CI sind die häufigsten stillen Störungen bei API-Demos. Der Autor empfiehlt, die Phase „Benchmark Realities and Strategy“ am besten als messbaren Rahmen zu betrachten. Erfassen Sie vor der Erweiterung des Umfangs ein „goldenes Transkript“, einen Fehlerfall sowie eine Notiz zum Rollback. Ziehen Sie kleine, testbare Einheiten vor umfangreichen Skripten vor. Wenn ein Schritt fehlschlägt, sollte der Fehler auf eine einzige Verantwortung verweisen und nicht auf ein verworrenes Ablaufverfahren.

def main():
    logging.info(
        "Starting Multi-Agent Volatility Breakout Optimization Pipeline.")

    loader = MarketDataLoader(Config.TICKERS, Config.BENCHMARK)
    close_df, high_df, low_df, volume_df = loader.fetch_data()

    backtester = VolatilityStrategyBacktester(
        close_df, high_df, low_df, volume_df, Config.BENCHMARK)

    # Run initial baseline backtest
    baseline_p_ret, baseline_b_ret = backtester.backtest(Config.INITIAL_PARAMS)

    coordinator = PersonaDebateCoordinator(
        backtester, Config.INITIAL_PARAMS, Config.MAX_ITERATIONS)
    summary_results = coordinator.run_iterative_loop()

    # Write output files exactly as specified
    with open("volatility_debate_summary.json", "w") as f:
        json.dump(summary_results, f, indent=4)

    with open("iteration_debate_audit_log.json", "w") as f:
        json.dump(coordinator.audit_log, f, indent=4)

    logging.info("Successfully generated output JSON files.")

    # Generate annotated plot
    fig, ax = plt.subplots(figsize=(10, 6))
    optimized_p_ret, _ = backtester.backtest(coordinator.current_params)

    wealth_baseline = (1 + baseline_p_ret).cumprod()
    wealth_optimized = (1 + optimized_p_ret).cumprod()
    wealth_benchmark = (1 + baseline_b_ret).cumprod()

    ax.plot(wealth_baseline.index, wealth_baseline,
            label="Baseline Strategy", color="gray", linestyle="--")
    ax.plot(wealth_optimized.index, wealth_optimized,
            label="Optimized Multi-Agent Strategy", color="blue", linewidth=2)
    ax.plot(wealth_benchmark.index, wealth_benchmark,
            label="SPY Benchmark", color="orange", alpha=0.7)

    # Annotate final peak / convergence
    max_idx = wealth_optimized.idxmax()
    max_val = wealth_optimized.max()
    ax.annotate(f"Optimized Peak: {max_val:.2f}x",
                xy=(max_idx, max_val),
                xytext=(max_idx - pd.Timedelta(days=90), max_val * 0.9),
                arrowprops=dict(facecolor='blue', shrink=0.05, width=1, headwidth=6))

    ax.set_title("Multi-Agent Volatility Breakout Portfolio vs. SPY Benchmark",
                 fontsize=12, fontweight='bold')
    ax.set_xlabel("Date", fontsize=10)
    ax.set_ylabel("Growth of 1.00", fontsize=10)
    ax.legend(loc="upper left")
    ax.grid(True, linestyle=":", alpha=0.6)

    plt.tight_layout()
    plt.show()
    logging.info("Successfully generated strategy performance plot.")
if __name__ == "__main__":
    main()
INFO - Successfully generated strategy performance plot.

Fazit und nächste Schritte in der Produktion

In der Phase des Fazits und der weiteren Schritte in der Produktion sollten die Eingaben, der Verantwortliche für den jeweiligen Schritt sowie die Abbruchkriterien vor dem Ändern des Codes definiert werden. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen. Betrachten Sie diese Phase als Vertrag zwischen den Eingaben und den validierten Ausgaben. Benennen Sie die Erzeugnisse, definieren Sie Erfolgskontrollen und lehnen Sie stille, unvollständige Abschlüsse ab. Trennen Sie den Aufbau des Clients vom Nachrichtenzyklus, damit Provider ausgetauscht werden können, ohne die Zustandsmaschine des Dialogs neu schreiben zu müssen.

Operative Kontrollliste

In der Phase der operativen Kontrollliste sollten die Eingaben, der Verantwortliche für den jeweiligen Schritt sowie die Abbruchkriterien vor dem Ändern des Codes definiert werden. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen.

Dokumentieren Sie den erfolgreichen Ablauf sowie den Wiederherstellungsprozess gemeinsam. Versuche, menschliche Eingriffe und die Handhabung von Fehlnachrichten gehören zum Produkt selbst, nicht zu späteren Optimierungen.

Trennen Sie den Aufbau des Clients von dem Nachrichtenzyklus, damit Provider ausgetauscht werden können, ohne den Zustandsautomaten der Konversation umschreiben zu müssen.

Führen Sie Checkpoints nach aufwändigen Schritten durch. Die Wiederaufnahme des Vorgangs sollte keine erneute Gebührenberechnung für denselben LLM-Aufruf vornehmen, wenn ein Operator einen späteren Knoten erneut versucht.

Pinnen Sie Abhängigkeitsversionen fest und dokumentieren Sie den Bild-Digest, mit dem die Demo ausgeführt wurde. Reproduzierbarkeit ist besser als kollektives Wissen.

Notieren Sie die Laufzeiten sowie die Kosten pro Token oder Abfrage zusammen mit den funktionalen Ergebnissen. Frühzeitige Sichtbarkeit der Kosten verhindert überraschende Rechnungen, wenn der Ablauf von einer Demo in gemeinsame Umgebungen wechselt.

Vor der Einführung des Stacks sollten Versionen eingefroren werden, ein „goldener“ Transkript für den kritischen Pfad erstellt und die Rollback-Schritte bestätigt werden. Gemeinsam genutzte Umgebungen benötigen Rate Limits, Überprüfungen der Nutzerrechte sowie einen klaren Verantwortlichen für die Rotation von Geheimnissen. Man sollte langweilige Zuverlässigkeit vor cleveren, einmaligen Demonstrationen bevorzugen.

Batch-Hinweis für 476dcdb15114: Halten Sie die Provider-Schlüssel außerhalb des Repositories, legen Sie eine Obergrenze für Session-Tokens fest und speichern Sie die Transkripte neben den Evaluierungs-Fixtures, damit spätere Modellwechsel vergleichbar bleiben.