Skip to content
This repository was archived by the owner on Feb 21, 2026. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions Agent/Evaluators/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Drakkar-Software OctoBot-Tentacles
# Copyright (c) Drakkar-Software, All rights reserved.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 3.0 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library.

from .technical_analysis_agent import *
from .sentiment_analysis_agent import *
from .real_time_analysis_agent import *
from .summarization_agent import *
29 changes: 29 additions & 0 deletions Agent/Evaluators/real_time_analysis_agent/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Drakkar-Software OctoBot-Tentacles
# Copyright (c) Drakkar-Software, All rights reserved.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 3.0 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library.

from .real_time_analysis_agent import (
RealTimeAnalysisAIAgentChannel,
RealTimeAnalysisAIAgentConsumer,
RealTimeAnalysisAIAgentProducer,
)
from .models import RealTimeAnalysisOutput

__all__ = [
"RealTimeAnalysisAIAgentChannel",
"RealTimeAnalysisAIAgentConsumer",
"RealTimeAnalysisAIAgentProducer",
"RealTimeAnalysisOutput",
]
6 changes: 6 additions & 0 deletions Agent/Evaluators/real_time_analysis_agent/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"version": "1.0.0",
"origin_package": "OctoBot-Default-Tentacles",
"tentacles": ["RealTimeAnalysisAgent"],
"tentacles-requirements": []
}
94 changes: 94 additions & 0 deletions Agent/Evaluators/real_time_analysis_agent/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Drakkar-Software OctoBot-Tentacles
# Copyright (c) Drakkar-Software, All rights reserved.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 3.0 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library.

"""
Pydantic models for real-time analysis agent outputs.
"""
from typing import List, Optional
from pydantic import BaseModel, Field, field_validator


class RealTimeAnalysisOutput(BaseModel):
"""Output from the real-time analysis agent."""
eval_note: float = Field(
ge=-1.0,
le=1.0,
description="Evaluation score from -1 (strong selling pressure) to 1 (strong buying pressure)."
)
confidence: float = Field(
ge=0.0,
le=1.0,
description="Confidence level of the real-time analysis (0-1)."
)
description: str = Field(
description="Summary description of the real-time market analysis."
)
price_momentum: Optional[float] = Field(
default=None,
ge=-1.0,
le=1.0,
description="Price momentum indicator from -1 (strong downward) to 1 (strong upward). Leave empty if no momentum."
)
current_status: Optional[str] = Field(
default=None,
description="Current market status: 'bullish', 'bearish', 'neutral', 'volatile'. Leave empty if unclear."
)
volume_signal: Optional[str] = Field(
default=None,
description="Volume analysis: 'high', 'normal', 'low'. Leave empty if no volume data."
)
urgency_level: Optional[str] = Field(
default=None,
description="Action urgency: 'immediate', 'high', 'medium', 'low', 'none'. Leave empty if no urgency."
)
critical_events: Optional[List[str]] = Field(
default=None,
description="Any critical events or catalysts detected. Leave empty if none."
)
recommendations: Optional[List[str]] = Field(
default=None,
description="Real-time trading recommendations. Leave empty if none."
)

@field_validator("current_status")
def validate_status(cls, v: str) -> str:
if v is None:
return None
allowed_statuses = ["bullish", "bearish", "neutral", "volatile"]
v_lower = v.lower()
if v_lower not in allowed_statuses:
raise ValueError(f"Status must be one of {allowed_statuses}")
return v_lower

@field_validator("volume_signal")
def validate_volume(cls, v: str) -> str:
if v is None:
return None
allowed_volumes = ["high", "normal", "low"]
v_lower = v.lower()
if v_lower not in allowed_volumes:
raise ValueError(f"Volume signal must be one of {allowed_volumes}")
return v_lower

@field_validator("urgency_level")
def validate_urgency(cls, v: str) -> str:
if v is None:
return None
allowed_urgencies = ["immediate", "high", "medium", "low", "none"]
v_lower = v.lower()
if v_lower not in allowed_urgencies:
raise ValueError(f"Urgency level must be one of {allowed_urgencies}")
return v_lower
117 changes: 117 additions & 0 deletions Agent/Evaluators/real_time_analysis_agent/real_time_analysis_agent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# Drakkar-Software OctoBot-Tentacles
# Copyright (c) Drakkar-Software, All rights reserved.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 3.0 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library.
import json

import octobot_agents as agent

from .models import RealTimeAnalysisOutput


class RealTimeAnalysisAIAgentChannel(agent.AbstractAgentChannel):
"""Channel for RealTimeAnalysisAIAgentProducer."""
OUTPUT_SCHEMA = RealTimeAnalysisOutput


class RealTimeAnalysisAIAgentConsumer(agent.AbstractAIAgentChannelConsumer):
"""Consumer for RealTimeAnalysisAIAgentProducer."""
pass


class RealTimeAnalysisAIAgentProducer(agent.AbstractAIAgentChannelProducer):
"""Producer specialized in real-time market analysis."""

AGENT_NAME = "RealTimeAnalysisAgent"
AGENT_VERSION = "1.0.0"
AGENT_CHANNEL = RealTimeAnalysisAIAgentChannel
AGENT_CONSUMER = RealTimeAnalysisAIAgentConsumer

def __init__(self, channel, **kwargs):
super().__init__(channel, **kwargs)

def _get_default_prompt(self) -> str:
return (
"You are a Real-Time Market Analysis AI expert. Follow these steps to analyze the provided real-time evaluator signals:\n"
"1. Examine real-time data comprehensively: Review order book dynamics, recent trades, price velocity, and market depth.\n"
"2. Assess market momentum: Determine current buying/selling pressure, accumulation/distribution patterns, and directional bias.\n"
"3. Evaluate market microstructure: Consider bid-ask spreads, order book imbalance, and trade flow characteristics.\n"
"4. Calculate momentum eval_note: Use the full range from -1 (strong selling pressure) to 1 (strong buying pressure), but most real-time data shows neutral to mild momentum.\n"
"5. Assess confidence (0-1) based on data quality: Higher confidence for strong, consistent signals; lower for noisy or conflicting data.\n"
"6. Provide detailed description: Explain current market dynamics, momentum indicators, and short-term outlook.\n\n"
"Important: Real-time momentum is rarely extreme. Use extreme values (-1/1) only for very strong, sustained pressure.\n\n"
"MANDATORY FIELDS (always include):\n"
"- eval_note: float between -1 (strong selling pressure) to 1 (strong buying pressure)\n"
"- confidence: float between 0 (low confidence) to 1 (high confidence)\n"
"- description: detailed explanation of current market momentum and dynamics\n\n"
"OPTIONAL FIELDS (only include if available):\n"
"- price_momentum: float for price momentum strength (-1 to 1) - Leave empty if not clearly identifiable\n"
"- current_status: string like 'accumulating', 'distributing', 'consolidating' - Leave empty if unclear\n"
"- volume_signal: string describing volume patterns - Leave empty if no strong volume signals\n"
"- urgency_level: string like 'low', 'medium', 'high' - Leave empty if no clear urgency\n"
"- critical_events: list of critical market events affecting momentum - Leave empty if none\n"
"- recommendations: list of action recommendations based on real-time analysis - Leave empty if none\n\n"
"If you lack data for any optional field, omit it from the response (leave as null).\n"
"Output only valid JSON matching the RealTimeAnalysisOutput schema."
)

async def execute(self, input_data, ai_service) -> dict:
"""Evaluate aggregated real-time market data."""
aggregated_data = input_data
if not aggregated_data:
return {
"eval_note": 0,
"eval_note_description": "No real-time market data available",
"confidence": 0,
}

data_str = json.dumps(aggregated_data, indent=2)

messages = [
ai_service.create_message("system", self.prompt),
ai_service.create_message(
"user",
f"Real-time market data:\n{data_str}\n\n"
"Provide evaluation as JSON matching the RealTimeAnalysisOutput schema. "
"Include mandatory fields (eval_note, confidence, description). "
"Include optional fields only if you have data for them.",
),
]

try:
# Uses RealTimeAnalysisAIAgentChannel.OUTPUT_SCHEMA by default
parsed = await self._call_llm(
messages,
ai_service,
json_output=True,
)
eval_note = float(parsed.get("eval_note", 0))
eval_note_description = parsed.get("description", "Real-time analysis")
confidence = float(parsed.get("confidence", 0))

# Clamp values
eval_note = max(-1, min(1, eval_note))
confidence = max(0, min(1, confidence))

return {
"eval_note": eval_note,
"eval_note_description": eval_note_description,
"confidence": int(confidence * 100), # Convert to 0-100 range
}
except RuntimeError as e:
return {
"eval_note": 0,
"eval_note_description": f"Error in real-time analysis: {str(e)}",
"confidence": 0,
}
29 changes: 29 additions & 0 deletions Agent/Evaluators/sentiment_analysis_agent/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Drakkar-Software OctoBot-Tentacles
# Copyright (c) Drakkar-Software, All rights reserved.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 3.0 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library.

from .sentiment_analysis_agent import (
SentimentAnalysisAIAgentChannel,
SentimentAnalysisAIAgentConsumer,
SentimentAnalysisAIAgentProducer,
)
from .models import SentimentAnalysisOutput

__all__ = [
"SentimentAnalysisAIAgentChannel",
"SentimentAnalysisAIAgentConsumer",
"SentimentAnalysisAIAgentProducer",
"SentimentAnalysisOutput",
]
6 changes: 6 additions & 0 deletions Agent/Evaluators/sentiment_analysis_agent/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"version": "1.0.0",
"origin_package": "OctoBot-Default-Tentacles",
"tentacles": ["SentimentAnalysisAgent"],
"tentacles-requirements": []
}
72 changes: 72 additions & 0 deletions Agent/Evaluators/sentiment_analysis_agent/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Drakkar-Software OctoBot-Tentacles
# Copyright (c) Drakkar-Software, All rights reserved.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 3.0 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library.

"""
Pydantic models for sentiment analysis agent outputs.
"""
from typing import List, Optional
from pydantic import BaseModel, Field, field_validator


class SentimentMetrics(BaseModel):
"""Sentiment analysis metrics."""
sentiment_score: float = Field(
ge=-1.0,
le=1.0,
description="Sentiment score from -1 (very negative) to 1 (very positive)."
)

@field_validator("sentiment_score")
def validate_score(cls, v: float) -> float:
return max(-1.0, min(1.0, v))


class SentimentAnalysisOutput(BaseModel):
"""Output from the sentiment analysis agent."""
eval_note: float = Field(
ge=-1.0,
le=1.0,
description="Evaluation score from -1 (very negative) to 1 (very positive)."
)
confidence: float = Field(
ge=0.0,
le=1.0,
description="Confidence level of the sentiment analysis (0-1)."
)
description: str = Field(
description="Summary description of the sentiment analysis."
)
sentiment_score: float = Field(
ge=-1.0,
le=1.0,
description="Detailed sentiment score from -1 to 1. Same as eval_note."
)
sources_analyzed: Optional[List[str]] = Field(
default=None,
description="Data sources used for sentiment analysis. Leave empty if none identified."
)
key_mentions: Optional[List[str]] = Field(
default=None,
description="Key mentions or topics driving sentiment. Leave empty if none."
)
market_implications: Optional[str] = Field(
default=None,
description="Implications of sentiment for market direction. Leave empty if unclear."
)
recommendations: Optional[List[str]] = Field(
default=None,
description="Trading recommendations based on sentiment. Leave empty if none."
)
Loading
Loading