Files
btc-trading/src/strategies/ma_strategy.py
2026-02-17 10:39:39 +01:00

78 lines
2.8 KiB
Python

"""
Moving Average Strategy
Configurable trend following strategy.
- Long when Price > MA(period)
- Short when Price < MA(period)
"""
from typing import Dict, Any, List, Optional
from .base import BaseStrategy, StrategySignal, SignalType
class MAStrategy(BaseStrategy):
"""
Configurable Moving Average Strategy.
Config:
- period: int - MA period (default: 44)
"""
DEFAULT_PERIOD = 44
@property
def name(self) -> str:
return "ma_trend"
@property
def required_indicators(self) -> List[str]:
# Dynamic based on config
period = self.config.get('period', self.DEFAULT_PERIOD)
return [f"ma{period}"]
@property
def display_name(self) -> str:
return "MA Strategy"
@property
def description(self) -> str:
return "Configurable Moving Average strategy. Parameters: period (5-500, default: 44). Goes long when price > MA(period), short when price < MA(period). Optional multi-timeframe trend filter available."
def analyze(
self,
candle: Dict[str, Any],
indicators: Dict[str, float],
current_position: Optional[Dict[str, Any]] = None
) -> StrategySignal:
period = self.config.get('period', self.DEFAULT_PERIOD)
ma_key = f"ma{period}"
price = candle['close']
ma_value = indicators.get(ma_key)
if ma_value is None:
return StrategySignal(SignalType.HOLD, 0.0, f"MA{period} not available")
# Current position state
is_long = current_position and current_position.get('type') == 'long'
is_short = current_position and current_position.get('type') == 'short'
# Logic: Price > MA -> Bullish
if price > ma_value:
if is_long:
return StrategySignal(SignalType.HOLD, 1.0, f"Price {price:.2f} > MA{period} {ma_value:.2f}. Stay Long.")
elif is_short:
return StrategySignal(SignalType.CLOSE_SHORT, 1.0, f"Price {price:.2f} crossed above MA{period} {ma_value:.2f}. Close Short.")
else:
return StrategySignal(SignalType.OPEN_LONG, 1.0, f"Price {price:.2f} > MA{period} {ma_value:.2f}. Open Long.")
# Logic: Price < MA -> Bearish
elif price < ma_value:
if is_short:
return StrategySignal(SignalType.HOLD, 1.0, f"Price {price:.2f} < MA{period} {ma_value:.2f}. Stay Short.")
elif is_long:
return StrategySignal(SignalType.CLOSE_LONG, 1.0, f"Price {price:.2f} crossed below MA{period} {ma_value:.2f}. Close Long.")
else:
return StrategySignal(SignalType.OPEN_SHORT, 1.0, f"Price {price:.2f} < MA{period} {ma_value:.2f}. Open Short.")
return StrategySignal(SignalType.HOLD, 0.0, f"Price == MA{period}")