RSI-Stoch-MA-EA/Openai.mqh

415 lines
15 KiB
MQL5
Raw Permalink Normal View History

2026-01-20 09:55:52 +00:00
//+------------------------------------------------------------------+
//| OpenAI.mqh |
//| OpenAI API Integration Module |
//+------------------------------------------------------------------+
#property copyright "QuarterTheory x VIZION"
#property strict
#include "GlobalVariables.mqh"
#include "InputParams.mqh"
#include "Utilities.mqh"
2026-01-22 04:48:51 -06:00
#include "Tradeexecution.mqh"
#include "Openai.mqh"
2026-01-20 09:55:52 +00:00
2026-01-20 10:24:54 +00:00
//================ FORWARD DECLARATIONS ==================//
2026-01-22 04:48:51 -06:00
//bool IsAIEnabled();
2026-01-20 10:24:54 +00:00
2026-01-20 09:55:52 +00:00
//================ OPENAI GLOBALS ==================//
2026-01-20 10:28:08 +00:00
string OpenAI_API_Key_Internal = "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"; // Internal storage
string OpenAI_Model = "gpt-4o-mini"; // or "gpt-4o-mini" for faster/cheaper
2026-01-20 09:55:52 +00:00
string OpenAI_Endpoint = "https://api.openai.com/v1/chat/completions";
// Response cache to avoid duplicate API calls
struct OpenAI_Cache
{
string last_question;
string last_response;
datetime last_time;
};
OpenAI_Cache AI_Cache;
//+------------------------------------------------------------------+
//| Initialize OpenAI API |
//+------------------------------------------------------------------+
bool InitializeOpenAI(string api_key)
{
if(StringLen(api_key) < 20)
{
Print("❌ OpenAI API key invalid or too short");
return false;
}
2026-01-20 10:24:54 +00:00
OpenAI_API_Key_Internal = api_key; // Store internally
2026-01-20 09:55:52 +00:00
AI_Cache.last_question = "";
AI_Cache.last_response = "";
AI_Cache.last_time = 0;
Print("✅ OpenAI API initialized with model: ", OpenAI_Model);
return true;
}
2026-01-22 04:48:51 -06:00
2026-01-20 09:55:52 +00:00
//+------------------------------------------------------------------+
//| Build market context for AI analysis |
//+------------------------------------------------------------------+
string BuildMarketContext()
{
string context = "Current Market Context:\n";
context += "=======================\n\n";
// Market Mode
context += "MARKET MODE:\n";
context += "- Family: " + FamilyToText(Current_Family) + "\n";
context += "- Bias: " + BiasToText(Current_Bias) + "\n";
context += "- Strength: " + StrengthToText(Current_Strength) + "\n";
context += "- State: " + StateToText(Current_State) + "\n";
context += "- MFIB Bias: " + BiasToText(MFIB_Bias) + "\n\n";
// Technical Indicators
context += "INDICATORS:\n";
context += "- ADX: " + DoubleToString(Current_ADX, 1) + "\n";
context += "- ATR: " + DoubleToString(Current_ATR, 5) + "\n";
context += "- Stoch K: " + DoubleToString(Stoch_K_Current, 1) + "\n";
context += "- Stoch D: " + DoubleToString(Stoch_D_Current, 1) + "\n\n";
// MA Positions
context += "MOVING AVERAGES:\n";
context += "- MA7: " + DoubleToString(MA_Current[0], 5) + "\n";
context += "- MA14: " + DoubleToString(MA_Current[1], 5) + "\n";
context += "- MA21: " + DoubleToString(MA_Current[2], 5) + "\n";
context += "- MA50: " + DoubleToString(MA_Current[3], 5) + "\n";
context += "- MA140: " + DoubleToString(MA_Current[4], 5) + "\n\n";
// Price Levels
double current = MidPrice();
context += "PRICE LEVELS:\n";
context += "- Current: " + DoubleToString(current, 5) + "\n";
context += "- MFIB .382: " + DoubleToString(MFIB_Level_382, 5) + "\n";
context += "- MFIB .618: " + DoubleToString(MFIB_Level_618, 5) + "\n\n";
// Signals
context += "SIGNALS:\n";
context += "- Praise Count: " + IntegerToString(Praise_Count) + "/8\n";
context += "- Warning Count: " + IntegerToString(Warning_Confluence_Count) + "\n";
if(Praise_Count > 0)
{
context += "- Active Praise: ";
if(Praise_Triple_Magnet) context += "TripleMagnet ";
if(Praise_Power_Couple) context += "PowerCouple ";
if(Praise_MFIB_Staircase) context += "MFIB-Staircase ";
if(Praise_MFIB_Express) context += "MFIB-Express ";
if(Praise_MFIB_Breakout) context += "MFIB-Breakout ";
if(Praise_MA_Stack) context += "MA-Stack ";
if(Praise_Clean_Reclaim) context += "CleanReclaim ";
if(Praise_Multi_Breakout) context += "MultiBreakout ";
context += "\n";
}
if(Warning_Confluence_Count > 0)
{
context += "- Active Warnings: ";
if(MA7_Cross_14_Warning) context += "MA7x14 ";
if(MA7_Cross_21_Warning) context += "MA7x21 ";
if(Stoch_Extreme_Warning) context += "StochExtreme ";
if(MFIB_Reject_Warning) context += "MFIB-Reject ";
if(Band_Snap_Warning) context += "BandSnap ";
context += "\n";
}
context += "\n";
// Open Positions
int total_positions = ArraySize(OpenPositions);
context += "POSITIONS:\n";
context += "- Total Open: " + IntegerToString(total_positions) + "\n";
int buy_count = 0, sell_count = 0;
double total_profit = 0;
for(int i=0; i<total_positions; i++)
{
if(OpenPositions[i].is_buy) buy_count++;
else sell_count++;
// Calculate floating P&L
if(PositionSelectByTicket(OpenPositions[i].ticket))
{
total_profit += PositionGetDouble(POSITION_PROFIT);
}
}
context += "- Buys: " + IntegerToString(buy_count) + " | Sells: " + IntegerToString(sell_count) + "\n";
context += "- Floating P&L: $" + DoubleToString(total_profit, 2) + "\n";
return context;
}
//+------------------------------------------------------------------+
//| Call OpenAI API |
//+------------------------------------------------------------------+
string CallOpenAI(string prompt, string system_message = "")
{
// Check cache (avoid duplicate calls within 60 seconds)
if(prompt == AI_Cache.last_question &&
TimeCurrent() - AI_Cache.last_time < 60)
{
Print("📦 Using cached AI response");
return AI_Cache.last_response;
}
2026-01-20 10:24:54 +00:00
if(StringLen(OpenAI_API_Key_Internal) < 20)
2026-01-20 09:55:52 +00:00
{
Print("❌ OpenAI API key not configured");
return "ERROR: API key not set";
}
// Default system message
if(system_message == "")
{
system_message = "You are an expert forex trading analyst integrated into the QuarterTheory trading system. ";
system_message += "Provide concise, actionable analysis. Focus on key insights. ";
system_message += "Use clear language. Keep responses under 200 words unless asked for detail.";
}
// Build JSON request
string json_request = "{";
json_request += "\"model\":\"" + OpenAI_Model + "\",";
json_request += "\"messages\":[";
json_request += "{\"role\":\"system\",\"content\":\"" + EscapeJSON(system_message) + "\"},";
json_request += "{\"role\":\"user\",\"content\":\"" + EscapeJSON(prompt) + "\"}";
json_request += "],";
json_request += "\"temperature\":0.7,";
json_request += "\"max_tokens\":500";
json_request += "}";
// Prepare HTTP request
char post_data[];
char result_data[];
string result_headers;
StringToCharArray(json_request, post_data, 0, StringLen(json_request));
// Set headers
string headers = "Content-Type: application/json\r\n";
2026-01-20 10:24:54 +00:00
headers += "Authorization: Bearer " + OpenAI_API_Key_Internal + "\r\n";
2026-01-20 09:55:52 +00:00
// Make API call
Print("🤖 Calling OpenAI API...");
int timeout = 10000; // 10 seconds
int res = WebRequest(
"POST",
OpenAI_Endpoint,
headers,
timeout,
post_data,
result_data,
result_headers
);
if(res == -1)
{
int error = GetLastError();
Print("❌ WebRequest error: ", error);
Print("Make sure ", OpenAI_Endpoint, " is in allowed URLs");
Print("Tools → Options → Expert Advisors → Allow WebRequest for listed URL");
return "ERROR: WebRequest failed (" + IntegerToString(error) + ")";
}
// Parse response
string response = CharArrayToString(result_data);
// Extract content from JSON
string ai_response = ExtractAIResponse(response);
// Cache the response
AI_Cache.last_question = prompt;
AI_Cache.last_response = ai_response;
AI_Cache.last_time = TimeCurrent();
Print("✅ OpenAI response received");
return ai_response;
}
//+------------------------------------------------------------------+
//| Escape JSON special characters |
//+------------------------------------------------------------------+
string EscapeJSON(string text)
{
string result = text;
StringReplace(result, "\\", "\\\\");
StringReplace(result, "\"", "\\\"");
StringReplace(result, "\n", "\\n");
StringReplace(result, "\r", "\\r");
StringReplace(result, "\t", "\\t");
return result;
}
//+------------------------------------------------------------------+
//| Extract AI response from JSON |
//+------------------------------------------------------------------+
string ExtractAIResponse(string json)
{
// Simple JSON parsing - find "content":"..."
int start_pos = StringFind(json, "\"content\":\"");
if(start_pos == -1)
{
Print("⚠️ Could not parse AI response");
return "ERROR: Invalid response format";
}
start_pos += 11; // Length of "content":"
int end_pos = StringFind(json, "\"", start_pos);
if(end_pos == -1)
{
return "ERROR: Malformed response";
}
string content = StringSubstr(json, start_pos, end_pos - start_pos);
// Unescape JSON
StringReplace(content, "\\n", "\n");
StringReplace(content, "\\r", "\r");
StringReplace(content, "\\t", "\t");
StringReplace(content, "\\\"", "\"");
StringReplace(content, "\\\\", "\\");
return content;
}
//+------------------------------------------------------------------+
//| AI-powered market analysis |
//+------------------------------------------------------------------+
string GetAIMarketAnalysis()
{
string context = BuildMarketContext();
string prompt = context + "\n\nBased on this market data, provide:\n";
prompt += "1. Current market sentiment (1-2 sentences)\n";
prompt += "2. Key risk factors (2-3 points)\n";
prompt += "3. Trading recommendation (aggressive/moderate/defensive)\n";
prompt += "\nBe concise and actionable.";
return CallOpenAI(prompt);
}
//+------------------------------------------------------------------+
//| AI trade validation |
//+------------------------------------------------------------------+
string ValidateTradeWithAI(string setup_name, bool is_buy, TRADE_CATEGORY category)
{
string context = BuildMarketContext();
string direction = is_buy ? "BUY" : "SELL";
string cat_text = (category == CATEGORY_CONTINUATION) ? "CONTINUATION" : "COUNTER-TREND";
string prompt = context + "\n\nI'm about to take a " + direction + " trade:\n";
prompt += "- Setup: " + setup_name + "\n";
prompt += "- Category: " + cat_text + "\n";
prompt += "- Praise Signals: " + IntegerToString(Praise_Count) + "/8\n";
prompt += "- Warning Signals: " + IntegerToString(Warning_Confluence_Count) + "\n\n";
prompt += "Should I take this trade? Provide:\n";
prompt += "1. YES/NO/MAYBE\n";
prompt += "2. Brief reasoning (2-3 sentences)\n";
prompt += "3. Suggested position size adjustment (if any)";
return CallOpenAI(prompt);
}
//+------------------------------------------------------------------+
//| AI position management advice |
//+------------------------------------------------------------------+
string GetAIPositionAdvice(ulong ticket)
{
if(!PositionSelectByTicket(ticket))
return "ERROR: Position not found";
double entry = PositionGetDouble(POSITION_PRICE_OPEN);
double current_price = PositionGetDouble(POSITION_PRICE_CURRENT);
double profit = PositionGetDouble(POSITION_PROFIT);
bool is_buy = (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY);
string context = BuildMarketContext();
string prompt = context + "\n\nI have an open position:\n";
prompt += "- Type: " + (is_buy ? "BUY" : "SELL") + "\n";
prompt += "- Entry: " + DoubleToString(entry, 5) + "\n";
prompt += "- Current: " + DoubleToString(current_price, 5) + "\n";
prompt += "- Profit: $" + DoubleToString(profit, 2) + "\n\n";
prompt += "Should I:\n";
prompt += "1. Hold\n";
prompt += "2. Take partial profit\n";
prompt += "3. Close completely\n";
prompt += "4. Add to position\n\n";
prompt += "Provide recommendation with brief reasoning.";
return CallOpenAI(prompt);
}
//+------------------------------------------------------------------+
//| AI daily briefing |
//+------------------------------------------------------------------+
string GetAIDailyBriefing()
{
string context = BuildMarketContext();
string prompt = context + "\n\nProvide a daily trading briefing:\n";
prompt += "1. Market environment summary\n";
prompt += "2. Best trading opportunities today\n";
prompt += "3. Key levels to watch\n";
prompt += "4. Risk management priorities\n\n";
prompt += "Format as a brief morning briefing (150 words max).";
string system_msg = "You are a professional forex market analyst providing a morning briefing. ";
system_msg += "Be precise, factual, and focused on actionable insights.";
return CallOpenAI(prompt, system_msg);
}
//+------------------------------------------------------------------+
//| AI pattern recognition |
//+------------------------------------------------------------------+
string IdentifyPatternsWithAI()
{
string context = BuildMarketContext();
// Get recent price action
string price_data = "\nRecent Price Action (last 10 bars):\n";
for(int i=0; i<10; i++)
{
double open = iOpen(_Symbol, PERIOD_CURRENT, i);
double high = iHigh(_Symbol, PERIOD_CURRENT, i);
double low = iLow(_Symbol, PERIOD_CURRENT, i);
double close = iClose(_Symbol, PERIOD_CURRENT, i);
price_data += "Bar " + IntegerToString(i) + ": O=" + DoubleToString(open, 5);
price_data += " H=" + DoubleToString(high, 5);
price_data += " L=" + DoubleToString(low, 5);
price_data += " C=" + DoubleToString(close, 5) + "\n";
}
string prompt = context + price_data + "\n\nAnalyze this data and identify:\n";
prompt += "1. Any chart patterns forming (head & shoulders, triangles, wedges, etc.)\n";
prompt += "2. Trend characteristics (strong/weak, accelerating/decelerating)\n";
prompt += "3. Support/resistance levels\n";
prompt += "4. Potential reversal or continuation signals\n\n";
prompt += "Be specific and cite the evidence.";
return CallOpenAI(prompt);
}
//+------------------------------------------------------------------+
//| Check if AI features are enabled |
//+------------------------------------------------------------------+
bool IsAIEnabled()
{
2026-01-20 10:24:54 +00:00
return (StringLen(OpenAI_API_Key_Internal) >= 20);
2026-01-20 09:55:52 +00:00
}