//+------------------------------------------------------------------+ //| AISignalConfirmation.mqh | //| AI-Powered Signal Confirmation System | //| Combines OpenAI API + MQL5 Neural Network capabilities | //| Validates signal clusters before trading | //+------------------------------------------------------------------+ //================ AI CONFIRMATION STRUCTURE ==================// struct AIConfirmation { bool approved; // Final decision double confidence; // 0-100 string reasoning; // Why approved/rejected string ai_bias; // "bullish", "bearish", "neutral" string pattern_detected; // Pattern identified by AI double risk_score; // 0-100 (higher = riskier) string recommendation; // Specific trading advice }; //================ GLOBAL AI STATE ==================// AIConfirmation LastAIDecision; datetime LastAICallTime = 0; int AI_Call_Cooldown = 60; // 60 seconds between AI calls string AI_Context_Memory = ""; // Stores recent market context //================ NEURAL NETWORK VARIABLES ==================// // These would connect to MQL5's neural network library // For full implementation, see: https://www.mql5.com/en/neurobook bool UseNeuralNetwork = false; // Enable when NN model is trained string NeuralModelPath = ""; // Path to trained model double NNConfidence = 0; // NN model confidence //+------------------------------------------------------------------+ //| Initialize AI Confirmation System | //+------------------------------------------------------------------+ void InitializeAIConfirmation() { LastAIDecision.approved = false; LastAIDecision.confidence = 0; // Check if we have a trained neural network model NeuralModelPath = "Files\\TrainingModels\\QuarterTheory_NN.nnw"; if(FileIsExist(NeuralModelPath)) { UseNeuralNetwork = true; Print("✅ Neural Network model found: ", NeuralModelPath); } else { Print("ℹ️ No Neural Network model - using OpenAI only"); } Print("✅ AI Signal Confirmation initialized"); } //+------------------------------------------------------------------+ //| Request AI Confirmation for Signal Cluster | //+------------------------------------------------------------------+ AIConfirmation RequestAIConfirmation(SignalCluster &cluster) { AIConfirmation decision; // Rate limiting - don't call AI too frequently if(TimeCurrent() - LastAICallTime < AI_Call_Cooldown) { Print("⏱️ AI cooldown active - using last decision"); return LastAIDecision; } //============================================================== // PHASE 1: PREPARE MARKET CONTEXT //============================================================== string context = BuildMarketContext(cluster); //============================================================== // PHASE 2: GET NEURAL NETWORK ANALYSIS (if available) //============================================================== double nn_confidence = 0; string nn_pattern = ""; if(UseNeuralNetwork) { // This would call the trained NN model // For now, placeholder nn_confidence = AnalyzeWithNeuralNetwork(context); nn_pattern = GetNNPatternPrediction(); Print("🧠 Neural Network Confidence: ", nn_confidence, "%"); Print("🧠 NN Pattern: ", nn_pattern); } //============================================================== // PHASE 3: GET OPENAI ANALYSIS //============================================================== string ai_response = ""; if(Use_OpenAI && AI_Initialized) { ai_response = GetOpenAIAnalysis(context, cluster, nn_pattern); Print("🤖 OpenAI Analysis received"); } else { // Fallback to rule-based decision Print("ℹ️ OpenAI not available - using rules-based decision"); decision = MakeRuleBasedDecision(cluster, nn_confidence); LastAIDecision = decision; LastAICallTime = TimeCurrent(); return decision; } //============================================================== // PHASE 4: PARSE AI RESPONSE //============================================================== decision = ParseAIResponse(ai_response, cluster); //============================================================== // PHASE 5: COMBINE WITH NEURAL NETWORK (if available) //============================================================== if(UseNeuralNetwork && nn_confidence > 0) { // Weighted combination: 70% OpenAI, 30% Neural Network double combined_confidence = (decision.confidence * 0.7) + (nn_confidence * 0.3); decision.confidence = combined_confidence; // Only approve if both agree on direction if(decision.ai_bias != GetNNBias() && nn_confidence > 60) { decision.approved = false; decision.reasoning = "OpenAI and Neural Network disagree on direction"; Print("⚠️ AI CONFLICT: OpenAI says ", decision.ai_bias, " but NN says ", GetNNBias()); } } //============================================================== // PHASE 6: FINAL DECISION LOGGING //============================================================== Print("========================================"); Print("🤖 AI CONFIRMATION RESULT:"); Print(" Decision: ", decision.approved ? "APPROVED ✅" : "REJECTED ❌"); Print(" Confidence: ", decision.confidence, "%"); Print(" AI Bias: ", decision.ai_bias); Print(" Pattern: ", decision.pattern_detected); Print(" Risk Score: ", decision.risk_score); Print(" Reasoning: ", decision.reasoning); Print(" Recommendation: ", decision.recommendation); Print("========================================"); LastAIDecision = decision; LastAICallTime = TimeCurrent(); return decision; } //+------------------------------------------------------------------+ //| Build Comprehensive Market Context for AI | //+------------------------------------------------------------------+ string BuildMarketContext(SignalCluster &cluster) { string context = ""; // Current market conditions context += "MARKET CONDITIONS:\n"; context += "Symbol: " + _Symbol + "\n"; context += "Timeframe: " + EnumToString((ENUM_TIMEFRAMES)_Period) + "\n"; context += "Mode: " + CurrentMode + "\n"; context += "State: " + CurrentState + "\n"; context += "Price: " + DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_BID), 5) + "\n"; context += "\n"; // Signal cluster information context += "SIGNAL CLUSTER:\n"; context += "Count: " + IntegerToString(cluster.count) + " signals\n"; context += "Direction: " + cluster.consensus_direction + "\n"; context += "Type: " + cluster.consensus_type + "\n"; context += "Strength: " + DoubleToString(cluster.combined_strength, 1) + "/100\n"; context += "Conflict Score: " + DoubleToString(cluster.conflict_score, 1) + "/100\n"; context += "\n"; // Individual signals context += "ACTIVE SIGNALS:\n"; for(int i = 0; i < cluster.count; i++) { CoordinatedSignal sig = cluster.signals[i]; context += StringFormat("- %s: %s %s at %s (strength: %.0f)\n", sig.source, sig.direction, sig.action, sig.location, sig.strength); } context += "\n"; // Technical levels context += "KEY LEVELS:\n"; context += "MFIB Levels:\n"; context += " 1.000: " + DoubleToString(MFIB_1000, 5) + "\n"; context += " 0.786: " + DoubleToString(MFIB_786, 5) + "\n"; context += " 0.618: " + DoubleToString(MFIB_618, 5) + "\n"; context += " 0.500: " + DoubleToString(MFIB_500, 5) + "\n"; context += " 0.382: " + DoubleToString(MFIB_382, 5) + "\n"; context += " 0.236: " + DoubleToString(MFIB_236, 5) + "\n"; context += "\n"; // Moving averages context += "Moving Averages:\n"; context += " MA500: " + DoubleToString(MA_500_Value, 5) + "\n"; context += " MA230: " + DoubleToString(MA_230_Value, 5) + "\n"; context += " MA140: " + DoubleToString(MA_140_Value, 5) + "\n"; context += " MA50: " + DoubleToString(MA_50_Value, 5) + "\n"; context += " MA20: " + DoubleToString(MA_20_Value, 5) + "\n"; context += "\n"; // Recent patterns if(PatternCount > 0) { context += "CANDLESTICK PATTERNS:\n"; for(int i = 0; i < MathMin(PatternCount, 5); i++) { PatternSignal pattern = ActivePatterns[i]; context += StringFormat("- %s at %s (strength: %.0f)\n", pattern.name, pattern.location, pattern.adjusted_strength); } context += "\n"; } // Stochastic context += "STOCHASTIC:\n"; context += " Main: " + DoubleToString(StochBuffer_Main[0], 1) + "\n"; context += " Signal: " + DoubleToString(StochBuffer_Signal[0], 1) + "\n"; context += "\n"; // Add context memory (recent AI insights) if(AI_Context_Memory != "") { context += "RECENT AI INSIGHTS:\n"; context += AI_Context_Memory + "\n\n"; } return context; } //+------------------------------------------------------------------+ //| Get OpenAI Analysis | //+------------------------------------------------------------------+ string GetOpenAIAnalysis(string context, SignalCluster &cluster, string nn_pattern) { string prompt = "You are an expert forex trader analyzing the following market conditions.\n\n"; prompt += context; if(nn_pattern != "") { prompt += "NEURAL NETWORK DETECTED PATTERN: " + nn_pattern + "\n\n"; } prompt += "Based on this information, please provide:\n"; prompt += "1. Your directional bias (bullish/bearish/neutral)\n"; prompt += "2. Confidence level (0-100)\n"; prompt += "3. Approval (YES/NO) for taking this trade\n"; prompt += "4. Risk score (0-100, higher = riskier)\n"; prompt += "5. Key reasoning (2-3 sentences)\n"; prompt += "6. Specific recommendation\n\n"; prompt += "Format your response EXACTLY as:\n"; prompt += "BIAS: [bullish/bearish/neutral]\n"; prompt += "CONFIDENCE: [0-100]\n"; prompt += "APPROVAL: [YES/NO]\n"; prompt += "RISK: [0-100]\n"; prompt += "REASONING: [your reasoning]\n"; prompt += "RECOMMENDATION: [your recommendation]\n"; // Call OpenAI (from OpenAI.mqh) string response = CallOpenAI(prompt); return response; } //+------------------------------------------------------------------+ //| Parse AI Response into Structured Decision | //+------------------------------------------------------------------+ AIConfirmation ParseAIResponse(string response, SignalCluster &cluster) { AIConfirmation decision; // Extract BIAS int bias_pos = StringFind(response, "BIAS:"); if(bias_pos >= 0) { int bias_end = StringFind(response, "\n", bias_pos); string bias_line = StringSubstr(response, bias_pos + 5, bias_end - bias_pos - 5); StringTrimLeft(bias_line); StringTrimRight(bias_line); decision.ai_bias = StringToLower(bias_line); } else { decision.ai_bias = "neutral"; } // Extract CONFIDENCE int conf_pos = StringFind(response, "CONFIDENCE:"); if(conf_pos >= 0) { int conf_end = StringFind(response, "\n", conf_pos); string conf_line = StringSubstr(response, conf_pos + 11, conf_end - conf_pos - 11); StringTrimLeft(conf_line); StringTrimRight(conf_line); decision.confidence = StringToDouble(conf_line); } else { decision.confidence = 0; } // Extract APPROVAL int appr_pos = StringFind(response, "APPROVAL:"); if(appr_pos >= 0) { int appr_end = StringFind(response, "\n", appr_pos); string appr_line = StringSubstr(response, appr_pos + 9, appr_end - appr_pos - 9); StringTrimLeft(appr_line); StringTrimRight(appr_line); decision.approved = (StringFind(StringToUpper(appr_line), "YES") >= 0); } else { decision.approved = false; } // Extract RISK int risk_pos = StringFind(response, "RISK:"); if(risk_pos >= 0) { int risk_end = StringFind(response, "\n", risk_pos); string risk_line = StringSubstr(response, risk_pos + 5, risk_end - risk_pos - 5); StringTrimLeft(risk_line); StringTrimRight(risk_line); decision.risk_score = StringToDouble(risk_line); } else { decision.risk_score = 50; } // Extract REASONING int reas_pos = StringFind(response, "REASONING:"); if(reas_pos >= 0) { int reas_end = StringFind(response, "RECOMMENDATION:", reas_pos); if(reas_end < 0) reas_end = StringLen(response); decision.reasoning = StringSubstr(response, reas_pos + 10, reas_end - reas_pos - 10); StringTrimLeft(decision.reasoning); StringTrimRight(decision.reasoning); } else { decision.reasoning = "No reasoning provided"; } // Extract RECOMMENDATION int rec_pos = StringFind(response, "RECOMMENDATION:"); if(rec_pos >= 0) { decision.recommendation = StringSubstr(response, rec_pos + 15); StringTrimLeft(decision.recommendation); StringTrimRight(decision.recommendation); } else { decision.recommendation = "Follow standard trade management"; } // Validate that AI bias matches cluster direction if(decision.ai_bias != cluster.consensus_direction && decision.ai_bias != "neutral") { Print("⚠️ AI DISAGREES: Cluster says ", cluster.consensus_direction, " but AI says ", decision.ai_bias); decision.approved = false; decision.reasoning += " AI directional bias conflicts with signal cluster."; } return decision; } //+------------------------------------------------------------------+ //| Fallback Rule-Based Decision (when AI not available) | //+------------------------------------------------------------------+ AIConfirmation MakeRuleBasedDecision(SignalCluster &cluster, double nn_conf) { AIConfirmation decision; // Use cluster consensus decision.ai_bias = cluster.consensus_direction; decision.confidence = cluster.combined_strength; // Incorporate NN confidence if available if(nn_conf > 0) { decision.confidence = (decision.confidence * 0.7) + (nn_conf * 0.3); } // Approval criteria decision.approved = (cluster.conflict_score < 40 && decision.confidence >= 60 && cluster.consensus_direction != "neutral"); // Risk score (inverse of confidence, adjusted for conflict) decision.risk_score = 100 - decision.confidence + cluster.conflict_score; decision.reasoning = "Rule-based decision: " + IntegerToString(cluster.count) + " signals, " + DoubleToString(cluster.conflict_score, 1) + "% conflict"; decision.recommendation = decision.approved ? "Proceed with standard position size" : "Skip this setup"; return decision; } //+------------------------------------------------------------------+ //| Neural Network Analysis (Placeholder for MQL5 NN implementation)| //+------------------------------------------------------------------+ double AnalyzeWithNeuralNetwork(string context) { // This is a placeholder for the actual NN implementation // Full implementation requires: // 1. Training a model using MQL5's neural network library // 2. Saving the model to file // 3. Loading and running inference here // See: https://www.mql5.com/en/neurobook for full implementation guide // For now, return 0 (not implemented) return 0; } //+------------------------------------------------------------------+ //| Get Neural Network Pattern Prediction | //+------------------------------------------------------------------+ string GetNNPatternPrediction() { // Placeholder - would return pattern identified by NN return ""; } //+------------------------------------------------------------------+ //| Get Neural Network Bias | //+------------------------------------------------------------------+ string GetNNBias() { // Placeholder - would return directional bias from NN return "neutral"; } //+------------------------------------------------------------------+ //| Update AI Context Memory (for continuity between calls) | //+------------------------------------------------------------------+ void UpdateAIContextMemory(string new_insight) { // Keep only last 3 insights if(AI_Context_Memory != "") { int newline_count = 0; for(int i = 0; i < StringLen(AI_Context_Memory); i++) { if(StringGetCharacter(AI_Context_Memory, i) == '\n') newline_count++; if(newline_count >= 3) { AI_Context_Memory = StringSubstr(AI_Context_Memory, 0, i); break; } } } AI_Context_Memory = new_insight + "\n" + AI_Context_Memory; } //+------------------------------------------------------------------+ //| Calculate Defensive Multiplier Based on AI Risk Score | //+------------------------------------------------------------------+ double GetAIRiskMultiplier(AIConfirmation &decision) { // Convert risk score to position size multiplier // Low risk (0-30) = 1.2x multiplier // Medium risk (31-60) = 1.0x multiplier // High risk (61-100) = 0.7x multiplier double multiplier = 1.0; if(decision.risk_score <= 30) multiplier = 1.2; // Low risk - can be aggressive else if(decision.risk_score <= 60) multiplier = 1.0; // Medium risk - standard size else if(decision.risk_score <= 80) multiplier = 0.8; // High risk - defensive else multiplier = 0.6; // Very high risk - very defensive // Adjust based on confidence if(decision.confidence >= 85) multiplier += 0.2; else if(decision.confidence < 60) multiplier -= 0.1; return MathMax(0.5, MathMin(multiplier, 1.5)); } //+------------------------------------------------------------------+ //| Get AI Decision Summary for Display | //+------------------------------------------------------------------+ string GetAIDecisionSummary() { if(LastAIDecision.confidence == 0) return "No AI decision yet"; string summary = ""; summary += LastAIDecision.approved ? "✅ APPROVED" : "❌ REJECTED"; summary += " | " + LastAIDecision.ai_bias; summary += " | " + DoubleToString(LastAIDecision.confidence, 0) + "% conf"; summary += " | " + DoubleToString(LastAIDecision.risk_score, 0) + "% risk"; return summary; }