//+------------------------------------------------------------------+
//|               AI ProfitMaster v4.1 Autonomous Edition            |
//+------------------------------------------------------------------+
#property copyright "AI ProfitMaster"
#property version   "4.10"
#property strict

#include <Trade\Trade.mqh>  // Include clasa de trading MQL5

// INPUTS
input string DeepSeekAPIKey = "";           // Cheia ta pentru DeepSeek AI
input string FinnhubAPIKey = "";            // Cheia ta pentru Finnhub
input string AV_APIKey = "";                 // Cheia ta pentru Alpha Vantage
input int MaxOpenPositions = 5;
input double RiskPercent_Default = 1.5;
input int StopLossPips_Default = 20;
input int TakeProfitPips_Default = 60;
input bool UseStopLoss = false;
input bool EnableMultipleEntries = true;
input double MaxPartialClosePercent = 0.5;
input double ProfitLockThreshold = 20.0;
input int MinTradeDelaySec = 60;
input int DefaultDeviation = 10;
input string SymbolsList = "EURUSD,GBPUSD,USDJPY";
input string TimeframesStr = "1,15,60";

// GLOBALS
double pipFactor = 1.0;
datetime lastTradeTime = 0;

#define MAX_HISTORY 20

struct TradeResult {
   bool win;
   double profit;
};

TradeResult tradeHistory[MAX_HISTORY];
int historyIndex = 0;
double aiConfidence = 0.6;
int consecutiveWins = 0;
int consecutiveLosses = 0;

struct Params {
   double riskPercent;
   int stopLossPips;
   int takeProfitPips;
};

Params currentParams;
double minLot = 0.01;
double maxLot = 100.0;
double lotStep = 0.01;
int tradeDeviation = 10;

struct MarketData {
   double currentPrice;
   string sentiment;
   double targetPrice;
   double rsi;
   double macd;
};

struct TradeDecision {
   string action;
   double riskPercent;
   int stopLossPips;
   int takeProfitPips;
   double confidence;
};

enum TradeSignal {
   SIGNAL_BUY,
   SIGNAL_SELL,
   SIGNAL_HOLD
};

// ===== UTILITIES ======

string StringTrim(string s)
{
   while(StringLen(s) > 0)
   {
      ushort ch = StringGetCharacter(s, 0);
      if(ch == 32 || ch == 9 || ch == 10 || ch == 13)
         s = StringSubstr(s,1);
      else break;
   }
   while(StringLen(s) > 0)
   {
      int len = StringLen(s);
      ushort ch = StringGetCharacter(s, len-1);
      if(ch == 32 || ch == 9 || ch == 10 || ch == 13)
         s = StringSubstr(s,0,len-1);
      else break;
   }
   return s;
}

int StringSplit(string text, char delimiter, string &result[])
{
   int count = 0;
   int start = 0;
   int len = StringLen(text);
   for(int i=0; i<=len; i++)
   {
      if(i==len || text[i] == delimiter)
      {
         int size = i-start;
         if(size > 0)
         {
            string part = StringSubstr(text,start,size);
            ArrayResize(result, count+1);
            result[count++] = part;
         }
         start = i+1;
      }
   }
   return count;
}

void ParseTimeframes()
{
   string parts[];
   int TimeframeCount = StringSplit(TimeframesStr, ',', parts);
   ENUM_TIMEFRAMES Timeframes[10];
   if(TimeframeCount > ArraySize(Timeframes)) TimeframeCount = ArraySize(Timeframes);
   for(int i=0; i < TimeframeCount; i++)
   {
      int t = (int)StringToInteger(parts[i]);
      switch(t)
      {
         case 1: Timeframes[i] = PERIOD_M1; break;
         case 5: Timeframes[i] = PERIOD_M5; break;
         case 15: Timeframes[i] = PERIOD_M15; break;
         case 30: Timeframes[i] = PERIOD_M30; break;
         case 60: Timeframes[i] = PERIOD_H1; break;
         case 240: Timeframes[i] = PERIOD_H4; break;
         case 1440: Timeframes[i] = PERIOD_D1; break;
         default: Timeframes[i] = PERIOD_CURRENT; break;
      }
   }
}

void AutoDetectBrokerParameters()
{
   minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
   maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
   lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
   if(minLot <= 0) minLot = 0.01;
   if(maxLot <= 0) maxLot = 100;
   if(lotStep <= 0) lotStep = 0.01;
   tradeDeviation = DefaultDeviation;
   PrintFormat("Broker params: minLot=%.4f maxLot=%.2f lotStep=%.4f deviation=%d", minLot, maxLot, lotStep, tradeDeviation);
}

string JSON_GetString(const string json, const string key)
{
   string search = "\"" + key + "\"";
   int pos = StringFind(json, search);
   if(pos < 0) return "";
   pos = StringFind(json, ":", pos);
   if(pos < 0) return "";
   pos++;
   while(pos < StringLen(json) && (json[pos]==' ' || json[pos]=='\"')) pos++;
   int start=pos;
   if(json[start]=='\"')
   {
      start++;
      int end=StringFind(json, "\"", start);
      if(end < 0) end = StringLen(json);
      return StringSubstr(json, start, end-start);
   }
   else
   {
      int end = start;
      while(end < StringLen(json) && ((json[end]>='0' && json[end]<='9') || json[end]=='.'
             || json[end]=='-' || json[end]==',' || json[end]=='}')) end++;
      return StringSubstr(json, start, end-start);
   }
}

string JSON_GetLastValue(const string json, const string key)
{
   string search = "\"" + key + "\":{";
   int pos = StringFind(json, search);
   if(pos < 0) return "";
   pos += StringLen(search);
   int braces=1;
   int i=pos;
   string lastKey="";
   int lastKeyPos=-1;
   while(i < StringLen(json) && braces > 0)
   {
      if(json[i] == '{') braces++;
      else if(json[i] == '}') braces--;
      else if(json[i] == '\"')
      {
         int keyStart = i+1;
         int keyEnd = StringFind(json, "\"", keyStart);
         if(keyEnd == -1) break;
         lastKey = StringSubstr(json,keyStart,keyEnd - keyStart);
         lastKeyPos = keyStart;
         i = keyEnd;
      }
      i++;
   }
   if(lastKey == "") return "";
   int valStart = StringFind(json, ":", lastKeyPos) + 1;
   while(valStart < StringLen(json) && (json[valStart]==' ' || json[valStart]=='\"')) valStart++;
   int valEnd = valStart;
   while(valEnd < StringLen(json) && ((json[valEnd]>='0' && json[valEnd]<='9') || json[valEnd]=='.'
          || json[valEnd]=='-')) valEnd++;
   return StringSubstr(json,valStart,valEnd-valStart);
}

string GetFinnhubData(string sym, string apiKey, string &sentiment, double &targetPrice)
{
   string url = "https://finnhub.io/api/v1/stock/recommendation?symbol=" + sym + "&token=" + apiKey;
   char result[];
   string cookies="", headers="";
   int timeout = 5000;
   char post[];
   int res = WebRequest("GET", url, NULL, timeout, post, result, headers);
   if(res == 200)
   {
      string json = CharArrayToString(result);
      targetPrice = StringToDouble(JSON_GetString(json, "targetMean"));
      sentiment = JSON_GetString(json, "recommendation");
      return json;
   }
   return "";
}

string GetAlphaVantageData(string sym, string apiKey, double &rsi, double &macd)
{
   string url = "https://www.alphavantage.co/query?function=MACD&symbol=" + sym + "&interval=15min&apikey=" + apiKey;
   char result[];
   string cookies="", headers="";
   int timeout = 5000;
   char post[];
   int res = WebRequest("GET", url, NULL, timeout, post, result, headers);
   if(res == 200)
   {
      string json = CharArrayToString(result);
      rsi = StringToDouble(JSON_GetString(json, "rsi"));
      macd = StringToDouble(JSON_GetString(json, "macd"));
      return json;
   }
   return "";
}

string DeepSeek_GetAIRecommendation(string prompt, string apiKey)
{
   if(StringLen(apiKey)==0)
   {
      Print("DeepSeek API missing -- default BUY");
      return "ACTION: BUY\nRISK: 1.5\nSTOPLOSS: 20\nTAKEPROFIT: 60\nCONFIDENCE: 0.85";
   }
   string url = "https://api.deepseek.ai/v1/chat";
   string jsonRequest = "{\"prompt\":\""+StringReplace(prompt,"\"","\\\"")+"\"}";
   char post[], result[];
   StringToCharArray(jsonRequest, post, 0, StringLen(jsonRequest));
   string cookies="";
   string headers="Content-Type: application/json\r\nAuthorization: Bearer "+apiKey+"\r\n";
   int timeout = 20000;
   int res = WebRequest("POST", url, headers, timeout, post, result, cookies);
   if(res != 200)
   {
      PrintFormat("DeepSeek HTTP error: %d", res);
      return "";
   }
   return CharArrayToString(result);
}

double CalculateLot(Params &params)
{
   double balance = AccountInfoDouble(ACCOUNT_BALANCE);
   double risk_amount = balance * params.riskPercent / 100.0;
   double tick_value = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE);
   if(tick_value == 0) tick_value = 1;
   double sl_dist = params.stopLossPips * _Point * pipFactor;
   double lot;
   if(UseStopLoss)
      lot = risk_amount / ((sl_dist/_Point)*tick_value);
   else
      lot = risk_amount / ((50*_Point*pipFactor/_Point)*tick_value)*(EnableMultipleEntries ? 1.2 : 1.0);
   if(lotStep <= 0) lotStep = 0.01;
   lot = MathFloor(lot / lotStep) * lotStep;
   lot = MathMax(minLot, MathMin(maxLot, lot));
   return NormalizeDouble(lot,2);
}

CTrade trade;  // Instanțiem clasa de trading

bool Buy(double volume, string symbol, double sl = 0, double tp = 0)
{
   double price = NormalizeDouble(SymbolInfoDouble(symbol, SYMBOL_ASK), (int)SymbolInfoInteger(symbol,SYMBOL_DIGITS));
   return trade.Buy(volume, price, sl, tp, NULL, tradeDeviation);
}

bool Sell(double volume, string symbol, double sl = 0, double tp = 0)
{
   double price = NormalizeDouble(SymbolInfoDouble(symbol, SYMBOL_BID), (int)SymbolInfoInteger(symbol,SYMBOL_DIGITS));
   return trade.Sell(volume, price, sl, tp, NULL, tradeDeviation);
}

bool CanTradeNow()
{
   int day = TimeDayOfWeek(TimeCurrent());
   if(day == 0 || day == 6)
      return false;
   return true;
}

double GetRSIValue(string symbol, ENUM_TIMEFRAMES timeframe, int period, int applied_price, int shift)
{
   int handle = iRSI(symbol, timeframe, period, applied_price);
   if(handle == INVALID_HANDLE)
      return 0;
   double buffer[];
   if(CopyBuffer(handle, 0, shift, 1, buffer) <= 0)
   {
      IndicatorRelease(handle);
      return 0;
   }
   IndicatorRelease(handle);
   return buffer[0];
}

TradeSignal GetRSISignal(string symbol, ENUM_TIMEFRAMES tf)
{
   double rsi = GetRSIValue(symbol, tf, 14, PRICE_CLOSE, 0);
   if(rsi > 70) return SIGNAL_SELL;
   else if(rsi < 30) return SIGNAL_BUY;
   else return SIGNAL_HOLD;
}

TradeSignal AggregateSignals(string symbol)
{
   int buyCount=0, sellCount=0;
   ENUM_TIMEFRAMES Timeframes[3] = {PERIOD_M15, PERIOD_H1, PERIOD_D1};
   for(int i=0; i<3; i++)
   {
      TradeSignal sig = GetRSISignal(symbol, Timeframes[i]);
      if(sig == SIGNAL_BUY) buyCount++;
      else if(sig == SIGNAL_SELL) sellCount++;
   }
   if(buyCount >= 2) return SIGNAL_BUY;
   if(sellCount >= 2) return SIGNAL_SELL;
   return SIGNAL_HOLD;
}

bool ParseAIResponse(string response, TradeDecision &decision)
{
   decision.action = "hold";
   decision.riskPercent = 1.0;
   decision.stopLossPips = 20;
   decision.takeProfitPips = 60;
   decision.confidence = 0.6;
   int pos;
   pos = StringFind(response, "ACTION:");
   if(pos >= 0)
   {
      int eol = StringFind(response, "\n", pos);
      if(eol < 0) eol = StringLen(response);
      string val = StringTrim(StringSubstr(response, pos + 7, eol - (pos + 7)));
      val = StringToLower(val);
      if(StringFind(val, "buy") >= 0)
         decision.action = "buy";
      else if(StringFind(val,"sell")>=0)
         decision.action="sell";
      else
         decision.action = "hold";
   }
   pos = StringFind(response, "RISK:");
   if(pos >= 0)
   {
      string val = StringTrim(StringSubstr(response, pos + 5, 5));
      if(StringLen(val) > 0)
         decision.riskPercent = MathMax(0.1, MathMin(5.0, StringToDouble(val)));
   }
   pos = StringFind(response, "STOPLOSS:");
   if(pos >= 0)
   {
      string val = StringTrim(StringSubstr(response, pos + 9, 5));
      if(StringLen(val) > 0)
         decision.stopLossPips = MathMax(5, (int)StringToInteger(val));
   }
   pos = StringFind(response, "TAKEPROFIT:");
   if(pos >= 0)
   {
      string val = StringTrim(StringSubstr(response, pos + 11, 5));
      if(StringLen(val) > 0)
         decision.takeProfitPips = MathMax(decision.stopLossPips, (int)StringToInteger(val));
   }
   pos = StringFind(response, "CONFIDENCE:");
   if(pos >= 0)
   {
      string val = StringTrim(StringSubstr(response, pos + 11, 5));
      if(StringLen(val) > 0)
         decision.confidence = MathMax(0.1, MathMin(1.0, StringToDouble(val)));
   }
   return true;
}

void ManageScaling(string symbol, string action, double lotToTrade)
{
   int count = 0;
   for(int i=0; i<PositionsTotal(); i++)
   {
      ulong ticket = PositionGetTicket(i);
      if(PositionSelectByTicket(ticket))
      {
         if(PositionGetString(POSITION_SYMBOL)==symbol &&
            PositionGetInteger(POSITION_TYPE)==(StringCompare(action,"buy")==0?POSITION_TYPE_BUY:POSITION_TYPE_SELL))
            count++;
      }
   }
   if(count>0 && aiConfidence>0.75 && lotToTrade>0)
   {
      double scaledLot = lotToTrade * 0.7;
      if(count < MaxOpenPositions)
      {
         PrintFormat("Scaling into %s, lot %.2f", action, scaledLot);
         if(StringCompare(action, "buy") == 0)
            Buy(scaledLot, symbol, 0, 0);
         else
            Sell(scaledLot, symbol, 0, 0);
      }
   }
   else if(count == 0)
   {
      PrintFormat("Opening new %s position, lot %.2f", action, lotToTrade);
      if(StringCompare(action, "buy") == 0)
         Buy(lotToTrade, symbol, 0, 0);
      else
         Sell(lotToTrade, symbol, 0, 0);
   }
}

int OnInit()
{
   int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
   pipFactor = (digits == 3 || digits == 5) ? 10 : 1;
   AutoDetectBrokerParameters();
   for(int i=0; i < MAX_HISTORY; i++)
   {
      tradeHistory[i].win = false;
      tradeHistory[i].profit = 0;
   }
   currentParams.riskPercent = RiskPercent_Default;
   currentParams.stopLossPips = StopLossPips_Default;
   currentParams.takeProfitPips = TakeProfitPips_Default;
   Print("AI ProfitMaster v4.1 autonomous ready.");
   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason)
{
}

void OnTick()
{
   if(!CanTradeNow())
      return;

   string symbols[];
   int symCount = StringSplit(SymbolsList, ',', symbols);

   for(int s=0; s<symCount; s++)
   {
      string sym = StringTrim(symbols[s]);
      if(!SymbolSelect(sym, true))
         continue;

      TradeSignal sig = AggregateSignals(sym);
      if(sig == SIGNAL_HOLD)
         continue;

      MarketData md;
      md.currentPrice = SymbolInfoDouble(sym, SYMBOL_BID);
      md.sentiment = "";
      md.targetPrice = 0;
      md.rsi = 0;
      md.macd = 0;

      GetFinnhubData(sym, FinnhubAPIKey, md.sentiment, md.targetPrice);
      GetAlphaVantageData(sym, AV_APIKey, md.rsi, md.macd);

      string prompt = "Current Price: " + DoubleToString(md.currentPrice, 5) +
                     ", Sentiment: " + md.sentiment +
                     ", Target: " + DoubleToString(md.targetPrice, 5) +
                     ", RSI: " + DoubleToString(md.rsi, 2) +
                     ", MACD: " + DoubleToString(md.macd, 4) +
                     ", Win Streak: " + IntegerToString(consecutiveWins) +
                     ", Loss Streak: " + IntegerToString(consecutiveLosses);

      string aiResp = DeepSeek_GetAIRecommendation(prompt, DeepSeekAPIKey);
      if(aiResp == "")
         continue;

      TradeDecision decision;
      if(ParseAIResponse(aiResp, decision))
      {
         aiConfidence = decision.confidence;
         currentParams.riskPercent = decision.riskPercent;
         currentParams.stopLossPips = decision.stopLossPips;
         currentParams.takeProfitPips = decision.takeProfitPips;

         double lot = CalculateLot(currentParams);

         PrintFormat("Symbol %s, Action %s, Lot %.2f", sym, StringToUpper(decision.action), lot);
         ManageScaling(sym, decision.action, lot);
      }
   }

   PrintFormat("Can trade now: %s", CanTradeNow() ? "YES" : "NO");
}


ofera codul dirct pentru compilare cu reparatiile de rigoare
Trade.mqh			
Object.mqh			
StdLibErr.mqh			
OrderInfo.mqh			
HistoryOrderInfo.mqh			
PositionInfo.mqh			
DealInfo.mqh			
implicit conversion from 'int' to 'string'	250linii.mq5	261	42
implicit conversion from 'number' to 'string'	250linii.mq5	299	29
implicit conversion from 'number' to 'string'	250linii.mq5	299	50
implicit conversion from 'number' to 'string'	250linii.mq5	305	30
implicit conversion from 'number' to 'string'	250linii.mq5	305	51
'TimeDayOfWeek' - undeclared identifier	250linii.mq5	310	14
'TimeCurrent' - some operator expected	250linii.mq5	310	28
implicit conversion from 'bool' to 'string'	250linii.mq5	368	13
2 errors, 6 warnings		3	7