Certamente. Ho analizzato lo script Pine Script “TAPLOT SlingShot”.
Analisi della Logica Originale:
- Indicatore: Calcola una EMA (Media Mobile Esponenziale) basata sui Massimi (
high), non sulla chiusura. La lunghezza di default è 4. - 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 dfNote per l’integrazione:
- Posizione: Salva il file in
fire/strategies/slingshot_strategy.py. - Configurabilità: Ho mantenuto
ema_length = 4nel costruttore. In futuro, potremo esporre questo parametro all’UI tramite un dizionarioself.params. - 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:
-
Modificare SlingShotStrategy per esporre la serie EMA.
-
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 :
- Lanci un backtest su STLAM.MI.
- Il backtest finisce.
- Nel frattempo, clicchi sulla watchlist su ENEL.MI (lo stato globale cambia).
- Clicchi “Copia Report” nel pannello dei risultati e il pannello con i trade log è vuoto! avviene già così ed è giusto che sia vuoto