Certamente. Ho analizzato lo script Pine Script “TAPLOT SlingShot”.

Analisi della Logica Originale:

  1. Indicatore: Calcola una EMA (Media Mobile Esponenziale) basata sui Massimi (high), non sulla chiusura. La lunghezza di default è 4.
  2. Trigger (SlingShot):
    • La candela corrente chiude sopra la EMA dei massimi.
    • Le 3 candele precedenti hanno chiuso sotto la rispettiva EMA dei massimi.
    • Concetto: Identifica un pullback di 3 barre in un trend, seguito da una rottura al rialzo.

Piano di Implementazione per FIRE: Creeremo una nuova strategia Python che eredita da BaseStrategy. Utilizzeremo pandas per il calcolo vettoriale (veloce) della EMA e delle condizioni logiche, senza cicli for.

Ecco il file completo per la nuova strategia.

Delta modifiche: +58 / -0 (Nuovo File)

# VERSION: v1.0 - fire/strategies/slingshot_strategy.py
# RESP: Implementazione della strategia "TAPLOT SlingShot" convertita da Pine Script.
# DEPS: pandas, fire.strategies.base_strategy
# ARCH_ROLE: feature
# LAYER: fire-app
 
import pandas as pd
import logging
from fire.strategies.base_strategy import BaseStrategy
 
logger = logging.getLogger(__name__)
 
class SlingShotStrategy(BaseStrategy):
    """
    TAPLOT SlingShot Strategy
    
    Conversione diretta dall'indicatore Pine Script di TaPlot.
    Identifica setup di continuazione del trend dopo un pullback.
    
    Logica:
    1. Calcola EMA(High, 4)
    2. Trigger Long se:
       - Close > EMA
       - Close[1] < EMA[1]
       - Close[2] < EMA[2]
       - Close[3] < EMA[3]
    """
 
    def __init__(self):
        # Nome e descrizione per l'UI
        super().__init__(
            name="TAPLOT SlingShot", 
            description="Setup di pullback momentum basato su EMA 4 dei Massimi."
        )
        # Parametri configurabili (hardcoded per ora come da standard v1.0)
        self.ema_length = 4
 
    def generate_signals(self, df: pd.DataFrame) -> pd.DataFrame:
        """
        Applica la logica della strategia al DataFrame dei dati di mercato.
        """
        # 0. Pulizia preliminare standard
        df = df.copy()
        if 'signal' not in df.columns:
            df['signal'] = 0
        
        # 1. Calcolo Indicatori
        # Pine: EMALine = ta.ema(high, EMAlen)
        # Nota: Usiamo 'adjust=False' per replicare il comportamento standard delle EMA di TradingView
        df['ema_high'] = df['high'].ewm(span=self.ema_length, adjust=False).mean()
 
        # 2. Preparazione dati shiftati per confronto veloce (vettoriale)
        close = df['close']
        ema = df['ema_high']
        
        # Shift [1], [2], [3] come in Pine Script
        close_1 = close.shift(1)
        ema_1 = ema.shift(1)
        
        close_2 = close.shift(2)
        ema_2 = ema.shift(2)
        
        close_3 = close.shift(3)
        ema_3 = ema.shift(3)
 
        # 3. Logica di Ingresso (The Slingshot)
        # Pine: close > EMALine and close[1] < EMALine[1] and close[2] < EMALine[2] and close[3] < EMALine[3]
        entry_condition = (
            (close > ema) &       # Rottura al rialzo corrente
            (close_1 < ema_1) &   # Pullback barra precedente
            (close_2 < ema_2) &   # Pullback 2 barre fa
            (close_3 < ema_3)     # Pullback 3 barre fa
        )
 
        # 4. Applicazione Segnali
        df.loc[entry_condition, 'signal'] = 1
        df.loc[entry_condition, 'entry_type'] = 'long'
        df.loc[entry_condition, 'entry_reason'] = 'Slingshot Trigger (3-bar pullback break)'
 
        # 5. Logica di Uscita (Opzionale/Default)
        # Lo script originale NON definisce una uscita, è solo un segnale di entry.
        # Per permettere il backtest in FIRE, aggiungiamo una uscita semplice se il prezzo chiude sotto la EMA.
        # In un utilizzo reale "Scanner", questo non serve, ma per il "Backtester" è utile.
        exit_condition = (close < ema) & (df['signal'] != 1) # Non uscire se stiamo entrando
        
        df.loc[exit_condition, 'signal'] = -1
        df.loc[exit_condition, 'exit_type'] = 'close_position'
        df.loc[exit_condition, 'exit_reason'] = 'Trend Broken (Close < EMA High)'
 
        return df

Note per l’integrazione:

  1. Posizione: Salva il file in fire/strategies/slingshot_strategy.py.
  2. Configurabilità: Ho mantenuto ema_length = 4 nel costruttore. In futuro, potremo esporre questo parametro all’UI tramite un dizionario self.params.
  3. Uscita: Poiché lo script originale è un indicator (segnala solo l’ingresso), ho dovuto inferire una logica di uscita basilare (Close < EMA) per renderlo testabile nel modulo Backtest. Se lo usi solo nello Scanner, ignorerà semplicemente i segnali di uscita.

Vuoi che proceda a creare un Test Manuale (secondo le Testing Guidelines) per verificare che i segnali vengano generati correttamente?


3. Visual Parity (Colori, Linee e Pallini)

Attualmente FIRE mostra solo le frecce di Buy/Sell generate dal motore. Manca la parte di “Visualizzazione Personalizzata” che in PineScript fai con plot, barcolor e plotshape.

Per ottenere lo stesso risultato in FIRE, dobbiamo estendere la strategia per “esportare” queste informazioni grafiche in modo che il LightweightChartWidget possa disegnarle.

Attualmente, l’architettura di FIRE gestisce automaticamente i trade, ma per Linee Custom (EMA) e Colori Barre, serve un passaggio in più.

Prossimo Passo Operativo:
Vuoi che implementi la visualizzazione della linea EMA arancione sul grafico?
Questo richiede di:

  1. Modificare SlingShotStrategy per esporre la serie EMA.

  2. Verificare se il BacktestPlottingHandler è configurato per leggere e disegnare indicatori extra (di solito tramite un attributo self.indicators o un metodo get_extra_plots).

Dato che stiamo lavorando in un contesto “Backtest”, la cosa più semplice e immediata per ora è verificare la correttezza logica (punto 2). Se quella torna, possiamo occuparci della “cosmetica” (linee e colori).


Il Problema Fondamentale: “Stato Vivo” vs “Snapshot”

Quando un utente copia un report, si aspetta di vedere i dati relativi in quel momento.

  • Scenario :
    1. Lanci un backtest su STLAM.MI.
    2. Il backtest finisce.
    3. Nel frattempo, clicchi sulla watchlist su ENEL.MI (lo stato globale cambia).
    4. Clicchi “Copia Report” nel pannello dei risultati e il pannello con i trade log è vuoto! avviene già così ed è giusto che sia vuoto