need commit to update repository

This commit is contained in:
DaM
2026-03-09 07:59:49 +01:00
parent ca36383bb3
commit f3de09067e
27 changed files with 1134 additions and 459 deletions

View File

@@ -0,0 +1,130 @@
#src/strategies/donchian_breakout.py
"""
Estrategia de breakout de rango Donchian.
"""
from __future__ import annotations
import pandas as pd
from ..core.strategy import Strategy, Signal, calculate_donchian_channels, cross_above, cross_below
class DonchianBreakout(Strategy):
"""
Breakout de máximos/mínimos de N barras.
Señales:
- BUY: close rompe por encima del máximo Donchian previo
- SELL: close rompe por debajo del mínimo Donchian previo
"""
strategy_id = "donchian_breakout"
strategy_family = "breakout"
display_name = "Donchian Breakout"
description = "Breakout de rango basado en máximos y mínimos rolling."
def __init__(self, donchian_window: int = 20, exit_window: int = 10):
params = {
"donchian_window": donchian_window,
"exit_window": exit_window,
}
super().__init__(name="Donchian Breakout", params=params)
self.donchian_window = int(donchian_window)
self.exit_window = int(exit_window)
@classmethod
def default_parameters(cls) -> dict:
return {
"donchian_window": 20,
"exit_window": 10,
}
@classmethod
def strategy_metadata(cls) -> dict:
return {
"strategy_id": cls.strategy_id,
"name": cls.display_name,
"family": cls.strategy_family,
"direction": "long_short",
"description": cls.description,
}
@classmethod
def strategy_definition(cls) -> dict:
return {
"meta": cls.strategy_metadata(),
"defaults": cls.default_parameters(),
"parameters_schema": cls.parameters_schema(),
}
@classmethod
def parameters_schema(cls) -> dict:
return {
"donchian_window": {
"type": "int",
"min": 2,
"max": 300,
"default": 20,
},
"exit_window": {
"type": "int",
"min": 2,
"max": 300,
"default": 10,
},
}
def init_indicators(self, data: pd.DataFrame) -> pd.DataFrame:
high = data["high"]
low = data["low"]
close = data["close"]
data["donchian_high"], data["donchian_low"] = calculate_donchian_channels(
high,
low,
period=self.donchian_window,
shift=1,
)
data["exit_high"], data["exit_low"] = calculate_donchian_channels(
high,
low,
period=self.exit_window,
shift=1,
)
data["breakout_up"] = cross_above(close, data["donchian_high"])
data["breakout_down"] = cross_below(close, data["donchian_low"])
data["lose_exit_low"] = cross_below(close, data["exit_low"])
data["lose_exit_high"] = cross_above(close, data["exit_high"])
return data
def generate_signal(self, idx: int) -> Signal:
if self.data is None:
raise ValueError("Data no establecida")
if idx < 1:
return Signal.HOLD
row = self.data.iloc[idx]
needed = ["donchian_high", "donchian_low", "exit_high", "exit_low"]
if any(pd.isna(row[c]) for c in needed):
return Signal.HOLD
if bool(row["breakout_up"]) and self.current_position <= 0:
return Signal.BUY
if bool(row["breakout_down"]) and self.current_position >= 0:
return Signal.SELL
if self.current_position > 0 and bool(row["lose_exit_low"]):
return Signal.SELL
if self.current_position < 0 and bool(row["lose_exit_high"]):
return Signal.BUY
return Signal.HOLD