//+------------------------------------------------------------------+
//|               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)
{
   trade.SetDeviation(tradeDeviation);
   bool result = trade.Buy(volume, symbol, NormalizeDouble(SymbolInfoDouble(symbol, SYMBOL_ASK), (int)SymbolInfoInteger(symbol,SYMBOL_DIGITS)), sl, tp);
   return result;
}

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

bool CanTradeNow()
{
   int day = TimeDayOfWeek(TimeCurrent()); // Sunday=0, Saturday=6
   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);
      }
   }

   // Exemplu print corect pentru bool → string
   PrintFormat("Can trade now: %s", CanTradeNow() ? "YES" : "NO");
}


'250linii.mq5'			1
Trade.mqh			
Object.mqh			
StdLibErr.mqh			
OrderInfo.mqh			
HistoryOrderInfo.mqh			
PositionInfo.mqh			
DealInfo.mqh			
implicit conversion from 'int' to 'string'	250linii.mq5	261	42
'SetDeviation' - undeclared identifier	250linii.mq5	298	10
'tradeDeviation' - some operator expected	250linii.mq5	298	23
'SetDeviation' - undeclared identifier	250linii.mq5	305	10
'tradeDeviation' - some operator expected	250linii.mq5	305	23
'TimeDayOfWeek' - undeclared identifier	250linii.mq5	312	14
'TimeCurrent' - some operator expected	250linii.mq5	312	28
implicit conversion from 'bool' to 'string'	250linii.mq5	370	13
6 errors, 2 warnings		7	3