From 790bd9ccdd1299381c3c5bbabd7085a45a6fdbee Mon Sep 17 00:00:00 2001 From: Ajasra Date: Thu, 29 May 2025 13:05:44 +0800 Subject: [PATCH] exposing parameters for metatrand too --- IncrementalTrader/strategies/metatrend.py | 65 ++++++++++++++++++----- 1 file changed, 51 insertions(+), 14 deletions(-) diff --git a/IncrementalTrader/strategies/metatrend.py b/IncrementalTrader/strategies/metatrend.py index 54efb79..9e79999 100644 --- a/IncrementalTrader/strategies/metatrend.py +++ b/IncrementalTrader/strategies/metatrend.py @@ -65,6 +65,11 @@ class MetaTrendStrategy(IncStrategyBase): name: Strategy name/identifier weight: Strategy weight for combination (default: 1.0) params: Strategy parameters + - timeframe: Primary timeframe for analysis (default: "15min") + - enable_logging: Enable detailed logging (default: False) + - supertrend_periods: List of periods for Supertrend indicators (default: [12, 10, 11]) + - supertrend_multipliers: List of multipliers for Supertrend indicators (default: [3.0, 1.0, 2.0]) + - min_trend_agreement: Minimum fraction of indicators that must agree (default: 1.0, meaning all) """ super().__init__(name, weight, params) @@ -76,12 +81,28 @@ class MetaTrendStrategy(IncStrategyBase): if self.enable_logging: logger.setLevel(logging.DEBUG) - # Initialize Supertrend collection with exact parameters from original strategy - self.supertrend_configs = [ - (12, 3.0), # period=12, multiplier=3.0 - (10, 1.0), # period=10, multiplier=1.0 - (11, 2.0) # period=11, multiplier=2.0 - ] + # Get configurable Supertrend parameters from params or use defaults + default_periods = [12, 10, 11] + default_multipliers = [3.0, 1.0, 2.0] + + supertrend_periods = self.params.get("supertrend_periods", default_periods) + supertrend_multipliers = self.params.get("supertrend_multipliers", default_multipliers) + + # Validate parameters + if len(supertrend_periods) != len(supertrend_multipliers): + raise ValueError(f"supertrend_periods ({len(supertrend_periods)}) and " + f"supertrend_multipliers ({len(supertrend_multipliers)}) must have same length") + + if len(supertrend_periods) < 1: + raise ValueError("At least one Supertrend indicator is required") + + # Initialize Supertrend collection with configurable parameters + self.supertrend_configs = list(zip(supertrend_periods, supertrend_multipliers)) + + # Store agreement threshold + self.min_trend_agreement = self.params.get("min_trend_agreement", 1.0) + if not 0.0 <= self.min_trend_agreement <= 1.0: + raise ValueError("min_trend_agreement must be between 0.0 and 1.0") self.supertrend_collection = SupertrendCollection(self.supertrend_configs) @@ -101,6 +122,8 @@ class MetaTrendStrategy(IncStrategyBase): logger.info(f"MetaTrendStrategy initialized: timeframe={self.primary_timeframe}, " f"aggregation_enabled={self._timeframe_aggregator is not None}") + logger.info(f"Supertrend configs: {self.supertrend_configs}, " + f"min_agreement={self.min_trend_agreement}") if self.enable_logging: logger.info(f"Using new timeframe utilities with mathematically correct aggregation") @@ -292,10 +315,10 @@ class MetaTrendStrategy(IncStrategyBase): """ Calculate meta-trend from SupertrendCollection results. - Meta-trend logic (matching original DefaultStrategy): - - All 3 Supertrends must agree for directional signal - - If all trends are the same, meta-trend = that trend - - If trends disagree, meta-trend = 0 (neutral) + Meta-trend logic (enhanced with configurable agreement threshold): + - Uses min_trend_agreement to determine consensus requirement + - If agreement threshold is met for a direction, meta-trend = that direction + - If no consensus, meta-trend = 0 (neutral) Args: supertrend_results: Results from SupertrendCollection.update() @@ -304,12 +327,26 @@ class MetaTrendStrategy(IncStrategyBase): int: Meta-trend value (1, -1, or 0) """ trends = supertrend_results['trends'] + total_indicators = len(trends) - # Check if all trends agree - if all(trend == trends[0] for trend in trends): - return trends[0] # All agree: return the common trend + if total_indicators == 0: + return 0 + + # Count votes for each direction + uptrend_votes = sum(1 for trend in trends if trend == 1) + downtrend_votes = sum(1 for trend in trends if trend == -1) + + # Calculate agreement percentages + uptrend_agreement = uptrend_votes / total_indicators + downtrend_agreement = downtrend_votes / total_indicators + + # Check if agreement threshold is met + if uptrend_agreement >= self.min_trend_agreement: + return 1 + elif downtrend_agreement >= self.min_trend_agreement: + return -1 else: - return 0 # Neutral when trends disagree + return 0 # No consensus def _check_entry_condition(self) -> bool: """