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
|
# Re-export from base_collector for convenience
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'DataType',
|
'DataType',
|
||||||
|
|||||||
@ -8,7 +8,7 @@ from sqlalchemy import desc, and_, func
|
|||||||
from sqlalchemy.orm import joinedload
|
from sqlalchemy.orm import joinedload
|
||||||
|
|
||||||
from ..models import StrategySignal, StrategyRun
|
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
|
from .base_repository import BaseRepository, DatabaseOperationError
|
||||||
|
|
||||||
|
|
||||||
@ -95,23 +95,25 @@ class StrategyRepository(BaseRepository):
|
|||||||
with self.get_session() as session:
|
with self.get_session() as session:
|
||||||
for result in strategy_results:
|
for result in strategy_results:
|
||||||
for signal in result.signals:
|
for signal in result.signals:
|
||||||
strategy_signal = StrategySignal(
|
# Only store BUY or SELL signals, not HOLD
|
||||||
run_id=run_id,
|
if signal.signal_type.value in ["BUY", "SELL"]:
|
||||||
strategy_name=result.strategy_name,
|
strategy_signal = StrategySignal(
|
||||||
strategy_config=None, # Could be populated from StrategyRun.config
|
run_id=run_id,
|
||||||
symbol=signal.symbol,
|
strategy_name=result.strategy_name,
|
||||||
timeframe=signal.timeframe,
|
strategy_config=None, # Could be populated from StrategyRun.config
|
||||||
timestamp=signal.timestamp,
|
symbol=signal.symbol,
|
||||||
signal_type=signal.signal_type.value,
|
timeframe=signal.timeframe,
|
||||||
price=Decimal(str(signal.price)),
|
timestamp=signal.timestamp,
|
||||||
confidence=Decimal(str(signal.confidence)),
|
signal_type=signal.signal_type.value,
|
||||||
signal_metadata={
|
price=Decimal(str(signal.price)),
|
||||||
'indicators_used': result.indicators_used,
|
confidence=Decimal(str(signal.confidence)),
|
||||||
'metadata': signal.metadata or {}
|
signal_metadata={
|
||||||
}
|
'indicators_used': result.indicators_used,
|
||||||
)
|
'metadata': signal.metadata or {}
|
||||||
session.add(strategy_signal)
|
}
|
||||||
signals_stored += 1
|
)
|
||||||
|
session.add(strategy_signal)
|
||||||
|
signals_stored += 1
|
||||||
|
|
||||||
session.commit()
|
session.commit()
|
||||||
self.log_info(f"Stored {signals_stored} strategy signals for run {run_id}")
|
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 .base import BaseStrategy
|
||||||
from .factory import StrategyFactory
|
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 .manager import StrategyManager, StrategyConfig, StrategyType, StrategyCategory, get_strategy_manager
|
||||||
from .data_integration import StrategyDataIntegrator, StrategyDataIntegrationConfig, get_strategy_data_integrator
|
from .data_integration import StrategyDataIntegrator, StrategyDataIntegrationConfig, get_strategy_data_integrator
|
||||||
from .validation import StrategySignalValidator, ValidationConfig
|
from .validation import StrategySignalValidator, ValidationConfig
|
||||||
|
|||||||
@ -20,7 +20,7 @@ from data.common.data_types import OHLCVCandle
|
|||||||
from data.common.indicators import TechnicalIndicators
|
from data.common.indicators import TechnicalIndicators
|
||||||
from components.charts.config.indicator_defs import convert_database_candles_to_ohlcv
|
from components.charts.config.indicator_defs import convert_database_candles_to_ohlcv
|
||||||
from .factory import StrategyFactory
|
from .factory import StrategyFactory
|
||||||
from .data_types import StrategyResult
|
from data.common.data_types import StrategyResult
|
||||||
from utils.logger import get_logger
|
from utils.logger import get_logger
|
||||||
|
|
||||||
# Initialize 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
|
result = signal.strategy_result
|
||||||
context = signal.context
|
context = signal.context
|
||||||
|
|
||||||
signal_data.append({
|
# Only store BUY or SELL signals, not HOLD
|
||||||
'strategy_name': context.strategy_name,
|
if result.signal and result.signal.signal_type in [SignalType.BUY, SignalType.SELL]:
|
||||||
'strategy_config': context.strategy_config,
|
signal_data.append({
|
||||||
'symbol': context.symbol,
|
'strategy_name': context.strategy_name,
|
||||||
'timeframe': context.timeframe,
|
'strategy_config': context.strategy_config,
|
||||||
'exchange': context.exchange,
|
'symbol': context.symbol,
|
||||||
'timestamp': result.timestamp,
|
'timeframe': context.timeframe,
|
||||||
'signal_type': result.signal.signal_type.value if result.signal else 'HOLD',
|
'exchange': context.exchange,
|
||||||
'price': float(result.price) if result.price else None,
|
'timestamp': result.timestamp,
|
||||||
'confidence': result.confidence,
|
'signal_type': result.signal.signal_type.value,
|
||||||
'signal_metadata': result.metadata or {},
|
'price': float(result.price) if result.price else None,
|
||||||
'generation_time': signal.generation_time
|
'confidence': result.confidence,
|
||||||
})
|
'signal_metadata': result.metadata or {},
|
||||||
|
'generation_time': signal.generation_time
|
||||||
|
})
|
||||||
|
|
||||||
# Batch insert into database
|
if signal_data: # Only call store_signals_batch if there are signals to store
|
||||||
self.db_ops.strategy.store_signals_batch(signal_data)
|
# 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 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:
|
except Exception as e:
|
||||||
if self.logger:
|
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.
|
- **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.
|
- **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
|
## Tasks
|
||||||
|
|
||||||
- [x] 1.0 Core Strategy Foundation Setup
|
- [x] 1.0 Core Strategy Foundation Setup
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user