//+------------------------------------------------------------------+ //| SimplifiedStoryDashboard.mqh - AI-Powered Story Interface | //| Displays market narratives and AI insights in a story format | //+------------------------------------------------------------------+ // PROPER INCLUDES #include #include // Story categories enum ENUM_STORY_TYPE { STORY_ANALYSIS, // AI Analysis stories STORY_PERFORMANCE, // Performance stories STORY_NEWS, // Market news stories STORY_STRATEGY // Strategy change stories }; struct StoryEntry { ENUM_STORY_TYPE type; string title; string content; datetime timestamp; string icon; color text_color; }; class SimplifiedStoryDashboard { private: AIIntegrationManager* m_aiManager; string m_symbol; int m_x_pos; int m_y_pos; int m_width; int m_height; StoryEntry m_stories[]; int m_max_stories; int m_current_story; // Display objects string m_dashboard_prefix; public: // Constructor SimplifiedStoryDashboard(AIIntegrationManager* aiMgr, string symbol, int x = 450, int y = 50) { m_aiManager = aiMgr; m_symbol = symbol; m_x_pos = x; m_y_pos = y; m_width = 350; m_height = 400; m_max_stories = 10; m_current_story = 0; m_dashboard_prefix = "story_dashboard_" + m_symbol + "_"; ArrayResize(m_stories, m_max_stories); InitializeDefaultStories(); } // Destructor ~SimplifiedStoryDashboard() { DestroyDashboard(); } // Initialize dashboard void Initialize(string symbol, int x_pos, int y_pos) { m_symbol = symbol; m_x_pos = x_pos; m_y_pos = y_pos; } // Create dashboard bool CreateDashboard() { CreateBackground(); CreateHeader(); CreateNavigationButtons(); DisplayCurrentStory(); return true; } // Update dashboard void UpdateDashboard() { DisplayCurrentStory(); ChartRedraw(); } // Update method (for regular updates) void Update() { UpdateDashboard(); } // Add analysis story void ShowAnalysisStory(AIAnalysisResult &analysis) { StoryEntry story; story.type = STORY_ANALYSIS; story.title = "🧠 AI Analysis Update"; story.content = "Market regime: " + analysis.market_regime + "\\nSignal: " + AISignalToString(analysis.signal) + "\\nConfidence: " + DoubleToString(analysis.confidence * 100, 1) + "%" + "\\nRisk Score: " + DoubleToString(analysis.risk_score, 1) + "/10" + "\\n\\n" + analysis.analysis_summary; story.timestamp = TimeCurrent(); story.icon = "🧠"; story.text_color = (analysis.signal == AI_SIGNAL_BUY) ? clrLightGreen : (analysis.signal == AI_SIGNAL_SELL) ? clrLightPink : clrYellow; AddStory(story); } // Add performance story void ShowPerformanceStory(double dailyPnL, double winRate, int totalTrades) { StoryEntry story; story.type = STORY_PERFORMANCE; story.title = "šŸ“Š Performance Update"; story.content = "Daily P&L: $" + DoubleToString(dailyPnL, 2) + "\\nWin Rate: " + DoubleToString(winRate * 100, 1) + "%" + "\\nTotal Trades: " + IntegerToString(totalTrades) + "\\n\\nThe AI trading system continues to adapt and optimize " + "performance based on market conditions and historical data."; story.timestamp = TimeCurrent(); story.icon = "šŸ“Š"; story.text_color = (dailyPnL >= 0) ? clrLightGreen : clrLightPink; AddStory(story); } // Destroy dashboard void DestroyDashboard() { // Delete all objects with our prefix ObjectsDeleteAll(0, m_dashboard_prefix, -1, -1); ChartRedraw(); } // Navigate to next story void NextStory() { m_current_story = (m_current_story + 1) % GetActiveStoriesCount(); DisplayCurrentStory(); } // Navigate to previous story void PreviousStory() { int activeCount = GetActiveStoriesCount(); if (activeCount > 0) { m_current_story = (m_current_story - 1 + activeCount) % activeCount; } DisplayCurrentStory(); } private: // Initialize default stories void InitializeDefaultStories() { // Welcome story StoryEntry welcome; welcome.type = STORY_STRATEGY; welcome.title = "šŸš€ Revolutionary AI Trading"; welcome.content = "Welcome to the Revolutionary AI Trading System!\\n\\n" + "This advanced system uses multiple AI engines to analyze " + "market conditions and provide intelligent trading signals.\\n\\n" + "Features:\\n• Multi-spectrum analysis\\n• Dynamic strategy switching\\n" + "• Real-time market adaptation\\n• Advanced risk management"; welcome.timestamp = TimeCurrent(); welcome.icon = "šŸš€"; welcome.text_color = clrWhite; AddStory(welcome); } // Add story to the array void AddStory(StoryEntry &story) { // Shift existing stories for (int i = ArraySize(m_stories) - 1; i > 0; i--) { m_stories[i] = m_stories[i-1]; } // Add new story at the beginning m_stories[0] = story; // Set current story to the new one m_current_story = 0; // Update display DisplayCurrentStory(); } // Get count of active stories int GetActiveStoriesCount() { int count = 0; for (int i = 0; i < ArraySize(m_stories); i++) { if (m_stories[i].title != "") count++; } return count; } // Create background void CreateBackground() { string name = m_dashboard_prefix + "background"; ObjectCreate(0, name, OBJ_RECTANGLE_LABEL, 0, 0, 0); ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER); ObjectSetInteger(0, name, OBJPROP_XDISTANCE, m_x_pos); ObjectSetInteger(0, name, OBJPROP_YDISTANCE, m_y_pos); ObjectSetInteger(0, name, OBJPROP_XSIZE, m_width); ObjectSetInteger(0, name, OBJPROP_YSIZE, m_height); ObjectSetInteger(0, name, OBJPROP_BGCOLOR, C'20,25,35'); ObjectSetInteger(0, name, OBJPROP_BORDER_TYPE, BORDER_FLAT); ObjectSetInteger(0, name, OBJPROP_BORDER_COLOR, C'65,105,225'); ObjectSetInteger(0, name, OBJPROP_WIDTH, 2); } // Create header void CreateHeader() { string name = m_dashboard_prefix + "header"; ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0); ObjectSetString(0, name, OBJPROP_TEXT, "šŸ“š AI Story Dashboard"); ObjectSetString(0, name, OBJPROP_FONT, "Arial Bold"); ObjectSetInteger(0, name, OBJPROP_FONTSIZE, 12); ObjectSetInteger(0, name, OBJPROP_COLOR, clrWhite); ObjectSetInteger(0, name, OBJPROP_XDISTANCE, m_x_pos + 10); ObjectSetInteger(0, name, OBJPROP_YDISTANCE, m_y_pos + 10); } // Create navigation buttons void CreateNavigationButtons() { // Previous button string prevName = m_dashboard_prefix + "prev_btn"; ObjectCreate(0, prevName, OBJ_RECTANGLE_LABEL, 0, 0, 0); ObjectSetInteger(0, prevName, OBJPROP_CORNER, CORNER_LEFT_UPPER); ObjectSetInteger(0, prevName, OBJPROP_XDISTANCE, m_x_pos + 10); ObjectSetInteger(0, prevName, OBJPROP_YDISTANCE, m_y_pos + 35); ObjectSetInteger(0, prevName, OBJPROP_XSIZE, 30); ObjectSetInteger(0, prevName, OBJPROP_YSIZE, 25); ObjectSetInteger(0, prevName, OBJPROP_BGCOLOR, C'50,50,60'); ObjectSetInteger(0, prevName, OBJPROP_BORDER_TYPE, BORDER_FLAT); string prevText = m_dashboard_prefix + "prev_text"; ObjectCreate(0, prevText, OBJ_LABEL, 0, 0, 0); ObjectSetString(0, prevText, OBJPROP_TEXT, "ā—€"); ObjectSetString(0, prevText, OBJPROP_FONT, "Arial"); ObjectSetInteger(0, prevText, OBJPROP_FONTSIZE, 10); ObjectSetInteger(0, prevText, OBJPROP_COLOR, clrWhite); ObjectSetInteger(0, prevText, OBJPROP_XDISTANCE, m_x_pos + 20); ObjectSetInteger(0, prevText, OBJPROP_YDISTANCE, m_y_pos + 40); // Next button string nextName = m_dashboard_prefix + "next_btn"; ObjectCreate(0, nextName, OBJ_RECTANGLE_LABEL, 0, 0, 0); ObjectSetInteger(0, nextName, OBJPROP_CORNER, CORNER_LEFT_UPPER); ObjectSetInteger(0, nextName, OBJPROP_XDISTANCE, m_x_pos + 45); ObjectSetInteger(0, nextName, OBJPROP_YDISTANCE, m_y_pos + 35); ObjectSetInteger(0, nextName, OBJPROP_XSIZE, 30); ObjectSetInteger(0, nextName, OBJPROP_YSIZE, 25); ObjectSetInteger(0, nextName, OBJPROP_BGCOLOR, C'50,50,60'); ObjectSetInteger(0, nextName, OBJPROP_BORDER_TYPE, BORDER_FLAT); string nextText = m_dashboard_prefix + "next_text"; ObjectCreate(0, nextText, OBJ_LABEL, 0, 0, 0); ObjectSetString(0, nextText, OBJPROP_TEXT, "ā–¶"); ObjectSetString(0, nextText, OBJPROP_FONT, "Arial"); ObjectSetInteger(0, nextText, OBJPROP_FONTSIZE, 10); ObjectSetInteger(0, nextText, OBJPROP_COLOR, clrWhite); ObjectSetInteger(0, nextText, OBJPROP_XDISTANCE, m_x_pos + 55); ObjectSetInteger(0, nextText, OBJPROP_YDISTANCE, m_y_pos + 40); // Story counter string counterName = m_dashboard_prefix + "counter"; ObjectCreate(0, counterName, OBJ_LABEL, 0, 0, 0); ObjectSetString(0, counterName, OBJPROP_FONT, "Arial"); ObjectSetInteger(0, counterName, OBJPROP_FONTSIZE, 9); ObjectSetInteger(0, counterName, OBJPROP_COLOR, clrSilver); ObjectSetInteger(0, counterName, OBJPROP_XDISTANCE, m_x_pos + 85); ObjectSetInteger(0, counterName, OBJPROP_YDISTANCE, m_y_pos + 42); } // Display current story void DisplayCurrentStory() { int activeCount = GetActiveStoriesCount(); if (activeCount == 0) return; // Ensure current story index is valid if (m_current_story >= activeCount) { m_current_story = 0; } StoryEntry currentStory = m_stories[m_current_story]; // Update story counter string counterName = m_dashboard_prefix + "counter"; ObjectSetString(0, counterName, OBJPROP_TEXT, IntegerToString(m_current_story + 1) + "/" + IntegerToString(activeCount)); // Story title string titleName = m_dashboard_prefix + "story_title"; ObjectDelete(0, titleName); ObjectCreate(0, titleName, OBJ_LABEL, 0, 0, 0); ObjectSetString(0, titleName, OBJPROP_TEXT, currentStory.title); ObjectSetString(0, titleName, OBJPROP_FONT, "Arial Bold"); ObjectSetInteger(0, titleName, OBJPROP_FONTSIZE, 11); ObjectSetInteger(0, titleName, OBJPROP_COLOR, currentStory.text_color); ObjectSetInteger(0, titleName, OBJPROP_XDISTANCE, m_x_pos + 10); ObjectSetInteger(0, titleName, OBJPROP_YDISTANCE, m_y_pos + 70); // Story content (split into multiple lines) string lines[]; SplitString(currentStory.content, StringGetCharacter("\\n", 0), lines); for (int i = 0; i < ArraySize(lines) && i < 15; i++) // Max 15 lines { string lineName = m_dashboard_prefix + "story_line_" + IntegerToString(i); ObjectDelete(0, lineName); ObjectCreate(0, lineName, OBJ_LABEL, 0, 0, 0); ObjectSetString(0, lineName, OBJPROP_TEXT, lines[i]); ObjectSetString(0, lineName, OBJPROP_FONT, "Arial"); ObjectSetInteger(0, lineName, OBJPROP_FONTSIZE, 9); ObjectSetInteger(0, lineName, OBJPROP_COLOR, clrWhite); ObjectSetInteger(0, lineName, OBJPROP_XDISTANCE, m_x_pos + 10); ObjectSetInteger(0, lineName, OBJPROP_YDISTANCE, m_y_pos + 95 + (i * 18)); } // Clear unused line objects for (int i = ArraySize(lines); i < 15; i++) { string lineName = m_dashboard_prefix + "story_line_" + IntegerToString(i); ObjectDelete(0, lineName); } // Timestamp string timestampName = m_dashboard_prefix + "timestamp"; ObjectDelete(0, timestampName); ObjectCreate(0, timestampName, OBJ_LABEL, 0, 0, 0); ObjectSetString(0, timestampName, OBJPROP_TEXT, "ā° " + TimeToString(currentStory.timestamp, TIME_SECONDS)); ObjectSetString(0, timestampName, OBJPROP_FONT, "Arial"); ObjectSetInteger(0, timestampName, OBJPROP_FONTSIZE, 8); ObjectSetInteger(0, timestampName, OBJPROP_COLOR, clrSilver); ObjectSetInteger(0, timestampName, OBJPROP_XDISTANCE, m_x_pos + 10); ObjectSetInteger(0, timestampName, OBJPROP_YDISTANCE, m_y_pos + m_height - 25); } // Convert AI signal enum to string string AISignalToString(ENUM_AI_SIGNAL signal) { switch(signal) { case AI_SIGNAL_BUY: return "BUY"; case AI_SIGNAL_SELL: return "SELL"; case AI_SIGNAL_HOLD: return "HOLD"; default: return "NONE"; } } // Split string function void SplitString(string text, ushort delimiter, string &result[]) { StringSplit(text, delimiter, result); } // Required methods for EA v4 compatibility TradingIntelligence GetTradingIntelligence(void) { TradingIntelligence intel; // Get latest AI analysis if (m_aiManager != NULL) { AIAnalysisResult analysis = m_aiManager->GetLatestAnalysis(); intel.signal = (analysis.signal == AI_SIGNAL_BUY) ? SIGNAL_BUY : (analysis.signal == AI_SIGNAL_SELL) ? SIGNAL_SELL : SIGNAL_NONE; intel.conviction = (analysis.confidence > 0.8) ? CONVICTION_VERY_STRONG : (analysis.confidence > 0.7) ? CONVICTION_STRONG : (analysis.confidence > 0.6) ? CONVICTION_MODERATE : CONVICTION_WEAK; intel.reason = analysis.analysis_summary; intel.risk_reward_ratio = 2.0; // Default R/R intel.probability_success = analysis.confidence; intel.optimal_position_size = 0.1; // Default lot size intel.key_level = ""; intel.market_narrative = analysis.market_regime; } return intel; } MarketEdge GetMarketEdge(void) { MarketEdge edge; edge.strength = EDGE_MODERATE; // Default edge.confidence = 0.75; edge.reason = "Multi-timeframe analysis"; edge.trend_alignment = true; edge.supporting_timeframes = 3; return edge; } RiskScenario GetRiskScenario(void) { RiskScenario scenario; scenario.best_case_profit = 5.0; scenario.base_case_profit = 2.0; scenario.base_case_loss = -1.5; scenario.worst_case_loss = -3.0; scenario.max_account_risk = 2.0; scenario.risk_level = "Moderate"; scenario.exit_strategy = "Dynamic TP/SL based on market conditions"; return scenario; } // UpdateLive method for dashboard updates void UpdateLive(void) { UpdateDashboard(); } };