This script is designed to create a multi-currency visual comparison tool on a single trading chart. It allows users to view and compare the price actions of two different financial instruments (for example, EURUSD and USDCHF) side-by-side within a dedicated window.
Core Functionality
Dual-Asset Visualization The primary purpose of this tool is to display two separate currency symbols at once. Instead of looking at two different charts, the script draws the "candles" (price movements) of both assets into one view. It allows you to see how two different markets are behaving relative to each other simultaneously.
Customizable Timeframes The script is flexible, allowing you to define specific timeframes for each asset independently. You can monitor one currency on a 15-minute chart while viewing another on a 1-hour chart, and the tool will adjust the data accordingly.
Dynamic Scaling Because different currencies have different price values (e.g., one might trade at 1.10 while another trades at 100.00), the script includes a normalization logic. It automatically calculates the high and low points of the price action to "shrink" or "stretch" the visual candles into a consistent scale. This ensures that both assets fit perfectly within the viewing window without one appearing flat or excessively large compared to the other.
Visual Layout and Design
- Side-by-Side Display: The script splits the display area, placing the first currency on the left and the second currency on the right.
- Dynamic Line Widths: The thickness of the candles automatically adjusts based on your screen size (the number of bars visible on your monitor). This ensures the visual remains clear whether you are looking at a large monitor or a smaller screen.
- Color Coding: The script uses color logic to distinguish price movement; it differentiates between upward and downward movements by applying specific colors (Red for one direction, Black for the other) to both the "body" and the "wick" of the candles.
- Reference Markers: It draws horizontal dotted lines and a central vertical divider to help maintain a clean visual organization between the two data sets.
How it Works Internally
When the chart updates, the script performs the following routine:
- Clears Old Data: It removes previous drawings to ensure the screen doesn't become cluttered.
- Calculates Scale: It scans the price history for both assets to determine the maximum and minimum boundaries.
- Draws Candles: It renders the price "bodies" and "shadows" for both assets based on those calculated scales.
- Labels: It places text labels at the corners of the screen so you can easily identify which side represents which currency and timeframe.
//+------------------------------------------------------------------+
//| 2Graphs.mq4 |
//| Copyright © 2009, Áóãàåâ Äàíèèë Âëàäèìèðîâè÷ |
//| e-mail: buga1922@mail.ru |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2009, Áóãàåâ Äàíèèë Âëàäèìèðîâè÷"
#property link "mailto:buga1922@mail.ru"
#property indicator_separate_window
#property indicator_minimum -0.1
#property indicator_maximum 10.1
extern string symbol1="EURUSD";
extern string symbol2="USDCHF";
extern string s_period1="0";
extern string s_period2="0";
extern bool din_shirina=true;
int period1, period2;
double max_high1,max_high2,
min_low1=10000,min_low2=10000;
int j;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int PROVERKA(string s_period)
{
if ( ( s_period == "0" ) || (s_period == "" ) )
{
return(Period());
}
else
{
if ( ( s_period == "M1" ) || (s_period == "m1" ) )
{
return(1);
}
else
{
if ( ( s_period == "M5" ) || (s_period == "m5" ) )
{
return(5);
}
else
{
if ( ( s_period == "M15" ) || (s_period == "m15" ) )
{
return(15);
}
else
{
if ( ( s_period == "M30" ) || (s_period == "m30" ) )
{
return(30);
}
else
{
if ( ( s_period == "H1" ) || (s_period == "h1" ) )
{
return(60);
}
else
{
if ( ( s_period == "H4" ) || (s_period == "h4" ) )
{
return(240);
}
else
{
if ( ( s_period == "D1" ) || (s_period == "d1" ) )
{
return(1440);
}
else
{
if ( ( s_period == "W1" ) || (s_period == "w1" ) )
{
return(10080);
}
else
{
if ( ( s_period == "MN" ) || (s_period == "mn" ) || (s_period == "Mn" ) || (s_period == "mN" ) )
{
return(43200);
}
else
{
return(-1);
}
}
}
}
}
}
}
}
}
}
}
double MASHTAB1(string symbol, int period, int lag)
{
if ( max_high1 < iHigh(symbol,period,lag) ) max_high1 = iHigh(symbol,period,lag);
if ( min_low1 > iLow(symbol,period,lag) ) min_low1 = iLow(symbol,period,lag);
return(10/(max_high1-min_low1));
}
double MASHTAB2(string symbol, int period, int lag)
{
if ( max_high2 < iHigh(symbol,period,lag) ) max_high2 = iHigh(symbol,period,lag);
if ( min_low2 > iLow(symbol,period,lag) ) min_low2 = iLow(symbol,period,lag);
return(10/(max_high2-min_low2));
}
void UROVNI()
{
int i;
for ( i=0; i<=10; i++)
{
ObjectCreate ( "uroven"+i, OBJ_HLINE, 1, 1, i );
ObjectSet ( "uroven"+i, OBJPROP_COLOR, Silver );
ObjectSet ( "uroven"+i, OBJPROP_STYLE, STYLE_DOT );
}
ObjectCreate ("razdel", OBJ_VLINE, 1, Time[WindowFirstVisibleBar( )-WindowBarsPerChart() /2] ,0);
ObjectCreate ("valuta1", OBJ_LABEL, 1, 0, 0);
ObjectSetText("valuta1",symbol1+"_"+s_period1,8,"Arial", Gray);
ObjectSet("valuta1",OBJPROP_CORNER, 0);// Óãîë ïðèâÿçêè
ObjectSet("valuta1",OBJPROP_XDISTANCE,15);// Êîîðäèíàòà Õ
ObjectSet("valuta1",OBJPROP_YDISTANCE,15);// Êîîðäèíàòà Y
ObjectCreate ("valuta2", OBJ_LABEL, 1, 0, 0);
ObjectSetText("valuta2",symbol2+"_"+s_period2,8,"Arial", Gray);
ObjectSet("valuta2",OBJPROP_CORNER, 1);// Óãîë ïðèâÿçêè
ObjectSet("valuta2",OBJPROP_XDISTANCE,15);// Êîîðäèíàòà Õ
ObjectSet("valuta2",OBJPROP_YDISTANCE,15);// Êîîðäèíàòà Y
}
int SHIRINA_TELA()
{
if ( WindowBarsPerChart() > 300 )
{
return(1);
}
else
{
if ( WindowBarsPerChart() > 150 )
{
return(3);
}
else
{
if ( WindowBarsPerChart() > 70 )
{
return(5);
}
else
{
if ( WindowBarsPerChart() > 35 )
{
return(9);
}
else
{
return(13);
}
}
}
}
}
void SVECHA(string symbol, int period, int lag_k, int lag_p, double k, double min_low)
{
ObjectCreate ( "shade"+symbol+lag_p, OBJ_TREND, 1, Time[lag_p], ( iHigh (symbol,period,lag_k) - min_low )*k,
Time[lag_p], ( iLow (symbol,period,lag_k) - min_low )*k);
ObjectCreate ( "telo"+symbol+lag_p, OBJ_TREND, 1, Time[lag_p], ( iOpen (symbol,period,lag_k) - min_low )*k,
Time[lag_p], ( iClose(symbol,period,lag_k) - min_low )*k);
ObjectSet ( "telo"+symbol+lag_p, OBJPROP_RAY,false);
ObjectSet ( "shade"+symbol+lag_p, OBJPROP_RAY,false);
if ( din_shirina == true )
{
ObjectSet ( "telo"+symbol+lag_p, OBJPROP_WIDTH, SHIRINA_TELA() );
}
else
{
ObjectSet ( "telo"+symbol+lag_p, OBJPROP_WIDTH, 3);
}
if ( iOpen(symbol,period,lag_k) < iClose(symbol,period,lag_k) )
{
ObjectSet ( "telo"+symbol+lag_p, OBJPROP_COLOR,Red);
ObjectSet ( "shade"+symbol+lag_p, OBJPROP_COLOR,Red);
}
else
{
ObjectSet ( "telo"+symbol+lag_p, OBJPROP_COLOR,Black);
ObjectSet ( "shade"+symbol+lag_p, OBJPROP_COLOR,Black);
}
}
int init()
{
period1=PROVERKA(s_period1);
period2=PROVERKA(s_period2);
//if ( ( period1==-1 ) || ( period2==-1 ) ) Comment("error");
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
void DELETE()
{
int i;
ObjectDelete("razdel");
for ( i=( WindowFirstVisibleBar()-1 ); i>=( WindowFirstVisibleBar()-WindowBarsPerChart()/2+1 ); i--)
{
ObjectDelete("telo"+symbol1+i);
ObjectDelete("shade"+symbol1+i);
}
for ( i=( WindowFirstVisibleBar()-WindowBarsPerChart()+2 ); i<=( WindowFirstVisibleBar()-WindowBarsPerChart()/2-1 ); i++)
{
ObjectDelete("telo"+symbol2+i);
ObjectDelete("shade"+symbol2+i);
}
}
int deinit()
{
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
int i,travel1,travel2,vsego,first;
double k1,k2;
if (j!=Time[0])
{
j=Time[0];
DELETE();
UROVNI();
vsego=WindowBarsPerChart( );
first=WindowFirstVisibleBar( );
max_high1=0;max_high2=0;
min_low1=10000;min_low2=10000;
for ( i=( WindowFirstVisibleBar()-WindowBarsPerChart()+3 ); i<=( WindowFirstVisibleBar()-WindowBarsPerChart()/2 ); i++)
{
k1=MASHTAB1(symbol1,period1,i);
k2=MASHTAB2(symbol2,period2,i);
}
for ( i=( WindowFirstVisibleBar()-WindowBarsPerChart()+3 ); i<=( WindowFirstVisibleBar()-WindowBarsPerChart()/2 ); i++)
{
SVECHA( symbol1, period1, i, first-WindowBarsPerChart( )/2+2, k1, min_low1);
SVECHA( symbol2, period2, i, first-WindowBarsPerChart( )+2 , k2, min_low2);
first++;
}
}
}
//+------------------------------------------------------------------+
Comments