# VAMPStrategy.py - Freqtrade Strategy for VAMP from freqtrade.strategy import IStrategy from pandas import DataFrame import redis import hashlib import numpy as np import os import sys # Add path for UPE sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) from adapters.upe import upe_fingerprint class VAMPStrategy(IStrategy): """ VAMP Strategy - Uses Redis brain with 90% win rate clusters """ # Strategy parameters timeframe = '5m' startup_candle_count = 50 # ROI table - take profit at these levels minimal_roi = { "0": 0.02, # 2% profit "10": 0.01, # 1% after 10 minutes "30": 0.005, # 0.5% after 30 minutes "60": 0 # Any profit after 60 minutes } # Stop loss stoploss = -0.02 # 2% stop loss trailing_stop = True trailing_stop_positive = 0.01 trailing_stop_positive_offset = 0.02 # Trade settings use_exit_signal = True exit_profit_only = False ignore_roi_if_entry_signal = False # Number of candles to use for UPE window_size = 50 def __init__(self, config: dict) -> None: super().__init__(config) # Connect to Redis redis_host = os.getenv('REDIS_HOST', 'vamp_redis') self.redis = redis.Redis(host=redis_host, port=6379, decode_responses=True) # Load DECIDE script try: with open('lua/DECIDE.lua', 'r') as f: self.DECIDE_SHA = self.redis.script_load(f.read()) print(f"[VAMP] DECIDE script loaded: {self.DECIDE_SHA}") except Exception as e: print(f"[VAMP] Error loading DECIDE script: {e}") self.DECIDE_SHA = None # Load SETTLE script try: with open('lua/SETTLE.lua', 'r') as f: self.SETTLE_SHA = self.redis.script_load(f.read()) print(f"[VAMP] SETTLE script loaded: {self.SETTLE_SHA}") except Exception as e: print(f"[VAMP] Error loading SETTLE script: {e}") self.SETTLE_SHA = None print("[VAMP] Strategy initialized - Connected to Redis brain with 90% win rate clusters!") def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: """ Add any indicators we need (none for VAMP - we use UPE) """ # We don't need traditional indicators - VAMP uses chaos signatures dataframe['volume_check'] = dataframe['volume'] > 0 return dataframe def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: """ Based on VAMP Redis brain decisions """ dataframe.loc[:, 'enter_long'] = 0 dataframe.loc[:, 'enter_short'] = 0 if not self.DECIDE_SHA: print("[VAMP] No DECIDE script loaded, skipping") return dataframe # Only check the last candle if len(dataframe) < self.window_size: return dataframe # Get last 50 closes for UPE closes = dataframe['close'].iloc[-self.window_size:].values.tolist() try: # Calculate UPE fingerprint fp, cid, metrics = upe_fingerprint(closes) # Get pair name pair = metadata['pair'].replace('/', '').lower() # Query Redis brain for decision result = self.redis.evalsha( self.DECIDE_SHA, 0, "crypto", pair, self.timeframe, fp, cid, str(int(dataframe['date'].iloc[-1].timestamp())), "ENTER_LONG,ENTER_SHORT,HOLD" ) action, source = result.split("|") # Log decision print(f"[VAMP] {pair} | Pattern: {metrics['state']} | Decision: {action} via {source}") # Check cluster stats cluster_key = f"cluster:crypto:{pair}:{self.timeframe}:{cid}" cluster_data = self.redis.hgetall(cluster_key) if cluster_data: winrate = cluster_data.get('winrate', '0') winrate_long = cluster_data.get('winrate_long', '0') winrate_short = cluster_data.get('winrate_short', '0') locked = cluster_data.get('locked_action', 'none') print(f"[VAMP] Cluster {cid[:6]} | WR: {winrate} | Long: {winrate_long} | Short: {winrate_short} | Locked: {locked}") # Set entry signals based on VAMP decision if action == "ENTER_LONG": dataframe.loc[dataframe.index[-1], 'enter_long'] = 1 print(f"[VAMP] ✅ LONG signal for {pair}") elif action == "ENTER_SHORT": dataframe.loc[dataframe.index[-1], 'enter_short'] = 1 print(f"[VAMP] ✅ SHORT signal for {pair}") except Exception as e: print(f"[VAMP] Error in decision: {e}") return dataframe def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: """ Exit signals - can be based on VAMP or let ROI/stoploss handle it """ dataframe.loc[:, 'exit_long'] = 0 dataframe.loc[:, 'exit_short'] = 0 # For now, let ROI and stoploss handle exits # Could add VAMP-based exits later return dataframe def confirm_trade_entry(self, pair: str, order_type: str, amount: float, rate: float, time_in_force: str, current_time, entry_tag, side: str, **kwargs) -> bool: """ Final confirmation before trade execution """ print(f"[VAMP] Confirming {side} trade for {pair} at {rate}") # Could add additional checks here # For now, trust the VAMP brain return True def confirm_trade_exit(self, pair: str, trade, order_type: str, amount: float, rate: float, time_in_force: str, exit_reason: str, current_time, **kwargs) -> bool: """ Final confirmation before trade exit """ profit_pct = trade.calc_profit_ratio(rate) * 100 print(f"[VAMP] Exiting {pair} | Reason: {exit_reason} | Profit: {profit_pct:.2f}%") # Log to Redis for SETTLE later # This helps VAMP learn from outcomes return True