4.0
- fixing data-type circular import - removing HOLD signal from saving to database to reduce data size
This commit is contained in:
parent
0d6bfea48a
commit
061b467d43
@ -201,6 +201,67 @@ class ProcessingStats:
|
||||
}
|
||||
|
||||
|
||||
class SignalType(str, Enum):
|
||||
"""
|
||||
Types of trading signals that strategies can generate.
|
||||
"""
|
||||
BUY = "buy"
|
||||
SELL = "sell"
|
||||
HOLD = "hold"
|
||||
ENTRY_LONG = "entry_long"
|
||||
EXIT_LONG = "exit_long"
|
||||
ENTRY_SHORT = "entry_short"
|
||||
EXIT_SHORT = "exit_short"
|
||||
STOP_LOSS = "stop_loss"
|
||||
TAKE_PROFIT = "take_profit"
|
||||
|
||||
|
||||
@dataclass
|
||||
class StrategySignal:
|
||||
"""
|
||||
Container for individual strategy signals.
|
||||
|
||||
Attributes:
|
||||
timestamp: Signal timestamp (right-aligned with candle)
|
||||
symbol: Trading symbol
|
||||
timeframe: Candle timeframe
|
||||
signal_type: Type of signal (buy/sell/hold etc.)
|
||||
price: Price at which signal was generated
|
||||
confidence: Signal confidence score (0.0 to 1.0)
|
||||
metadata: Additional signal metadata (e.g., indicator values)
|
||||
"""
|
||||
timestamp: datetime
|
||||
symbol: str
|
||||
timeframe: str
|
||||
signal_type: SignalType
|
||||
price: float
|
||||
confidence: float = 1.0
|
||||
metadata: Optional[Dict[str, Any]] = None
|
||||
|
||||
|
||||
@dataclass
|
||||
class StrategyResult:
|
||||
"""
|
||||
Container for strategy calculation results.
|
||||
|
||||
Attributes:
|
||||
timestamp: Candle timestamp (right-aligned)
|
||||
symbol: Trading symbol
|
||||
timeframe: Candle timeframe
|
||||
strategy_name: Name of the strategy that generated this result
|
||||
signals: List[StrategySignal]
|
||||
indicators_used: Dictionary of indicator values used in calculation
|
||||
metadata: Additional calculation metadata
|
||||
"""
|
||||
timestamp: datetime
|
||||
symbol: str
|
||||
timeframe: str
|
||||
strategy_name: str
|
||||
signals: List[StrategySignal]
|
||||
indicators_used: Dict[str, float]
|
||||
metadata: Optional[Dict[str, Any]] = None
|
||||
|
||||
|
||||
# Re-export from base_collector for convenience
|
||||
__all__ = [
|
||||
'DataType',
|
||||
|
||||
@ -8,7 +8,7 @@ from sqlalchemy import desc, and_, func
|
||||
from sqlalchemy.orm import joinedload
|
||||
|
||||
from ..models import StrategySignal, StrategyRun
|
||||
from strategies.data_types import StrategySignal as StrategySignalDataType, StrategyResult
|
||||
from data.common.data_types import StrategySignal as StrategySignalDataType, StrategyResult
|
||||
from .base_repository import BaseRepository, DatabaseOperationError
|
||||
|
||||
|
||||
@ -95,23 +95,25 @@ class StrategyRepository(BaseRepository):
|
||||
with self.get_session() as session:
|
||||
for result in strategy_results:
|
||||
for signal in result.signals:
|
||||
strategy_signal = StrategySignal(
|
||||
run_id=run_id,
|
||||
strategy_name=result.strategy_name,
|
||||
strategy_config=None, # Could be populated from StrategyRun.config
|
||||
symbol=signal.symbol,
|
||||
timeframe=signal.timeframe,
|
||||
timestamp=signal.timestamp,
|
||||
signal_type=signal.signal_type.value,
|
||||
price=Decimal(str(signal.price)),
|
||||
confidence=Decimal(str(signal.confidence)),
|
||||
signal_metadata={
|
||||
'indicators_used': result.indicators_used,
|
||||
'metadata': signal.metadata or {}
|
||||
}
|
||||
)
|
||||
session.add(strategy_signal)
|
||||
signals_stored += 1
|
||||
# Only store BUY or SELL signals, not HOLD
|
||||
if signal.signal_type.value in ["BUY", "SELL"]:
|
||||
strategy_signal = StrategySignal(
|
||||
run_id=run_id,
|
||||
strategy_name=result.strategy_name,
|
||||
strategy_config=None, # Could be populated from StrategyRun.config
|
||||
symbol=signal.symbol,
|
||||
timeframe=signal.timeframe,
|
||||
timestamp=signal.timestamp,
|
||||
signal_type=signal.signal_type.value,
|
||||
price=Decimal(str(signal.price)),
|
||||
confidence=Decimal(str(signal.confidence)),
|
||||
signal_metadata={
|
||||
'indicators_used': result.indicators_used,
|
||||
'metadata': signal.metadata or {}
|
||||
}
|
||||
)
|
||||
session.add(strategy_signal)
|
||||
signals_stored += 1
|
||||
|
||||
session.commit()
|
||||
self.log_info(f"Stored {signals_stored} strategy signals for run {run_id}")
|
||||
|
||||
@ -14,7 +14,7 @@ IMPORTANT: Mirrors Indicator Patterns
|
||||
|
||||
from .base import BaseStrategy
|
||||
from .factory import StrategyFactory
|
||||
from .data_types import StrategySignal, SignalType, StrategyResult
|
||||
from data.common.data_types import StrategySignal, SignalType, StrategyResult
|
||||
from .manager import StrategyManager, StrategyConfig, StrategyType, StrategyCategory, get_strategy_manager
|
||||
from .data_integration import StrategyDataIntegrator, StrategyDataIntegrationConfig, get_strategy_data_integrator
|
||||
from .validation import StrategySignalValidator, ValidationConfig
|
||||
|
||||
@ -20,7 +20,7 @@ from data.common.data_types import OHLCVCandle
|
||||
from data.common.indicators import TechnicalIndicators
|
||||
from components.charts.config.indicator_defs import convert_database_candles_to_ohlcv
|
||||
from .factory import StrategyFactory
|
||||
from .data_types import StrategyResult
|
||||
from data.common.data_types import StrategyResult
|
||||
from utils.logger import get_logger
|
||||
|
||||
# Initialize logger
|
||||
|
||||
@ -1,72 +0,0 @@
|
||||
"""
|
||||
Strategy Data Types and Signal Definitions
|
||||
|
||||
This module provides data types for strategy calculations, signals,
|
||||
and results in a standardized format.
|
||||
"""
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from typing import Dict, Optional, Any, List
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class SignalType(str, Enum):
|
||||
"""
|
||||
Types of trading signals that strategies can generate.
|
||||
"""
|
||||
BUY = "buy"
|
||||
SELL = "sell"
|
||||
HOLD = "hold"
|
||||
ENTRY_LONG = "entry_long"
|
||||
EXIT_LONG = "exit_long"
|
||||
ENTRY_SHORT = "entry_short"
|
||||
EXIT_SHORT = "exit_short"
|
||||
STOP_LOSS = "stop_loss"
|
||||
TAKE_PROFIT = "take_profit"
|
||||
|
||||
|
||||
@dataclass
|
||||
class StrategySignal:
|
||||
"""
|
||||
Container for individual strategy signals.
|
||||
|
||||
Attributes:
|
||||
timestamp: Signal timestamp (right-aligned with candle)
|
||||
symbol: Trading symbol
|
||||
timeframe: Candle timeframe
|
||||
signal_type: Type of signal (buy/sell/hold etc.)
|
||||
price: Price at which signal was generated
|
||||
confidence: Signal confidence score (0.0 to 1.0)
|
||||
metadata: Additional signal metadata (e.g., indicator values)
|
||||
"""
|
||||
timestamp: datetime
|
||||
symbol: str
|
||||
timeframe: str
|
||||
signal_type: SignalType
|
||||
price: float
|
||||
confidence: float = 1.0
|
||||
metadata: Optional[Dict[str, Any]] = None
|
||||
|
||||
|
||||
@dataclass
|
||||
class StrategyResult:
|
||||
"""
|
||||
Container for strategy calculation results.
|
||||
|
||||
Attributes:
|
||||
timestamp: Candle timestamp (right-aligned)
|
||||
symbol: Trading symbol
|
||||
timeframe: Candle timeframe
|
||||
strategy_name: Name of the strategy that generated this result
|
||||
signals: List of signals generated for this timestamp
|
||||
indicators_used: Dictionary of indicator values used in calculation
|
||||
metadata: Additional calculation metadata
|
||||
"""
|
||||
timestamp: datetime
|
||||
symbol: str
|
||||
timeframe: str
|
||||
strategy_name: str
|
||||
signals: List[StrategySignal]
|
||||
indicators_used: Dict[str, float]
|
||||
metadata: Optional[Dict[str, Any]] = None
|
||||
@ -207,25 +207,31 @@ class StrategySignalBroadcaster:
|
||||
result = signal.strategy_result
|
||||
context = signal.context
|
||||
|
||||
signal_data.append({
|
||||
'strategy_name': context.strategy_name,
|
||||
'strategy_config': context.strategy_config,
|
||||
'symbol': context.symbol,
|
||||
'timeframe': context.timeframe,
|
||||
'exchange': context.exchange,
|
||||
'timestamp': result.timestamp,
|
||||
'signal_type': result.signal.signal_type.value if result.signal else 'HOLD',
|
||||
'price': float(result.price) if result.price else None,
|
||||
'confidence': result.confidence,
|
||||
'signal_metadata': result.metadata or {},
|
||||
'generation_time': signal.generation_time
|
||||
})
|
||||
# Only store BUY or SELL signals, not HOLD
|
||||
if result.signal and result.signal.signal_type in [SignalType.BUY, SignalType.SELL]:
|
||||
signal_data.append({
|
||||
'strategy_name': context.strategy_name,
|
||||
'strategy_config': context.strategy_config,
|
||||
'symbol': context.symbol,
|
||||
'timeframe': context.timeframe,
|
||||
'exchange': context.exchange,
|
||||
'timestamp': result.timestamp,
|
||||
'signal_type': result.signal.signal_type.value,
|
||||
'price': float(result.price) if result.price else None,
|
||||
'confidence': result.confidence,
|
||||
'signal_metadata': result.metadata or {},
|
||||
'generation_time': signal.generation_time
|
||||
})
|
||||
|
||||
# Batch insert into database
|
||||
self.db_ops.strategy.store_signals_batch(signal_data)
|
||||
|
||||
if self.logger:
|
||||
self.logger.debug(f"Stored batch of {len(signals)} real-time signals")
|
||||
if signal_data: # Only call store_signals_batch if there are signals to store
|
||||
# Batch insert into database
|
||||
self.db_ops.strategy.store_signals_batch(signal_data)
|
||||
|
||||
if self.logger:
|
||||
self.logger.debug(f"Stored batch of {len(signal_data)} real-time signals")
|
||||
else:
|
||||
if self.logger:
|
||||
self.logger.debug("No BUY/SELL signals to store in this batch.")
|
||||
|
||||
except Exception as e:
|
||||
if self.logger:
|
||||
|
||||
@ -102,6 +102,11 @@
|
||||
- **Reasoning**: Real-time strategy execution requires different architecture than batch processing - event-driven triggers, background signal processing, throttled chart updates, and integration with existing dashboard refresh cycles.
|
||||
- **Impact**: Enables live strategy signal generation that integrates seamlessly with the existing chart system. Provides concurrent strategy execution, real-time signal storage, error handling with automatic strategy disabling, and performance monitoring for production use.
|
||||
|
||||
### 11. Exclusion of "HOLD" Signals from All Signal Storage
|
||||
- **Decision**: Modified signal storage mechanisms across both real-time and batch processing to exclude "HOLD" signals, only persisting explicit "BUY" or "SELL" signals in the database.
|
||||
- **Reasoning**: To significantly reduce data volume and improve storage/query performance across all execution types, as the absence of a BUY/SELL signal implicitly means "HOLD" and can be inferred during analysis or visualization.
|
||||
- **Impact**: Leads to more efficient database usage and faster data retrieval for all stored signals. Requires careful handling in visualization and backtesting components to correctly interpret gaps as "HOLD" periods.
|
||||
|
||||
## Tasks
|
||||
|
||||
- [x] 1.0 Core Strategy Foundation Setup
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user