/* Format prices according to language */
/* @autor Martin Nachev (22.01.2014) */
/* @idea Google.bg: javascript split string every 3 characters at right */
function format_price( value, noDecimal ) {
var dec = 2;
var value = parseFloat(value).toFixed( dec ); // String
var noDecimal = typeof noDecimal == "boolean" ? noDecimal : false;
var decSep = SymexChartGlobals.language == "en" ? "." : ",";
var thousSep = SymexChartGlobals.language == "en" ? " " : ".";
var v = parseInt( value ) + ""; // String - main number part
var firstGroupLen = v.length % 3; // only first group could be less than 3 digits
var f = v.substring( firstGroupLen ).match( new RegExp( ".{3}", "g" ) ) || []; // Array !!!
if ( firstGroupLen > 0 ) {
f.unshift( v.substring( 0, firstGroupLen ) );
}
var formatted = f.join( thousSep );
if ( noDecimal == false ) {
formatted += decSep + value.match( new RegExp( "[0-9]+$" ) )[0];
}
return formatted;
}
function getURLParam()
{
var returnObject = {};
var href = document.location.href;
if ( href.indexOf("?") > -1 )
{
var param = href.substr(href.indexOf("?") + 1);
var arrayParam = param.split("&");
for ( var i = 0; i < arrayParam.length; i++ )
{
var value = arrayParam[i].split("=");
returnObject[value[0]] = value[1];
}
}
return returnObject;
}
function array_max( arr, x1, x2 )
{
var max_ = null;
for( var i = x1; i < x2; i++ ) {
if ( arr[i] && ( max_ === null || arr[i] > max_ ) ) {
max_ = arr[i];
}
}
return max_;
}
function array_min( arr, x1, x2 )
{
var min_ = null;
for( var i = x1; i < x2; i++ ) {
if ( arr[i] && ( min_ === null || arr[i] < min_ ) ) {
min_ = arr[i];
}
}
return min_;
}
function get_first_quote( arr, x1, x2 )
{
for( var i = x1; i <= x2; i++ )
{
if (arr[i]) return arr[i];
}
return null;
}
//convert date format: YYYY-mm-dd HH:ii:ss => dd/mm/YYYY
function date_eu(d){
var date_ = '';
if(typeof SymexChartSettings.lang_array[41] == "undefined"){var separateur = '/';}else{var separateur = SymexChartSettings.lang_array[41];}
if(typeof SymexChartSettings.settings[13] == "undefined"){
if(SymexChartGlobals.language == "en"){
if ( SymexChartGlobals.period_type == 'intra' )
{
date_ = d.substr(5,2) + separateur + d.substr(8,2) + ' ' + d.substr(11,2) + ':' + d.substr(14,2) ;
}
if ( SymexChartGlobals.period_type == 'week' )
{
date_ = d.substr(5,2) + separateur + d.substr(8,2) + ' ' + d.substr(11,2) + ':' + d.substr(14,2) ;
}
}else{
if ( SymexChartGlobals.period_type == 'intra' )
{
date_ = d.substr(8,2) + separateur + d.substr(5,2) + ' ' + d.substr(11,2) + ':' + d.substr(14,2) ;
}
if ( SymexChartGlobals.period_type == 'week' )
{
date_ = d.substr(8,2) + separateur+ d.substr(5,2) + ' ' + d.substr(11,2) + ':' + d.substr(14,2) ;
}
}
}else{
date_ = SymexChartSettings.settings[13];
date_ = date_.replace("d", d.substr(8,2));
date_ = date_.replace("m", d.substr(5,2));
date_ = date_.replace("Y", d.substr(0,4));
date_ = date_.replace("H", d.substr(11,2));
date_ = date_.replace("i", d.substr(14,2));
}
return date_;
}
function show_period( x1_, x2_ )
{
if ( x2_ == SymexChartGlobals.points_qty ) { x2_ = SymexChartGlobals.points_qty - 1; }
//from
var period = SymexChartSettings.lang_array[20] + date_eu( data_date[x1_] ) + ' ';
//to
period += SymexChartSettings.lang_array[21] + date_eu( data_date[x2_] );
jQuery('#period_info').html( period );
}
function show_header( x1_, x2_ )
{
if ( x2_ == SymexChartGlobals.points_qty ) { x2_ = SymexChartGlobals.points_qty - 1; }
//from
//to
var variation = (data_close_0[x2_] / veille_min_max[0]-1)*100 ;
if(variation < 0){
var class_var = "down";
var img_var ="-";
}else{
var class_var = "up";
var img_var ="+";
}
var period = "";
period += "";
if(SymexChartGlobals.language !="en"){
var close = data_close_0[x2_].toFixed(2).replace(".",",");
}
period += "";
jQuery('#head_close').html( period );
}
function drawLine( x1_, x2_ ){
// Override global var begin
SymexChartGlobals.begin = x1_;
x2_ = x2_ +1;
// Quantity of points to be draw for each ticker -> Local var (note we have global one!)
var points_qty = x2_ - x1_;
// Conteiner for canvas elements
var canvas_ = new Array();
// Add all canvas element in
for(var i = 0; i < SymexChartGlobals.tickers_qty; i++ ){
canvas_[i] = document.getElementById('price_' + i);
}
// Ff canvas container is ready
if (canvas_[0].getContext)
{
var context_ = new Array(); //2D plots container
var coefStepY;
var init_positionY;
var stepY;
var tmp_val;
var init_quotes = new Array(); // Collect first quote for each ticker
//get all 2D plots
for(var i = 0; i < SymexChartGlobals.tickers_qty; i++ ){
context_[i] = canvas_[i].getContext('2d');
}
// set global max / min for each ticker
// my secret => toFixed(1) => good digits after decimal separator
for( var w = 0; w < SymexChartGlobals.tickers_qty; w++ )
{
init_quotes[w] = get_first_quote(eval('data_close_' + w), x1_, x2_);
SymexChartGlobals.max_[w] = array_max( eval('data_close_' + w), x1_, x2_ );
SymexChartGlobals.min_[w] = array_min( eval('data_close_' + w), x1_, x2_ );
// Check if highest dot for a secondary ticker is higher then this of main ticker
var check_max = ( SymexChartGlobals.max_[w] / init_quotes[w] ) * init_quotes[0];
if (SymexChartGlobals.max_[0] < check_max) SymexChartGlobals.max_[0] = check_max;
// Check if lowest dot for a secondary ticker is lower then this of main ticker
var check_min = ( SymexChartGlobals.min_[w] / init_quotes[w] ) * init_quotes[0];
if (SymexChartGlobals.min_[0] > check_min) SymexChartGlobals.min_[0] = check_min;
}
// Take in mind veille values
for (var itveill = 0; itveill < veille_min_max.length; itveill++)
{
if (SymexChartGlobals.max_[0] < veille_min_max[itveill]) SymexChartGlobals.max_[0] = veille_min_max[itveill];
if (SymexChartGlobals.min_[0] > veille_min_max[itveill]) SymexChartGlobals.min_[0] = veille_min_max[itveill];
}
// Recalculate max / min for good `Y` scale
//console.log( "brut max " + SymexChartGlobals.max_[0] );
var values_scale_data = values_scale(SymexChartGlobals.max_[0], SymexChartGlobals.min_[0]);
SymexChartGlobals.max_[0] = values_scale_data[0];
SymexChartGlobals.min_[0] = values_scale_data[1];
//console.log( SymexChartGlobals.max_[0] );
SymexChartSettings.settings[0] = values_scale_data[2];
// Distance between two points in 'X' axis -> override global
//SymexChartGlobals.stepX = (SymexChartGlobals.chart_width - 1) / (points_qty - 1);
SymexChartGlobals.stepX = (SymexChartGlobals.chart_width) / (points_qty - 1);
// Distance between two points in 'Y' axis (based on main tickers!)
coefStepY = (SymexChartGlobals.max_[0] - SymexChartGlobals.min_[0]) / SymexChartGlobals.chart_height;
if ( SymexChartGlobals.mountain == 1 ){
var lingrad = context_[0].createLinearGradient( 0, 0, SymexChartGlobals.chart_width, 0 );
lingrad.addColorStop( 0, SymexChartSettings.colors_[21] ); //6699cc
lingrad.addColorStop( 1, SymexChartSettings.colors_[22] );
}
//loop for each ticker
for ( var i = 0; i < SymexChartGlobals.tickers_qty; i++ )
{
// Set init position => same for all tickers => depends to main ticker
init_positionY = (SymexChartGlobals.max_[0] - init_quotes[0]) / coefStepY;
//init drawing process
context_[i].beginPath();
context_[i].moveTo( 1, init_positionY );
//loop for each quotation
var iter = 0; //count steps
for ( var i_ = x1_ + 1; i_ <= x2_; i_++ ) //+1 => because 0 point is set with moveTo
{
//if empty point (no quotation for current date)
if ( ! eval('data_close_' + i + '[i_]') ) {
iter++;
continue;
}
if (i > 0)
{
var formula_convert;
formula_convert = 'tmp_val' + ' = ';
formula_convert += '(data_close_' + i + '[i_] / ';
formula_convert += get_first_quote( eval('data_close_' + i), x1_, x2_)+ ') * ';
formula_convert += get_first_quote( data_close_0, x1_, x2_ );
eval(formula_convert);
}
else {
tmp_val = data_close_0[i_]; // Current value for main ticker
}
// Calculate next 'Y' axis position
stepY = (SymexChartGlobals.max_[0] - tmp_val) / coefStepY;
// Draw line
context_[i].lineTo( (SymexChartGlobals.stepX * (iter + 1)).toFixed(2), stepY.toFixed(2) );
//remember last dot coords of main ticker => for mountain
if ( i == 0 ) { var last_dot_main = (SymexChartGlobals.stepX * (iter + 1)).toFixed(2); }
iter++;
}
//finish drawing process for current ticker
context_[i].strokeStyle = SymexChartSettings.colors_[i];
context_[i].lineWidth = SymexChartSettings.linesW_[i];
context_[i].stroke();
}
if ( SymexChartGlobals.mountain == 1 ){
context_[0].lineTo( last_dot_main, SymexChartGlobals.chart_height );
context_[0].lineTo( 0, SymexChartGlobals.chart_height );
context_[0].lineTo( 0, init_positionY );
context_[0].fillStyle = lingrad;
context_[0].fill();
}
} //if canvas */
} //end func
function drawLine_2()
{
//get canvas element
var canvas_sum = document.getElementById('summary_0');
//if canvas is ready
if (canvas_sum.getContext){
//get all 2D plots
context_sum = canvas_sum.getContext('2d');
var coefStepY;
var init_positionY;
var stepY;
var lingrad = context_sum.createLinearGradient( 0, 0, SymexChartGlobals.chart_width, 0 );
lingrad.addColorStop( 0, SymexChartSettings.colors_[23] );
lingrad.addColorStop( 1, SymexChartSettings.colors_[24] );
//MAX / MIN => calculate in function above, which is called before this one!!!
//distance between two points in 'Y' axis
coefStepY = (SymexChartGlobals.max_[0] - SymexChartGlobals.min_[0]) / SymexChartGlobals.chart_sum_height;
// Set init position => same for all tickers => depends to main ticker
init_positionY = (SymexChartGlobals.max_[0] - get_first_quote(data_close_0, 0, (SymexChartGlobals.points_qty - 1))) / coefStepY;
//init drawing process
context_sum.beginPath();
context_sum.moveTo( 1, init_positionY );
//loop for each quotation
var iter = 0; //count steps
for ( var i_ = 1; i_ < data_date.length; i_++ )
{
//if empty point (no quotation for current date)
if ( ! data_close_0[i_] ) {
iter++;
continue;
}
//calculate next 'Y' axis position
stepY = (SymexChartGlobals.max_[0] - data_close_0[i_]) / coefStepY ;
context_sum.lineTo( (SymexChartGlobals.stepX * (iter + 1)).toFixed(2), stepY.toFixed(2) );
iter++;
}
//finish drawing process for current ticker
context_sum.strokeStyle = SymexChartSettings.colors_[20];
context_sum.lineWidth = SymexChartSettings.linesW_[20];
context_sum.stroke();
context_sum.lineTo( (SymexChartGlobals.stepX * iter).toFixed(2), SymexChartGlobals.chart_sum_height );
context_sum.lineTo( 0, SymexChartGlobals.chart_sum_height );
context_sum.lineTo( 0, init_positionY );
context_sum.fillStyle = lingrad;
context_sum.fill();
} //if canvas */
} //end func
function drawVolumes( x1_, x2_ ) {
// Override begin
SymexChartGlobals.begin = x1_;
// Quantity of points to be draw for each ticker => OVERRIDE GLOBAL
var points_qty = x2_ - x1_;
var volData = {
_min: null,
_max: null,
_ampl: null,
_sum: null,
_average: null,
_highest: null,
_lowest: null,
min: function() {
if ( volData._min === null ) {
volData._min = 0;
}
return volData._min;
},
max: function() {
if ( volData._max === null ) {
volData._max = array_max( data_vol_0, x1_, x2_ );
}
return volData._max;
},
ampl: function() {
if ( volData._ampl === null ) {
volData._ampl = volData.max() - volData.min();
}
return volData._ampl;
},
sum: function() {
if ( volData._sum === null ) {
var total = 0;
for ( var i = x1_; i <= x2_; i ++ ) {
if ( data_vol_0[ i ] ) {
total += Math.round( data_vol_0[ i ] );
}
}
volData._sum = total;
}
return volData._sum;
},
average: function() {
if ( volData._average === null ) {
volData._average = Math.round( ( volData.sum() - volData.max() ) / ( points_qty - 1 ) );
}
return volData._average;
},
highest: function() {
if ( volData._highest === null ) {
// Old method
// volData._highest = volData.average() * 2;
var tmp = data_vol_0.slice( 0 );
tmp.sort( function( a, b ) {
return b - a;
});
if ( tmp.length > 1 ) {
volData._highest = Math.round( tmp[ 1 ] );
}
else {
volData._highest = tmp.length ? Math.round( tmp[ 0 ] ) : null;
}
}
return volData._highest;
},
lowest: function() {
if ( volData._lowest === null ) {
// Old method
// var tmp = volData.highest();
// for ( var i = x2_; i >= x1_; i -- ) {
// if ( data_vol_0[ i ] > 0 && data_vol_0[ i ] < tmp ) {
// tmp = data_vol_0[ i ];
// }
// }
// volData._lowest = tmp;
volData._lowest = 0;
}
return volData._lowest;
}
};
// Debug
// alert( volData.highest() + ' :: ' + volData.lowest() );
// Conteiner for canvas elements
var canvas_ = document.getElementById( 'volume_0' );
// Canvas container is ready
if ( canvas_.getContext ) {
// 2D plot container
var context_ = canvas_.getContext( '2d' );
// Distance between two points in 'X' axis ( override global )
SymexChartGlobals.stepX = ( SymexChartGlobals.chart_width - 1 ) / ( points_qty - 1 );
var maxVolume = volData.max();
var minVolume = volData.min();
if( SymexChartSettings.intraVolumesRelative === true ) {
maxVolume = volData.highest();
minVolume = volData.lowest();
}
// Distance between two points in 'Y' axis
var coefStepY = ( maxVolume - minVolume ) / SymexChartGlobals.chart_vol_height;
var stepY;
var iter = 0; // count steps
var tmpSet = SymexChartSettings;
var lineWidth = tmpSet.linesW_[ 0 ];
while ( lineWidth >= SymexChartGlobals.stepX && lineWidth > 1 ) {
lineWidth -= 1;
}
// Debug
// Tutorials: javascript canvas draw dotted line
for ( var i_ = x1_; i_ <= x2_; i_++ ) {
var currentVol = data_vol_0[ i_ ];
// If empty point (no quotation for current date)
if ( ! currentVol || currentVol < minVolume ) {
iter++;
continue;
}
context_.setLineDash( [] );
if ( currentVol > maxVolume ) {
currentVol = maxVolume;
context_.setLineDash( [2, 2] );
}
context_.beginPath();
// calculate next 'Y' axis position
stepY = ( maxVolume - currentVol ) / coefStepY;
// if (stepY > 49.9) stepY = 49.9; // Agains bug in IE browsers
context_.moveTo( ( SymexChartGlobals.stepX * iter + 1 ).toFixed( 2 ), stepY.toFixed( 2 ) );
context_.lineTo( (SymexChartGlobals.stepX * iter + 1).toFixed(2), SymexChartGlobals.chart_vol_height );
iter++;
// Finalize the current shape in the canvas
context_.strokeStyle = tmpSet.colors_[ 25 ] ? tmpSet.colors_[ 25 ] : tmpSet.colors_[ 0 ];
context_.lineWidth = lineWidth;
context_.stroke();
}
}
}
function values_scale(max_, min_)
{
var amplitude = max_ - min_;
var distance;
if (amplitude <= 0.01) { distance = 0.002; }
else if (amplitude <= 0.05) { distance = 0.01; }
else if (amplitude <= 0.1) { distance = 0.02; }
else if (amplitude <= 0.5) { distance = 0.1; }
else if (amplitude <= 1) { distance = 0.2; }
else if (amplitude <= 2) { distance = 0.5; }
else if (amplitude <= 5) { distance = 1; }
else if (amplitude <= 10) { distance = 2; }
else if (amplitude <= 20) { distance = 4; }
else if (amplitude <= 50) { distance = 10; }
else if (amplitude <= 100) { distance = 20; }
else if (amplitude <= 200) { distance = 40; }
else if (amplitude <= 300) { distance = 60; }
else if (amplitude <= 400) { distance = 80; }
else if (amplitude <= 500) { distance = 100; }
else if (amplitude <= 600) { distance = 120; }
else if (amplitude <= 700) { distance = 140; }
else if (amplitude <= 800) { distance = 160; }
else if (amplitude <= 900) { distance = 180; }
else if (amplitude <= 1000) { distance = 200; }
else if (amplitude <= 1100) { distance = 220; }
else if (amplitude <= 1200) { distance = 240; }
else if (amplitude <= 1400) { distance = 280; }
else if (amplitude <= 1600) { distance = 320; }
else if (amplitude <= 1800) { distance = 360; }
else if (amplitude <= 2000) { distance = 400; }
else if (amplitude <= 2400) { distance = 480; }
else if (amplitude <= 2800) { distance = 560; }
else if (amplitude <= 3200) { distance = 640; }
else if (amplitude <= 4000) { distance = 800; }
else if (amplitude <= 8000) { distance = 1600; }
else if (amplitude <= 16000) { distance = 3200; }
else if (amplitude <= 32000) { distance = 6400; }
else if (amplitude <= 64000) { distance = 12800; }
else if (amplitude <= 128000) { distance = 25600; }
else { distance = 30000; }
/* If we need to increase distace define next var in customer's css file! */
/*if (typeof SymexChartYdistaceCoef == "number") {
distance *= SymexChartYdistaceCoef;
}*/
var max_scale = Math.round(max_ / distance);
var min_scale = Math.round(min_ / distance);
if ((max_scale * distance) <= max_) {
max_scale = (max_scale + 1) * distance;
}
else {
max_scale = max_scale * distance;
}
if ((min_scale * distance) >= min_) { // `>` instead of `>=` else min scale value will be always less then 0
min_scale = (min_scale - 1) * distance;
}
else {
min_scale = min_scale * distance;
}
//if max_ or min_ is equal to the top or bottom line, we shift the element of 1 distance
if( Math.round( max_scale * 100 ) == Math.round( max_ * 100 ) ){
max_scale = max_scale + distance;
}
if( Math.round( min_scale * 100 ) == Math.round( min_ * 100 ) ){
min_scale = min_scale - distance;
}
min_ = min_scale;
max_ = max_scale;
var nhl = Math.round((max_scale - min_scale) / distance);
if (nhl < 2) nhl = 2;
/* If we need to controll number of labes in scale Y - define next var in customer's css file! */
if (typeof SymexChartYdistaceCoef == "number" && SymexChartYdistaceCoef > 0) {
var scaleYration = nhl / SymexChartYdistaceCoef;
distance *= scaleYration;
nhl = SymexChartYdistaceCoef;
}
return [max_, min_, nhl, distance];
}