Ofada Gold trader
Похожие материалы по тегам
Сообщите нам, если считаете, что материал размещён без разрешения.
Сообщить о материале
Обращение по товару «ofada_gold_trader_v230.mq5» отправится на рассмотрение. Укажите контакт для ответа и опишите причину.
О программе
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? После подтверждения оплаты файл сохранится в кабинете на этот email. Если аккаунта ещё нет, мы создадим его и пришлём ссылку для задания пароля. Если аккаунт уже есть, покупка добавится в него. Укажите адрес, к которому у вас есть доступ.
Чтобы оформить заказ, введите email и перейдите к оплате.