/* 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"){ variation = variation.toFixed(2).replace(".",","); //} period += variation + "%"; if(SymexChartGlobals.language !="en"){ var close = data_close_0[x2_].toFixed(2).replace(".",","); } period += "" + close + ""; 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]; }