- Implemented portfolio engine with risk-based allocation (50/50) - Added equity-based metrics for system-level evaluation - Validated portfolio against standalone strategies - Reduced max drawdown and volatility at system level - Quantitative decision closed before paper trading phase
65 lines
2.0 KiB
Python
65 lines
2.0 KiB
Python
# src/strategies/rsi_strategy.py
|
|
"""
|
|
Estrategia basada en RSI
|
|
"""
|
|
import pandas as pd
|
|
from ..core.strategy import Strategy, Signal, calculate_rsi
|
|
|
|
class RSIStrategy(Strategy):
|
|
"""
|
|
Estrategia basada en RSI (Relative Strength Index)
|
|
|
|
Señales:
|
|
- BUY: Cuando RSI < oversold_threshold (mercado sobrevendido)
|
|
- SELL: Cuando RSI > overbought_threshold (mercado sobrecomprado)
|
|
- HOLD: RSI en zona neutral
|
|
|
|
Parámetros:
|
|
rsi_period: Periodo del RSI (default: 14)
|
|
oversold_threshold: Umbral de sobreventa (default: 30)
|
|
overbought_threshold: Umbral de sobrecompra (default: 70)
|
|
"""
|
|
|
|
def __init__(self, rsi_period: int = 14, oversold_threshold: float = 30, overbought_threshold: float = 70):
|
|
|
|
params = {
|
|
'rsi_period': rsi_period,
|
|
'oversold': oversold_threshold,
|
|
'overbought': overbought_threshold
|
|
}
|
|
|
|
super().__init__(name="RSI Strategy", params=params)
|
|
|
|
self.rsi_period = rsi_period
|
|
self.oversold = oversold_threshold
|
|
self.overbought = overbought_threshold
|
|
|
|
def init_indicators(self, data: pd.DataFrame) -> pd.DataFrame:
|
|
"""
|
|
Calcula el RSI
|
|
"""
|
|
data['rsi'] = calculate_rsi(data['close'], self.rsi_period)
|
|
return data
|
|
|
|
def generate_signal(self, idx: int) -> Signal:
|
|
"""
|
|
Genera señal basada en niveles de RSI
|
|
"""
|
|
if self.data is None:
|
|
raise ValueError("Data no establecida")
|
|
|
|
rsi = self.data.iloc[idx]['rsi']
|
|
|
|
# Verificar que RSI está calculado
|
|
if pd.isna(rsi):
|
|
return Signal.HOLD
|
|
|
|
# Sobreventa: señal de compra
|
|
if rsi < self.oversold and self.current_position <= 0:
|
|
return Signal.BUY
|
|
|
|
# Sobrecompra: señal de venta
|
|
elif rsi > self.overbought and self.current_position >= 0:
|
|
return Signal.SELL
|
|
|
|
return Signal.HOLD |