mql5/Experts/Omega.mq5
MatimuNgoveni 49aa01a72c
2026-06-10 12:18:17 +02:00

922 lines
No EOL
43 KiB
MQL5

//+------------------------------------------------------------------+
//| Omega |
//| Copyright 2020, Sifu PriceAction |
//| https://www.mql5.com/en/users/matimungoveni |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, Matimu Ngoveni"
#property version "1.00"
#include <Arrays\ArrayObj.mqh>
//--- Global Configuration Parameters
input int InpHistoryDays = 72; // Total history days to render
input bool stay_on_M1 = false; // Stay on M1 timeframe
bool InpFillColor = true;
bool InpSendMobileAlerts = false; // Send Push Notifications to Mobile App?
//--- Global Database Handle Context
int gl_db_handle = INVALID_HANDLE;
//--- Helix Structural Analysis Data Model
struct CDeviationArc{
double high_deviation_pips;
double low_deviation_pips;
double mean_deviation;
int helix_polarity;
};
//+------------------------------------------------------------------+
//| sImPlY cOdE |
//+------------------------------------------------------------------+
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;
double m_weekly_anchor_high;
double m_weekly_anchor_low;
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);
void EvaluateWeeklyHelixEdge(double cycle_high, double cycle_low, double w_anchor_high, double w_anchor_low);
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; }
void SetWeeklyAnchorReferences(double w_high, double w_low) { m_weekly_anchor_high = w_high; m_weekly_anchor_low = w_low; }
};
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;
m_is_anchor_session = is_anchor;
m_anchor_high_ref = 0.0;
m_anchor_low_ref = 0.0;
m_weekly_anchor_high = 0.0;
m_weekly_anchor_low = 0.0;
};
CRectangleInstance::~CRectangleInstance(){
if(ObjectFind(0, m_rect_name) >= 0)
ObjectDelete(0, m_rect_name);
};
void CRectangleInstance::ProcessAnimation(void){
if(m_is_frozen && m_is_saved_to_db){
CheckCandleCloseBreakout();
return;
};
datetime current_time = TimeCurrent();
datetime target_end_time = current_time;
if(current_time > m_end_time){
target_end_time = m_end_time;
m_is_frozen = true;
};
if(current_time >= m_start_time){
double highest_price = 0.0;
double lowest_price = 0.0;
if(!GetPriceRange(target_end_time, highest_price, lowest_price)){
m_is_frozen = false;
return;
};
if(ObjectFind(0, m_rect_name) < 0)
CreateDrawing(highest_price, lowest_price, target_end_time);
else
UpdateDrawing(highest_price, lowest_price, target_end_time);
if(!m_is_frozen){
SaveToSQLite(highest_price, lowest_price);
}else if(m_is_frozen && !m_is_saved_to_db){
SaveToSQLite(highest_price, lowest_price);
m_final_high = highest_price;
m_final_low = lowest_price;
m_is_saved_to_db = true;
// Trigger mathematical arc deviation modeling if item is outside anchor range
if(!m_is_anchor_session){
EvaluateHelixEdge(m_final_high, m_final_low);
EvaluateWeeklyHelixEdge(m_final_high, m_final_low, m_weekly_anchor_high, m_weekly_anchor_low);
};
};
};
};
bool CRectangleInstance::GetPriceRange(datetime calculating_end_time, double &max_price, double &min_price){
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;
for(int i = 1; i < copied; i++){
if(rates[i].high > max_price)
max_price = rates[i].high;
if(rates[i].low < min_price)
min_price = rates[i].low;
};
return(true);
};
void CRectangleInstance::CreateDrawing(double high, double low, datetime end_time){
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));
};
void CRectangleInstance::UpdateDrawing(double high, double low, datetime end_time){
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);
}
void CRectangleInstance::SaveToSQLite(double high, double low){
if(gl_db_handle == INVALID_HANDLE)
return;
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);
if(!DatabaseExecute(gl_db_handle, query)){
Print("SQLite Error: Live stream write failed. Code: ", GetLastError());
};
};
void CRectangleInstance::CheckCandleCloseBreakout(){
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;
if(rates[0].close > m_final_high){
triggered = true;
type_text = "HIGH";
broken_level = m_final_high;
pips_moved = (rates[0].close - m_final_high) / pip_multiplier;
}else if(rates[0].close < m_final_low){
triggered = true;
type_text = "LOW";
broken_level = m_final_low;
pips_moved = (m_final_low - rates[0].close) / pip_multiplier;
};
if(triggered){
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);
if(InpSendMobileAlerts){
if(!SendNotification(alert_msg))
Print("Notification Transmission Failure. Code: ", GetLastError());
};
LogBreakoutToDatabase(type_text, broken_level, rates[0].close, pips_moved);
};
};
void CRectangleInstance::LogBreakoutToDatabase(string type, double target_level, double close_price, double pips_moved){
if(gl_db_handle == INVALID_HANDLE)
return;
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());
if(!DatabaseExecute(gl_db_handle, query)){
Print("SQLite Error: Breakout Event Logging insertion failed. Code: ", GetLastError());
};
};
void CRectangleInstance::EvaluateHelixEdge(double cycle_high, double cycle_low){
// Skip validation if this is the anchor session itself or if anchor ranges are empty
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;
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;
// Helix Weave Identification Logic
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));
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());
};
};
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)
arc.helix_polarity = -1;
else
arc.helix_polarity = 1;
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());
};
};
long CRectangleInstance::CalculateVisibilityFlags(ENUM_TIMEFRAMES min_tf, ENUM_TIMEFRAMES max_tf){
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,
PERIOD_H4, PERIOD_H6, PERIOD_H8, PERIOD_H12, PERIOD_D1, PERIOD_W1, PERIOD_MN1};
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,
OBJ_PERIOD_H4, OBJ_PERIOD_H6, OBJ_PERIOD_H8, OBJ_PERIOD_H12, OBJ_PERIOD_D1, OBJ_PERIOD_W1, OBJ_PERIOD_MN1};
long combined_flags = OBJ_NO_PERIODS;
for(int i = 0; i < ArraySize(tfs); i++){
if(tfs[i] >= min_tf && tfs[i] <= max_tf)
combined_flags |= flags[i];
};
return(combined_flags);
};
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);
void SetAnchorReferences(double a_high, double a_low);
void SetWeeklyAnchorReferences(double w_high, double w_low);
void UpdateAll();
};
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){
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);
};
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);
};
};
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);
};
};
void CAnimationController::UpdateAll(void){
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.ProcessAnimation();
};
};
ChartRedraw(0);
};
//+------------------------------------------------------------------+
//| Global System Context Instantiation |
//+------------------------------------------------------------------+
CAnimationController *Controller = NULL;
int OnInit(){
// Use 0 for the current active chart window
long activeChartId = 0;
if(stay_on_M1){
if(!ChartSetSymbolPeriod(activeChartId, NULL, PERIOD_M1)){
PrintFormat("Warning: Failed to switch timeframe to M1. Error: %d", GetLastError());
};
};
// Execute configuration and verify success
if(ApplyCustomChartSettings(activeChartId)){
Print("Success: Chart visual properties updated.");
}else{
Print("Warning: Some chart properties failed to update.");
};
gl_db_handle = DatabaseOpen("SessionHistory.sqlite", DATABASE_OPEN_READWRITE | DATABASE_OPEN_CREATE);
if(gl_db_handle == INVALID_HANDLE){
Print("SQLite Connection Error: Core Context failed to open. Error: ", GetLastError());
return(INIT_FAILED);
};
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"
");";
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"
");";
if(!DatabaseExecute(gl_db_handle, create_table_query) || !DatabaseExecute(gl_db_handle, create_history_query) ||
!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)){
Print("SQLite Initialization Aborted: Structural schema verification failed. Error: ", GetLastError());
DatabaseClose(gl_db_handle);
return(INIT_FAILED);
};
Controller = new CAnimationController();
datetime today = TimeCurrent();
datetime midnight = today - (today % 86400);
int processed_days = 0;
int check_offset = 0;
// --- Weekly tracking state ---
datetime last_week_monday = 0;
double weekly_anchor_high = 0.0;
double weekly_anchor_low = 0.0;
string all_day_prefixes[] = {
"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_"
};
while(processed_days <= InpHistoryDays){
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;
// --- Compute Monday of this day's ISO week ---
int days_since_monday = structure_date.day_of_week - 1;
datetime this_monday = base_time - (days_since_monday * 86400);
// --- On new week: resolve weekly anchor from Mon+Tue DB records ---
if(this_monday != last_week_monday){
last_week_monday = this_monday;
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);
};
};
};
};
// --- Draw weekly anchor trendlines: Mon 00:15 -> Fri 16:30 ---
if(weekly_anchor_high > 0.0 && weekly_anchor_low > 0.0){
datetime friday = this_monday + (4 * 86400);
datetime w_line_start = this_monday + 900;
datetime w_line_end = friday + 59400;
string week_suffix = TimeToString(this_monday, TIME_DATE);
StringReplace(week_suffix, ".", "_");
string w_high_line = "WeeklyAnchorHigh_" + week_suffix;
string w_low_line = "WeeklyAnchorLow_" + week_suffix;
if(ObjectFind(0, w_high_line) < 0)
ObjectCreate(0, w_high_line, OBJ_TREND, 0, w_line_start, weekly_anchor_high, w_line_end, weekly_anchor_high);
else{
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);
ObjectSetInteger(0, w_high_line, OBJPROP_STYLE, STYLE_SOLID);
ObjectSetInteger(0, w_high_line, OBJPROP_RAY_RIGHT, false);
ObjectSetInteger(0, w_high_line, OBJPROP_WIDTH, 1);
if(ObjectFind(0, w_low_line) < 0)
ObjectCreate(0, w_low_line, OBJ_TREND, 0, w_line_start, weekly_anchor_low, w_line_end, weekly_anchor_low);
else{
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);
ObjectSetInteger(0, w_low_line, OBJPROP_STYLE, STYLE_SOLID);
ObjectSetInteger(0, w_low_line, OBJPROP_RAY_RIGHT, false);
ObjectSetInteger(0, w_low_line, OBJPROP_WIDTH, 1);
};
// Broadcast weekly anchor to all rectangles already in the controller
if(weekly_anchor_high > 0.0 && weekly_anchor_low > 0.0)
Controller.SetWeeklyAnchorReferences(weekly_anchor_high, weekly_anchor_low);
};
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;
if(gl_db_handle != INVALID_HANDLE){
string search_prefixes[] = {"a_", "b_", "c_", "d_", "e_"};
for(int k = 0; k < 5; k++){
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);
if(request_handle != INVALID_HANDLE){
if(DatabaseRead(request_handle)){
double found_high = 0.0;
double found_low = 0.0;
if(DatabaseColumnDouble(request_handle, 0, found_high) && DatabaseColumnDouble(request_handle, 1, found_low)){
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;
};
};
DatabaseFinalize(request_handle);
};
};
};
// --- VISUALIZATION: Draw horizontal extensions from Cycle 1 start to 16:30
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)
string high_line_name = "AnchorHighExt_" + suffix;
string low_line_name = "AnchorLowExt_" + suffix;
// Upside Anchor Extension Line
if(ObjectFind(0, high_line_name) < 0){
ObjectCreate(0, high_line_name, OBJ_TREND, 0, line_start, anchor_high, line_end, anchor_high);
}else{
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);
};
ObjectSetInteger(0, high_line_name, OBJPROP_COLOR, clrBlack);
ObjectSetInteger(0, high_line_name, OBJPROP_STYLE, STYLE_DASH);
ObjectSetInteger(0, high_line_name, OBJPROP_RAY_RIGHT, false);
ObjectSetInteger(0, high_line_name, OBJPROP_WIDTH, 1);
// Downside Anchor Extension Line
if(ObjectFind(0, low_line_name) < 0){
ObjectCreate(0, low_line_name, OBJ_TREND, 0, line_start, anchor_low, line_end, anchor_low);
}else{
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);
};
ObjectSetInteger(0, low_line_name, OBJPROP_COLOR, clrBlack);
ObjectSetInteger(0, low_line_name, OBJPROP_STYLE, STYLE_DASH);
ObjectSetInteger(0, low_line_name, OBJPROP_RAY_RIGHT, false);
ObjectSetInteger(0, low_line_name, OBJPROP_WIDTH, 1);
};
// 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);
// 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
if(weekly_anchor_high > 0.0 && weekly_anchor_low > 0.0)
Controller.SetWeeklyAnchorReferences(weekly_anchor_high, weekly_anchor_low);
processed_days++;
};
if(Controller != NULL)
Controller.UpdateAll();
EventSetTimer(86400); // Daily maintenance timer
return(INIT_SUCCEEDED);
};
void OnDeinit(const int reason){
EventKillTimer();
if(Controller != NULL){
delete Controller;
Controller = NULL;
};
if(gl_db_handle != INVALID_HANDLE){
DatabaseClose(gl_db_handle);
gl_db_handle = INVALID_HANDLE;
};
ChartRedraw(0);
};
void OnTick(){
//if(Controller != NULL)
Controller.UpdateAll();
};
void RunDatabaseMaintenance(){
if(gl_db_handle == INVALID_HANDLE){
Print("DB Maintenance: Skipped — database handle is invalid.");
return;
};
ulong cutoff = (ulong)(TimeCurrent() - (5 * 86400));
ulong archived_at = (ulong)TimeCurrent();
Print(StringFormat("DB Maintenance: Starting. Cutoff = %s | Archiving records older than 5 days.",
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();
};
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);
//--- 4. Zoom Settings
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);
};
//--- 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);
};