2026-06-09 20:25:41 +02:00
|
|
|
//+------------------------------------------------------------------+
|
2026-06-05 11:14:54 +02:00
|
|
|
//| Omega |
|
|
|
|
|
//| Copyright 2020, Sifu PriceAction |
|
|
|
|
|
//| https://www.mql5.com/en/users/matimungoveni |
|
2026-06-05 11:09:30 +02:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
|
|
|
|
|
#property copyright "Copyright 2026, Matimu Ngoveni"
|
2026-06-09 19:37:24 +02:00
|
|
|
#property version "1.00"
|
2026-06-05 11:09:30 +02:00
|
|
|
|
|
|
|
|
#include <Arrays\ArrayObj.mqh>
|
|
|
|
|
|
|
|
|
|
//--- Global Configuration Parameters
|
2026-06-05 11:28:32 +02:00
|
|
|
input int InpHistoryDays = 72; // Total history days to render
|
2026-06-05 13:14:07 +02:00
|
|
|
input bool stay_on_M1 = false; // Stay on M1 timeframe
|
2026-06-05 11:28:32 +02:00
|
|
|
|
|
|
|
|
bool InpFillColor = true;
|
|
|
|
|
bool InpSendMobileAlerts = false; // Send Push Notifications to Mobile App?
|
2026-06-05 11:09:30 +02:00
|
|
|
|
|
|
|
|
//--- Global Database Handle Context
|
|
|
|
|
int gl_db_handle = INVALID_HANDLE;
|
|
|
|
|
|
|
|
|
|
//--- Helix Structural Analysis Data Model
|
2026-06-05 11:28:32 +02:00
|
|
|
struct CDeviationArc{
|
|
|
|
|
double high_deviation_pips;
|
|
|
|
|
double low_deviation_pips;
|
|
|
|
|
double mean_deviation;
|
|
|
|
|
int helix_polarity;
|
|
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-06-05 11:28:32 +02:00
|
|
|
//| sImPlY cOdE |
|
2026-06-05 11:09:30 +02:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
|
2026-06-05 11:28:32 +02:00
|
|
|
class CRectangleInstance : public CObject{
|
|
|
|
|
private:
|
|
|
|
|
string m_base_name;
|
|
|
|
|
string m_rect_name;
|
|
|
|
|
datetime m_start_time;
|
|
|
|
|
datetime m_end_time;
|
|
|
|
|
color m_color;
|
|
|
|
|
int m_width;
|
|
|
|
|
long m_visibility_flags;
|
|
|
|
|
bool m_is_background;
|
|
|
|
|
bool m_is_frozen;
|
|
|
|
|
bool m_is_saved_to_db;
|
|
|
|
|
double m_final_high;
|
|
|
|
|
double m_final_low;
|
|
|
|
|
bool m_alert_triggered;
|
|
|
|
|
datetime m_last_alert_bar;
|
|
|
|
|
bool m_is_anchor_session;
|
|
|
|
|
int m_parent_cycle_id;
|
|
|
|
|
double m_anchor_high_ref;
|
|
|
|
|
double m_anchor_low_ref;
|
2026-06-08 19:43:54 +02:00
|
|
|
double m_weekly_anchor_high;
|
|
|
|
|
double m_weekly_anchor_low;
|
2026-06-05 11:28:32 +02:00
|
|
|
bool GetPriceRange(datetime calculating_end_time, double &max_price, double &min_price);
|
|
|
|
|
void CreateDrawing(double high, double low, datetime end_time);
|
|
|
|
|
void UpdateDrawing(double high, double low, datetime end_time);
|
|
|
|
|
long CalculateVisibilityFlags(ENUM_TIMEFRAMES min_tf, ENUM_TIMEFRAMES max_tf);
|
|
|
|
|
void SaveToSQLite(double high, double low);
|
|
|
|
|
void CheckCandleCloseBreakout();
|
|
|
|
|
void LogBreakoutToDatabase(string type, double target_level, double close_price, double pips_moved);
|
|
|
|
|
void EvaluateHelixEdge(double cycle_high, double cycle_low);
|
2026-06-08 19:43:54 +02:00
|
|
|
void EvaluateWeeklyHelixEdge(double cycle_high, double cycle_low, double w_anchor_high, double w_anchor_low);
|
2026-06-05 11:28:32 +02:00
|
|
|
public:
|
|
|
|
|
CRectangleInstance(string name, datetime start, datetime end, color clr, int width, ENUM_TIMEFRAMES min_tf,
|
|
|
|
|
ENUM_TIMEFRAMES max_tf, bool background, int cycle_id, bool is_anchor);
|
|
|
|
|
~CRectangleInstance();
|
|
|
|
|
void ProcessAnimation();
|
|
|
|
|
void SetAnchorReferences(double a_high, double a_low) { m_anchor_high_ref = a_high; m_anchor_low_ref = a_low; }
|
2026-06-08 19:43:54 +02:00
|
|
|
void SetWeeklyAnchorReferences(double w_high, double w_low) { m_weekly_anchor_high = w_high; m_weekly_anchor_low = w_low; }
|
2026-06-05 11:28:32 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
CRectangleInstance::CRectangleInstance(string name, datetime start, datetime end, color clr, int width,
|
|
|
|
|
ENUM_TIMEFRAMES min_tf, ENUM_TIMEFRAMES max_tf, bool background, int cycle_id, bool is_anchor){
|
|
|
|
|
m_base_name = name;
|
|
|
|
|
m_rect_name = name + "_box";
|
|
|
|
|
m_start_time = start;
|
|
|
|
|
m_end_time = end;
|
|
|
|
|
m_color = clr;
|
|
|
|
|
m_width = width;
|
|
|
|
|
m_visibility_flags = CalculateVisibilityFlags(min_tf, max_tf);
|
|
|
|
|
m_is_background = background;
|
|
|
|
|
m_is_frozen = false;
|
|
|
|
|
m_is_saved_to_db = false;
|
|
|
|
|
m_final_high = 0.0;
|
|
|
|
|
m_final_low = 0.0;
|
|
|
|
|
m_alert_triggered = false;
|
|
|
|
|
m_last_alert_bar = 0;
|
|
|
|
|
m_parent_cycle_id = cycle_id;
|
2026-06-05 11:09:30 +02:00
|
|
|
m_is_anchor_session = is_anchor;
|
2026-06-05 11:28:32 +02:00
|
|
|
m_anchor_high_ref = 0.0;
|
|
|
|
|
m_anchor_low_ref = 0.0;
|
2026-06-08 19:43:54 +02:00
|
|
|
m_weekly_anchor_high = 0.0;
|
|
|
|
|
m_weekly_anchor_low = 0.0;
|
2026-06-05 11:28:32 +02:00
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
|
2026-06-05 11:28:32 +02:00
|
|
|
CRectangleInstance::~CRectangleInstance(){
|
2026-06-05 11:09:30 +02:00
|
|
|
if(ObjectFind(0, m_rect_name) >= 0)
|
|
|
|
|
ObjectDelete(0, m_rect_name);
|
2026-06-05 11:28:32 +02:00
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
|
2026-06-05 11:28:32 +02:00
|
|
|
void CRectangleInstance::ProcessAnimation(void){
|
|
|
|
|
if(m_is_frozen && m_is_saved_to_db){
|
2026-06-05 11:09:30 +02:00
|
|
|
CheckCandleCloseBreakout();
|
|
|
|
|
return;
|
2026-06-05 11:28:32 +02:00
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
|
|
|
|
|
datetime current_time = TimeCurrent();
|
|
|
|
|
datetime target_end_time = current_time;
|
|
|
|
|
|
2026-06-05 11:28:32 +02:00
|
|
|
if(current_time > m_end_time){
|
2026-06-05 11:09:30 +02:00
|
|
|
target_end_time = m_end_time;
|
|
|
|
|
m_is_frozen = true;
|
2026-06-05 11:28:32 +02:00
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
|
2026-06-05 11:28:32 +02:00
|
|
|
if(current_time >= m_start_time){
|
2026-06-05 11:09:30 +02:00
|
|
|
double highest_price = 0.0;
|
|
|
|
|
double lowest_price = 0.0;
|
|
|
|
|
|
2026-06-05 11:28:32 +02:00
|
|
|
if(!GetPriceRange(target_end_time, highest_price, lowest_price)){
|
2026-06-05 11:09:30 +02:00
|
|
|
m_is_frozen = false;
|
|
|
|
|
return;
|
2026-06-05 11:28:32 +02:00
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
|
|
|
|
|
if(ObjectFind(0, m_rect_name) < 0)
|
|
|
|
|
CreateDrawing(highest_price, lowest_price, target_end_time);
|
|
|
|
|
else
|
|
|
|
|
UpdateDrawing(highest_price, lowest_price, target_end_time);
|
|
|
|
|
|
2026-06-05 11:28:32 +02:00
|
|
|
if(!m_is_frozen){
|
2026-06-05 11:09:30 +02:00
|
|
|
SaveToSQLite(highest_price, lowest_price);
|
2026-06-05 11:28:32 +02:00
|
|
|
}else if(m_is_frozen && !m_is_saved_to_db){
|
2026-06-05 11:09:30 +02:00
|
|
|
SaveToSQLite(highest_price, lowest_price);
|
2026-06-05 11:28:32 +02:00
|
|
|
m_final_high = highest_price;
|
|
|
|
|
m_final_low = lowest_price;
|
2026-06-05 11:09:30 +02:00
|
|
|
m_is_saved_to_db = true;
|
|
|
|
|
|
|
|
|
|
// Trigger mathematical arc deviation modeling if item is outside anchor range
|
2026-06-05 11:28:32 +02:00
|
|
|
if(!m_is_anchor_session){
|
2026-06-05 11:09:30 +02:00
|
|
|
EvaluateHelixEdge(m_final_high, m_final_low);
|
2026-06-08 19:43:54 +02:00
|
|
|
EvaluateWeeklyHelixEdge(m_final_high, m_final_low, m_weekly_anchor_high, m_weekly_anchor_low);
|
2026-06-05 11:28:32 +02:00
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
|
2026-06-05 11:31:38 +02:00
|
|
|
bool CRectangleInstance::GetPriceRange(datetime calculating_end_time, double &max_price, double &min_price){
|
2026-06-05 11:09:30 +02:00
|
|
|
MqlRates rates[];
|
|
|
|
|
ArraySetAsSeries(rates, true);
|
|
|
|
|
|
|
|
|
|
int copied = CopyRates(_Symbol, _Period, m_start_time, calculating_end_time, rates);
|
|
|
|
|
if(copied <= 0)
|
|
|
|
|
return(false);
|
|
|
|
|
|
|
|
|
|
max_price = rates[0].high;
|
|
|
|
|
min_price = rates[0].low;
|
|
|
|
|
|
2026-06-05 11:31:38 +02:00
|
|
|
for(int i = 1; i < copied; i++){
|
2026-06-05 11:09:30 +02:00
|
|
|
if(rates[i].high > max_price)
|
|
|
|
|
max_price = rates[i].high;
|
|
|
|
|
if(rates[i].low < min_price)
|
|
|
|
|
min_price = rates[i].low;
|
2026-06-05 11:31:38 +02:00
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
return(true);
|
2026-06-05 11:31:38 +02:00
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
|
2026-06-05 11:31:38 +02:00
|
|
|
void CRectangleInstance::CreateDrawing(double high, double low, datetime end_time){
|
2026-06-05 11:09:30 +02:00
|
|
|
ObjectCreate(0, m_rect_name, OBJ_RECTANGLE, 0, m_start_time, high, end_time, low);
|
|
|
|
|
ObjectSetInteger(0, m_rect_name, OBJPROP_COLOR, m_color);
|
|
|
|
|
ObjectSetInteger(0, m_rect_name, OBJPROP_WIDTH, m_width);
|
|
|
|
|
ObjectSetInteger(0, m_rect_name, OBJPROP_RAY_RIGHT, false);
|
|
|
|
|
ObjectSetInteger(0, m_rect_name, OBJPROP_TIMEFRAMES, m_visibility_flags);
|
|
|
|
|
ObjectSetInteger(0, m_rect_name, OBJPROP_DRAWLINES, false);
|
|
|
|
|
ObjectSetInteger(0, m_rect_name, OBJPROP_BACK, m_is_background);
|
|
|
|
|
ObjectSetInteger(0, m_rect_name, OBJPROP_FILL, (m_is_background ? InpFillColor : false));
|
2026-06-05 11:31:38 +02:00
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
|
2026-06-05 11:31:38 +02:00
|
|
|
void CRectangleInstance::UpdateDrawing(double high, double low, datetime end_time){
|
2026-06-05 11:09:30 +02:00
|
|
|
ObjectSetDouble(0, m_rect_name, OBJPROP_PRICE, 0, high);
|
|
|
|
|
ObjectSetDouble(0, m_rect_name, OBJPROP_PRICE, 1, low);
|
|
|
|
|
ObjectSetInteger(0, m_rect_name, OBJPROP_TIME, 1, end_time);
|
2026-06-05 11:31:38 +02:00
|
|
|
}
|
2026-06-05 11:09:30 +02:00
|
|
|
|
2026-06-05 11:31:38 +02:00
|
|
|
void CRectangleInstance::SaveToSQLite(double high, double low){
|
2026-06-05 11:09:30 +02:00
|
|
|
if(gl_db_handle == INVALID_HANDLE)
|
|
|
|
|
return;
|
|
|
|
|
|
2026-06-05 11:31:38 +02:00
|
|
|
string query = StringFormat("INSERT OR REPLACE INTO SessionRectangles (BoxID, Symbol, StartTime, EndTime, HighPrice, LowPrice) "
|
|
|
|
|
"VALUES ('%s', '%s', %I64u, %I64u, %f, %f);", m_rect_name, _Symbol, (ulong)m_start_time, (ulong)m_end_time, high, low);
|
2026-06-05 11:09:30 +02:00
|
|
|
|
2026-06-05 11:31:38 +02:00
|
|
|
if(!DatabaseExecute(gl_db_handle, query)){
|
2026-06-05 11:09:30 +02:00
|
|
|
Print("SQLite Error: Live stream write failed. Code: ", GetLastError());
|
2026-06-05 11:31:38 +02:00
|
|
|
};
|
|
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
|
2026-06-05 11:40:26 +02:00
|
|
|
void CRectangleInstance::CheckCandleCloseBreakout(){
|
2026-06-05 11:09:30 +02:00
|
|
|
if(m_final_high == 0.0 || m_final_low == 0.0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
MqlRates rates[];
|
|
|
|
|
ArraySetAsSeries(rates, true);
|
|
|
|
|
|
|
|
|
|
if(CopyRates(_Symbol, _Period, 1, 1, rates) <= 0)
|
|
|
|
|
return;
|
|
|
|
|
if(rates[0].time == m_last_alert_bar)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
bool triggered = false;
|
|
|
|
|
string type_text = "";
|
|
|
|
|
double broken_level = 0.0;
|
|
|
|
|
double pips_moved = 0.0;
|
|
|
|
|
|
|
|
|
|
double pip_multiplier = (_Digits == 3 || _Digits == 5) ? (_Point * 10.0) : _Point;
|
|
|
|
|
|
2026-06-05 11:40:26 +02:00
|
|
|
if(rates[0].close > m_final_high){
|
2026-06-05 11:09:30 +02:00
|
|
|
triggered = true;
|
|
|
|
|
type_text = "HIGH";
|
|
|
|
|
broken_level = m_final_high;
|
|
|
|
|
pips_moved = (rates[0].close - m_final_high) / pip_multiplier;
|
2026-06-05 11:40:26 +02:00
|
|
|
}else if(rates[0].close < m_final_low){
|
2026-06-05 11:09:30 +02:00
|
|
|
triggered = true;
|
|
|
|
|
type_text = "LOW";
|
|
|
|
|
broken_level = m_final_low;
|
|
|
|
|
pips_moved = (m_final_low - rates[0].close) / pip_multiplier;
|
2026-06-05 11:40:26 +02:00
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
|
2026-06-05 11:40:26 +02:00
|
|
|
if(triggered){
|
2026-06-05 11:09:30 +02:00
|
|
|
m_last_alert_bar = rates[0].time;
|
|
|
|
|
m_alert_triggered = true;
|
|
|
|
|
|
|
|
|
|
string alert_msg = StringFormat("CLOSE BREAKOUT %s: %s crossed %s level. Closed past it by %.1f Pips at price %f",
|
|
|
|
|
type_text, _Symbol, m_base_name, pips_moved, rates[0].close);
|
|
|
|
|
|
|
|
|
|
Print(alert_msg);
|
|
|
|
|
|
2026-06-05 11:40:26 +02:00
|
|
|
if(InpSendMobileAlerts){
|
2026-06-05 11:09:30 +02:00
|
|
|
if(!SendNotification(alert_msg))
|
|
|
|
|
Print("Notification Transmission Failure. Code: ", GetLastError());
|
2026-06-05 11:40:26 +02:00
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
|
|
|
|
|
LogBreakoutToDatabase(type_text, broken_level, rates[0].close, pips_moved);
|
2026-06-05 11:40:26 +02:00
|
|
|
};
|
|
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
|
2026-06-05 11:40:26 +02:00
|
|
|
void CRectangleInstance::LogBreakoutToDatabase(string type, double target_level, double close_price, double pips_moved){
|
2026-06-05 11:09:30 +02:00
|
|
|
if(gl_db_handle == INVALID_HANDLE)
|
|
|
|
|
return;
|
|
|
|
|
|
2026-06-05 11:40:26 +02:00
|
|
|
string query = StringFormat("INSERT INTO BreakoutHistory (BoxID, Symbol, Period, Type, TargetLevel, ClosePrice, PipsTravelled, Timestamp) "
|
|
|
|
|
"VALUES ('%s', '%s', '%s', '%s', %f, %f, %.1f, %I64u);", m_rect_name, _Symbol, EnumToString(_Period),
|
|
|
|
|
type, target_level, close_price, pips_moved, (ulong)TimeCurrent());
|
2026-06-05 11:09:30 +02:00
|
|
|
|
2026-06-05 11:40:26 +02:00
|
|
|
if(!DatabaseExecute(gl_db_handle, query)){
|
2026-06-05 11:09:30 +02:00
|
|
|
Print("SQLite Error: Breakout Event Logging insertion failed. Code: ", GetLastError());
|
2026-06-05 11:40:26 +02:00
|
|
|
};
|
|
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
|
2026-06-05 11:40:26 +02:00
|
|
|
void CRectangleInstance::EvaluateHelixEdge(double cycle_high, double cycle_low){
|
|
|
|
|
// Skip validation if this is the anchor session itself or if anchor ranges are empty
|
2026-06-05 11:09:30 +02:00
|
|
|
if(m_is_anchor_session || m_anchor_high_ref == 0.0 || m_anchor_low_ref == 0.0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
double pip_size = (_Digits == 3 || _Digits == 5) ? (_Point * 10.0) : _Point;
|
|
|
|
|
double anchor_range = (m_anchor_high_ref - m_anchor_low_ref) / pip_size;
|
|
|
|
|
if(anchor_range <= 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
CDeviationArc arc;
|
|
|
|
|
arc.high_deviation_pips = (cycle_high - m_anchor_high_ref) / pip_size;
|
2026-06-05 11:40:26 +02:00
|
|
|
arc.low_deviation_pips = (m_anchor_low_ref - cycle_low) / pip_size;
|
|
|
|
|
arc.mean_deviation = (arc.high_deviation_pips - arc.low_deviation_pips) / 2.0;
|
2026-06-05 11:09:30 +02:00
|
|
|
|
2026-06-05 11:40:26 +02:00
|
|
|
// Helix Weave Identification Logic
|
2026-06-05 11:09:30 +02:00
|
|
|
if(arc.high_deviation_pips > 0 && arc.low_deviation_pips > 0)
|
|
|
|
|
arc.helix_polarity = -1; // Opposing Arcs present (Helix Weave form)
|
|
|
|
|
else
|
|
|
|
|
arc.helix_polarity = 1; // Directional Expansion Edge expansion layout
|
|
|
|
|
|
|
|
|
|
string edge_bias = "NEUTRAL";
|
|
|
|
|
if(arc.mean_deviation > (anchor_range * 0.5) && arc.helix_polarity == 1)
|
|
|
|
|
edge_bias = "BULLISH EDGE (Expansion)";
|
|
|
|
|
else
|
|
|
|
|
if(arc.mean_deviation < -(anchor_range * 0.5) && arc.helix_polarity == 1)
|
|
|
|
|
edge_bias = "BEARISH EDGE (Expansion)";
|
|
|
|
|
else
|
|
|
|
|
if(arc.helix_polarity == -1)
|
|
|
|
|
edge_bias = "HELIX WEAVE (Choppy Reversals)";
|
|
|
|
|
|
|
|
|
|
Print(StringFormat("Helix Edge Report [%s | Cycle %d]: High Dev: %.1f Pips, Low Dev: %.1f Pips | Polarity: %d -> BIAS: %s",
|
|
|
|
|
m_base_name, m_parent_cycle_id, arc.high_deviation_pips, arc.low_deviation_pips, arc.helix_polarity, edge_bias));
|
2026-06-05 11:40:26 +02:00
|
|
|
|
|
|
|
|
if(gl_db_handle == INVALID_HANDLE)
|
|
|
|
|
return;
|
|
|
|
|
string query = StringFormat("INSERT INTO HelixAnalytics (BoxID, CycleID, HighDevPips, LowDevPips, HelixPolarity, EdgeBias, Timestamp) "
|
|
|
|
|
"VALUES ('%s', %d, %.2f, %.2f, %d, '%s', %I64u);", m_rect_name, m_parent_cycle_id, arc.high_deviation_pips,
|
|
|
|
|
arc.low_deviation_pips, arc.helix_polarity, edge_bias, (ulong)TimeCurrent());
|
|
|
|
|
if(!DatabaseExecute(gl_db_handle, query)){
|
|
|
|
|
Print("SQLite Error: Helix Logging failed. Code: ", GetLastError());
|
|
|
|
|
};
|
|
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
|
2026-06-08 19:43:54 +02:00
|
|
|
void CRectangleInstance::EvaluateWeeklyHelixEdge(double cycle_high, double cycle_low, double w_anchor_high, double w_anchor_low){
|
|
|
|
|
if(w_anchor_high == 0.0 || w_anchor_low == 0.0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
double pip_size = (_Digits == 3 || _Digits == 5) ? (_Point * 10.0) : _Point;
|
|
|
|
|
double anchor_range = (w_anchor_high - w_anchor_low) / pip_size;
|
|
|
|
|
if(anchor_range <= 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
CDeviationArc arc;
|
|
|
|
|
arc.high_deviation_pips = (cycle_high - w_anchor_high) / pip_size;
|
|
|
|
|
arc.low_deviation_pips = (w_anchor_low - cycle_low) / pip_size;
|
|
|
|
|
arc.mean_deviation = (arc.high_deviation_pips - arc.low_deviation_pips) / 2.0;
|
|
|
|
|
|
|
|
|
|
if(arc.high_deviation_pips > 0 && arc.low_deviation_pips > 0)
|
2026-06-09 19:37:24 +02:00
|
|
|
arc.helix_polarity = -1;
|
2026-06-08 19:43:54 +02:00
|
|
|
else
|
2026-06-09 19:37:24 +02:00
|
|
|
arc.helix_polarity = 1;
|
2026-06-08 19:43:54 +02:00
|
|
|
|
|
|
|
|
string edge_bias = "NEUTRAL";
|
|
|
|
|
if(arc.mean_deviation > (anchor_range * 0.5) && arc.helix_polarity == 1)
|
|
|
|
|
edge_bias = "BULLISH EDGE (Weekly Expansion)";
|
|
|
|
|
else if(arc.mean_deviation < -(anchor_range * 0.5) && arc.helix_polarity == 1)
|
|
|
|
|
edge_bias = "BEARISH EDGE (Weekly Expansion)";
|
|
|
|
|
else if(arc.helix_polarity == -1)
|
|
|
|
|
edge_bias = "HELIX WEAVE (Weekly Choppy Reversals)";
|
|
|
|
|
|
|
|
|
|
Print(StringFormat("Weekly Helix Edge Report [%s | Cycle %d]: High Dev: %.1f Pips, Low Dev: %.1f Pips | Polarity: %d -> BIAS: %s",
|
|
|
|
|
m_base_name, m_parent_cycle_id, arc.high_deviation_pips, arc.low_deviation_pips, arc.helix_polarity, edge_bias));
|
|
|
|
|
|
|
|
|
|
if(gl_db_handle == INVALID_HANDLE)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
string query = StringFormat("INSERT INTO HelixAnalytics (BoxID, CycleID, HighDevPips, LowDevPips, HelixPolarity, EdgeBias, Timestamp) "
|
|
|
|
|
"VALUES ('%s', 0, %.2f, %.2f, %d, '%s', %I64u);",
|
|
|
|
|
m_rect_name, arc.high_deviation_pips, arc.low_deviation_pips,
|
|
|
|
|
arc.helix_polarity, edge_bias, (ulong)TimeCurrent());
|
|
|
|
|
if(!DatabaseExecute(gl_db_handle, query)){
|
|
|
|
|
Print("SQLite Error: Weekly Helix Logging failed. Code: ", GetLastError());
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
2026-06-05 11:40:26 +02:00
|
|
|
long CRectangleInstance::CalculateVisibilityFlags(ENUM_TIMEFRAMES min_tf, ENUM_TIMEFRAMES max_tf){
|
2026-06-05 11:09:30 +02:00
|
|
|
if(min_tf > max_tf)
|
|
|
|
|
return(OBJ_ALL_PERIODS);
|
|
|
|
|
|
|
|
|
|
ENUM_TIMEFRAMES tfs[] = {PERIOD_M1, PERIOD_M2, PERIOD_M3, PERIOD_M4, PERIOD_M5, PERIOD_M6, PERIOD_M10,
|
|
|
|
|
PERIOD_M12, PERIOD_M15, PERIOD_M20, PERIOD_M30, PERIOD_H1, PERIOD_H2, PERIOD_H3,
|
2026-06-05 11:40:26 +02:00
|
|
|
PERIOD_H4, PERIOD_H6, PERIOD_H8, PERIOD_H12, PERIOD_D1, PERIOD_W1, PERIOD_MN1};
|
2026-06-05 11:09:30 +02:00
|
|
|
|
|
|
|
|
long flags[] = {OBJ_PERIOD_M1, OBJ_PERIOD_M2, OBJ_PERIOD_M3, OBJ_PERIOD_M4, OBJ_PERIOD_M5, OBJ_PERIOD_M6, OBJ_PERIOD_M10,
|
|
|
|
|
OBJ_PERIOD_M12, OBJ_PERIOD_M15, OBJ_PERIOD_M20, OBJ_PERIOD_M30, OBJ_PERIOD_H1, OBJ_PERIOD_H2, OBJ_PERIOD_H3,
|
2026-06-05 11:40:26 +02:00
|
|
|
OBJ_PERIOD_H4, OBJ_PERIOD_H6, OBJ_PERIOD_H8, OBJ_PERIOD_H12, OBJ_PERIOD_D1, OBJ_PERIOD_W1, OBJ_PERIOD_MN1};
|
2026-06-05 11:09:30 +02:00
|
|
|
|
|
|
|
|
long combined_flags = OBJ_NO_PERIODS;
|
2026-06-05 11:40:26 +02:00
|
|
|
for(int i = 0; i < ArraySize(tfs); i++){
|
2026-06-05 11:09:30 +02:00
|
|
|
if(tfs[i] >= min_tf && tfs[i] <= max_tf)
|
|
|
|
|
combined_flags |= flags[i];
|
2026-06-05 11:40:26 +02:00
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
return(combined_flags);
|
2026-06-05 11:40:26 +02:00
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
|
2026-06-05 11:49:35 +02:00
|
|
|
class CAnimationController{
|
|
|
|
|
private:
|
|
|
|
|
CArrayObj m_rectangles;
|
|
|
|
|
public:
|
|
|
|
|
CAnimationController(){};
|
|
|
|
|
~CAnimationController(){m_rectangles.Clear();};
|
|
|
|
|
void AddRectangle(string name, datetime start, datetime end, color clr, int width, ENUM_TIMEFRAMES min_tf,
|
|
|
|
|
ENUM_TIMEFRAMES max_tf, bool background, int cycle_id, bool is_anchor);
|
2026-06-09 19:37:24 +02:00
|
|
|
void SetAnchorReferences(double a_high, double a_low);
|
2026-06-08 19:43:54 +02:00
|
|
|
void SetWeeklyAnchorReferences(double w_high, double w_low);
|
2026-06-05 11:49:35 +02:00
|
|
|
void UpdateAll();
|
|
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
|
2026-06-05 11:49:35 +02:00
|
|
|
void CAnimationController::AddRectangle(string name, datetime start, datetime end, color clr, int width,
|
|
|
|
|
ENUM_TIMEFRAMES min_tf, ENUM_TIMEFRAMES max_tf,
|
|
|
|
|
bool background, int cycle_id, bool is_anchor){
|
2026-06-05 11:09:30 +02:00
|
|
|
if(start >= end)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
CRectangleInstance *new_rect = new CRectangleInstance(name, start, end, clr, width, min_tf, max_tf, background, cycle_id, is_anchor);
|
|
|
|
|
m_rectangles.Add(new_rect);
|
2026-06-05 11:49:35 +02:00
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
|
2026-06-09 19:37:24 +02:00
|
|
|
void CAnimationController::SetAnchorReferences(double a_high, double a_low){
|
|
|
|
|
int total = m_rectangles.Total();
|
|
|
|
|
for(int i = 0; i < total; i++){
|
|
|
|
|
CObject *obj_ptr = m_rectangles.At(i);
|
|
|
|
|
CRectangleInstance *rect = dynamic_cast<CRectangleInstance*>(obj_ptr);
|
|
|
|
|
if(rect != NULL)
|
|
|
|
|
rect.SetAnchorReferences(a_high, a_low);
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
2026-06-08 19:43:54 +02:00
|
|
|
void CAnimationController::SetWeeklyAnchorReferences(double w_high, double w_low){
|
|
|
|
|
int total = m_rectangles.Total();
|
|
|
|
|
for(int i = 0; i < total; i++){
|
|
|
|
|
CObject *obj_ptr = m_rectangles.At(i);
|
|
|
|
|
CRectangleInstance *rect = dynamic_cast<CRectangleInstance*>(obj_ptr);
|
|
|
|
|
if(rect != NULL)
|
|
|
|
|
rect.SetWeeklyAnchorReferences(w_high, w_low);
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
2026-06-05 11:49:35 +02:00
|
|
|
void CAnimationController::UpdateAll(void){
|
2026-06-05 11:09:30 +02:00
|
|
|
int total = m_rectangles.Total();
|
2026-06-05 11:49:35 +02:00
|
|
|
for(int i = 0; i < total; i++){
|
2026-06-05 11:09:30 +02:00
|
|
|
CObject *obj_ptr = m_rectangles.At(i);
|
|
|
|
|
CRectangleInstance *rect = dynamic_cast<CRectangleInstance*>(obj_ptr);
|
2026-06-05 11:49:35 +02:00
|
|
|
if(rect != NULL){
|
2026-06-05 11:09:30 +02:00
|
|
|
rect.ProcessAnimation();
|
2026-06-05 11:49:35 +02:00
|
|
|
};
|
|
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
ChartRedraw(0);
|
2026-06-05 11:49:35 +02:00
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Global System Context Instantiation |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
CAnimationController *Controller = NULL;
|
|
|
|
|
|
2026-06-05 11:49:35 +02:00
|
|
|
int OnInit(){
|
2026-06-05 12:57:00 +02:00
|
|
|
|
|
|
|
|
// Use 0 for the current active chart window
|
2026-06-05 13:14:07 +02:00
|
|
|
long activeChartId = 0;
|
2026-06-05 12:57:00 +02:00
|
|
|
|
2026-06-05 13:14:07 +02:00
|
|
|
if(stay_on_M1){
|
|
|
|
|
if(!ChartSetSymbolPeriod(activeChartId, NULL, PERIOD_M1)){
|
|
|
|
|
PrintFormat("Warning: Failed to switch timeframe to M1. Error: %d", GetLastError());
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
2026-06-05 12:57:00 +02:00
|
|
|
// Execute configuration and verify success
|
|
|
|
|
if(ApplyCustomChartSettings(activeChartId)){
|
|
|
|
|
Print("Success: Chart visual properties updated.");
|
|
|
|
|
}else{
|
|
|
|
|
Print("Warning: Some chart properties failed to update.");
|
|
|
|
|
};
|
|
|
|
|
|
2026-06-05 11:09:30 +02:00
|
|
|
gl_db_handle = DatabaseOpen("SessionHistory.sqlite", DATABASE_OPEN_READWRITE | DATABASE_OPEN_CREATE);
|
|
|
|
|
|
2026-06-05 11:49:35 +02:00
|
|
|
if(gl_db_handle == INVALID_HANDLE){
|
2026-06-05 11:09:30 +02:00
|
|
|
Print("SQLite Connection Error: Core Context failed to open. Error: ", GetLastError());
|
|
|
|
|
return(INIT_FAILED);
|
2026-06-05 11:49:35 +02:00
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
|
|
|
|
|
string create_table_query =
|
|
|
|
|
"CREATE TABLE IF NOT EXISTS SessionRectangles ("
|
|
|
|
|
"BoxID TEXT PRIMARY KEY, Symbol TEXT, StartTime INTEGER, EndTime INTEGER, HighPrice REAL, LowPrice REAL"
|
|
|
|
|
");";
|
|
|
|
|
|
|
|
|
|
string create_history_query =
|
|
|
|
|
"CREATE TABLE IF NOT EXISTS BreakoutHistory ("
|
|
|
|
|
"EventID INTEGER PRIMARY KEY AUTOINCREMENT, BoxID TEXT, Symbol TEXT, Period TEXT, Type TEXT, TargetLevel REAL, ClosePrice REAL, PipsTravelled REAL, Timestamp INTEGER"
|
|
|
|
|
");";
|
|
|
|
|
|
|
|
|
|
string create_analytics_query =
|
|
|
|
|
"CREATE TABLE IF NOT EXISTS HelixAnalytics ("
|
|
|
|
|
"EventID INTEGER PRIMARY KEY AUTOINCREMENT, BoxID TEXT, CycleID INTEGER, HighDevPips REAL, LowDevPips REAL, HelixPolarity INTEGER, EdgeBias TEXT, Timestamp INTEGER"
|
|
|
|
|
");";
|
|
|
|
|
|
2026-06-09 20:25:41 +02:00
|
|
|
string create_archive_sessions_query =
|
|
|
|
|
"CREATE TABLE IF NOT EXISTS SessionRectangles_Archive ("
|
|
|
|
|
"BoxID TEXT, Symbol TEXT, StartTime INTEGER, EndTime INTEGER, HighPrice REAL, LowPrice REAL, ArchivedAt INTEGER"
|
|
|
|
|
");";
|
|
|
|
|
|
|
|
|
|
string create_archive_breakouts_query =
|
|
|
|
|
"CREATE TABLE IF NOT EXISTS BreakoutHistory_Archive ("
|
|
|
|
|
"EventID INTEGER, BoxID TEXT, Symbol TEXT, Period TEXT, Type TEXT, TargetLevel REAL, ClosePrice REAL, PipsTravelled REAL, Timestamp INTEGER, ArchivedAt INTEGER"
|
|
|
|
|
");";
|
|
|
|
|
|
|
|
|
|
string create_archive_analytics_query =
|
|
|
|
|
"CREATE TABLE IF NOT EXISTS HelixAnalytics_Archive ("
|
|
|
|
|
"EventID INTEGER, BoxID TEXT, CycleID INTEGER, HighDevPips REAL, LowDevPips REAL, HelixPolarity INTEGER, EdgeBias TEXT, Timestamp INTEGER, ArchivedAt INTEGER"
|
|
|
|
|
");";
|
|
|
|
|
|
2026-06-05 11:49:35 +02:00
|
|
|
if(!DatabaseExecute(gl_db_handle, create_table_query) || !DatabaseExecute(gl_db_handle, create_history_query) ||
|
2026-06-09 20:25:41 +02:00
|
|
|
!DatabaseExecute(gl_db_handle, create_analytics_query) ||
|
|
|
|
|
!DatabaseExecute(gl_db_handle, create_archive_sessions_query) ||
|
|
|
|
|
!DatabaseExecute(gl_db_handle, create_archive_breakouts_query) ||
|
|
|
|
|
!DatabaseExecute(gl_db_handle, create_archive_analytics_query)){
|
2026-06-05 11:49:35 +02:00
|
|
|
Print("SQLite Initialization Aborted: Structural schema verification failed. Error: ", GetLastError());
|
|
|
|
|
DatabaseClose(gl_db_handle);
|
|
|
|
|
return(INIT_FAILED);
|
|
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
|
|
|
|
|
Controller = new CAnimationController();
|
|
|
|
|
|
|
|
|
|
datetime today = TimeCurrent();
|
|
|
|
|
datetime midnight = today - (today % 86400);
|
|
|
|
|
|
|
|
|
|
int processed_days = 0;
|
|
|
|
|
int check_offset = 0;
|
|
|
|
|
|
2026-06-08 19:43:54 +02:00
|
|
|
// --- Weekly tracking state ---
|
2026-06-09 19:37:24 +02:00
|
|
|
datetime last_week_monday = 0;
|
2026-06-08 19:43:54 +02:00
|
|
|
double weekly_anchor_high = 0.0;
|
|
|
|
|
double weekly_anchor_low = 0.0;
|
|
|
|
|
|
|
|
|
|
string all_day_prefixes[] = {
|
2026-06-09 19:37:24 +02:00
|
|
|
"a_","b_","c_","d_","e_",
|
|
|
|
|
"f_","g_","h_","i_","j_",
|
|
|
|
|
"k_","l_","m_","n_","o_",
|
|
|
|
|
"p_","q_","r_","s_","t_",
|
|
|
|
|
"u_","v_","w_","x_","y_",
|
|
|
|
|
"z_","a2_","b2_","c2_","d2_",
|
|
|
|
|
"e2_","f2_","g2_","h2_","i2_",
|
|
|
|
|
"j2_","k2_","l2_","m2_","n2_",
|
|
|
|
|
"o2_","p2_","q2_","r2_","s2_"
|
2026-06-08 19:43:54 +02:00
|
|
|
};
|
|
|
|
|
|
2026-06-05 11:49:35 +02:00
|
|
|
while(processed_days <= InpHistoryDays){
|
2026-06-05 11:09:30 +02:00
|
|
|
datetime base_time = midnight - (check_offset * 86400);
|
|
|
|
|
MqlDateTime structure_date;
|
|
|
|
|
TimeToStruct(base_time, structure_date);
|
|
|
|
|
|
|
|
|
|
check_offset = check_offset + 1;
|
|
|
|
|
|
|
|
|
|
if(structure_date.day_of_week == 0 || structure_date.day_of_week == 6)
|
|
|
|
|
continue;
|
|
|
|
|
|
2026-06-08 19:43:54 +02:00
|
|
|
// --- Compute Monday of this day's ISO week ---
|
2026-06-09 19:37:24 +02:00
|
|
|
int days_since_monday = structure_date.day_of_week - 1;
|
2026-06-08 19:43:54 +02:00
|
|
|
datetime this_monday = base_time - (days_since_monday * 86400);
|
|
|
|
|
|
2026-06-09 19:37:24 +02:00
|
|
|
// --- On new week: resolve weekly anchor from Mon+Tue DB records ---
|
2026-06-08 19:43:54 +02:00
|
|
|
if(this_monday != last_week_monday){
|
2026-06-09 19:37:24 +02:00
|
|
|
last_week_monday = this_monday;
|
2026-06-08 19:43:54 +02:00
|
|
|
weekly_anchor_high = 0.0;
|
|
|
|
|
weekly_anchor_low = 0.0;
|
|
|
|
|
|
|
|
|
|
if(gl_db_handle != INVALID_HANDLE){
|
|
|
|
|
datetime anchor_days[2];
|
|
|
|
|
anchor_days[0] = this_monday;
|
|
|
|
|
anchor_days[1] = this_monday + 86400;
|
|
|
|
|
|
|
|
|
|
for(int d = 0; d < 2; d++){
|
|
|
|
|
string day_suffix = TimeToString(anchor_days[d], TIME_DATE);
|
|
|
|
|
StringReplace(day_suffix, ".", "_");
|
|
|
|
|
|
|
|
|
|
for(int k = 0; k < ArraySize(all_day_prefixes); k++){
|
|
|
|
|
string target_box = all_day_prefixes[k] + day_suffix + "_box";
|
|
|
|
|
string sel_query = StringFormat("SELECT HighPrice, LowPrice FROM SessionRectangles WHERE BoxID='%s';", target_box);
|
|
|
|
|
|
|
|
|
|
int rh = DatabasePrepare(gl_db_handle, sel_query);
|
|
|
|
|
if(rh != INVALID_HANDLE){
|
|
|
|
|
if(DatabaseRead(rh)){
|
|
|
|
|
double fh = 0.0, fl = 0.0;
|
|
|
|
|
if(DatabaseColumnDouble(rh, 0, fh) && DatabaseColumnDouble(rh, 1, fl)){
|
|
|
|
|
if(fh > weekly_anchor_high) weekly_anchor_high = fh;
|
|
|
|
|
if(weekly_anchor_low == 0.0 || (fl < weekly_anchor_low && fl > 0.0)) weekly_anchor_low = fl;
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
DatabaseFinalize(rh);
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
2026-06-09 19:37:24 +02:00
|
|
|
// --- Draw weekly anchor trendlines: Mon 00:15 -> Fri 16:30 ---
|
2026-06-08 19:43:54 +02:00
|
|
|
if(weekly_anchor_high > 0.0 && weekly_anchor_low > 0.0){
|
2026-06-09 19:37:24 +02:00
|
|
|
datetime friday = this_monday + (4 * 86400);
|
|
|
|
|
datetime w_line_start = this_monday + 900;
|
|
|
|
|
datetime w_line_end = friday + 59400;
|
2026-06-08 19:43:54 +02:00
|
|
|
|
2026-06-09 19:37:24 +02:00
|
|
|
string week_suffix = TimeToString(this_monday, TIME_DATE);
|
2026-06-08 19:43:54 +02:00
|
|
|
StringReplace(week_suffix, ".", "_");
|
|
|
|
|
string w_high_line = "WeeklyAnchorHigh_" + week_suffix;
|
|
|
|
|
string w_low_line = "WeeklyAnchorLow_" + week_suffix;
|
|
|
|
|
|
2026-06-09 19:37:24 +02:00
|
|
|
if(ObjectFind(0, w_high_line) < 0)
|
2026-06-08 19:43:54 +02:00
|
|
|
ObjectCreate(0, w_high_line, OBJ_TREND, 0, w_line_start, weekly_anchor_high, w_line_end, weekly_anchor_high);
|
2026-06-09 19:37:24 +02:00
|
|
|
else{
|
2026-06-08 19:43:54 +02:00
|
|
|
ObjectSetDouble(0, w_high_line, OBJPROP_PRICE, 0, weekly_anchor_high);
|
|
|
|
|
ObjectSetDouble(0, w_high_line, OBJPROP_PRICE, 1, weekly_anchor_high);
|
|
|
|
|
ObjectSetInteger(0, w_high_line, OBJPROP_TIME, 0, w_line_start);
|
|
|
|
|
ObjectSetInteger(0, w_high_line, OBJPROP_TIME, 1, w_line_end);
|
|
|
|
|
};
|
|
|
|
|
ObjectSetInteger(0, w_high_line, OBJPROP_COLOR, clrDarkViolet);
|
2026-06-09 19:37:24 +02:00
|
|
|
ObjectSetInteger(0, w_high_line, OBJPROP_STYLE, STYLE_SOLID);
|
2026-06-08 19:43:54 +02:00
|
|
|
ObjectSetInteger(0, w_high_line, OBJPROP_RAY_RIGHT, false);
|
|
|
|
|
ObjectSetInteger(0, w_high_line, OBJPROP_WIDTH, 1);
|
|
|
|
|
|
2026-06-09 19:37:24 +02:00
|
|
|
if(ObjectFind(0, w_low_line) < 0)
|
2026-06-08 19:43:54 +02:00
|
|
|
ObjectCreate(0, w_low_line, OBJ_TREND, 0, w_line_start, weekly_anchor_low, w_line_end, weekly_anchor_low);
|
2026-06-09 19:37:24 +02:00
|
|
|
else{
|
2026-06-08 19:43:54 +02:00
|
|
|
ObjectSetDouble(0, w_low_line, OBJPROP_PRICE, 0, weekly_anchor_low);
|
|
|
|
|
ObjectSetDouble(0, w_low_line, OBJPROP_PRICE, 1, weekly_anchor_low);
|
|
|
|
|
ObjectSetInteger(0, w_low_line, OBJPROP_TIME, 0, w_line_start);
|
|
|
|
|
ObjectSetInteger(0, w_low_line, OBJPROP_TIME, 1, w_line_end);
|
|
|
|
|
};
|
|
|
|
|
ObjectSetInteger(0, w_low_line, OBJPROP_COLOR, clrDarkViolet);
|
2026-06-09 19:37:24 +02:00
|
|
|
ObjectSetInteger(0, w_low_line, OBJPROP_STYLE, STYLE_SOLID);
|
2026-06-08 19:43:54 +02:00
|
|
|
ObjectSetInteger(0, w_low_line, OBJPROP_RAY_RIGHT, false);
|
|
|
|
|
ObjectSetInteger(0, w_low_line, OBJPROP_WIDTH, 1);
|
|
|
|
|
};
|
|
|
|
|
|
2026-06-09 19:37:24 +02:00
|
|
|
// Broadcast weekly anchor to all rectangles already in the controller
|
2026-06-08 19:43:54 +02:00
|
|
|
if(weekly_anchor_high > 0.0 && weekly_anchor_low > 0.0)
|
|
|
|
|
Controller.SetWeeklyAnchorReferences(weekly_anchor_high, weekly_anchor_low);
|
|
|
|
|
};
|
|
|
|
|
|
2026-06-05 11:09:30 +02:00
|
|
|
string suffix = TimeToString(base_time, TIME_DATE);
|
|
|
|
|
StringReplace(suffix, ".", "_");
|
|
|
|
|
|
|
|
|
|
// --- Database Lookup: Fetching locked Cycle 1 Anchor Range boundaries
|
|
|
|
|
double anchor_high = 0.0;
|
|
|
|
|
double anchor_low = 0.0;
|
|
|
|
|
|
2026-06-05 11:49:35 +02:00
|
|
|
if(gl_db_handle != INVALID_HANDLE){
|
2026-06-05 11:09:30 +02:00
|
|
|
string search_prefixes[] = {"a_", "b_", "c_", "d_", "e_"};
|
2026-06-05 11:49:35 +02:00
|
|
|
for(int k = 0; k < 5; k++){
|
2026-06-05 11:09:30 +02:00
|
|
|
string target_box = search_prefixes[k] + suffix + "_box";
|
|
|
|
|
string select_query = StringFormat("SELECT HighPrice, LowPrice FROM SessionRectangles WHERE BoxID='%s';", target_box);
|
|
|
|
|
|
|
|
|
|
int request_handle = DatabasePrepare(gl_db_handle, select_query);
|
2026-06-05 11:49:35 +02:00
|
|
|
if(request_handle != INVALID_HANDLE){
|
|
|
|
|
if(DatabaseRead(request_handle)){
|
2026-06-05 11:09:30 +02:00
|
|
|
double found_high = 0.0;
|
|
|
|
|
double found_low = 0.0;
|
2026-06-05 11:49:35 +02:00
|
|
|
if(DatabaseColumnDouble(request_handle, 0, found_high) && DatabaseColumnDouble(request_handle, 1, found_low)){
|
2026-06-05 11:09:30 +02:00
|
|
|
if(found_high > anchor_high)
|
|
|
|
|
anchor_high = found_high;
|
|
|
|
|
if(anchor_low == 0.0 || (found_low < anchor_low && found_low > 0.0))
|
|
|
|
|
anchor_low = found_low;
|
2026-06-05 11:49:35 +02:00
|
|
|
};
|
|
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
DatabaseFinalize(request_handle);
|
2026-06-05 11:49:35 +02:00
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
|
|
|
|
|
// --- VISUALIZATION: Draw horizontal extensions from Cycle 1 start to 16:30
|
2026-06-05 11:49:35 +02:00
|
|
|
if(anchor_high > 0.0 && anchor_low > 0.0){
|
|
|
|
|
datetime line_start = base_time + 900; // Start of Session a_ (Cycle 1 start)
|
|
|
|
|
datetime line_end = base_time + 59400; // 16:30 in seconds from midnight (16*3600 + 30*60)
|
2026-06-05 11:09:30 +02:00
|
|
|
|
|
|
|
|
string high_line_name = "AnchorHighExt_" + suffix;
|
|
|
|
|
string low_line_name = "AnchorLowExt_" + suffix;
|
|
|
|
|
|
|
|
|
|
// Upside Anchor Extension Line
|
2026-06-05 11:49:35 +02:00
|
|
|
if(ObjectFind(0, high_line_name) < 0){
|
2026-06-05 11:09:30 +02:00
|
|
|
ObjectCreate(0, high_line_name, OBJ_TREND, 0, line_start, anchor_high, line_end, anchor_high);
|
2026-06-05 11:49:35 +02:00
|
|
|
}else{
|
2026-06-05 11:09:30 +02:00
|
|
|
ObjectSetDouble(0, high_line_name, OBJPROP_PRICE, 0, anchor_high);
|
|
|
|
|
ObjectSetDouble(0, high_line_name, OBJPROP_PRICE, 1, anchor_high);
|
|
|
|
|
ObjectSetInteger(0, high_line_name, OBJPROP_TIME, 0, line_start);
|
|
|
|
|
ObjectSetInteger(0, high_line_name, OBJPROP_TIME, 1, line_end);
|
2026-06-05 11:49:35 +02:00
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
ObjectSetInteger(0, high_line_name, OBJPROP_COLOR, clrBlack);
|
2026-06-09 19:37:24 +02:00
|
|
|
ObjectSetInteger(0, high_line_name, OBJPROP_STYLE, STYLE_DASH);
|
2026-06-05 11:09:30 +02:00
|
|
|
ObjectSetInteger(0, high_line_name, OBJPROP_RAY_RIGHT, false);
|
|
|
|
|
ObjectSetInteger(0, high_line_name, OBJPROP_WIDTH, 1);
|
|
|
|
|
|
|
|
|
|
// Downside Anchor Extension Line
|
2026-06-05 11:49:35 +02:00
|
|
|
if(ObjectFind(0, low_line_name) < 0){
|
2026-06-05 11:09:30 +02:00
|
|
|
ObjectCreate(0, low_line_name, OBJ_TREND, 0, line_start, anchor_low, line_end, anchor_low);
|
2026-06-05 11:49:35 +02:00
|
|
|
}else{
|
2026-06-05 11:09:30 +02:00
|
|
|
ObjectSetDouble(0, low_line_name, OBJPROP_PRICE, 0, anchor_low);
|
|
|
|
|
ObjectSetDouble(0, low_line_name, OBJPROP_PRICE, 1, anchor_low);
|
|
|
|
|
ObjectSetInteger(0, low_line_name, OBJPROP_TIME, 0, line_start);
|
|
|
|
|
ObjectSetInteger(0, low_line_name, OBJPROP_TIME, 1, line_end);
|
2026-06-05 11:49:35 +02:00
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
ObjectSetInteger(0, low_line_name, OBJPROP_COLOR, clrBlack);
|
2026-06-09 19:37:24 +02:00
|
|
|
ObjectSetInteger(0, low_line_name, OBJPROP_STYLE, STYLE_DASH);
|
2026-06-05 11:09:30 +02:00
|
|
|
ObjectSetInteger(0, low_line_name, OBJPROP_RAY_RIGHT, false);
|
|
|
|
|
ObjectSetInteger(0, low_line_name, OBJPROP_WIDTH, 1);
|
2026-06-05 11:49:35 +02:00
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
|
2026-06-09 20:25:41 +02:00
|
|
|
|
2026-06-05 11:09:30 +02:00
|
|
|
// Cycle 1 (Offset: 0s) -> Base Anchor Range (is_anchor = true)
|
|
|
|
|
int shift1 = 0;
|
|
|
|
|
Controller.AddRectangle("a_" + suffix, base_time + shift1 + 900, base_time + shift1 + 1800, C'0x4B,0x00,0x82', 1, PERIOD_M1, PERIOD_M5, true, 1, true);
|
|
|
|
|
Controller.AddRectangle("b_" + suffix, base_time + shift1 + 1800, base_time + shift1 + 3600, C'0xFF,0x45,0x00', 1, PERIOD_M1, PERIOD_M30, true, 1, true);
|
|
|
|
|
Controller.AddRectangle("c_" + suffix, base_time + shift1 + 3600, base_time + shift1 + 7200, C'0x1E,0x90,0xFF', 1, PERIOD_M1, PERIOD_M30, true, 1, true);
|
|
|
|
|
Controller.AddRectangle("d_" + suffix, base_time + shift1 + 7200, base_time + shift1 + 9000, C'0xFF,0x8C,0x00', 1, PERIOD_M1, PERIOD_M30, true, 1, true);
|
|
|
|
|
Controller.AddRectangle("e_" + suffix, base_time + shift1 + 9000, base_time + shift1 + 9900, C'0x8A,0x2B,0xE2', 1, PERIOD_M1, PERIOD_M5, true, 1, true);
|
|
|
|
|
|
|
|
|
|
// Cycle 2 (Offset: 9900s) -> Evaluates depth vs Cycle 1 Anchor
|
|
|
|
|
int shift2 = 9900;
|
|
|
|
|
Controller.AddRectangle("f_" + suffix, base_time + shift2 + 900, base_time + shift2 + 1800, C'0x00,0x80,0x80', 1, PERIOD_M1, PERIOD_M5, true, 2, false);
|
|
|
|
|
Controller.AddRectangle("g_" + suffix, base_time + shift2 + 1800, base_time + shift2 + 3600, C'0xD2,0x69,0x1E', 1, PERIOD_M1, PERIOD_M30, true, 2, false);
|
|
|
|
|
Controller.AddRectangle("h_" + suffix, base_time + shift2 + 3600, base_time + shift2 + 7200, C'0x00,0x00,0x8B', 1, PERIOD_M1, PERIOD_M30, true, 2, false);
|
|
|
|
|
Controller.AddRectangle("i_" + suffix, base_time + shift2 + 7200, base_time + shift2 + 9000, C'0xCD,0x85,0x3F', 1, PERIOD_M1, PERIOD_M30, true, 2, false);
|
|
|
|
|
Controller.AddRectangle("j_" + suffix, base_time + shift2 + 9000, base_time + shift2 + 9900, C'0x20,0xB2,0xAA', 1, PERIOD_M1, PERIOD_M5, true, 2, false);
|
|
|
|
|
|
|
|
|
|
// Cycle 3 (Offset: 19800s)
|
|
|
|
|
int shift3 = 19800;
|
|
|
|
|
Controller.AddRectangle("k_" + suffix, base_time + shift3 + 900, base_time + shift3 + 1800, C'0x2E,0x8B,0x57', 1, PERIOD_M1, PERIOD_M5, true, 3, false);
|
|
|
|
|
Controller.AddRectangle("l_" + suffix, base_time + shift3 + 1800, base_time + shift3 + 3600, C'0xB8,0x86,0x0B', 1, PERIOD_M1, PERIOD_M30, true, 3, false);
|
|
|
|
|
Controller.AddRectangle("m_" + suffix, base_time + shift3 + 3600, base_time + shift3 + 7200, C'0x46,0x82,0xB4', 1, PERIOD_M1, PERIOD_M30, true, 3, false);
|
|
|
|
|
Controller.AddRectangle("n_" + suffix, base_time + shift3 + 7200, base_time + shift3 + 9000, C'0xD2,0xB4,0x8C', 1, PERIOD_M1, PERIOD_M30, true, 3, false);
|
|
|
|
|
Controller.AddRectangle("o_" + suffix, base_time + shift3 + 9000, base_time + shift3 + 9900, C'0x6B,0x8E,0x23', 1, PERIOD_M1, PERIOD_M5, true, 3, false);
|
|
|
|
|
|
|
|
|
|
// Cycle 4 (Offset: 29700s)
|
|
|
|
|
int shift4 = 29700;
|
|
|
|
|
Controller.AddRectangle("p_" + suffix, base_time + shift4 + 900, base_time + shift4 + 1800, C'0x80,0x00,0x00', 1, PERIOD_M1, PERIOD_M5, true, 4, false);
|
|
|
|
|
Controller.AddRectangle("q_" + suffix, base_time + shift4 + 1800, base_time + shift4 + 3600, C'0xE9,0x96,0x7A', 1, PERIOD_M1, PERIOD_M30, true, 4, false);
|
|
|
|
|
Controller.AddRectangle("r_" + suffix, base_time + shift4 + 3600, base_time + shift4 + 7200, C'0x41,0x69,0xE1', 1, PERIOD_M1, PERIOD_M30, true, 4, false);
|
|
|
|
|
Controller.AddRectangle("s_" + suffix, base_time + shift4 + 7200, base_time + shift4 + 9000, C'0xF4,0xA4,0x60', 1, PERIOD_M1, PERIOD_M30, true, 4, false);
|
|
|
|
|
Controller.AddRectangle("t_" + suffix, base_time + shift4 + 9000, base_time + shift4 + 9900, C'0xA0,0x52,0x2D', 1, PERIOD_M1, PERIOD_M5, true, 4, false);
|
|
|
|
|
|
|
|
|
|
// Cycle 5 (Offset: 39600s)
|
|
|
|
|
int shift5 = 39600;
|
|
|
|
|
Controller.AddRectangle("u_" + suffix, base_time + shift5 + 900, base_time + shift5 + 1800, C'0x8B,0x00,0x00', 1, PERIOD_M1, PERIOD_M5, true, 5, false);
|
|
|
|
|
Controller.AddRectangle("v_" + suffix, base_time + shift5 + 1800, base_time + shift5 + 3600, C'0xC7,0x15,0x85', 1, PERIOD_M1, PERIOD_M30, true, 5, false);
|
|
|
|
|
Controller.AddRectangle("w_" + suffix, base_time + shift5 + 3600, base_time + shift5 + 7200, C'0xFF,0x63,0x47', 1, PERIOD_M1, PERIOD_M30, true, 5, false);
|
|
|
|
|
Controller.AddRectangle("x_" + suffix, base_time + shift5 + 7200, base_time + shift5 + 9000, C'0x00,0x00,0x80', 1, PERIOD_M1, PERIOD_M30, true, 5, false);
|
|
|
|
|
Controller.AddRectangle("y_" + suffix, base_time + shift5 + 9000, base_time + shift5 + 9900, C'0xFF,0x7F,0x50', 1, PERIOD_M1, PERIOD_M5, true, 5, false);
|
|
|
|
|
|
|
|
|
|
// Cycle 6 (Offset: 49500s)
|
|
|
|
|
int shift6 = 49500;
|
|
|
|
|
Controller.AddRectangle("z_" + suffix, base_time + shift6 + 900, base_time + shift6 + 1800, C'0xDB,0x70,0x93', 1, PERIOD_M1, PERIOD_M5, true, 6, false);
|
|
|
|
|
Controller.AddRectangle("a2_" + suffix, base_time + shift6 + 1800, base_time + shift6 + 3600, C'0xFF,0x14,0x93', 1, PERIOD_M1, PERIOD_M30, true, 6, false);
|
|
|
|
|
Controller.AddRectangle("b2_" + suffix, base_time + shift6 + 3600, base_time + shift6 + 7200, C'0xBA,0x55,0xD3', 1, PERIOD_M1, PERIOD_M30, true, 6, false);
|
|
|
|
|
Controller.AddRectangle("c2_" + suffix, base_time + shift6 + 7200, base_time + shift6 + 9000, C'0xBC,0x8F,0x8F', 1, PERIOD_M1, PERIOD_M30, true, 6, false);
|
|
|
|
|
Controller.AddRectangle("d2_" + suffix, base_time + shift6 + 9000, base_time + shift6 + 9900, C'0x7B,0x68,0xEE', 1, PERIOD_M1, PERIOD_M5, true, 6, false);
|
|
|
|
|
|
|
|
|
|
// Cycle 7 (Offset: 59400s)
|
|
|
|
|
int shift7 = 59400;
|
|
|
|
|
Controller.AddRectangle("e2_" + suffix, base_time + shift7 + 900, base_time + shift7 + 1800, C'0xB2,0x22,0x22', 1, PERIOD_M1, PERIOD_M5, true, 7, false);
|
|
|
|
|
Controller.AddRectangle("f2_" + suffix, base_time + shift7 + 1800, base_time + shift7 + 3600, C'0x48,0x3D,0x8B', 1, PERIOD_M1, PERIOD_M30, true, 7, false);
|
|
|
|
|
Controller.AddRectangle("g2_" + suffix, base_time + shift7 + 3600, base_time + shift7 + 7200, C'0xD8,0xBF,0xD8', 1, PERIOD_M1, PERIOD_M30, true, 7, false);
|
|
|
|
|
Controller.AddRectangle("h2_" + suffix, base_time + shift7 + 7200, base_time + shift7 + 9000, C'0x00,0xCE,0xD1', 1, PERIOD_M1, PERIOD_M30, true, 7, false);
|
|
|
|
|
Controller.AddRectangle("i2_" + suffix, base_time + shift7 + 9000, base_time + shift7 + 9900, C'0xCD,0x5C,0x5C', 1, PERIOD_M1, PERIOD_M5, true, 7, false);
|
|
|
|
|
|
|
|
|
|
// Cycle 8 (Offset: 69300s)
|
|
|
|
|
int shift8 = 69300;
|
|
|
|
|
Controller.AddRectangle("j2_" + suffix, base_time + shift8 + 900, base_time + shift8 + 1800, C'0x48,0x3D,0x8B', 1, PERIOD_M1, PERIOD_M5, true, 8, false);
|
|
|
|
|
Controller.AddRectangle("k2_" + suffix, base_time + shift8 + 1800, base_time + shift8 + 3600, C'0x70,0x80,0x90', 1, PERIOD_M1, PERIOD_M30, true, 8, false);
|
|
|
|
|
Controller.AddRectangle("l2_" + suffix, base_time + shift8 + 3600, base_time + shift8 + 7200, C'0x19,0x19,0x70', 1, PERIOD_M1, PERIOD_M30, true, 8, false);
|
|
|
|
|
Controller.AddRectangle("m2_" + suffix, base_time + shift8 + 7200, base_time + shift8 + 9000, C'0x8B,0x45,0x13', 1, PERIOD_M1, PERIOD_M30, true, 8, false);
|
|
|
|
|
Controller.AddRectangle("n2_" + suffix, base_time + shift8 + 9000, base_time + shift8 + 9900, C'0x2B,0x65,0xEC', 1, PERIOD_M1, PERIOD_M5, true, 8, false);
|
|
|
|
|
|
|
|
|
|
// Cycle 9 (Accelerated end-of-day sequence layout)
|
|
|
|
|
int shift9 = 79200;
|
|
|
|
|
Controller.AddRectangle("o2_" + suffix, base_time + shift9 + 900, base_time + shift9 + 1800, C'0x80,0x80,0x00', 1, PERIOD_M1, PERIOD_M5, true, 9, false);
|
|
|
|
|
Controller.AddRectangle("p2_" + suffix, base_time + shift9 + 1800, base_time + shift9 + 3600, C'0x48,0x00,0x7D', 1, PERIOD_M1, PERIOD_M30, true, 9, false);
|
|
|
|
|
Controller.AddRectangle("q2_" + suffix, base_time + shift9 + 3600, base_time + shift9 + 4500, C'0x3A,0x00,0x4D', 1, PERIOD_M1, PERIOD_M5, true, 9, false);
|
|
|
|
|
Controller.AddRectangle("r2_" + suffix, base_time + shift9 + 4500, base_time + shift9 + 8100, C'0x20,0x60,0x3D', 1, PERIOD_M5, PERIOD_H1, true, 9, false);
|
|
|
|
|
Controller.AddRectangle("s2_" + suffix, base_time + shift9 + 8100, base_time + shift9 + 15300, C'0x7E,0x15,0x15', 1, PERIOD_M15, PERIOD_H4, true, 9, false);
|
|
|
|
|
|
2026-06-09 19:37:24 +02:00
|
|
|
// Propagate daily anchor to all rectangles for this day
|
|
|
|
|
if(anchor_high > 0.0 && anchor_low > 0.0)
|
|
|
|
|
Controller.SetAnchorReferences(anchor_high, anchor_low);
|
|
|
|
|
|
|
|
|
|
// Propagate weekly anchor to newly added rectangles for this day
|
2026-06-08 19:43:54 +02:00
|
|
|
if(weekly_anchor_high > 0.0 && weekly_anchor_low > 0.0)
|
|
|
|
|
Controller.SetWeeklyAnchorReferences(weekly_anchor_high, weekly_anchor_low);
|
|
|
|
|
|
2026-06-05 11:09:30 +02:00
|
|
|
processed_days++;
|
2026-06-05 11:49:35 +02:00
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
|
|
|
|
|
if(Controller != NULL)
|
|
|
|
|
Controller.UpdateAll();
|
2026-06-09 20:25:41 +02:00
|
|
|
|
|
|
|
|
EventSetTimer(86400); // Daily maintenance timer
|
2026-06-05 11:09:30 +02:00
|
|
|
return(INIT_SUCCEEDED);
|
2026-06-05 11:49:35 +02:00
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
|
2026-06-05 11:49:35 +02:00
|
|
|
void OnDeinit(const int reason){
|
2026-06-09 20:25:41 +02:00
|
|
|
EventKillTimer();
|
|
|
|
|
|
2026-06-05 11:49:35 +02:00
|
|
|
if(Controller != NULL){
|
2026-06-05 11:09:30 +02:00
|
|
|
delete Controller;
|
|
|
|
|
Controller = NULL;
|
2026-06-05 11:49:35 +02:00
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
|
2026-06-05 11:49:35 +02:00
|
|
|
if(gl_db_handle != INVALID_HANDLE){
|
2026-06-05 11:09:30 +02:00
|
|
|
DatabaseClose(gl_db_handle);
|
|
|
|
|
gl_db_handle = INVALID_HANDLE;
|
2026-06-05 11:49:35 +02:00
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
|
|
|
|
|
ChartRedraw(0);
|
2026-06-05 11:49:35 +02:00
|
|
|
};
|
2026-06-05 11:09:30 +02:00
|
|
|
|
2026-06-05 11:49:35 +02:00
|
|
|
void OnTick(){
|
2026-06-08 19:43:54 +02:00
|
|
|
//if(Controller != NULL)
|
2026-06-05 11:09:30 +02:00
|
|
|
Controller.UpdateAll();
|
2026-06-05 12:57:00 +02:00
|
|
|
};
|
|
|
|
|
|
2026-06-09 20:25:41 +02:00
|
|
|
void RunDatabaseMaintenance(){
|
|
|
|
|
if(gl_db_handle == INVALID_HANDLE){
|
|
|
|
|
Print("DB Maintenance: Skipped — database handle is invalid.");
|
|
|
|
|
return;
|
|
|
|
|
};
|
|
|
|
|
|
2026-06-10 12:18:17 +02:00
|
|
|
ulong cutoff = (ulong)(TimeCurrent() - (5 * 86400));
|
2026-06-09 20:25:41 +02:00
|
|
|
ulong archived_at = (ulong)TimeCurrent();
|
|
|
|
|
|
2026-06-10 12:18:17 +02:00
|
|
|
Print(StringFormat("DB Maintenance: Starting. Cutoff = %s | Archiving records older than 5 days.",
|
2026-06-09 20:25:41 +02:00
|
|
|
TimeToString((datetime)cutoff, TIME_DATE|TIME_MINUTES)));
|
|
|
|
|
|
|
|
|
|
// --- Archive + purge SessionRectangles (age column: StartTime) ---
|
|
|
|
|
string arc_sessions = StringFormat(
|
|
|
|
|
"INSERT OR IGNORE INTO SessionRectangles_Archive (BoxID, Symbol, StartTime, EndTime, HighPrice, LowPrice, ArchivedAt) "
|
|
|
|
|
"SELECT BoxID, Symbol, StartTime, EndTime, HighPrice, LowPrice, %I64u "
|
|
|
|
|
"FROM SessionRectangles WHERE StartTime < %I64u;", archived_at, cutoff);
|
|
|
|
|
|
|
|
|
|
string del_sessions = StringFormat(
|
|
|
|
|
"DELETE FROM SessionRectangles WHERE StartTime < %I64u;", cutoff);
|
|
|
|
|
|
|
|
|
|
// --- Archive + purge BreakoutHistory (age column: Timestamp) ---
|
|
|
|
|
string arc_breakouts = StringFormat(
|
|
|
|
|
"INSERT INTO BreakoutHistory_Archive (EventID, BoxID, Symbol, Period, Type, TargetLevel, ClosePrice, PipsTravelled, Timestamp, ArchivedAt) "
|
|
|
|
|
"SELECT EventID, BoxID, Symbol, Period, Type, TargetLevel, ClosePrice, PipsTravelled, Timestamp, %I64u "
|
|
|
|
|
"FROM BreakoutHistory WHERE Timestamp < %I64u;", archived_at, cutoff);
|
|
|
|
|
|
|
|
|
|
string del_breakouts = StringFormat(
|
|
|
|
|
"DELETE FROM BreakoutHistory WHERE Timestamp < %I64u;", cutoff);
|
|
|
|
|
|
|
|
|
|
// --- Archive + purge HelixAnalytics (age column: Timestamp) ---
|
|
|
|
|
string arc_analytics = StringFormat(
|
|
|
|
|
"INSERT INTO HelixAnalytics_Archive (EventID, BoxID, CycleID, HighDevPips, LowDevPips, HelixPolarity, EdgeBias, Timestamp, ArchivedAt) "
|
|
|
|
|
"SELECT EventID, BoxID, CycleID, HighDevPips, LowDevPips, HelixPolarity, EdgeBias, Timestamp, %I64u "
|
|
|
|
|
"FROM HelixAnalytics WHERE Timestamp < %I64u;", archived_at, cutoff);
|
|
|
|
|
|
|
|
|
|
string del_analytics = StringFormat(
|
|
|
|
|
"DELETE FROM HelixAnalytics WHERE Timestamp < %I64u;", cutoff);
|
|
|
|
|
|
|
|
|
|
// Execute archive then delete for each table
|
|
|
|
|
bool ok = true;
|
|
|
|
|
|
|
|
|
|
if(!DatabaseExecute(gl_db_handle, arc_sessions)){
|
|
|
|
|
Print("DB Maintenance: SessionRectangles archive failed. Code: ", GetLastError()); ok = false;
|
|
|
|
|
}else if(!DatabaseExecute(gl_db_handle, del_sessions)){
|
|
|
|
|
Print("DB Maintenance: SessionRectangles purge failed. Code: ", GetLastError()); ok = false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if(!DatabaseExecute(gl_db_handle, arc_breakouts)){
|
|
|
|
|
Print("DB Maintenance: BreakoutHistory archive failed. Code: ", GetLastError()); ok = false;
|
|
|
|
|
}else if(!DatabaseExecute(gl_db_handle, del_breakouts)){
|
|
|
|
|
Print("DB Maintenance: BreakoutHistory purge failed. Code: ", GetLastError()); ok = false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if(!DatabaseExecute(gl_db_handle, arc_analytics)){
|
|
|
|
|
Print("DB Maintenance: HelixAnalytics archive failed. Code: ", GetLastError()); ok = false;
|
|
|
|
|
}else if(!DatabaseExecute(gl_db_handle, del_analytics)){
|
|
|
|
|
Print("DB Maintenance: HelixAnalytics purge failed. Code: ", GetLastError()); ok = false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Reclaim freed pages from all deletions
|
|
|
|
|
if(!DatabaseExecute(gl_db_handle, "VACUUM;")){
|
|
|
|
|
Print("DB Maintenance: VACUUM failed. Code: ", GetLastError()); ok = false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if(ok)
|
|
|
|
|
Print("DB Maintenance: Completed successfully. File compacted.");
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void OnTimer(){
|
|
|
|
|
RunDatabaseMaintenance();
|
|
|
|
|
};
|
|
|
|
|
|
2026-06-05 12:57:00 +02:00
|
|
|
bool ApplyCustomChartSettings(const long chart_id){
|
|
|
|
|
// Clear any previous error codes
|
|
|
|
|
ResetLastError();
|
|
|
|
|
|
|
|
|
|
// Track overall success flag
|
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
|
|
//--- 1. Set Core Layout Properties
|
|
|
|
|
success &= ChartSetInteger(chart_id, CHART_MODE, CHART_CANDLES);
|
|
|
|
|
success &= ChartSetInteger(chart_id, CHART_AUTOSCROLL, true);
|
|
|
|
|
success &= ChartSetInteger(chart_id, CHART_SHIFT, true);
|
|
|
|
|
success &= ChartSetInteger(chart_id, CHART_FOREGROUND, false);
|
|
|
|
|
|
|
|
|
|
//--- 2. Manage UI Element Visibility
|
|
|
|
|
success &= ChartSetInteger(chart_id, CHART_SHOW_GRID, false);
|
|
|
|
|
success &= ChartSetInteger(chart_id, CHART_SHOW_ONE_CLICK, true);
|
|
|
|
|
success &= ChartSetInteger(chart_id, CHART_SHOW_TRADE_LEVELS, true);
|
|
|
|
|
success &= ChartSetInteger(chart_id, CHART_SHOW_OHLC, true);
|
|
|
|
|
success &= ChartSetInteger(chart_id, CHART_SHOW_PERIOD_SEP, true);
|
|
|
|
|
|
|
|
|
|
//--- 3. Color Theme Application
|
|
|
|
|
success &= ChartSetInteger(chart_id, CHART_COLOR_BACKGROUND, clrIvory);
|
|
|
|
|
success &= ChartSetInteger(chart_id, CHART_COLOR_FOREGROUND, clrBlack);
|
|
|
|
|
|
|
|
|
|
// Bullish candles
|
|
|
|
|
success &= ChartSetInteger(chart_id, CHART_COLOR_CHART_UP, clrGreen);
|
|
|
|
|
success &= ChartSetInteger(chart_id, CHART_COLOR_CANDLE_BULL, clrGreen);
|
|
|
|
|
|
|
|
|
|
// Bearish candles
|
|
|
|
|
success &= ChartSetInteger(chart_id, CHART_COLOR_CHART_DOWN, clrRed);
|
|
|
|
|
success &= ChartSetInteger(chart_id, CHART_COLOR_CANDLE_BEAR, clrRed);
|
|
|
|
|
|
|
|
|
|
// NEW: Enable Bid and Ask horizontal lines
|
|
|
|
|
success &= ChartSetInteger(chart_id, CHART_SHOW_BID_LINE, true);
|
|
|
|
|
success &= ChartSetInteger(chart_id, CHART_SHOW_ASK_LINE, true);
|
|
|
|
|
success &= ChartSetInteger(chart_id, CHART_COLOR_BID, clrGray);
|
|
|
|
|
success &= ChartSetInteger(chart_id, CHART_COLOR_ASK, clrOrange);
|
2026-06-05 13:14:07 +02:00
|
|
|
|
|
|
|
|
//--- 4. Zoom Settings
|
2026-06-05 18:34:26 +02:00
|
|
|
if(ChartPeriod() == PERIOD_M1){
|
|
|
|
|
success &= ChartSetInteger(chart_id, CHART_SCALE, 0);
|
|
|
|
|
}else if(ChartPeriod() == PERIOD_M5){
|
|
|
|
|
success &= ChartSetInteger(chart_id, CHART_SCALE, 1);
|
|
|
|
|
}else if(ChartPeriod() == PERIOD_M15){
|
|
|
|
|
success &= ChartSetInteger(chart_id, CHART_SCALE, 2);
|
|
|
|
|
}else if(ChartPeriod() == PERIOD_M30){
|
|
|
|
|
success &= ChartSetInteger(chart_id, CHART_SCALE, 3);
|
|
|
|
|
}else if(ChartPeriod() == PERIOD_H1){
|
|
|
|
|
success &= ChartSetInteger(chart_id, CHART_SCALE, 4);
|
|
|
|
|
}else if(ChartPeriod() >= PERIOD_H4){
|
|
|
|
|
success &= ChartSetInteger(chart_id, CHART_SCALE, 3);
|
|
|
|
|
}else{
|
|
|
|
|
success &= ChartSetInteger(chart_id, CHART_SCALE, 5);
|
|
|
|
|
};
|
2026-06-05 12:57:00 +02:00
|
|
|
|
|
|
|
|
//--- 5. Error Reporting and Rendering
|
|
|
|
|
if(!success){
|
|
|
|
|
PrintFormat("Error configuring chart. Error Code: %d", GetLastError());
|
|
|
|
|
return(false);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Force terminal engine to instantly redraw the visual layout
|
|
|
|
|
ChartRedraw(chart_id);
|
|
|
|
|
return(true);
|
|
|
|
|
};
|