← К каталогу
Исходный код · ID 4256

Ofada Gold trader

ofada_gold_trader_v230.mq5

Похожие материалы по тегам

pro +.pineTradingView · 3 общих теговmulti strategy algo combined by enigma mode.pineTradingView · 3 общих теговmelona ob strategy 6th update (by 3dots).pineTradingView · 3 общих теговsmc+ict+indicators+scalping master.pineTradingView · 3 общих теговpremium_super_scalping killer algo.pineTradingView · 3 общих тегов2 to 1 strategy with signals.pineTradingView · 3 общих тегов
Вы автор или правообладатель?

Сообщите нам, если считаете, что материал размещён без разрешения.

Краткий обзор

О программе

Ofada Gold trader — торговый советник для MetaTrader 5, построенный на системе самообучения с использованием подхода обучения с подкреплением (RL). В основе работы лежит коллективный разум («Collective Mind»), состоящий из нескольких независимых «мозгов» — нейронных моделей, которые анализируют рыночные состояния, запоминают успешные действия и корректируют торговые решения на основе накопленного опыта.

Советник формирует торговые сигналы на основе консенсуса множества мозгов, каждый из которых оценивает текущее состояние рынка через набор технических индикаторов и ценовых признаков. Решение о входе в сделку принимается только при достижении минимального уровня уверенности. Доступны адаптивный размер лота, частичное закрытие, перевод в безубыток, трейлинг-стоп, фильтр рыночной структуры и временной фильтр GMT+1.

Система поддерживает сохранение и загрузку обученных мозгов в файлы, что позволяет переносить накопленный опыт между сессиями. Встроенный дашборд отображает ключевые параметры торговли, состояние позиций и финансовые результаты за текущий день. Советник также включает защиту от превышения максимальной просадки и лимит дневной прибыли.

Настройки программы

НастройкаОписание
Initial lot (InitialLot) Начальный лот — Начальный лот
Maximum lot (MaxLot) Максимальный лот — Максимальный лот
Magic number (MagicNumber) Магический номер — Магический номер
EA order comment (TradeComment) Комментарий к сделкам — Комментарий к ордерам советника
Observation window size (WindowSize) Размер окна наблюдения — Размер окна наблюдения
Holding period for evaluation (HoldingPeriod) Период оценки — Период удержания для оценки
Maximum number of lags (MaxLags) Максимальное число лагов — Максимальное количество лагов
Learning rate (LearningRate) Скорость обучения — Скорость обучения
Exploration rate (ExplorationRate) Коэффициент исследования — Коэффициент исследования
Discount coefficient (Gamma) Коэффициент дисконтирования — Коэффициент дисконтирования
Memory decay (MemoryDecay) Затухание памяти — Затухание памяти
Maximum risk per trade (%) (MaxRiskPercent) Максимальный риск на сделку (%) — Максимальный риск на сделку (%)
Stop loss in points (StopLossPips) Стоп-лосс (точки) — Стоп-лосс в точках
Take profit in points (TakeProfitPips) Тейк-профит (точки) — Тейк-профит в точках
Maximum drawdown (%) (MaxDrawdownPercent) Максимальная просадка (%) — Максимальная просадка (%)
Use adaptive lots (UseAdaptiveLots) Адаптивные лоты — Использовать адаптивные лоты
EnablePartialClose Включить частичное закрытие — Включить частичное закрытие
PartialCloseMode Режим частичного закрытия — Режим срабатывания частичного закрытия
Trigger distance in points (PartialClosePips) Триггер частичного закрытия (точки) — Расстояние срабатывания в точках
PartialCloseRR Соотношение риск/прибыль для частичного закрытия — Соотношение риск/прибыль для срабатывания частичного закрытия
PartialClosePercent Процент частичного закрытия — Процент объёма для частичного закрытия
EnableBreakeven Включить безубыток — Включить безубыток
BreakevenMode Режим безубытка — Режим срабатывания безубытка
Profit pips needed to activate BE (BreakevenTriggerPips) Триггер безубытка (пипсы) — Пипсы прибыли для активации безубытка
BreakevenRR Соотношение риск/прибыль для безубытка — Соотношение риска и прибыли для срабатывания безубытка
Pips of profit to lock beyond entry (BreakevenLockPips) Фиксация безубытка (пипсы) — Пипсы прибыли для фиксации сверх точки входа
Move remainder to BE after partial (BreakevenAfterPartialClose) Безубыток после частичного закрытия — Перевод остатка в безубыток после частичного закрытия
EnableTrailing Включить трейлинг-стоп — Включить трейлинг-стоп
TrailingMode Режим трейлинг-стопа — Режим трейлинг-стопа
Start distance in points (TrailingStartPips) Начальное расстояние трейлинга (точки) — Начальное расстояние трейлинга в точках
TrailingStartRR Начало трейлинга (риск/прибыль) — Соотношение риск/прибыль для старта трейлинга
TrailingDistancePips Расстояние трейлинга (точки) — Расстояние трейлинг-стопа в точках
TrailingDistanceRR Расстояние трейлинга (риск/прибыль) — Соотношение риск/прибыль для расстояния трейлинг-стопа
TrailingATRTimeframe Таймфрейм ATR трейлинга — Таймфрейм ATR для трейлинг-стопа
TrailingATRPeriod Период ATR трейлинга — Период ATR для трейлинг-стопа
TrailingATRStartMultiplier Множитель старта трейлинга (ATR) — Множитель стартового расстояния трейлинга по ATR
TrailingATRDistanceMultiplier Множитель расстояния трейлинга (ATR) — Множитель расстояния трейлинг-стопа по ATR
TrailingOnlyAfterPartialClose Трейлинг только после частичного закрытия — Трейлинг только после частичного закрытия
TrailingOnlyAfterBreakeven Трейлинг только после безубытка — Трейлинг только после безубытка
0 disables; stops new entries (MaxDailyProfitUSD) Максимальная дневная прибыль (USD) — Максимальная дневная прибыль в долларах (0 отключает)
UseTimeFilter Временной фильтр — Использовать временной фильтр
StartHourGMT1 Час начала сессии GMT+1 — Час начала торговой сессии GMT+1
StartMinuteGMT1 Минута начала сессии GMT+1 — Минута начала торговой сессии GMT+1
StopHourGMT1 Час окончания сессии GMT+1 — Час окончания торговой сессии GMT+1
StopMinuteGMT1 Минута окончания сессии GMT+1 — Минута окончания торговой сессии GMT+1
UseStructureTrendFilter Фильтр тренда структуры — Использовать фильтр тренда рыночной структуры
StructureTimeframe Таймфрейм структуры — Таймфрейм для анализа рыночной структуры
StructureLookbackBars Бары для анализа структуры — Количество баров для анализа структуры
StructureSwingStrength Сила свинга структуры — Сила свинга для определения структуры
BlockTradesWhenStructureNeutral Блокировка при нейтральной структуре — Блокировать сделки, когда рыночная структура нейтральная
UseTradeCooldown Пауза между сделками — Использовать паузу между сделками
TradeCooldownMinutes Пауза между сделками (минуты) — Пауза между сделками в минутах
ShowDashboard Показать дашборд — Показать дашборд
DashboardCorner Угол дашборда — Угол расположения дашборда
DashboardX Смещение дашборда по X — Горизонтальное смещение дашборда
DashboardY Смещение дашборда по Y — Вертикальное смещение дашборда
DashboardBackground Цвет фона дашборда — Цвет фона дашборда
DashboardText Цвет текста дашборда — Цвет текста дашборда
DashboardProfitColor Цвет прибыли дашборда — Цель прибыли на дашборде
DashboardLossColor Цвет убытков дашборда — Цвет убытков на дашборде
Number of brains in the team (BrainsCount) Количество мозгов — Количество мозгов в команде
Use consensus decision (UseConsensus) Консенсусное решение — Использовать консенсусное решение
Minimum confidence for a deal (MinConfidence) Минимальная уверенность — Минимальная уверенность для сделки
Enable learning (EnableLearning) Включить обучение — Включить обучение
Enable trading (EnableTrading) Включить торговлю — Включить торговлю
Learning period (bars) (LearningPeriod) Период обучения (бары) — Период обучения (бары)
Detailed log (ShowDetailedLog) Подробный журнал — Подробный журнал
Save brains (SaveBrains) Сохранять мозги — Сохранять мозги
Load brains (LoadBrains) Загружать мозги — Загружать мозги
Save interval (bars) (SaveInterval) Интервал сохранения (бары) — Интервал сохранения (бары)
Folder to save (BrainFolder) Папка мозгов — Папка для сохранения мозгов
Use RSI (UseRSI) Использовать RSI — Использовать RSI
Use CCI (UseCCI) Использовать CCI — Использовать CCI
Use Stochastic (UseStochastic) Использовать стохастик — Использовать стохастик
Use MACD (UseMACD) Использовать MACD — Использовать MACD
Use ATR (UseATR) Использовать ATR — Использовать ATR
Use Bollinger Bands (UseBollinger) Использовать полосы Боллинджера — Использовать полосы Боллинджера
Use Moving Averages (UseMA) Использовать скользящие средние — Использовать скользящие средние
Use fractals (UseFractals) Использовать фракталы — Использовать фракталы
Use ADX (UseADX) Использовать ADX — Использовать ADX
Use Williams %R (UseWPR) Использовать Williams %R — Использовать Williams %R
Получить полный код

Поиск по коду файла

#property version   "2.30"
#property strict

#include <Trade\Trade.mqh>
#include <Trade\AccountInfo.mqh>
#include <Arrays\ArrayObj.mqh>

input group "=== BASIC SETTINGS ==="
input double   InitialLot = 0.01;           // Initial lot
input double   MaxLot = 0.5;                // Maximum lot
input int      MagicNumber = 777888;        // Magic number
input string   TradeComment = "Ofada Gold trader"; // EA order comment

input group "=== LEARNING PARAMETERS ==="
input int      WindowSize = 240;            // Observation window size
input int      HoldingPeriod = 22;          // Holding period for evaluation
input int      MaxLags = 200;               // Maximum number of lags
input double   LearningRate = 0.1;          // Learning rate
input double   ExplorationRate = 0.3;       // Exploration rate
input double   Gamma = 0.9;                 // Discount coefficient
input double   MemoryDecay = 0.99;          // Memory decay

input group "=== RISK MANAGEMENT ==="
input double   MaxRiskPercent = 2.0;        // Maximum risk per trade (%)
input int      StopLossPips = 500;          // Stop loss in points
input int      TakeProfitPips = 1000;       // Take profit in points
input double   MaxDrawdownPercent = 10.0;   // Maximum drawdown (%)
input bool     UseAdaptiveLots = true;      // Use adaptive lots

enum ENUM_TRIGGER_MODE
{
   TRIGGER_BY_PIPS = 0,
   TRIGGER_BY_RR   = 1
};

enum ENUM_TRAILING_MODE
{
   TRAILING_BY_PIPS = 0,
   TRAILING_BY_RR   = 1,
   TRAILING_BY_ATR  = 2
};

input group "=== POSITION MANAGEMENT ==="
input bool              EnablePartialClose = false;
input ENUM_TRIGGER_MODE PartialCloseMode = TRIGGER_BY_PIPS;
input double            PartialClosePips = 300.0;  // Trigger distance in points
input double            PartialCloseRR = 1.0;
input double            PartialClosePercent = 50.0;
input bool              EnableBreakeven = true;
input ENUM_TRIGGER_MODE BreakevenMode = TRIGGER_BY_PIPS;
input double            BreakevenTriggerPips = 250.0; // Profit pips needed to activate BE
input double            BreakevenRR = 1.0;
input double            BreakevenLockPips = 0.0;   // Pips of profit to lock beyond entry
input bool              BreakevenAfterPartialClose = true; // Move remainder to BE after partial
input bool              EnableTrailing = false;
input ENUM_TRAILING_MODE TrailingMode = TRAILING_BY_PIPS;
input double            TrailingStartPips = 300.0; // Start distance in points
input double            TrailingStartRR = 1.0;
input double            TrailingDistancePips = 200.0;
input double            TrailingDistanceRR = 0.5;
input ENUM_TIMEFRAMES    TrailingATRTimeframe = PERIOD_M15;
input int                TrailingATRPeriod = 14;
input double             TrailingATRStartMultiplier = 1.0;
input double             TrailingATRDistanceMultiplier = 1.0;
input bool               TrailingOnlyAfterPartialClose = true;
input bool               TrailingOnlyAfterBreakeven = true;

input group "=== DAILY LIMIT AND GMT+1 TIME FILTER ==="
input double   MaxDailyProfitUSD = 0.0;     // 0 disables; stops new entries
input bool     UseTimeFilter = false;
input int      StartHourGMT1 = 7;
input int      StartMinuteGMT1 = 0;
input int      StopHourGMT1 = 20;
input int      StopMinuteGMT1 = 0;

input group "=== MARKET STRUCTURE TREND FILTER ==="
input bool              UseStructureTrendFilter = true;
input ENUM_TIMEFRAMES   StructureTimeframe = PERIOD_M15;
input int               StructureLookbackBars = 120;
input int               StructureSwingStrength = 3;
input bool              BlockTradesWhenStructureNeutral = true;

input group "=== TRADE COOLDOWN ==="
input bool              UseTradeCooldown = true;
input int               TradeCooldownMinutes = 15;

input group "=== DASHBOARD ==="
input bool     ShowDashboard = true;
input ENUM_BASE_CORNER DashboardCorner = CORNER_LEFT_UPPER;
input int      DashboardX = 10;
input int      DashboardY = 20;
input color    DashboardBackground = C'24,28,36';
input color    DashboardText = clrWhite;
input color    DashboardProfitColor = clrLimeGreen;
input color    DashboardLossColor = clrTomato;

input group "=== COLLECTIVE MIND ==="
input int      BrainsCount = 5;             // Number of brains in the team
input bool     UseConsensus = true;         // Use consensus decision
input double   MinConfidence = 0.15;        // Minimum confidence for a deal

input group "=== OPERATING MODES ==="
input bool     EnableLearning = true;       // Enable learning
input bool     EnableTrading = true;        // Enable trading
input int      LearningPeriod = 100;        // Learning period (bars)
input bool     ShowDetailedLog = true;      // Detailed log

input group "=== SAVE/LOAD ==="
input bool     SaveBrains = true;           // Save brains
input bool     LoadBrains = true;           // Load brains
input int      SaveInterval = 500;          // Save interval (bars)
input string   BrainFolder = "BrainRL";     // Folder to save

input group "=== STATIONARY FEATURES ==="
input bool     UseRSI = true;               // Use RSI
input bool     UseCCI = true;               // Use CCI
input bool     UseStochastic = true;        // Use Stochastic
input bool     UseMACD = true;              // Use MACD
input bool     UseATR = true;               // Use ATR
input bool     UseBollinger = true;         // Use Bollinger Bands
input bool     UseMA = true;                // Use Moving Averages
input bool     UseFractals = true;          // Use fractals
input bool     UseADX = true;               // Use ADX
input bool     UseWPR = true;               // Use Williams %R

CTrade Trade;
CAccountInfo Account;

datetime LastBarTime = 0;
double StartingBalance = 0;
int TotalTrades = 0;
int WinTrades = 0;
int BarsSinceLastSave = 0;
string DashboardPrefix = "OfadaDash_";
datetime LastFullCloseTime = 0;

int h_RSI = INVALID_HANDLE;
int h_CCI = INVALID_HANDLE;
int h_Stochastic = INVALID_HANDLE;
int h_MACD = INVALID_HANDLE;
int h_ATR = INVALID_HANDLE;
int h_Bollinger = INVALID_HANDLE;
int h_MA_Fast = INVALID_HANDLE;
int h_MA_Slow = INVALID_HANDLE;
int h_ADX = INVALID_HANDLE;
int h_WPR = INVALID_HANDLE;
int h_TrailingATR = INVALID_HANDLE;

struct MarketStateBinary
{
   int       binaryCode[32];
   double    volatility;
   double    momentum;
   double    trend;
   double    price;
   datetime  timestamp;
   double    outcome;
   int       activations;
};

class CMemoryNeuron : public CObject
{
public:
   MarketStateBinary marketState;
   double    action;
   double    reward;
   double    qValue;
   double    confidence;
   datetime  birthTime;
   int       activations;
   double    successRate;
   double    importance;
   int       generation;

   CMemoryNeuron()
   {
      action = 0.5;
      reward = 0;
      qValue = 0;
      confidence = 0.5;
      birthTime = TimeCurrent();
      activations = 0;
      successRate = 0.5;
      importance = 1.0;
      generation = 1;
      ArrayInitialize(marketState.binaryCode, 0);
      marketState.volatility = 0;
      marketState.momentum = 0;
      marketState.trend = 0;
      marketState.price = 0;
      marketState.timestamp = 0;
      marketState.outcome = 0;
      marketState.activations = 0;
   }

   void UpdateMetrics(double newReward)
   {
      activations++;
      reward = newReward;

      qValue = qValue + LearningRate * (newReward - qValue);

      if(newReward > 0)
         successRate = successRate * 0.9 + 0.1;
      else if(newReward < 0)
         successRate = successRate * 0.9;

      importance = successRate * MathLog(activations + 1);
      confidence = (successRate + MathAbs(qValue)) / 2.0;
   }
};

struct Episode
{
   MarketStateBinary state;
   double action;
   double reward;
   datetime timestamp;
};

class CMachineBrain : public CObject
{
private:
   CArrayObj     m_neurons;              // Array of neurons
   Episode       m_episodes[];           // Episode history
   int           m_episodesCount;
   int           m_currentGeneration;
   double        m_brainAge;
   double        m_brainComplexity;
   double        m_overallIntelligence;
   double        m_learningRate;
   double        m_explorationRate;
   double        m_gamma;
   double        m_memoryDecay;
   int           m_lastActivatedNeuron;
   MarketStateBinary m_currentMarketState;
   double        m_totalReward;
   int           m_totalTrades;
   int           m_successfulTrades;
   string        m_name;

   int           m_buySignals;
   int           m_sellSignals;
   int           m_buyTrades;
   int           m_sellTrades;
   double        m_buyReward;
   double        m_sellReward;

public:
   CMachineBrain(string name, double lr, double eps, double gamma)
   {
      m_name = name;
      m_learningRate = lr;
      m_explorationRate = eps;
      m_gamma = gamma;
      m_memoryDecay = MemoryDecay;
      m_currentGeneration = 1;
      m_totalReward = 0;
      m_totalTrades = 0;
      m_successfulTrades = 0;
      m_lastActivatedNeuron = -1;
      m_episodesCount = 0;
      m_brainComplexity = 0.1;
      m_overallIntelligence = 0;

      m_buySignals = 0;
      m_sellSignals = 0;
      m_buyTrades = 0;
      m_sellTrades = 0;
      m_buyReward = 0;
      m_sellReward = 0;

      ArrayResize(m_episodes, 0);

      if(ShowDetailedLog)
         Print("🧠 Brain '", name, "' activated | LR: ", lr, " | Epsilon: ", eps);
   }

   ~CMachineBrain()
   {
      m_neurons.Clear();
   }

   void EncodeToBinary(double &features[], MarketStateBinary &state)
   {
      int size = ArraySize(features);
      state.volatility = CalculateVolatility(features, size);
      state.momentum = CalculateMomentum(features, size);
      state.trend = CalculateTrend(features, size);
      state.price = size > 0 ? features[0] : 0;
      state.timestamp = TimeCurrent();

      ArrayInitialize(state.binaryCode, 0);
      int bitIndex = 0;

      int volLevel = (int)(MathMax(0, MathMin(1.0, state.volatility)) * 7);
      for(int i = 0; i < 3; i++)
         state.binaryCode[bitIndex++] = (volLevel >> i) & 1;

      int momLevel = (int)((state.momentum + 1.0) / 2.0 * 7);
      momLevel = MathMax(0, MathMin(7, momLevel));
      for(int i = 0; i < 3; i++)
         state.binaryCode[bitIndex++] = (momLevel >> i) & 1;

      int trendLevel = (int)((state.trend + 1.0) / 2.0 * 7);
      trendLevel = MathMax(0, MathMin(7, trendLevel));
      for(int i = 0; i < 3; i++)
         state.binaryCode[bitIndex++] = (trendLevel >> i) & 1;
   }

   double CalculateVolatility(double &features[], int size)
   {
      if(size < 2) return 0.5;

      double sum = 0;
      int count = MathMin(size - 1, 10);

      for(int i = 0; i < count; i++)
         sum += MathAbs(features[i]);

      return MathMin(1.0, sum / count);
   }

   double CalculateMomentum(double &features[], int size)
   {
      if(size < 5) return 0.0;

      double momentum = 0;
      int count = MathMin(5, size);

      for(int i = 0; i < count; i++)
         momentum += features[i];

      return MathMax(-1.0, MathMin(1.0, momentum));
   }

   double CalculateTrend(double &features[], int size)
   {
      if(size < 3) return 0.0;

      double trend = 0;
      int count = MathMin(10, size);

      for(int i = 0; i < count; i++)
         trend += features[i] * (count - i) / count;

      return MathMax(-1.0, MathMin(1.0, trend));
   }

   int FindSimilarState(MarketStateBinary &state)
   {
      int bestMatch = -1;
      double bestSimilarity = 0;

      for(int i = 0; i < m_neurons.Total(); i++)
      {
         CMemoryNeuron *neuron = m_neurons.At(i);
         if(neuron == NULL) continue;

         double similarity = CalculateSimilarity(state, neuron.marketState);

         if(similarity > bestSimilarity)
         {
            bestSimilarity = similarity;
            bestMatch = i;
         }
      }

      return bestSimilarity > 0.75 ? bestMatch : -1;
   }

   double CalculateSimilarity(MarketStateBinary &state1, MarketStateBinary &state2)
   {
      int matches = 0;
      for(int i = 0; i < 32; i++)
         if(state1.binaryCode[i] == state2.binaryCode[i]) 
            matches++;

      return (double)matches / 32.0;
   }

   double Think(double &features[])
   {
      EncodeToBinary(features, m_currentMarketState);

      int similarNeuron = FindSimilarState(m_currentMarketState);
      double action = 0.5;
      double randomValue = (double)(MathRand() % 10001) / 10000.0;

      if(m_totalTrades < 150)
      {
         int cycle = m_totalTrades % 6;
         if(cycle == 0 || cycle == 1)
            action = 0.75 + randomValue * 0.2;  // BUY
         else if(cycle == 2 || cycle == 3)
            action = 0.1 + randomValue * 0.2;   // SELL
         else
            action = 0.4 + randomValue * 0.2;   // HOLD

         m_lastActivatedNeuron = -1;

         if(m_totalTrades % 10 == 0 && ShowDetailedLog)
            Print("🎲 [", m_name, "] Exploration: Trade ", m_totalTrades, 
                  " | Action: ", DoubleToString(action, 3));
      }
      else if(similarNeuron >= 0)
      {
         CMemoryNeuron *neuron = m_neurons.At(similarNeuron);

         if(randomValue > m_explorationRate)
         {

            action = neuron.action;

            if(neuron.successRate > 0.6)
               action = MathMin(1.0, action * 1.1);
            else if(neuron.successRate < 0.4)
               action = MathMax(0.0, action * 0.9);

            if(m_totalTrades % 20 == 0 && ShowDetailedLog)
               Print("🧠 [", m_name, "] Exploit: Action=", DoubleToString(action, 3), 
                     " | SR=", DoubleToString(neuron.successRate, 2));
         }
         else
         {

            action = randomValue;

            if(m_totalTrades % 20 == 0 && ShowDetailedLog)
               Print("🎲 [", m_name, "] Explore: Random=", DoubleToString(action, 3));
         }

         m_lastActivatedNeuron = similarNeuron;
         neuron.activations++;
      }
      else
      {

         action = randomValue;
         m_lastActivatedNeuron = -1;

         if(m_totalTrades % 20 == 0 && ShowDetailedLog)
            Print("🆕 [", m_name, "] New state: Random=", DoubleToString(action, 3));
      }

      m_overallIntelligence = GetSuccessRate() * m_brainComplexity * 0.1;

      int totalSignals = m_buySignals + m_sellSignals;
      double buyRatio = totalSignals > 0 ? (double)m_buySignals / totalSignals : 0.5;
      double sellRatio = totalSignals > 0 ? (double)m_sellSignals / totalSignals : 0.5;

      if(totalSignals > 50) // Start balancing after 50 signals
      {
         if(buyRatio > 0.70 && action > 0.6) // Too many BUYs
         {

            action = action * 0.7 - 0.15;
            action = MathMax(0.0, action);

            if(ShowDetailedLog && m_totalTrades % 50 == 0)
               Print("⚖️ [", m_name, "] Balance: BUY ratio=", DoubleToString(buyRatio, 2), 
                     " → Shift toward SELL");
         }
         else if(sellRatio > 0.70 && action < 0.4) // Too many SELLs
         {

            action = action * 0.7 + 0.35;
            action = MathMin(1.0, action);

            if(ShowDetailedLog && m_totalTrades % 50 == 0)
               Print("⚖️ [", m_name, "] Balance: SELL ratio=", DoubleToString(sellRatio, 2), 
                     " → Shift toward BUY");
         }
      }

      if(m_buyTrades > 10 && m_sellTrades > 10)
      {
         double buyWinRate = m_buyTrades > 0 ? m_buyReward / m_buyTrades : 0;
         double sellWinRate = m_sellTrades > 0 ? m_sellReward / m_sellTrades : 0;

         if(buyWinRate > sellWinRate + 0.3 && action > 0.4 && action < 0.6)
         {
            action = action * 1.2; // Strengthen BUY in the neutral zone
            action = MathMin(1.0, action);
         }
         else if(sellWinRate > buyWinRate + 0.3 && action > 0.4 && action < 0.6)
         {
            action = action * 0.8; // Strengthen SELL in the neutral zone
            action = MathMax(0.0, action);
         }
      }

      if(action > 0.6)
         m_buySignals++;
      else if(action < 0.4)
         m_sellSignals++;

      return action;
   }

   void Remember(double action)
   {
      CMemoryNeuron *newNeuron = new CMemoryNeuron();
      newNeuron.marketState = m_currentMarketState;
      newNeuron.action = action;
      newNeuron.generation = m_currentGeneration;

      m_neurons.Add(newNeuron);

      m_lastActivatedNeuron = m_neurons.Total() - 1;
      m_brainComplexity = MathLog(m_neurons.Total() + 1);
   }

   void Learn(double reward)
   {
      if(m_lastActivatedNeuron >= 0 && m_lastActivatedNeuron < m_neurons.Total())
      {
         CMemoryNeuron *neuron = m_neurons.At(m_lastActivatedNeuron);
         neuron.UpdateMetrics(reward);

         if(neuron.action > 0.6) // BUY
         {
            m_buyTrades++;
            m_buyReward += reward;
         }
         else if(neuron.action < 0.4) // SELL
         {
            m_sellTrades++;
            m_sellReward += reward;
         }

         if(reward > 0)
            m_successfulTrades++;

         m_totalReward += reward;
         m_totalTrades++;
      }

      if(m_totalTrades % 100 == 0 && m_totalTrades > 0)
      {
         Prune();
         Evolve();
      }
   }

   void Prune()
   {
      if(m_neurons.Total() < 1000) return;

      int removed = 0;

      for(int i = m_neurons.Total() - 1; i >= 0 && removed < 100; i--)
      {
         CMemoryNeuron *neuron = m_neurons.At(i);
         if(neuron == NULL) continue;

         if(neuron.activations > 10 && neuron.successRate < 0.35)
         {
            m_neurons.Delete(i);
            removed++;
         }
      }

      if(removed > 0 && ShowDetailedLog)
         Print("🧹 [", m_name, "] Pruning: removed ", removed, " neurons");
   }

   void Evolve()
   {
      m_currentGeneration++;
      m_explorationRate *= m_memoryDecay;
      m_explorationRate = MathMax(0.01, m_explorationRate);

      if(ShowDetailedLog)
         Print("🧬 [", m_name, "] Generation ", m_currentGeneration, 
               " | Exploration: ", DoubleToString(m_explorationRate, 3));
   }

   int GetNeuronsCount() { return m_neurons.Total(); }
   double GetSuccessRate() { return m_totalTrades > 0 ? (double)m_successfulTrades / m_totalTrades : 0; }
   double GetIntelligence() { return m_overallIntelligence; }
   double GetTotalReward() { return m_totalReward; }
   int GetTotalTrades() { return m_totalTrades; }
   string GetName() { return m_name; }

   void PrintStats()
   {
      double buyWinRate = m_buyTrades > 0 ? m_buyReward / m_buyTrades : 0;
      double sellWinRate = m_sellTrades > 0 ? m_sellReward / m_sellTrades : 0;
      int totalSignals = m_buySignals + m_sellSignals;
      double buyRatio = totalSignals > 0 ? (double)m_buySignals / totalSignals * 100 : 0;
      double sellRatio = totalSignals > 0 ? (double)m_sellSignals / totalSignals * 100 : 0;

      Print("╔══════════════════════════════════════════╗");
      Print("║  🧠 BRAIN STATISTICS: ", m_name);
      Print("╠══════════════════════════════════════════╣");
      Print("║  Neurons: ", m_neurons.Total());
      Print("║  Generation: ", m_currentGeneration);
      Print("║  Trades: ", m_totalTrades);
      Print("║  Win Rate: ", DoubleToString(GetSuccessRate() * 100, 1), "%");
      Print("║  Profit: ", DoubleToString(m_totalReward, 2));
      Print("║  Intelligence: ", DoubleToString(m_overallIntelligence, 4));
      Print("╠══════════════════════════════════════════╣");
      Print("║  ⚖️ CLASS BALANCE:");
      Print("║  BUY signals: ", m_buySignals, " (", DoubleToString(buyRatio, 1), "%)");
      Print("║  SELL signals: ", m_sellSignals, " (", DoubleToString(sellRatio, 1), "%)");
      Print("║  BUY trades: ", m_buyTrades, " | Avg: ", DoubleToString(buyWinRate, 3));
      Print("║  SELL trades: ", m_sellTrades, " | Avg: ", DoubleToString(sellWinRate, 3));
      Print("╚══════════════════════════════════════════╝");
   }

   bool SaveToFile(string folderName)
   {
      string filename = folderName + "\\" + m_name + ".brain";
      int handle = FileOpen(filename, FILE_WRITE | FILE_BIN | FILE_COMMON);

      if(handle == INVALID_HANDLE)
      {
         Print("❌ Error creating file: ", filename, " Error: ", GetLastError());
         return false;
      }

      FileWriteInteger(handle, m_neurons.Total());
      FileWriteInteger(handle, m_currentGeneration);
      FileWriteDouble(handle, m_totalReward);
      FileWriteInteger(handle, m_totalTrades);
      FileWriteInteger(handle, m_successfulTrades);
      FileWriteDouble(handle, m_learningRate);
      FileWriteDouble(handle, m_explorationRate);
      FileWriteDouble(handle, m_gamma);

      FileWriteInteger(handle, m_buySignals);
      FileWriteInteger(handle, m_sellSignals);
      FileWriteInteger(handle, m_buyTrades);
      FileWriteInteger(handle, m_sellTrades);
      FileWriteDouble(handle, m_buyReward);
      FileWriteDouble(handle, m_sellReward);

      int toSave = MathMin(m_neurons.Total(), 5000000);
      FileWriteInteger(handle, toSave);

      for(int i = 0; i < toSave; i++)
      {
         CMemoryNeuron *neuron = m_neurons.At(i);
         if(neuron == NULL) continue;

         for(int j = 0; j < 32; j++)
            FileWriteInteger(handle, neuron.marketState.binaryCode[j]);

         FileWriteDouble(handle, neuron.marketState.volatility);
         FileWriteDouble(handle, neuron.marketState.momentum);
         FileWriteDouble(handle, neuron.marketState.trend);
         FileWriteDouble(handle, neuron.marketState.price);

         FileWriteDouble(handle, neuron.action);
         FileWriteDouble(handle, neuron.reward);
         FileWriteDouble(handle, neuron.qValue);
         FileWriteDouble(handle, neuron.confidence);
         FileWriteInteger(handle, neuron.activations);
         FileWriteDouble(handle, neuron.successRate);
         FileWriteDouble(handle, neuron.importance);
         FileWriteInteger(handle, neuron.generation);
      }

      FileClose(handle);

      Print("💾 Brain '", m_name, "' saved: ", toSave, " neurons in ", filename);
      return true;
   }

   bool LoadFromFile(string folderName)
   {
      string filename = folderName + "\\" + m_name + ".brain";
      int handle = FileOpen(filename, FILE_READ | FILE_BIN | FILE_COMMON);

      if(handle == INVALID_HANDLE)
      {
         Print("⚠️ File not found: ", filename, " - creating a new brain");
         return false;
      }

      m_neurons.Clear();

      int neuronsCount = FileReadInteger(handle);
      m_currentGeneration = FileReadInteger(handle);
      m_totalReward = FileReadDouble(handle);
      m_totalTrades = FileReadInteger(handle);
      m_successfulTrades = FileReadInteger(handle);
      m_learningRate = FileReadDouble(handle);
      m_explorationRate = FileReadDouble(handle);
      m_gamma = FileReadDouble(handle);

      m_buySignals = FileReadInteger(handle);
      m_sellSignals = FileReadInteger(handle);
      m_buyTrades = FileReadInteger(handle);
      m_sellTrades = FileReadInteger(handle);
      m_buyReward = FileReadDouble(handle);
      m_sellReward = FileReadDouble(handle);

      int savedNeurons = FileReadInteger(handle);

      for(int i = 0; i < savedNeurons; i++)
      {
         CMemoryNeuron *neuron = new CMemoryNeuron();

         for(int j = 0; j < 32; j++)
            neuron.marketState.binaryCode[j] = FileReadInteger(handle);

         neuron.marketState.volatility = FileReadDouble(handle);
         neuron.marketState.momentum = FileReadDouble(handle);
         neuron.marketState.trend = FileReadDouble(handle);
         neuron.marketState.price = FileReadDouble(handle);

         neuron.action = FileReadDouble(handle);
         neuron.reward = FileReadDouble(handle);
         neuron.qValue = FileReadDouble(handle);
         neuron.confidence = FileReadDouble(handle);
         neuron.activations = FileReadInteger(handle);
         neuron.successRate = FileReadDouble(handle);
         neuron.importance = FileReadDouble(handle);
         neuron.generation = FileReadInteger(handle);

         m_neurons.Add(neuron);
      }

      FileClose(handle);

      m_brainComplexity = MathLog(m_neurons.Total() + 1);
      m_overallIntelligence = GetSuccessRate() * m_brainComplexity * 0.1;

      int totalSignals = m_buySignals + m_sellSignals;
      double buyRatio = totalSignals > 0 ? (double)m_buySignals / totalSignals * 100 : 50;
      double sellRatio = totalSignals > 0 ? (double)m_sellSignals / totalSignals * 100 : 50;

      Print("✅ Brain '", m_name, "' loaded: ", m_neurons.Total(), " neurons | ",
            "Generation: ", m_currentGeneration, " | Win Rate: ", 
            DoubleToString(GetSuccessRate() * 100, 1), "% | ",
            "BUY/SELL: ", DoubleToString(buyRatio, 0), "%/", DoubleToString(sellRatio, 0), "%");

      return true;
   }
};

class CCollectiveMind : public CObject
{
private:
   CArrayObj     m_brains;
   string        m_groupName;

public:
   CCollectiveMind(string name, int brainsCount, double lr, double eps, double gamma)
   {
      m_groupName = name;

      for(int i = 0; i < brainsCount; i++)
      {
         string brainName = name + "_Brain" + IntegerToString(i);
         double brainLR = lr * (0.8 + (MathRand() % 1000) / 10000.0 * 0.4);
         double brainEps = eps * (0.8 + (MathRand() % 1000) / 10000.0 * 0.4);

         CMachineBrain *brain = new CMachineBrain(brainName, brainLR, brainEps, gamma);
         m_brains.Add(brain);
      }

      Print("🌐 Collective mind '", name, "' created | Brains: ", brainsCount);
   }

   ~CCollectiveMind()
   {
      m_brains.Clear();
   }

   double ConsensusThink(double &state[])
   {
      double totalAction = 0;
      double totalWeight = 0;

      for(int i = 0; i < m_brains.Total(); i++)
      {
         CMachineBrain *brain = m_brains.At(i);
         if(brain == NULL) continue;

         double action = brain.Think(state);
         double weight = brain.GetSuccessRate() + 0.1;

         totalAction += action * weight;
         totalWeight += weight;
      }

      return totalWeight > 0 ? totalAction / totalWeight : 0.5;
   }

   void CollectiveRemember(double action)
   {
      for(int i = 0; i < m_brains.Total(); i++)
      {
         CMachineBrain *brain = m_brains.At(i);
         if(brain != NULL)
            brain.Remember(action);
      }
   }

   void CollectiveLearn(double reward)
   {
      for(int i = 0; i < m_brains.Total(); i++)
      {
         CMachineBrain *brain = m_brains.At(i);
         if(brain != NULL)
            brain.Learn(reward);
      }
   }

   int GetTotalNeurons()
   {
      int total = 0;
      for(int i = 0; i < m_brains.Total(); i++)
      {
         CMachineBrain *brain = m_brains.At(i);
         if(brain != NULL)
            total += brain.GetNeuronsCount();
      }
      return total;
   }

   double GetCollectiveIntelligence()
   {
      double total = 0;
      int count = 0;

      for(int i = 0; i < m_brains.Total(); i++)
      {
         CMachineBrain *brain = m_brains.At(i);
         if(brain == NULL) continue;

         total += brain.GetIntelligence();
         count++;
      }

      return count > 0 ? total / count : 0;
   }

   void PrintCollectiveStats()
   {
      Print("╔════════════════════════════════════════════╗");
      Print("║  🌐 COLLECTIVE MIND: ", m_groupName);
      Print("╠════════════════════════════════════════════╣");
      Print("║  Brains: ", m_brains.Total());
      Print("║  Neurons: ", GetTotalNeurons());
      Print("║  Intelligence: ", DoubleToString(GetCollectiveIntelligence(), 4));

      for(int i = 0; i < m_brains.Total(); i++)
      {
         CMachineBrain *brain = m_brains.At(i);
         if(brain == NULL) continue;

         Print("║  Brain ", i, ": ", brain.GetNeuronsCount(), " neurons | ",
               "IQ: ", DoubleToString(brain.GetIntelligence(), 3), " | ",
               "Win: ", DoubleToString(brain.GetSuccessRate() * 100, 1), "%");
      }

      Print("╚════════════════════════════════════════════╝");
   }

   bool SaveAllBrains(string folderName)
   {
      bool allSuccess = true;

      for(int i = 0; i < m_brains.Total(); i++)
      {
         CMachineBrain *brain = m_brains.At(i);
         if(brain == NULL) continue;

         if(!brain.SaveToFile(folderName))
            allSuccess = false;
      }

      if(allSuccess)
         Print("💾 Team '", m_groupName, "' completely saved");

      return allSuccess;
   }

   bool LoadAllBrains(string folderName)
   {
      bool anyLoaded = false;

      for(int i = 0; i < m_brains.Total(); i++)
      {
         CMachineBrain *brain = m_brains.At(i);
         if(brain == NULL) continue;

         if(brain.LoadFromFile(folderName))
            anyLoaded = true;
      }

      if(anyLoaded)
         Print("✅ Team '", m_groupName, "' loaded");
      else
         Print("🆕 Team '", m_groupName, "' created from scratch");

      return anyLoaded;
   }
};

CCollectiveMind *g_collectiveMind = NULL;

void CreateFeatures(double &features[])
{
   MqlRates rates[];
   int copied = CopyRates(_Symbol, PERIOD_CURRENT, 0, WindowSize + MaxLags + 1, rates);

   if(copied <= 0)
   {
      ArrayResize(features, 0);
      return;
   }

   int featureIndex = 0;
   int totalFeatures = 0;

   totalFeatures += WindowSize; // Base price changes
   if(UseRSI) totalFeatures += 3;
   if(UseCCI) totalFeatures += 1;
   if(UseStochastic) totalFeatures += 2;
   if(UseMACD) totalFeatures += 3;
   if(UseATR) totalFeatures += 1;
   if(UseBollinger) totalFeatures += 3;
   if(UseMA) totalFeatures += 4;
   if(UseFractals) totalFeatures += 2;
   if(UseADX) totalFeatures += 3;
   if(UseWPR) totalFeatures += 1;

   ArrayResize(features, totalFeatures);
   ArrayInitialize(features, 0);

   for(int i = 0; i < WindowSize && i < copied - 1; i++)
   {
      if(rates[copied - 1 - i - 1].close > 0)
         features[featureIndex++] = (rates[copied - 1 - i].close - rates[copied - 1 - i - 1].close) / 
                                   rates[copied - 1 - i - 1].close;
      else
         features[featureIndex++] = 0;
   }

   if(UseRSI && h_RSI != INVALID_HANDLE)
   {
      double rsi[];
      if(CopyBuffer(h_RSI, 0, 0, 3, rsi) > 0)
      {
         features[featureIndex++] = (rsi[0] - 50) / 50;  // Normalization [-1, 1]

         if(ArraySize(rsi) >= 2)
            features[featureIndex++] = (rsi[0] - rsi[1]) / 50;
         else
            features[featureIndex++] = 0;

         if(rsi[0] > 70)
            features[featureIndex++] = 1;
         else if(rsi[0] < 30)
            features[featureIndex++] = -1;
         else
            features[featureIndex++] = 0;
      }
      else
         featureIndex += 3;
   }

   if(UseCCI && h_CCI != INVALID_HANDLE)
   {
      double cci[];
      if(CopyBuffer(h_CCI, 0, 0, 1, cci) > 0)
      {
         features[featureIndex++] = MathMax(-1, MathMin(1, cci[0] / 200));  // Normalization
      }
      else
         featureIndex++;
   }

   if(UseStochastic && h_Stochastic != INVALID_HANDLE)
   {
      double main[], signal[];
      if(CopyBuffer(h_Stochastic, 0, 0, 1, main) > 0 && 
         CopyBuffer(h_Stochastic, 1, 0, 1, signal) > 0)
      {
         features[featureIndex++] = (main[0] - 50) / 50;     // Main line
         features[featureIndex++] = (signal[0] - 50) / 50;   // Signal line
      }
      else
         featureIndex += 2;
   }

   if(UseMACD && h_MACD != INVALID_HANDLE)
   {
      double main[], signal[];
      if(CopyBuffer(h_MACD, 0, 0, 2, main) > 0 && 
         CopyBuffer(h_MACD, 1, 0, 2, signal) > 0)
      {
         double avgPrice = (rates[copied-1].high + rates[copied-1].low) / 2;
         if(avgPrice > 0)
         {
            features[featureIndex++] = main[0] / avgPrice;      // Normalized MACD
            features[featureIndex++] = signal[0] / avgPrice;    // Normalized signal
            features[featureIndex++] = (main[0] - signal[0]) / avgPrice;  // Histogram
         }
         else
            featureIndex += 3;
      }
      else
         featureIndex += 3;
   }

   if(UseATR && h_ATR != INVALID_HANDLE)
   {
      double atr[];
      if(CopyBuffer(h_ATR, 0, 0, 1, atr) > 0)
      {
         if(rates[copied-1].close > 0)
            features[featureIndex++] = atr[0] / rates[copied-1].close;  // Relative volatility
         else
            features[featureIndex++] = 0;
      }
      else
         featureIndex++;
   }

   if(UseBollinger && h_Bollinger != INVALID_HANDLE)
   {
      double upper[], middle[], lower[];
      if(CopyBuffer(h_Bollinger, 0, 0, 1, upper) > 0 &&
         CopyBuffer(h_Bollinger, 1, 0, 1, middle) > 0 &&
         CopyBuffer(h_Bollinger, 2, 0, 1, lower) > 0)
      {
         double currentPrice = rates[copied-1].close;
         double bandwidth = upper[0] - lower[0];

         if(bandwidth > 0)
         {

            features[featureIndex++] = (currentPrice - middle[0]) / bandwidth;

            features[featureIndex++] = bandwidth / middle[0];

            features[featureIndex++] = (currentPrice - lower[0]) / bandwidth;
         }
         else
            featureIndex += 3;
      }
      else
         featureIndex += 3;
   }

   if(UseMA && h_MA_Fast != INVALID_HANDLE && h_MA_Slow != INVALID_HANDLE)
   {
      double ma_fast[], ma_slow[];
      if(CopyBuffer(h_MA_Fast, 0, 0, 2, ma_fast) > 0 &&
         CopyBuffer(h_MA_Slow, 0, 0, 2, ma_slow) > 0)
      {
         double currentPrice = rates[copied-1].close;

         if(ma_fast[0] > 0 && ma_slow[0] > 0)
         {

            features[featureIndex++] = (currentPrice - ma_fast[0]) / ma_fast[0];

            features[featureIndex++] = (currentPrice - ma_slow[0]) / ma_slow[0];

            features[featureIndex++] = (ma_fast[0] - ma_slow[0]) / ma_slow[0];

            if(ArraySize(ma_fast) >= 2 && ma_fast[1] > 0)
               features[featureIndex++] = (ma_fast[0] - ma_fast[1]) / ma_fast[1];
            else
               features[featureIndex++] = 0;
         }
         else
            featureIndex += 4;
      }
      else
         featureIndex += 4;
   }

   if(UseFractals)
   {

      bool upFractal = false;
      if(copied >= 5)
      {
         int idx = copied - 3;
         if(rates[idx].high > rates[idx-2].high && 
            rates[idx].high > rates[idx-1].high &&
            rates[idx].high > rates[idx+1].high && 
            rates[idx].high > rates[idx+2].high)
            upFractal = true;
      }
      features[featureIndex++] = upFractal ? 1 : 0;

      bool downFractal = false;
      if(copied >= 5)
      {
         int idx = copied - 3;
         if(rates[idx].low < rates[idx-2].low && 
            rates[idx].low < rates[idx-1].low &&
            rates[idx].low < rates[idx+1].low && 
            rates[idx].low < rates[idx+2].low)
            downFractal = true;
      }
      features[featureIndex++] = downFractal ? 1 : 0;
   }

   if(UseADX && h_ADX != INVALID_HANDLE)
   {
      double adx[], plus_di[], minus_di[];
      if(CopyBuffer(h_ADX, 0, 0, 1, adx) > 0 &&
         CopyBuffer(h_ADX, 1, 0, 1, plus_di) > 0 &&
         CopyBuffer(h_ADX, 2, 0, 1, minus_di) > 0)
      {
         features[featureIndex++] = adx[0] / 100;  // Trend strength [0, 1]
         features[featureIndex++] = (plus_di[0] - 20) / 80;  // +DI normalized
         features[featureIndex++] = (minus_di[0] - 20) / 80; // -DI normalized
      }
      else
         featureIndex += 3;
   }

   if(UseWPR && h_WPR != INVALID_HANDLE)
   {
      double wpr[];
      if(CopyBuffer(h_WPR, 0, 0, 1, wpr) > 0)
      {
         features[featureIndex++] = (wpr[0] + 50) / 50;  // Normalization [-1, 1]
      }
      else
         featureIndex++;
   }

   for(int i = 0; i < ArraySize(features); i++)
   {
      if(!MathIsValidNumber(features[i]))
         features[i] = 0;
   }
}

double CalculateAdaptiveLot(double confidence)
{
   if(!UseAdaptiveLots)
      return InitialLot;

   double balance = Account.Balance();
   double riskAmount = balance * MaxRiskPercent / 100.0;

   double adjustedRisk = riskAmount * MathAbs(confidence - 0.5) * 2.0;

   double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
   double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_T

Показано первые 50% кода (символов: 54255)

Открыть по тарифу

Купите тариф с пакетом открытий или войдите, если тариф уже есть. Открытый файл останется в вашем кабинете навсегда.

Разовая покупка файла

На этой странице откроется полный исходный код файла вместо ознакомительного фрагмента.

Чтобы оформить заказ, введите email и перейдите к оплате.

Стоимость полного кода
5 425,50₽ ≈ $66.32