MCVA
Download scriptThe Multichart Visual Analyser is a specialized tool designed for traders who need to synchronize visual data across multiple currency pairs or timeframes simultaneously. Its primary purpose is to allow you to align specific points in time across different charts so that you can perform a cohesive multi-asset analysis.
Core Functionality
The script creates three interconnected visual elements on your trading chart:
- Two Vertical Lines: These act as anchor points.
- One Regression Line: This connects the two vertical lines to provide a visual trend between them.
How it Works
The logic relies on a "synchronized movement" system. Instead of forcing you to manually place three separate items on every single window, the script links them together:
- Interconnected Movement: If you click and drag any one of the three objects (either of the vertical lines or the regression line) on a single chart, the script automatically calculates the new positions for the other two.
- Multi-Chart Synchronization: This is the tool's most powerful feature. If you have this script running on multiple charts (e.g., EURUSD, GBPUSD, and Gold), moving an object on one chart will instantly move it to the exact same relative time on every other chart where the script is active.
- Automated Positioning: The script handles all the heavy lifting of calculating coordinates. When you move a vertical line, it updates the start or end point of the regression line automatically, ensuring that the visual geometry remains consistent across your entire workspace.
Practical Use Case
This tool is ideal for "Contextual Analysis." For example, if you want to see how three different assets reacted during a specific news event or a specific price move:
- You can place the two vertical lines on the start and end times of that event on one chart.
- The script will instantly mirror those exact same timestamps onto all your other open charts.
- This allows you to see the "big picture" of how various markets moved in tandem over that specific period without having to manually hunt for the correct times on every window.
Technical Behavior Summary
- Persistence: The script uses global variables to remember where the lines are placed, ensuring they stay put as you navigate your platform.
- Efficiency: It includes a "smart pause" logic, which ensures the script runs smoothly and doesn't put unnecessary strain on your computer's performance while updating the visuals.
- Cleanup: When the script is removed from the charts, it is designed to clean up after itself by deleting the objects it created, leaving your workspace tidy.
//+------------------------------------------------------------------+
//| Multichart Visual Analyser.mq4 |
//| Strator |
//| k-v-p@yandex.ru |
//+------------------------------------------------------------------+
//|Ñêðèïò ïðåäíàçíà÷åí äëÿ âèçóàëüíîãî àíàëèçà äâèæåíèÿ íåñêîëüêèõ |
//|âàëþòíûõ ïàð íà ïðîèçâîëüíîì âðåìåííîì èíòåðâàëå |
//+------------------------------------------------------------------+
//Ñêðèïò ñîçäàåò íà ÷àðòå òðè "ñâÿçàííûõ" ãðàôè÷åñêèõ îáúåêòà: äâå âåðòèêàëüíûå ëèíèè
//è ëèíåéíóþ ðåãðåññèþ.
//Ïðè ïåðåìåùåíèè ïîëüçîâàòåëåì êàêîãî-ëèáî èç òðåõ îáúåêòîâ
//àâòîìàòè÷åñêè âûïîëíÿåòñÿ ïîçèöèîíèðîâàíèå íà ÷àðòå "ñâÿçàííûõ" îáúåêòîâ.
//Ïðè çàïóñêå ñêðèïòà íà íåñêîëüêèõ ÷àðòàõ, ïåðåìåùàòü îáúåêòû ìîæíî íà ëþáîì èç íèõ,
//ïðè ýòîì ïîçèöèîíèðîâàíèå "ñâÿçàííûõ" îáúåêòîâ âûïîëíÿåòñÿ íà âñåõ ÷àðòàõ.
#property copyright "Strator"
#property link "k-v-p@yandex.ru"
#define id "MCVA Script"
#define vline1_name "MCVA vl1_time"
#define vline2_name "MCVA vl2_time"
#define linreg_name "MCVA lr"
//Ïðåäûäóøåå ñîñòîÿíèå ãëîáàëüíûõ ïåðåìåííûõ
datetime glvar_prv_time1;
datetime glvar_prv_time2;
//Òåêóùåå ñîñòîÿíèå ãëîáàëüíûõ ïåðåìåííûõ
datetime glvar_cur_time1;
datetime glvar_cur_time2;
//Ïðåäûäóùèå ïàðàìåòðû ãðàôè÷åñêèõ îáúåêòîâ
datetime vline_prv_time1; //Ïðåäûäóùåå ïîëîæåíèå Ïåðâîé âåðòèêàëüíîé ëèíèè
datetime vline_prv_time2; //Ïðåäûäóùåå ïîëîæåíèå Âòîðîé âåðòèêàëüíîé ëèíèè
datetime linreg_prv_time1; //Ïðåäûäóùåå ïîëîæåíèå Ëåâîé êîîðäèíàòû ëèíåéíîé ðåãðåññèè
datetime linreg_prv_time2; //Ïðåäûäóùåå ïîëîæåíèå Ïðàâîé êîîðäèíàòû ëèíåéíîé ðåãðåññèè
//Òåêóùèå ïàðàìåòðû ãðàôè÷åñêèõ îáúåêòîâ
datetime vline_cur_time1;
datetime vline_cur_time2;
datetime linreg_cur_time1;
datetime linreg_cur_time2;
//Ôëàã äëÿ ïåðåðèñîâêè ÷àðòà
bool redraw=false;
//+------------------------------------------------------------------+
//| Script initialization function |
//+------------------------------------------------------------------+
int init()
{
//Óâåëè÷èì ñ÷åò÷èê êîëè÷åñòâà çàïóøåííûõ ñêðèïòîâ
int value=GlobalVariableGet(id);
GlobalVariableSet(id, value+1);
return(0);
}
//+------------------------------------------------------------------+
//| Script deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//Óìåíüøèì ñ÷åò÷èê êîëè÷åñòâà çàïóøåííûõ ñêðèïòîâ
//Åñëè óäàëÿåòñÿ åäèíñòâåííûé ýêçåìïëÿð ñêðèïòà, òî óäàëèì ãëîáàëüíûå ïåðåìåííûå
int value=GlobalVariableGet(id);
if (value>1) GlobalVariableSet(id, value-1);
else
{
GlobalVariableDel(id);
GlobalVariableDel(vline1_name);
GlobalVariableDel(vline2_name);
}
//óäàëèì ãðàôè÷åñêèå îáúåêòû
ObjectDelete(vline1_name);
ObjectDelete(vline2_name);
ObjectDelete(linreg_name);
RedrawChart();
return(0);
}
//+------------------------------------------------------------------+
//| script program start function |
//+------------------------------------------------------------------+
int start()
{
while (!IsStopped())
{
//Åñëè ãëîáàëüíàÿ ïåðåìåííàÿ <id> áûëà óäàëåíà, çàâåðøèòü ðàáîòó ñêðèïòà
if (!GlobalVariableCheck(id)) break;
//Îáíîâèòü ïðåäîïðåäåëåííûå ïåðåìåííûå
RefreshRates();
//ñáðîñèòü ôëàã ïåðåðèñîâêè ÷àðòà
redraw=false;
//âûïîëíèòü ïðîãðàììó
main();
//ïåðåðèñîâàòü ÷àðò, åñëè ýòî íåîáõîäèìî
if (redraw) RedrawChart();
//çàäåðæêà âûïîëíåíèÿ ñêðèïòà
Pause();
}
return(0);
}
void main()
{
//Ïðîâåðêà íà íàëè÷èå è ñîçäàíèå íåîáõîäèìûõ ãëîáàëüíûõ ïåðåìåííûõ
GlobalVariablesCheckPresent();
//Ïðîâåðêà íà íàëè÷èå è ñîçäàíèå íåîáõîäèìûõ ãðàôè÷åñêèõ îáúåêòîâ
ObjectsCheckPresent();
//Ïðîâåðêà íà èçìåíåíèå ãëîáàëüíûõ ïåðåìåííûõ
GlobalVariablesCheckModify();
//Ïðîâåðêà íà èçìåíåíèå ïîëîæåíèÿ ãðàôè÷åñêèõ îáúåêòîâ íà ÷àðòå
ObjectsCheckModify();
}
void ObjectsCheckModify()
{
vline_cur_time1=ObjectGet(vline1_name, OBJPROP_TIME1);
vline_cur_time2=ObjectGet(vline2_name, OBJPROP_TIME1);
linreg_cur_time1=ObjectGet(linreg_name, OBJPROP_TIME1);
linreg_cur_time2=ObjectGet(linreg_name, OBJPROP_TIME2);
if (vline_cur_time1!=vline_prv_time1) GlobalVariableSet(vline1_name, vline_cur_time1);
if (vline_cur_time2!=vline_prv_time2) GlobalVariableSet(vline2_name, vline_cur_time2);
if (linreg_cur_time1!=linreg_prv_time1) GlobalVariableSet(vline1_name, linreg_cur_time1);
if (linreg_cur_time2!=linreg_prv_time2) GlobalVariableSet(vline2_name, linreg_cur_time2);
GlobalVariablesCheckModify();
}
void GlobalVariablesCheckModify()
{
glvar_cur_time1=GlobalVariableGet(vline1_name);
glvar_cur_time2=GlobalVariableGet(vline2_name);
if (glvar_cur_time1!=glvar_prv_time1 || glvar_cur_time2!=glvar_prv_time2)
{
ObjectSet(vline1_name, OBJPROP_TIME1, glvar_cur_time1);
ObjectSet(vline2_name, OBJPROP_TIME1, glvar_cur_time2);
ObjectSet(linreg_name, OBJPROP_TIME1, MathMin(glvar_cur_time1, glvar_cur_time2));
ObjectSet(linreg_name, OBJPROP_TIME2, MathMax(glvar_cur_time1, glvar_cur_time2));
glvar_prv_time1=glvar_cur_time1;
glvar_prv_time2=glvar_cur_time2;
vline_prv_time1=ObjectGet(vline1_name, OBJPROP_TIME1);
vline_prv_time2=ObjectGet(vline2_name, OBJPROP_TIME1);
linreg_prv_time1=ObjectGet(linreg_name, OBJPROP_TIME1);
linreg_prv_time2=ObjectGet(linreg_name, OBJPROP_TIME2);
redraw=true;
}
}
void GlobalVariablesCheckPresent()
{
if (!GlobalVariableCheck(vline1_name))
{
GlobalVariableSet(vline1_name, Time[0]);
glvar_prv_time1=GlobalVariableGet(vline1_name);
}
if (!GlobalVariableCheck(vline2_name))
{
GlobalVariableSet(vline2_name, Time[100]);
glvar_prv_time2=GlobalVariableGet(vline2_name);
}
}
void ObjectsCheckPresent()
{
glvar_cur_time1=GlobalVariableGet(vline1_name);
glvar_cur_time2=GlobalVariableGet(vline2_name);
//åñëè îáúåêò ñ èìåíåì <vline1_name> (ïåðâàÿ âåðòèêàëüíàÿ ëèíèÿ) íå íàéäåí, ñîçäàòü åãî
if (ObjectFind(vline1_name)<0)
{
ObjectCreate(vline1_name, OBJ_VLINE, 0, glvar_cur_time1, 0);
ObjectSet(vline1_name, OBJPROP_STYLE, STYLE_DASH);
ObjectSet(vline1_name, OBJPROP_COLOR, Red);
vline_prv_time1=glvar_cur_time1;
redraw=true;
}
//åñëè îáúåêò ñ èìåíåì <vline2_name> (âòîðàÿ âåðòèêàëüíàÿ ëèíèÿ) íå íàéäåí, ñîçäàòü åãî
if (ObjectFind(vline2_name)<0)
{
ObjectCreate(vline2_name, OBJ_VLINE, 0, glvar_cur_time2, 0);
ObjectSet(vline2_name, OBJPROP_STYLE, STYLE_DASH);
ObjectSet(vline2_name, OBJPROP_COLOR, Red);
vline_prv_time2=glvar_cur_time2;
redraw=true;
}
//åñëè îáúåêò ñ èìåíåì <linreg_name> (ëèíåéíàÿ ðåãðåññèÿ) íå íàéäåí, ñîçäàòü åãî
if (ObjectFind(linreg_name)<0)
{
datetime time1=MathMin(glvar_cur_time1, glvar_cur_time2);
datetime time2=MathMax(glvar_cur_time1, glvar_cur_time2);
ObjectCreate(linreg_name, OBJ_REGRESSION, 0, time1, 0, time2, 0);
ObjectSet(linreg_name, OBJPROP_STYLE, STYLE_DASH);
ObjectSet(linreg_name, OBJPROP_COLOR, Red);
linreg_prv_time1=time1;
linreg_prv_time2=time2;
redraw=true;
}
}
void Pause()
{
static datetime lastmove;
if (redraw) lastmove=TimeLocal();
if (TimeLocal()-lastmove>5) Sleep(1000);
else Sleep(10);
}
void RedrawChart()
{
WindowRedraw();
}
Comments