669 lines
18 KiB
MQL5
669 lines
18 KiB
MQL5
|
|
#ifndef AI_GATEWAY_MQH
|
||
|
|
#define AI_GATEWAY_MQH
|
||
|
|
|
||
|
|
string AI_Trim(const string s)
|
||
|
|
{
|
||
|
|
string x = s;
|
||
|
|
StringTrimLeft(x);
|
||
|
|
StringTrimRight(x);
|
||
|
|
return x;
|
||
|
|
}
|
||
|
|
|
||
|
|
string AI_Upper(const string s)
|
||
|
|
{
|
||
|
|
string x = s;
|
||
|
|
StringToUpper(x);
|
||
|
|
return x;
|
||
|
|
}
|
||
|
|
|
||
|
|
string AI_JSONEscape(const string s)
|
||
|
|
{
|
||
|
|
string x = s;
|
||
|
|
StringReplace(x, "\\", "\\\\");
|
||
|
|
StringReplace(x, "\"", "\\\"");
|
||
|
|
StringReplace(x, "\n", " ");
|
||
|
|
StringReplace(x, "\r", " ");
|
||
|
|
return x;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool AI_ModeMandatory()
|
||
|
|
{
|
||
|
|
return (AI_Upper(AI_Mode) == "MANDATORY");
|
||
|
|
}
|
||
|
|
|
||
|
|
bool AI_ModeAdvisory()
|
||
|
|
{
|
||
|
|
return (AI_Upper(AI_Mode) == "ADVISORY");
|
||
|
|
}
|
||
|
|
|
||
|
|
bool AI_ModeOff()
|
||
|
|
{
|
||
|
|
return (AI_Upper(AI_Mode) == "OFF");
|
||
|
|
}
|
||
|
|
|
||
|
|
bool AI_ExtractNumber(const string &json, const string &key, double &out)
|
||
|
|
{
|
||
|
|
int k = StringFind(json, "\"" + key + "\"");
|
||
|
|
if(k < 0) return false;
|
||
|
|
|
||
|
|
int colon = StringFind(json, ":", k);
|
||
|
|
if(colon < 0) return false;
|
||
|
|
|
||
|
|
int endComma = StringFind(json, ",", colon);
|
||
|
|
int endBrace = StringFind(json, "}", colon);
|
||
|
|
int end = endComma;
|
||
|
|
if(end < 0 || (endBrace >= 0 && endBrace < end)) end = endBrace;
|
||
|
|
if(end < 0) return false;
|
||
|
|
|
||
|
|
string val = StringSubstr(json, colon + 1, end - (colon + 1));
|
||
|
|
val = AI_Trim(val);
|
||
|
|
out = StringToDouble(val);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool AI_ExtractInt(const string &json, const string &key, int &out)
|
||
|
|
{
|
||
|
|
double tmp = 0.0;
|
||
|
|
if(!AI_ExtractNumber(json, key, tmp)) return false;
|
||
|
|
out = (int)MathRound(tmp);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool AI_ExtractString(const string &json, const string &key, string &out)
|
||
|
|
{
|
||
|
|
int k = StringFind(json, "\"" + key + "\"");
|
||
|
|
if(k < 0) return false;
|
||
|
|
|
||
|
|
int colon = StringFind(json, ":", k);
|
||
|
|
if(colon < 0) return false;
|
||
|
|
|
||
|
|
int q1 = StringFind(json, "\"", colon + 1);
|
||
|
|
if(q1 < 0) return false;
|
||
|
|
|
||
|
|
int q2 = StringFind(json, "\"", q1 + 1);
|
||
|
|
if(q2 < 0) return false;
|
||
|
|
|
||
|
|
out = StringSubstr(json, q1 + 1, q2 - q1 - 1);
|
||
|
|
StringReplace(out, "\\n", " ");
|
||
|
|
StringReplace(out, "\\\"", "\"");
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool AI_Post(const string route, const string payload, string &response)
|
||
|
|
{
|
||
|
|
if(AI_ModeOff())
|
||
|
|
return false;
|
||
|
|
|
||
|
|
string base = AI_Trim(AI_Gateway_URL);
|
||
|
|
if(StringLen(base) < 8)
|
||
|
|
return false;
|
||
|
|
|
||
|
|
string url = base;
|
||
|
|
if(StringLen(route) > 0)
|
||
|
|
{
|
||
|
|
if(StringSubstr(base, StringLen(base) - 1, 1) == "/")
|
||
|
|
url = base + route;
|
||
|
|
else
|
||
|
|
url = base + "/" + route;
|
||
|
|
}
|
||
|
|
|
||
|
|
string headers = "Content-Type: application/json\r\n";
|
||
|
|
string token = AI_Trim(AI_Gateway_Token);
|
||
|
|
if(StringLen(token) > 0)
|
||
|
|
headers += "Authorization: Bearer " + token + "\r\n";
|
||
|
|
|
||
|
|
char post_data[];
|
||
|
|
StringToCharArray(payload, post_data, 0, WHOLE_ARRAY, CP_UTF8);
|
||
|
|
|
||
|
|
char result[];
|
||
|
|
string result_headers = "";
|
||
|
|
ResetLastError();
|
||
|
|
int code = WebRequest("POST", url, headers, MathMax(1000, AI_TimeoutMs), post_data, result, result_headers);
|
||
|
|
if(code <= 0)
|
||
|
|
{
|
||
|
|
AI_Last_Error = "AI gateway request failed err=" + IntegerToString(GetLastError()) + " route=" + route;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
response = CharArrayToString(result, 0, -1, CP_UTF8);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool InitializeAIGateway()
|
||
|
|
{
|
||
|
|
if(AI_ModeOff())
|
||
|
|
{
|
||
|
|
AI_Initialized = false;
|
||
|
|
AI_Last_Error = "AI mode is off";
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
string ping = "{\"symbol\":\"" + _Symbol + "\",\"tf\":\"" + EnumToString((ENUM_TIMEFRAMES)Period()) + "\"}";
|
||
|
|
string resp = "";
|
||
|
|
|
||
|
|
// Prefer a health endpoint; if not present, initialize optimistically for advisory mode.
|
||
|
|
if(AI_Post("health", ping, resp))
|
||
|
|
{
|
||
|
|
AI_Initialized = true;
|
||
|
|
AI_Last_Error = "";
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
AI_Initialized = AI_ModeAdvisory();
|
||
|
|
if(AI_Initialized)
|
||
|
|
AI_Last_Error = "Gateway health check unavailable; running advisory fallback.";
|
||
|
|
return AI_Initialized;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool IsAIEnabled()
|
||
|
|
{
|
||
|
|
return AI_Initialized && !AI_ModeOff();
|
||
|
|
}
|
||
|
|
|
||
|
|
bool AIValidateTrade(const string setup_name,
|
||
|
|
const bool is_buy,
|
||
|
|
double &size_multiplier,
|
||
|
|
string &reasoning,
|
||
|
|
string &decision_out)
|
||
|
|
{
|
||
|
|
size_multiplier = 1.0;
|
||
|
|
reasoning = "";
|
||
|
|
decision_out = "NO";
|
||
|
|
|
||
|
|
if(!AI_Validate_Trades || AI_ModeOff())
|
||
|
|
{
|
||
|
|
decision_out = "YES";
|
||
|
|
reasoning = "AI validation disabled";
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
if(!AI_Initialized)
|
||
|
|
{
|
||
|
|
if(AI_ModeMandatory())
|
||
|
|
{
|
||
|
|
reasoning = "AI gateway unavailable (mandatory mode)";
|
||
|
|
decision_out = "NO";
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
reasoning = "AI gateway unavailable (advisory fallback)";
|
||
|
|
decision_out = "YES";
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
string payload = "{";
|
||
|
|
payload += "\"symbol\":\"" + _Symbol + "\",";
|
||
|
|
payload += "\"tf\":\"" + EnumToString((ENUM_TIMEFRAMES)Period()) + "\",";
|
||
|
|
payload += "\"setup\":\"" + AI_JSONEscape(setup_name) + "\",";
|
||
|
|
payload += "\"side\":\"" + (is_buy ? "BUY" : "SELL") + "\",";
|
||
|
|
payload += "\"mode\":\"" + ModeToString(Current_Mode) + "\",";
|
||
|
|
payload += "\"state\":\"" + StateToString(Current_State) + "\",";
|
||
|
|
payload += "\"warnings\":" + IntegerToString(Active_Warnings) + ",";
|
||
|
|
payload += "\"praise\":" + IntegerToString(Active_Praise_Signals) + ",";
|
||
|
|
payload += "\"nn_bias\":" + IntegerToString(NN_Bias) + ",";
|
||
|
|
payload += "\"nn_confidence\":" + DoubleToString(NN_Confidence, 2) + ",";
|
||
|
|
payload += "\"nn_risk\":" + DoubleToString(NN_RiskScore, 2) + ",";
|
||
|
|
payload += "\"cluster_strength\":" + DoubleToString(Coordinator_Cluster_Strength, 2) + ",";
|
||
|
|
payload += "\"cluster_conflict\":" + DoubleToString(Coordinator_Conflict_Score, 2) + ",";
|
||
|
|
payload += "\"news_bias\":" + IntegerToString(News_Bias_Direction) + ",";
|
||
|
|
payload += "\"news_strength\":" + DoubleToString(News_Bias_Strength, 2);
|
||
|
|
payload += "}";
|
||
|
|
|
||
|
|
string resp = "";
|
||
|
|
if(!AI_Post("validate-trade", payload, resp))
|
||
|
|
{
|
||
|
|
if(AI_ModeMandatory())
|
||
|
|
{
|
||
|
|
reasoning = "AI gateway request failed";
|
||
|
|
decision_out = "NO";
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
reasoning = "AI gateway request failed (advisory fallback)";
|
||
|
|
decision_out = "YES";
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
string decision = "";
|
||
|
|
AI_ExtractString(resp, "decision", decision);
|
||
|
|
if(decision == "") decision = "NO";
|
||
|
|
decision = AI_Upper(decision);
|
||
|
|
|
||
|
|
double mult = 1.0;
|
||
|
|
if(AI_ExtractNumber(resp, "size_multiplier", mult))
|
||
|
|
size_multiplier = MathMax(0.1, MathMin(3.0, mult));
|
||
|
|
|
||
|
|
if(!AI_ExtractString(resp, "reason", reasoning))
|
||
|
|
reasoning = "gateway";
|
||
|
|
|
||
|
|
decision_out = decision;
|
||
|
|
|
||
|
|
if(decision == "YES") return true;
|
||
|
|
if(decision == "MAYBE")
|
||
|
|
{
|
||
|
|
if(size_multiplier > 1.0) size_multiplier = 1.0;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
string ValidateTradeWithAI(const string setup_name, const bool is_buy)
|
||
|
|
{
|
||
|
|
double mult = 1.0;
|
||
|
|
string reason = "";
|
||
|
|
string decision = "NO";
|
||
|
|
bool ok = AIValidateTrade(setup_name, is_buy, mult, reason, decision);
|
||
|
|
if(!ok && decision == "YES")
|
||
|
|
decision = "NO";
|
||
|
|
return decision + " | " + reason;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool AIFetchBriefing(const string tf,
|
||
|
|
const string context,
|
||
|
|
string &text,
|
||
|
|
int &bias,
|
||
|
|
double &confidence)
|
||
|
|
{
|
||
|
|
text = "";
|
||
|
|
bias = 0;
|
||
|
|
confidence = 0.0;
|
||
|
|
|
||
|
|
if(!AI_Initialized || AI_ModeOff())
|
||
|
|
return false;
|
||
|
|
|
||
|
|
string payload = "{";
|
||
|
|
payload += "\"symbol\":\"" + _Symbol + "\",";
|
||
|
|
payload += "\"tf\":\"" + AI_JSONEscape(tf) + "\",";
|
||
|
|
payload += "\"context\":\"" + AI_JSONEscape(context) + "\",";
|
||
|
|
payload += "\"mode\":\"" + ModeToString(Current_Mode) + "\",";
|
||
|
|
payload += "\"state\":\"" + StateToString(Current_State) + "\"";
|
||
|
|
payload += "}";
|
||
|
|
|
||
|
|
string resp = "";
|
||
|
|
if(!AI_Post("briefing", payload, resp))
|
||
|
|
return false;
|
||
|
|
|
||
|
|
string out_text = "";
|
||
|
|
int out_bias = 0;
|
||
|
|
double out_conf = 0.0;
|
||
|
|
|
||
|
|
if(!AI_ExtractString(resp, "summary", out_text))
|
||
|
|
out_text = "Briefing unavailable";
|
||
|
|
AI_ExtractInt(resp, "bias", out_bias);
|
||
|
|
AI_ExtractNumber(resp, "confidence", out_conf);
|
||
|
|
|
||
|
|
if(out_bias > 1) out_bias = 1;
|
||
|
|
if(out_bias < -1) out_bias = -1;
|
||
|
|
|
||
|
|
text = out_text;
|
||
|
|
bias = out_bias;
|
||
|
|
confidence = MathMax(0.0, MathMin(100.0, out_conf));
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
void DisplayAIBriefing(const string briefing)
|
||
|
|
{
|
||
|
|
Last_AI_Analysis = briefing;
|
||
|
|
Print("[AI BRIEFING] ", briefing);
|
||
|
|
}
|
||
|
|
|
||
|
|
string GetAIDailyBriefing()
|
||
|
|
{
|
||
|
|
string text = "";
|
||
|
|
int bias = 0;
|
||
|
|
double conf = 0.0;
|
||
|
|
if(!AIFetchBriefing("D1", AI_Brief_4H_Text, text, bias, conf))
|
||
|
|
return "AI briefing unavailable (gateway failed).";
|
||
|
|
|
||
|
|
AI_Brief_D_Text = text;
|
||
|
|
AI_Brief_D_Bias = bias;
|
||
|
|
AI_Brief_D_Confidence = conf;
|
||
|
|
AI_Brief_D_Time = TimeCurrent();
|
||
|
|
return text;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool AIFetchNewsBias(int &bias, double &strength, string &reason)
|
||
|
|
{
|
||
|
|
bias = 0;
|
||
|
|
strength = 0.0;
|
||
|
|
reason = "";
|
||
|
|
|
||
|
|
if(!AI_Initialized || AI_ModeOff() || !AI_Enable_News_Bias)
|
||
|
|
return false;
|
||
|
|
|
||
|
|
string payload = "{";
|
||
|
|
payload += "\"symbol\":\"" + _Symbol + "\",";
|
||
|
|
payload += "\"tf\":\"" + EnumToString((ENUM_TIMEFRAMES)Period()) + "\",";
|
||
|
|
payload += "\"local_news_report\":\"" + AI_JSONEscape(News_Bias_Report) + "\",";
|
||
|
|
payload += "\"last_headline\":\"" + AI_JSONEscape(News_Last_Headline) + "\"";
|
||
|
|
payload += "}";
|
||
|
|
|
||
|
|
string resp = "";
|
||
|
|
if(!AI_Post("news-bias", payload, resp))
|
||
|
|
return false;
|
||
|
|
|
||
|
|
int b = 0;
|
||
|
|
double s = 0.0;
|
||
|
|
string r = "";
|
||
|
|
|
||
|
|
bool okb = AI_ExtractInt(resp, "bias", b);
|
||
|
|
bool oks = AI_ExtractNumber(resp, "strength", s);
|
||
|
|
AI_ExtractString(resp, "reason", r);
|
||
|
|
|
||
|
|
if(!okb || !oks)
|
||
|
|
return false;
|
||
|
|
|
||
|
|
if(b > 1) b = 1;
|
||
|
|
if(b < -1) b = -1;
|
||
|
|
|
||
|
|
bias = b;
|
||
|
|
strength = MathMax(0.0, MathMin(100.0, s));
|
||
|
|
reason = r;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
void AI_GetSessionWindow(datetime now, datetime &sess_start, datetime &sess_end, string &sess_name)
|
||
|
|
{
|
||
|
|
MqlDateTime dt;
|
||
|
|
TimeToStruct(now, dt);
|
||
|
|
|
||
|
|
// UTC-style session buckets:
|
||
|
|
// Asia: 00-08, London: 08-13, New York: 13-21, Rollover: 21-24
|
||
|
|
int h = dt.hour;
|
||
|
|
|
||
|
|
MqlDateTime sdt = dt;
|
||
|
|
MqlDateTime edt = dt;
|
||
|
|
|
||
|
|
if(h >= 0 && h < 8)
|
||
|
|
{
|
||
|
|
sess_name = "ASIA";
|
||
|
|
sdt.hour = 0; sdt.min = 0; sdt.sec = 0;
|
||
|
|
edt.hour = 8; edt.min = 0; edt.sec = 0;
|
||
|
|
}
|
||
|
|
else if(h >= 8 && h < 13)
|
||
|
|
{
|
||
|
|
sess_name = "LONDON";
|
||
|
|
sdt.hour = 8; sdt.min = 0; sdt.sec = 0;
|
||
|
|
edt.hour = 13; edt.min = 0; edt.sec = 0;
|
||
|
|
}
|
||
|
|
else if(h >= 13 && h < 21)
|
||
|
|
{
|
||
|
|
sess_name = "NEWYORK";
|
||
|
|
sdt.hour = 13; sdt.min = 0; sdt.sec = 0;
|
||
|
|
edt.hour = 21; edt.min = 0; edt.sec = 0;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
sess_name = "ROLLOVER";
|
||
|
|
sdt.hour = 21; sdt.min = 0; sdt.sec = 0;
|
||
|
|
edt.hour = 23; edt.min = 59; edt.sec = 59;
|
||
|
|
}
|
||
|
|
|
||
|
|
sess_start = StructToTime(sdt);
|
||
|
|
sess_end = StructToTime(edt);
|
||
|
|
}
|
||
|
|
|
||
|
|
void AI_DrawSessionOverlay(const string phase,
|
||
|
|
const datetime sess_start,
|
||
|
|
const datetime sess_end,
|
||
|
|
const string sess_name,
|
||
|
|
const double confidence,
|
||
|
|
const string next_phase)
|
||
|
|
{
|
||
|
|
if(!AI_Session_Draw_Rectangles)
|
||
|
|
return;
|
||
|
|
|
||
|
|
int i_start = iBarShift(_Symbol, PERIOD_CURRENT, sess_start, false);
|
||
|
|
int i_end = iBarShift(_Symbol, PERIOD_CURRENT, sess_end, false);
|
||
|
|
if(i_start < 0 || i_end < 0)
|
||
|
|
return;
|
||
|
|
|
||
|
|
int lo = MathMin(i_start, i_end);
|
||
|
|
int hi = MathMax(i_start, i_end);
|
||
|
|
|
||
|
|
double p_hi = -DBL_MAX;
|
||
|
|
double p_lo = DBL_MAX;
|
||
|
|
for(int i = lo; i <= hi; ++i)
|
||
|
|
{
|
||
|
|
double h = iHigh(_Symbol, PERIOD_CURRENT, i);
|
||
|
|
double l = iLow(_Symbol, PERIOD_CURRENT, i);
|
||
|
|
if(h > p_hi) p_hi = h;
|
||
|
|
if(l < p_lo) p_lo = l;
|
||
|
|
}
|
||
|
|
|
||
|
|
if(p_hi <= p_lo)
|
||
|
|
return;
|
||
|
|
|
||
|
|
string key = IntegerToString((int)sess_start);
|
||
|
|
string rect = "AI_SESS_RECT_" + key;
|
||
|
|
string lbl = "AI_SESS_LBL_" + key;
|
||
|
|
|
||
|
|
if(ObjectFind(0, rect) < 0)
|
||
|
|
ObjectCreate(0, rect, OBJ_RECTANGLE, 0, sess_start, p_hi, sess_end, p_lo);
|
||
|
|
|
||
|
|
ObjectSetInteger(0, rect, OBJPROP_TIME, 0, sess_start);
|
||
|
|
ObjectSetDouble(0, rect, OBJPROP_PRICE, 0, p_hi);
|
||
|
|
ObjectSetInteger(0, rect, OBJPROP_TIME, 1, sess_end);
|
||
|
|
ObjectSetDouble(0, rect, OBJPROP_PRICE, 1, p_lo);
|
||
|
|
|
||
|
|
color c = clrSilver;
|
||
|
|
string u = AI_Upper(phase);
|
||
|
|
if(u == "ACCUMULATION") c = clrDodgerBlue;
|
||
|
|
if(u == "MANIPULATION") c = clrOrangeRed;
|
||
|
|
if(u == "DISTRIBUTION") c = clrGold;
|
||
|
|
|
||
|
|
ObjectSetInteger(0, rect, OBJPROP_COLOR, c);
|
||
|
|
ObjectSetInteger(0, rect, OBJPROP_BACK, true);
|
||
|
|
ObjectSetInteger(0, rect, OBJPROP_STYLE, STYLE_SOLID);
|
||
|
|
ObjectSetInteger(0, rect, OBJPROP_WIDTH, 1);
|
||
|
|
|
||
|
|
if(ObjectFind(0, lbl) < 0)
|
||
|
|
ObjectCreate(0, lbl, OBJ_TEXT, 0, sess_start, p_hi);
|
||
|
|
|
||
|
|
string txt = sess_name + " " + phase + " (" + DoubleToString(confidence, 1) + "%)";
|
||
|
|
if(AI_Session_Predict_Next && StringLen(next_phase) > 0)
|
||
|
|
txt += " -> next: " + next_phase;
|
||
|
|
|
||
|
|
ObjectSetString(0, lbl, OBJPROP_TEXT, txt);
|
||
|
|
ObjectSetInteger(0, lbl, OBJPROP_COLOR, c);
|
||
|
|
ObjectSetInteger(0, lbl, OBJPROP_FONTSIZE, 8);
|
||
|
|
ObjectSetInteger(0, lbl, OBJPROP_ANCHOR, ANCHOR_LEFT_UPPER);
|
||
|
|
ObjectSetInteger(0, lbl, OBJPROP_TIME, sess_start);
|
||
|
|
ObjectSetDouble(0, lbl, OBJPROP_PRICE, p_hi);
|
||
|
|
}
|
||
|
|
|
||
|
|
bool AIFetchSessionBriefing(const string sess_name,
|
||
|
|
const datetime sess_start,
|
||
|
|
const datetime sess_end,
|
||
|
|
string &phase,
|
||
|
|
double &confidence,
|
||
|
|
string &next_phase,
|
||
|
|
string &reason)
|
||
|
|
{
|
||
|
|
phase = "";
|
||
|
|
confidence = 0.0;
|
||
|
|
next_phase = "";
|
||
|
|
reason = "";
|
||
|
|
|
||
|
|
if(!AI_Initialized || !AI_Session_Briefing || AI_ModeOff())
|
||
|
|
return false;
|
||
|
|
|
||
|
|
string payload = "{";
|
||
|
|
payload += "\"symbol\":\"" + _Symbol + "\",";
|
||
|
|
payload += "\"session\":\"" + sess_name + "\",";
|
||
|
|
payload += "\"session_start\":" + IntegerToString((int)sess_start) + ",";
|
||
|
|
payload += "\"session_end\":" + IntegerToString((int)sess_end) + ",";
|
||
|
|
payload += "\"tf\":\"" + EnumToString((ENUM_TIMEFRAMES)Period()) + "\",";
|
||
|
|
payload += "\"frameworks\":\"Wyckoff,ICT\"";
|
||
|
|
payload += "}";
|
||
|
|
|
||
|
|
string resp = "";
|
||
|
|
if(!AI_Post("session-briefing", payload, resp))
|
||
|
|
return false;
|
||
|
|
|
||
|
|
string p = "";
|
||
|
|
string n = "";
|
||
|
|
string r = "";
|
||
|
|
double c = 0.0;
|
||
|
|
|
||
|
|
bool okp = AI_ExtractString(resp, "phase", p);
|
||
|
|
bool okc = AI_ExtractNumber(resp, "confidence", c);
|
||
|
|
AI_ExtractString(resp, "next_phase", n);
|
||
|
|
AI_ExtractString(resp, "reason", r);
|
||
|
|
|
||
|
|
if(!okp || !okc)
|
||
|
|
return false;
|
||
|
|
|
||
|
|
phase = p;
|
||
|
|
confidence = MathMax(0.0, MathMin(100.0, c));
|
||
|
|
next_phase = n;
|
||
|
|
reason = r;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
void AIUpdateBriefingsTimer()
|
||
|
|
{
|
||
|
|
if(!AI_Initialized || AI_ModeOff())
|
||
|
|
return;
|
||
|
|
|
||
|
|
static datetime last_h1_bar = 0;
|
||
|
|
static datetime last_h4_bar = 0;
|
||
|
|
static datetime last_d1_bar = 0;
|
||
|
|
static datetime last_w1_bar = 0;
|
||
|
|
static datetime last_mn1_bar = 0;
|
||
|
|
|
||
|
|
static string h4_day_compound = "";
|
||
|
|
|
||
|
|
datetime h1 = iTime(_Symbol, PERIOD_H1, 0);
|
||
|
|
datetime h4 = iTime(_Symbol, PERIOD_H4, 0);
|
||
|
|
datetime d1 = iTime(_Symbol, PERIOD_D1, 0);
|
||
|
|
datetime w1 = iTime(_Symbol, PERIOD_W1, 0);
|
||
|
|
datetime mn1 = iTime(_Symbol, PERIOD_MN1, 0);
|
||
|
|
|
||
|
|
if(AI_Briefing_1H && h1 > 0 && h1 != last_h1_bar)
|
||
|
|
{
|
||
|
|
string txt = "";
|
||
|
|
int b = 0;
|
||
|
|
double c = 0.0;
|
||
|
|
if(AIFetchBriefing("H1", AI_Brief_4H_Text, txt, b, c))
|
||
|
|
{
|
||
|
|
AI_Brief_1H_Text = txt;
|
||
|
|
AI_Brief_1H_Bias = b;
|
||
|
|
AI_Brief_1H_Confidence = c;
|
||
|
|
AI_Brief_1H_Time = TimeCurrent();
|
||
|
|
}
|
||
|
|
last_h1_bar = h1;
|
||
|
|
}
|
||
|
|
|
||
|
|
if(AI_Briefing_4H && h4 > 0 && h4 != last_h4_bar)
|
||
|
|
{
|
||
|
|
string txt = "";
|
||
|
|
int b = 0;
|
||
|
|
double c = 0.0;
|
||
|
|
if(AIFetchBriefing("H4", AI_Brief_1H_Text, txt, b, c))
|
||
|
|
{
|
||
|
|
AI_Brief_4H_Text = txt;
|
||
|
|
AI_Brief_4H_Bias = b;
|
||
|
|
AI_Brief_4H_Confidence = c;
|
||
|
|
AI_Brief_4H_Time = TimeCurrent();
|
||
|
|
|
||
|
|
string stamp = TimeToString(h4, TIME_DATE|TIME_MINUTES);
|
||
|
|
if(StringLen(h4_day_compound) > 0)
|
||
|
|
h4_day_compound += " || ";
|
||
|
|
h4_day_compound += "[" + stamp + "] " + txt;
|
||
|
|
}
|
||
|
|
last_h4_bar = h4;
|
||
|
|
}
|
||
|
|
|
||
|
|
if(AI_Briefing_Daily && d1 > 0 && d1 != last_d1_bar)
|
||
|
|
{
|
||
|
|
string ctx = h4_day_compound;
|
||
|
|
if(StringLen(ctx) == 0)
|
||
|
|
ctx = AI_Brief_4H_Text;
|
||
|
|
|
||
|
|
string txt = "";
|
||
|
|
int b = 0;
|
||
|
|
double c = 0.0;
|
||
|
|
if(AIFetchBriefing("D1", ctx, txt, b, c))
|
||
|
|
{
|
||
|
|
AI_Brief_D_Text = txt;
|
||
|
|
AI_Brief_D_Bias = b;
|
||
|
|
AI_Brief_D_Confidence = c;
|
||
|
|
AI_Brief_D_Time = TimeCurrent();
|
||
|
|
Last_AI_Analysis = txt;
|
||
|
|
}
|
||
|
|
|
||
|
|
h4_day_compound = "";
|
||
|
|
last_d1_bar = d1;
|
||
|
|
}
|
||
|
|
|
||
|
|
if(AI_Briefing_Weekly && w1 > 0 && w1 != last_w1_bar)
|
||
|
|
{
|
||
|
|
string txt = "";
|
||
|
|
int b = 0;
|
||
|
|
double c = 0.0;
|
||
|
|
if(AIFetchBriefing("W1", AI_Brief_D_Text, txt, b, c))
|
||
|
|
{
|
||
|
|
AI_Brief_W_Text = txt;
|
||
|
|
AI_Brief_W_Bias = b;
|
||
|
|
AI_Brief_W_Confidence = c;
|
||
|
|
AI_Brief_W_Time = TimeCurrent();
|
||
|
|
}
|
||
|
|
last_w1_bar = w1;
|
||
|
|
}
|
||
|
|
|
||
|
|
if(AI_Briefing_Monthly && mn1 > 0 && mn1 != last_mn1_bar)
|
||
|
|
{
|
||
|
|
string txt = "";
|
||
|
|
int b = 0;
|
||
|
|
double c = 0.0;
|
||
|
|
if(AIFetchBriefing("MN1", AI_Brief_W_Text, txt, b, c))
|
||
|
|
{
|
||
|
|
AI_Brief_M_Text = txt;
|
||
|
|
AI_Brief_M_Bias = b;
|
||
|
|
AI_Brief_M_Confidence = c;
|
||
|
|
AI_Brief_M_Time = TimeCurrent();
|
||
|
|
}
|
||
|
|
last_mn1_bar = mn1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void AIUpdateSessionTimer()
|
||
|
|
{
|
||
|
|
if(!AI_Initialized || !AI_Session_Briefing || AI_ModeOff())
|
||
|
|
return;
|
||
|
|
|
||
|
|
static datetime last_session_start = 0;
|
||
|
|
|
||
|
|
datetime now = TimeCurrent();
|
||
|
|
datetime sess_start = 0;
|
||
|
|
datetime sess_end = 0;
|
||
|
|
string sess_name = "";
|
||
|
|
AI_GetSessionWindow(now, sess_start, sess_end, sess_name);
|
||
|
|
|
||
|
|
if(sess_start <= 0 || sess_end <= 0)
|
||
|
|
return;
|
||
|
|
|
||
|
|
if(sess_start == last_session_start)
|
||
|
|
return;
|
||
|
|
|
||
|
|
string phase = "";
|
||
|
|
double conf = 0.0;
|
||
|
|
string next_phase = "";
|
||
|
|
string reason = "";
|
||
|
|
|
||
|
|
if(AIFetchSessionBriefing(sess_name, sess_start, sess_end, phase, conf, next_phase, reason))
|
||
|
|
{
|
||
|
|
AI_Session_Name = sess_name;
|
||
|
|
AI_Session_Phase = phase;
|
||
|
|
AI_Session_Next = next_phase;
|
||
|
|
AI_Session_Confidence = conf;
|
||
|
|
AI_Session_Reason = reason;
|
||
|
|
AI_Session_Start = sess_start;
|
||
|
|
AI_Session_End = sess_end;
|
||
|
|
|
||
|
|
AI_DrawSessionOverlay(phase, sess_start, sess_end, sess_name, conf, next_phase);
|
||
|
|
}
|
||
|
|
|
||
|
|
last_session_start = sess_start;
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif
|