Code: Select all
//+------------------------------------------------------------------+
//| Systematic_Omission_Journal.mq4/5 |
//| Institutional Risk Management |
//+------------------------------------------------------------------+
#property copyright "Pro Risk Management"
#property version "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 0
#property indicator_plots 0
//--- Enums for Dropdowns
enum ENUM_LOG_TYPE {
RBO = 0, // Rule-Based Omission
EH = 1 // Execution Hesitation
};
//--- Color Palette
color COL_RBO = C'8,153,129'; // Institutional Teal
color COL_EH = C'242,54,69'; // Institutional Red
color COL_TEXT = clrWhite;
color COL_LABEL = clrSilver;
//+------------------------------------------------------------------+
//| INPUT PARAMETERS (Supports up to 5 events per session) |
//+------------------------------------------------------------------+
input string spacer1 = "--- EVENT 1 ---";
input bool Log1_Active = false;
input datetime Log1_Time = D'2023.01.01 00:00';
input double Log1_Price = 0.0000;
input ENUM_LOG_TYPE Log1_Type = RBO;
input string Log1_Filter = "Spread/Cost Veto";
input string Log1_Note = "Risk parameters respected.";
input string spacer2 = "--- EVENT 2 ---";
input bool Log2_Active = false;
input datetime Log2_Time = D'2023.01.01 00:00';
input double Log2_Price = 0.0000;
input ENUM_LOG_TYPE Log2_Type = RBO;
input string Log2_Filter = "Macro/News Proximity";
input string Log2_Note = "Event risk too high.";
input string spacer3 = "--- EVENT 3 ---";
input bool Log3_Active = false;
input datetime Log3_Time = D'2023.01.01 00:00';
input double Log3_Price = 0.0000;
input ENUM_LOG_TYPE Log3_Type = RBO;
input string Log3_Filter = "HTF Invalidation";
input string Log3_Note = "Higher timeframe divergence.";
input string spacer4 = "--- EVENT 4 ---";
input bool Log4_Active = false;
input datetime Log4_Time = D'2023.01.01 00:00';
input double Log4_Price = 0.0000;
input ENUM_LOG_TYPE Log4_Type = RBO;
input string Log4_Filter = "Correlated Exposure";
input string Log4_Note = "Already in correlated trade.";
input string spacer5 = "--- EVENT 5 ---";
input bool Log5_Active = false;
input datetime Log5_Time = D'2023.01.01 00:00';
input double Log5_Price = 0.0000;
input ENUM_LOG_TYPE Log5_Type = EH;
input string Log5_Filter = "Psychological Fatigue";
input string Log5_Note = "Hesitated at the button.";
//+------------------------------------------------------------------+
//| GLOBAL VARIABLES |
//+------------------------------------------------------------------+
int rbo_total = 0;
int eh_total = 0;
//+------------------------------------------------------------------+
//| INITIALIZATION FUNCTION |
//+------------------------------------------------------------------+
int OnInit() {
DeleteAllObjects();
rbo_total = 0;
eh_total = 0;
// Process all 5 logs
ProcessLog(1, Log1_Active, Log1_Time, Log1_Price, Log1_Type, Log1_Filter, Log1_Note);
ProcessLog(2, Log2_Active, Log2_Time, Log2_Price, Log2_Type, Log2_Filter, Log2_Note);
ProcessLog(3, Log3_Active, Log3_Time, Log3_Price, Log3_Type, Log3_Filter, Log3_Note);
ProcessLog(4, Log4_Active, Log4_Time, Log4_Price, Log4_Type, Log4_Filter, Log4_Note);
ProcessLog(5, Log5_Active, Log5_Time, Log5_Price, Log5_Type, Log5_Filter, Log5_Note);
DrawHUD();
ChartRedraw();
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| DE-INITIALIZATION FUNCTION |
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
DeleteAllObjects();
ChartRedraw();
}
//+------------------------------------------------------------------+
//| ON CALCULATE (Required for indicators, left empty purposely) |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[],
const double &open[], const double &high[], const double &low[],
const double &close[], const long &tick_volume[], const long &volume[],
const int &spread[]) {
return(rates_total);
}
//+------------------------------------------------------------------+
//| CORE LOGIC: DRAW CHART ANNOTATIONS |
//+------------------------------------------------------------------+
void ProcessLog(int index, bool active, datetime time, double price, ENUM_LOG_TYPE type, string filter, string note) {
if(!active || time == 0 || price == 0) return;
if(type == RBO) rbo_total++;
else eh_total++;
string objPrefix = "SOJ_" + IntegerToString(index);
string txtName = objPrefix + "_Txt";
string lineName = objPrefix + "_Line";
color tagColor = (type == RBO) ? COL_RBO : COL_EH;
string tagText = (type == RBO) ? "RBO" : "EH";
string typeStr = (type == RBO) ? "Rule-Based Omission" : "Execution Hesitation";
// Formatting the Tooltip for MetaTrader
string tooltip = "CLASSIFICATION: " + typeStr + "\nFILTER: " + filter + "\nNOTES: " + note;
// 1. Draw Text Tag
ObjectCreate(0, txtName, OBJ_TEXT, 0, time, price);
ObjectSetString(0, txtName, OBJPROP_TEXT, tagText);
ObjectSetString(0, txtName, OBJPROP_FONT, "Arial");
ObjectSetInteger(0, txtName, OBJPROP_FONTSIZE, 9);
ObjectSetInteger(0, txtName, OBJPROP_COLOR, tagColor);
ObjectSetString(0, txtName, OBJPROP_TOOLTIP, tooltip);
ObjectSetInteger(0, txtName, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, txtName, OBJPROP_HIDDEN, true);
// 2. Draw Dotted Omission Line (Extends 30 periods into the future)
datetime endTime = time + (PeriodSeconds() * 30);
ObjectCreate(0, lineName, OBJ_TREND, 0, time, price, endTime, price);
ObjectSetInteger(0, lineName, OBJPROP_COLOR, tagColor);
ObjectSetInteger(0, lineName, OBJPROP_STYLE, STYLE_DOT);
ObjectSetInteger(0, lineName, OBJPROP_WIDTH, 1);
ObjectSetInteger(0, lineName, OBJPROP_RAY_RIGHT, false);
ObjectSetString(0, lineName, OBJPROP_TOOLTIP, tooltip);
ObjectSetInteger(0, lineName, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, lineName, OBJPROP_HIDDEN, true);
}
//+------------------------------------------------------------------+
//| CORE LOGIC: DRAW PERFORMANCE HUD |
//+------------------------------------------------------------------+
void DrawHUD() {
int total_events = rbo_total + eh_total;
double compliance = (total_events > 0) ? ((double)rbo_total / total_events) * 100.0 : 0.0;
color compColor = (compliance >= 80.0) ? COL_RBO : COL_EH;
// Create HUD Elements (Anchored Bottom Right)
CreateHUDLabel("SOJ_HUD_T1", "SESSION METRICS", 160, 90, COL_LABEL, 8, true);
CreateHUDLabel("SOJ_HUD_T2", "Systematic Omissions (RBO):", 160, 70, COL_RBO, 8, false);
CreateHUDLabel("SOJ_HUD_V2", IntegerToString(rbo_total), 20, 70, clrWhite, 8, false);
CreateHUDLabel("SOJ_HUD_T3", "Execution Hesitation (EH):", 160, 50, COL_EH, 8, false);
CreateHUDLabel("SOJ_HUD_V3", IntegerToString(eh_total), 20, 50, clrWhite, 8, false);
CreateHUDLabel("SOJ_HUD_T4", "Filter Compliance Rate:", 160, 30, COL_LABEL, 8, false);
CreateHUDLabel("SOJ_HUD_V4", DoubleToString(compliance, 1) + "%", 20, 30, compColor, 8, true);
}
//+------------------------------------------------------------------+
//| HELPER: CREATE HUD LABEL |
//+------------------------------------------------------------------+
void CreateHUDLabel(string name, string text, int x, int y, color clr, int size, bool bold) {
ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_RIGHT_LOWER);
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_LEFT_LOWER);
ObjectSetString(0, name, OBJPROP_TEXT, text);
ObjectSetString(0, name, OBJPROP_FONT, bold ? "Arial Bold" : "Arial");
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, size);
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
}
//+------------------------------------------------------------------+
//| HELPER: CLEANUP OBJECTS ON REMOVAL |
//+------------------------------------------------------------------+
void DeleteAllObjects() {
string prefix = "SOJ_";
int total = ObjectsTotal(0);
// Iterate backwards when deleting objects
for(int i = total - 1; i >= 0; i--) {
string name = ObjectName(0, i);
if(StringFind(name, prefix) == 0) {
ObjectDelete(0, name);
}
}
}
//+------------------------------------------------------------------+