RSI-Stoch-MA-EA/Aisignalconfirmation.mqh

526 lines
19 KiB
MQL5
Raw Permalink Normal View History

2026-01-20 20:08:21 +00:00
//+------------------------------------------------------------------+
//| 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;
}