Files
Trading-Bot/src/risk/stops/trailing_stop.py
DaM f85c522f22 feat: finalize portfolio system and quantitative validation- Finalized MA_Crossover(30,100) and TrendFiltered_MA(30,100,ADX=15)
- 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
2026-02-02 14:38:05 +01:00

71 lines
1.9 KiB
Python

# src/risk/stops/trailing_stop.py
import pandas as pd
from src.risk.stops.base import StopLoss
from src.core.trade import TradeType, Position
class TrailingStop(StopLoss):
"""
Trailing Stop porcentual basado en el precio de cierre.
- LONG: el stop solo sube
- SHORT: el stop solo baja
"""
def __init__(self, trailing_fraction: float):
"""
Args:
trailing_fraction: ej 0.05 = 5%
"""
if trailing_fraction <= 0 or trailing_fraction >= 1:
raise ValueError("trailing_fraction debe estar entre 0 y 1")
self.trailing_fraction = trailing_fraction
def get_stop_price(
self,
*,
data: pd.DataFrame,
idx: int,
entry_price: float,
trade_type: TradeType
) -> float:
"""
Stop inicial al abrir la posición
"""
if trade_type == TradeType.LONG:
return entry_price * (1 - self.trailing_fraction)
elif trade_type == TradeType.SHORT:
return entry_price * (1 + self.trailing_fraction)
else:
raise ValueError(f"TradeType no soportado: {trade_type}")
def update_stop(
self,
*,
data: pd.DataFrame,
idx: int,
position: Position
) -> float | None:
"""
Calcula un nuevo stop si el precio ha mejorado.
Devuelve None si el stop no debe moverse.
"""
current_price = data.iloc[idx]["close"]
if position.trade_type == TradeType.LONG:
candidate = current_price * (1 - self.trailing_fraction)
if position.stop_price is None or candidate > position.stop_price:
return candidate
elif position.trade_type == TradeType.SHORT:
candidate = current_price * (1 + self.trailing_fraction)
if position.stop_price is None or candidate < position.stop_price:
return candidate
return None