//+------------------------------------------------------------------+
//|                                         TrailingSkipHopfield.mqh |
//|                                  Copyright 2026, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert\ExpertTrailing.mqh>

// wizard description start
//+------------------------------------------------------------------+
//| Description of the class                                         |
//| Title=Trailing Stop with Skip List and Hopfield Network          |
//| Type=Trailing                                                    |
//| Name=SkipHopfield                                                |
//| Class=CTrailingSkipHopfield                                      |
//| Page=                                                            |
//| Parameter=SkipLevels,int,4,Max Skip List Levels                  |
//| Parameter=SkipMode,int,1,Skip List Mode (1 to 4)                 |
//| Parameter=UseHopfield,bool,true,Use Hopfield Network             |
//| Parameter=HopThreshold,double,-0.5,Hopfield Energy Threshold     |
//+------------------------------------------------------------------+
// wizard description end

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CTrailingSkipHopfield : public CExpertTrailing
  {
protected:
   //--- Skip List Parameters
   int               m_skip_levels;
   int               m_skip_mode;

   //--- Hopfield Network Parameters
   bool              m_use_hopfield;
   double            m_hop_threshold;
   double            m_weights[3][3];  //--- 3x3 Weight Matrix for Associative Memory
   double            m_state[3];       //--- 3-Neuron State (1.0 or -1.0)
   double            m_last_price;

   //--- Algorithm Iterations (Skip List Modes)
   double            SkipSearchLinear(double price);       //--- Mode 1
   double            SkipSearchGap(double price);          //--- Mode 2
   double            SkipSearchProbabilistic(double price);//--- Mode 3
   double            SkipSearchHybrid(double price);       //--- Mode 4

   //--- Neural Network Logic
   void              UpdateHopfield(double price);
   double            GetHopfieldEnergy();

public:
                     CTrailingSkipHopfield(void);
                    ~CTrailingSkipHopfield(void);

   //--- Setters for Wizard
   void              SkipLevels(int levels)     { m_skip_levels = levels;     }
   void              SkipMode(int mode)         { m_skip_mode = mode;         }
   void              UseHopfield(bool use)      { m_use_hopfield = use;       }
   void              HopThreshold(double t)     { m_hop_threshold = t;        }

   virtual bool      InitIndicators(CIndicators *indicators) override;
   virtual bool      CheckTrailingStopLong(CPositionInfo *position, double &sl, double &tp) override;
   virtual bool      CheckTrailingStopShort(CPositionInfo *position, double &sl, double &tp) override;
  };

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CTrailingSkipHopfield::CTrailingSkipHopfield(void) : m_last_price(0.0)
  {
  }

//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CTrailingSkipHopfield::~CTrailingSkipHopfield(void)
  {
  }

//+------------------------------------------------------------------+
//| Initialization: Set up Hopfield Weights                          |
//+------------------------------------------------------------------+
bool CTrailingSkipHopfield::InitIndicators(CIndicators *indicators)
  {
   if(!CExpertTrailing::InitIndicators(indicators))
      return false;
//--- Initialize Hopfield Weights with a basic stable memory pattern
   ArrayInitialize(m_state, 1.0);
   for(int i = 0; i < 3; i++)
     {
      for(int j = 0; j < 3; j++)
        {
         if(i == j)
            m_weights[i][j] = 0.0; //--- No self-connections
         else
            m_weights[i][j] = 0.5;       //--- Simple associative pull
        }
     }
   return true;
  }

//+------------------------------------------------------------------+
//| Check Long: Skip List -> Hopfield -> Execution                   |
//+------------------------------------------------------------------+
bool CTrailingSkipHopfield::CheckTrailingStopLong(CPositionInfo *position, double &sl, double &tp)
  {
   if(position == NULL)
      return false;
   double price = m_symbol.Bid();
//--- 1. Neural Network Filter (Hopfield)
   if(m_use_hopfield)
     {
      UpdateHopfield(price);
      //--- If energy is higher than threshold, pattern is unstable; do not trail
      if(GetHopfieldEnergy() > m_hop_threshold)
         return false;
     }
//--- 2. Skip List Algorithm (Select Mode)
   double base_price = price;
   switch(m_skip_mode)
     {
      case 1:
         base_price = SkipSearchLinear(price);
         break;
      case 2:
         base_price = SkipSearchGap(price);
         break;
      case 3:
         base_price = SkipSearchProbabilistic(price);
         break;
      case 4:
         base_price = SkipSearchHybrid(price);
         break;
      default:
         base_price = SkipSearchLinear(price);
         break;
     }
//--- 3. Trailing Execution
   double new_sl = base_price - (m_symbol.StopsLevel() * m_symbol.Point());
   double current_sl = position.StopLoss();
   if(new_sl > current_sl || current_sl == 0.0)
     {
      sl = NormalizeDouble(new_sl, m_symbol.Digits());
      return true;
     }
   return false;
  }

//+------------------------------------------------------------------+
//| Check Short: Skip List -> Hopfield -> Execution                  |
//+------------------------------------------------------------------+
bool CTrailingSkipHopfield::CheckTrailingStopShort(CPositionInfo *position, double &sl, double &tp)
  {
   if(position == NULL)
      return false;
   double price = m_symbol.Ask();
//--- 1. Neural Network Filter (Hopfield)
   if(m_use_hopfield)
     {
      UpdateHopfield(price);
      if(GetHopfieldEnergy() > m_hop_threshold)
         return false;
     }
//--- 2. Skip List Algorithm (Select Mode)
   double base_price = price;
   switch(m_skip_mode)
     {
      case 1:
         base_price = SkipSearchLinear(price);
         break;
      case 2:
         base_price = SkipSearchGap(price);
         break;
      case 3:
         base_price = SkipSearchProbabilistic(price);
         break;
      case 4:
         base_price = SkipSearchHybrid(price);
         break;
      default:
         base_price = SkipSearchLinear(price);
         break;
     }
//--- 3. Trailing Execution
   double new_sl = base_price + (m_symbol.StopsLevel() * m_symbol.Point());
   double current_sl = position.StopLoss();
   if(new_sl < current_sl || current_sl == 0.0)
     {
      sl = NormalizeDouble(new_sl, m_symbol.Digits());
      return true;
     }
   return false;
  }

//+------------------------------------------------------------------+
//| Skip List Mode 1: Deterministic Linear Search (Base Level)       |
//+------------------------------------------------------------------+
double CTrailingSkipHopfield::SkipSearchLinear(double price)
  {
//--- Evaluates price linearly without jumping gaps
   return price;
  }

//+------------------------------------------------------------------+
//| Skip List Mode 2: Gap Search (Jumps fixed levels)                |
//+------------------------------------------------------------------+
double CTrailingSkipHopfield::SkipSearchGap(double price)
  {
//--- Subtracts a fixed gap buffer based on defined skip levels
   double gap_buffer = (m_skip_levels * 2) * m_symbol.Point();
   return price - gap_buffer;
  }

//+------------------------------------------------------------------+
//| Skip List Mode 3: Probabilistic Search (Coin flip skips)         |
//+------------------------------------------------------------------+
double CTrailingSkipHopfield::SkipSearchProbabilistic(double price)
  {
//--- Simulates standard Skip List probability (typically P=0.5)
   int current_level = 1;
   while(current_level < m_skip_levels && (MathRand() % 2 == 0))
     {
      current_level++;
     }
   double prob_buffer = current_level * 5 * m_symbol.Point();
   return price - prob_buffer;
  }

//+------------------------------------------------------------------+
//| Skip List Mode 4: Hybrid Search (Max gap bypass)                 |
//+------------------------------------------------------------------+
double CTrailingSkipHopfield::SkipSearchHybrid(double price)
  {
//--- Forces search to the highest skip level immediately for high volatility
   double max_buffer = (m_skip_levels * 10) * m_symbol.Point();
   return price - max_buffer;
  }

//+------------------------------------------------------------------+
//| Hopfield Update: Shift states based on price momentum            |
//+------------------------------------------------------------------+
void CTrailingSkipHopfield::UpdateHopfield(double price)
  {
   if(m_last_price == 0.0)
     {
      m_last_price = price;
      return;
     }
//--- Determine input momentum: 1.0 (Up) or -1.0 (Down)
   double input_state = (price >= m_last_price) ? 1.0 : -1.0;
   m_last_price = price;
//--- Shift state array (rolling window)
   m_state[2] = m_state[1];
   m_state[1] = m_state[0];
   m_state[0] = input_state;
  }

//+------------------------------------------------------------------+
//| Hopfield Energy Calculation                                      |
//+------------------------------------------------------------------+
double CTrailingSkipHopfield::GetHopfieldEnergy()
  {
   double energy = 0.0;
//--- E = -0.5 * sum(W_ij * S_i * S_j)
   for(int i = 0; i < 3; i++)
     {
      for(int j = 0; j < 3; j++)
        {
         energy += m_weights[i][j] * m_state[i] * m_state[j];
        }
     }
   return -0.5 * energy;
  }
//+------------------------------------------------------------------+
