{# Jinja2 template — rendered by generator.py to produce a valid Jesse strategy #}
# --- Generated by VARRD {{ version }} ---
# This strategy was statistically validated by VARRD before generation.
# Do NOT modify the entry logic without re-validating.
#
# Hypothesis: {{ hypothesis_name }}
# Market:     {{ market }} ({{ pair }})
# Direction:  {{ direction }}
# Timeframe:  {{ timeframe }}
#
# --- VARRD Validation Stats ---
{%- if has_edge is not none %}
# Edge:         {{ "YES" if has_edge else "NO" }}
{%- endif %}
{%- if win_rate is not none %}
# Win Rate:     {{ "%.1f"|format(win_rate * 100) }}%
{%- endif %}
{%- if sharpe is not none %}
# Sharpe:       {{ "%.2f"|format(sharpe) }}
{%- endif %}
{%- if ev_per_trade is not none %}
# EV/Trade:     {{ "%.2f"|format(ev_per_trade) }}%
{%- endif %}
{%- if profit_factor is not none %}
# Profit Factor: {{ "%.2f"|format(profit_factor) }}
{%- endif %}
{%- if total_trades is not none %}
# Total Trades: {{ total_trades }}
{%- endif %}
{%- if risk_reward is not none %}
# Risk/Reward:  {{ "%.2f"|format(risk_reward) }}
{%- endif %}
{%- if stop_loss_atr is not none %}
# Stop Loss:    {{ "%.1f"|format(stop_loss_atr) }}x ATR
{%- endif %}
{%- if take_profit_atr is not none %}
# Take Profit:  {{ "%.1f"|format(take_profit_atr) }}x ATR
{%- endif %}
{%- if selected_horizon is not none %}
# Horizon:      {{ selected_horizon }} bars
{%- endif %}
{%- if explanation %}
#
{{ explanation }}
{%- endif %}
# --------------------------------

from jesse.strategies import Strategy
import jesse.indicators as ta
from jesse import utils


class {{ strategy_class }}(Strategy):
    """
    {{ hypothesis_name }}

    Generated by VARRD — statistically validated before deployment.
    https://varrd.com
    """

    def before(self) -> None:
        """Compute indicators each candle (VARRD setup_code)."""
        {{ indicators_code }}

    def should_long(self) -> bool:
        """Entry signal for long positions (VARRD formula)."""
{%- if direction == "LONG" %}
        return {{ entry_expr }}
{%- else %}
        return False
{%- endif %}

    def should_short(self) -> bool:
        """Entry signal for short positions (VARRD formula)."""
{%- if direction == "SHORT" %}
        return {{ entry_expr }}
{%- else %}
        return False
{%- endif %}

    def should_cancel_entry(self) -> bool:
        return False

    def go_long(self) -> None:
        """Open long position with ATR-based SL/TP and risk-based sizing."""
        entry = self.price
{%- if stop_loss_atr is not none %}
        sl_distance = {{ sl_expr }}
        sl_price = entry - sl_distance
{%- else %}
        sl_price = entry * 0.95  # 5% fallback
        sl_distance = entry - sl_price
{%- endif %}
{%- if risk_percent is not none %}
        qty = utils.risk_to_qty(self.balance, {{ risk_percent }}, entry, sl_price)
{%- else %}
        qty = utils.risk_to_qty(self.balance, 1, entry, sl_price)
{%- endif %}
{%- if take_profit_atr is not none %}
        tp_price = entry + {{ tp_expr }}
        self.buy = qty, entry
        self.stop_loss = qty, sl_price
        self.take_profit = qty, tp_price
{%- else %}
        self.buy = qty, entry
        self.stop_loss = qty, sl_price
{%- endif %}

    def go_short(self) -> None:
        """Open short position with ATR-based SL/TP and risk-based sizing."""
        entry = self.price
{%- if stop_loss_atr is not none %}
        sl_distance = {{ sl_expr }}
        sl_price = entry + sl_distance
{%- else %}
        sl_price = entry * 1.05  # 5% fallback
        sl_distance = sl_price - entry
{%- endif %}
{%- if risk_percent is not none %}
        qty = utils.risk_to_qty(self.balance, {{ risk_percent }}, entry, sl_price)
{%- else %}
        qty = utils.risk_to_qty(self.balance, 1, entry, sl_price)
{%- endif %}
{%- if take_profit_atr is not none %}
        tp_price = entry - {{ tp_expr }}
        self.sell = qty, entry
        self.stop_loss = qty, sl_price
        self.take_profit = qty, tp_price
{%- else %}
        self.sell = qty, entry
        self.stop_loss = qty, sl_price
{%- endif %}
{%- if selected_horizon is not none %}

    def update_position(self) -> None:
        """Time-based exit after {{ selected_horizon }} bars."""
        if self.reduced_count == 0 and self.index >= {{ selected_horizon }}:
            self.liquidate()
{%- endif %}
