var productMasterChart = { code : "", ucode : "", period : "", period_tab : "", interval : "", chart_type : "", container : "", chart : null, udata : null, isMobile: $('.m-only').is(':visible'), //isMobile: true, _top: ($('.m-only').is(':visible'))? 30:22, //_top: 30, init : function(code, period, interval, chart_type, ucode, callback){ var self = this; if (code != ""){ self.code = code; } if (ucode != ""){ self.ucode = ucode; } if(period == "") { period = '1d'; } self.period_tab = period; if(self.period_tab == '1d') { self.period = 'hour'; } else if(self.period_tab == '5d') { self.period = 'day'; } else if(self.period_tab == '1m') { self.period = 'week'; } else if(self.period_tab == '6m' || self.period_tab == 'ytd' || self.period_tab == '1y') { self.period = 'month'; } else if(self.period_tab == '5y') { self.period = 'year'; } if(interval == "") { interval = '5min'; } self.interval = interval; if(chart_type == "") { chart_type = 'candle'; } self.chart_type = chart_type; //self.period = period; $.getJSON('/'+lang+'/data/chart/productMasterChart?code='+self.code+"&period="+self.period_tab+"&interval="+self.interval+"&ucode="+self.ucode, function(_data) { var data = self.decode(_data); $((self.container=='')?'#productMasterChartContainer':'#'+self.container).highcharts('StockChart', self.getJSON(data), function(chart){ self.chart = chart; self.drawBackground(); if($('#cb_uchart').is(":checked")) { self.drawUnderlyingChart(true); }/* else { self.drawUnderlyingChart(false); }*/ if (callback!==undefined){ callback(chart,data); } }); }); }, decode : function(_data){ return _data; }, colors :{line: "#082A4E", uline: "#1DA7CD", bar: "#F4842A", label: "#84888B", gridline: "#999999", yTooltip: "#F28528", xTooltip: "#606060", lastc: "#F48528", black: "#000000", candleUpEn: "#367f2e", candleUpKr: "#e00400", candleDownEn: "#b51a28", candleDownKr: "#005dde", grey: "#8e8e8e"}, getJSON : function(_data){ var dp = 0; var close = []; var turnover = []; //var open = []; var udata = []; var data = _data.mainData; var fdata = _data.furtherData; var min_last = fdata.lastc*1; var max_last = fdata.lastc*1; var groupingUnits = [['minute',[5]], ['hour',[1]]]; if(data) { for (i = 0; i < data.length; i++) { if (data[i][1] == null) { data[i][5] = null; //data[i][8] = null; } if (min_last == 0 && data[i][1]*1 > 0) min_last = data[i][1]; if (data[i][1]*1 > 0) { min_last = Math.min(min_last, data[i][6]); } close.push([data[i][0], data[i][1], data[i][2], data[i][3], data[i][4]]); //open.push([data[i][0], data[i][1]]); udata.push([data[i][0], data[i][8]]); turnover.push([data[i][0], data[i][5]]); max_last = Math.max(max_last, data[i][7]); } } if (min_last == max_last) min_last = 0; var self = this; self.udata = udata; //console.log(close, open); //console.log(_data, self.udata); return { chart:{ //spacing: [0, 0, 0, 0], //marginLeft: 0, marginLeft: 55, marginRight: 43, marginTop: self._top, marginBottom: 22, }, plotOptions: { candlestick: { oxymoronic: true, color: (lang=='en') ? this.colors['candleDownEn'] : this.colors['candleDownKr'], lineColor: (lang=='en') ? this.colors['candleDownEn'] : this.colors['candleDownKr'], upColor: (lang=='en') ? this.colors['candleUpEn'] : this.colors['candleUpKr'], upLineColor: (lang=='en') ? this.colors['candleUpEn'] : this.colors['candleUpKr'], lineWidth: 1 }, line: { color: self.colors['line'], lineWidth: 1.5 }, ohlc: { color: self.colors['line'], lineWidth: 1 } }, tooltip: { backgroundColor: "none", borderWidth: 0, shadow: false, useHTML: true, shape: "square", padding: 0, formatter: function() { //console.log(this.points); var xval = this.points[0].x; var xpos = this.points[0].point.plotX; var yval, ypos, yval2, ypos2, ulast_val; $.each(this.points, function(i, val) { if(val.series.name == 'last') { yval = val.point.options; ypos = val.point.plotY; } else if(val.series.name == 'turnover') { yval2 = val.y; ypos2 = val.point.plotY; } else if(val.series.name == 'ulast') { ulast_val = val.y; } }); var arr = new Array(); arr['x'] = new Array(xval, xpos); arr['y1'] = new Array(yval, ypos); arr['y2'] = new Array(yval2, ypos2); arr['ulast'] = ulast_val; //console.log(data); self.drawTooltip(arr); } }, rangeSelector: { enabled: false, buttons: [{ type: 'day', count: 1, text: 'intraday' }, { type: 'week', count: 1, text: '1week' }, { type: 'all', text: 'All' }], selected: 0 }, xAxis: { tickLength:0, gridLineWidth: 0, gridZIndex: -1, lineWidth: 0, gridLineColor: self.colors["gridline"], gridLineDashStyle: "ShortDot", align: "top", opposite: false, margin: 100, /*events: { setExtremes: function(e) { if(typeof(e.rangeSelectorButton)!== 'undefined'){ if (e.rangeSelectorButton.type == "all"){ }else{ } } } },*/ labels: { y : 17, formatter : function() { if(self.period == "year") { return Highcharts.dateFormat('%m/%Y', this.value); } else if (self.period == "month" || self.period == "week" || self.period == "day"){ return Highcharts.dateFormat('%d/%m', this.value); }else{ return Highcharts.dateFormat('%H:00', this.value); } }, style: { color: self.colors['label'], fontSize: '11px' } }, tickPositioner: function () { var positions = []; var lastday = 0; var msec; if(!self.isMobile || self.period == "day") { if(self.period == "year" && close.length) { msec = 60*60*24*1000*30*6; lastday = Math.floor(close[0][0]/msec)*msec; } else if (self.period == "month" && close.length){ msec = 60*60*24*1000*30; lastday = Math.floor(close[0][0]/msec)*msec; }else if (self.period == "week"){ msec = 60*60*24*1000*7; //lastday = Math.floor(close[0][0]/msec)*msec; lastday = 0; }else if (self.period == "day"){ msec = 60*60*24*1000; //lastday = Math.floor(close[0][0]/msec)*msec; lastday = 0; }else if (self.period == "hour"){ msec = 60*60*1000; lastday = Math.floor(close[0][0]/msec)*msec; } for (i=0;i 1000) ? this.value.toFixed(0) : this.value; //return (this.isLast)?"":addcomma(this.value); this.value = (this.value >= 1000) ? this.value.toFixed(0) : this.value.toFixed(3); return (this.isLast)?"":this.value; }, style: { color: self.colors['label'], fontSize: '11px' } }, top:self._top, //top:0, offset:0, left: 0, height: ($('#productMasterChartContainer').height()-22-self._top)*0.7, //tickPixelInterval:40, tickAmount : 7, showFirstLabel: false, showLastLabel: true, gridLineColor: self.colors["gridline"], gridLineDashStyle: "ShortDot", gridZIndex: -1, gridLineWidth: 0, lineWidth: 0, lineColor: self.colors["gridline"], lineDashStyle: "ShortDot", opposite: false, max: (max_last*1 == fdata.lastc*1) ? max_last : null, min: (min_last*1 == fdata.lastc*1) ? min_last : null, plotLines: [{ value: fdata.lastc, color: self.colors["lastc"], dashStyle: "Solid", width: 1, zIndex: 7, }] }, { title: { text: null }, labels:{ align:'right', x:40, y:5, formatter: function () { return formatTurnover(this.value, true); }, style: { color: self.colors['label'], fontSize: '11px' } }, top: ($('#productMasterChartContainer').height()-22-self._top)*0.7 + 1 + 38 + self._top, offset:0, left: 0, height: (($('#productMasterChartContainer').height()-22-self._top)*0.3) - 38, //height: 124, min: 0, tickAmount : 4, //tickPixelInterval:40, showFirstLabel: false, showLastLabel: true, gridLineWidth: 0, gridZIndex: -1, lineWidth: 0, lineColor: self.colors["gridline"], lineDashStyle: "ShortDot", opposite: false }/*,{ //underlying chart title: { text: null }, labels:{ align:'left', x:-50, y:5, formatter: function () { //this.value = (this.value > 1000) ? this.value.toFixed(0) : this.value; //return (this.isLast)?"":addcomma(this.value); this.value = (this.value >= 1000) ? this.value.toFixed(0) : this.value.toFixed(3); return (this.isLast)?"":this.value; }, style: { color: self.colors['label'], fontSize: '11px' } }, top:self._top, //top:0, offset:0, left: 0, height: ($('#productMasterChartContainer').height()-22-self._top)*0.7, //tickPixelInterval:40, tickAmount : 7, showFirstLabel: false, showLastLabel: true, gridLineColor: self.colors["gridline"], gridLineDashStyle: "ShortDot", gridZIndex: -1, gridLineWidth: 0, lineWidth: 0, lineColor: self.colors["gridline"], lineDashStyle: "ShortDot", opposite: true, //linkedTo: 0 //max: (max_last*1 == fdata.lastc*1) ? max_last : null, //min: (min_last*1 == fdata.lastc*1) ? min_last : null, }*/], navigator : { enabled : false }, scrollbar : { enabled : false }, series : [{ name : "last", data : close, type: self.chart_type, tooltip: { valueDecimals: dp }, dataGrouping: { /*approximation: "close", enabled: true, forced: true, units: groupingUnits, groupPixelWidth: 10*/ enabled: false }, //lineWidth: 1.5, },{ id: 'turnover', name: 'turnover', type: 'column', data: turnover, yAxis: 1, /*dataGrouping: { approximation: "sum", enabled: true, forced: true, units: groupingUnits, groupPixelWidth: 10 },*/ color: self.colors["bar"], }/*,{ //underlying chart id: 'ulast', name: 'ulast', type: 'line', data: udata, color: self.colors["uline"], yAxis: 2, lineWidth: 1.5 }*/], exporting: { enabled: false }, credits: { enabled: false }, }; }, drawBackground: function(){ var chart = this.chart; var offsetx,offsety; var fontstyle = {color: this.colors["grey"], fontSize: '12.5px', 'font-weight': 'bold'}; offsetx = 0; offsety = chart.chartHeight - chart.marginBottom + 1; chart.renderer.rect(offsetx,offsety, chart.chartWidth, 1, 0).attr({ fill: this.colors["black"], 'stroke-width': 0, 'zIndex': 2, }).add(); offsety = chart.yAxis[0].height+this._top; chart.renderer.rect(offsetx,offsety, chart.chartWidth, 1, 0).attr({ fill: this.colors["black"], 'stroke-width': 0, 'zIndex': 2, }).add(); var txt = lang=='en'?"Last Intrinsic Close":'내재가치'; //offsety = chart.yAxis[0].height+38; offsety = chart.yAxis[0].height+16+this._top; chart.renderer.text(txt, 2, offsety).css(fontstyle).add(); offsety = offsety - 5; rectx = lang=='en'?140:60; chart.renderer.rect(rectx, offsety, 15, 2).attr({ fill: this.colors["lastc"], 'stroke-width': 0, 'zIndex': 2, }).add(); //console.log(chart.yAxis[0].height); }, drawTooltip: function(arr){ //arr[x, y1, y2] => arr[val, pos] var chart = this.chart; var fontstyle = {color: '#fff', fontSize: '11px'}; var textattr = {zIndex: 7, class: "tooltipElement"}; var tooltip_txt_arr = lang == 'en'?{Open:'Open',Close:'Close',High:'High',Low:'Low',Underlying:'Underlying'}:{Open:'시가',Close:'종가',High:'고가',Low:'저가',Underlying:'근본적인'}; $(".highcharts-axis-labels text").removeAttr("class", "tooltipElement"); $(".tooltipElement").remove(); //console.log(arr); //xAxis time x_posX = arr['x'][1]+55-19; x_posY = chart.chartHeight - chart.marginBottom + 5; var format; var w = 38; if(this.period == 'year' || this.period == 'week' || this.period == 'month' || (this.period_tab == '5d' && this.interval == '1day')) { format = '%d/%m/%Y'; w = 74; x_posX = x_posX - 19; } else { format = '%H:%M'; } if(x_posX < 0) { x_posX = 0; } chart.renderer.rect(x_posX, x_posY, w, 15, 0).attr({ fill: this.colors["xTooltip"], 'stroke-width': 0, 'zIndex':7, class: 'tooltipElement' }).add(); chart.renderer.text(Highcharts.dateFormat(format, arr['x'][0]), x_posX+3, (x_posY+12)).css(fontstyle).attr(textattr).add(); //yAxis turnover if(typeof(arr['y2'][1]) != 'undefined') { y2_posY = chart.yAxis[0].height + 44 + arr['y2'][1]-7; y2_posX = chart.chartWidth - chart.marginRight; chart.renderer.rect(y2_posX, y2_posY, chart.marginRight, 15, 0).attr({ fill: this.colors["yTooltip"], 'stroke-width': 0, 'zIndex':7, class: 'tooltipElement' }).add(); //chart.renderer.text(arr['y2'][0], y2_posX+5, (y2_posY+11.5)).css(fontstyle).attr(textattr).add(); turnoverLabel = chart.renderer.label(formatTurnover(arr['y2'][0], true), y2_posX, (y2_posY-3)).css(fontstyle).attr(textattr).add(); turnoverLabel.attr({ x: chart.chartWidth - turnoverLabel.width }); } //yAxis last if(typeof(arr['y1'][1]) != 'undefined') { y_posY = 5; var _open = arr['y1'][0]['open']; var _high = arr['y1'][0]['high']; var _low = arr['y1'][0]['low']; var _close = arr['y1'][0]['close']; date_format = (this.period_tab == '1d' || (this.period_tab == '5d' && this.interval != '1day'))? '%Y-%m-%d %H:%M':'%Y-%m-%d'; var datetime = Highcharts.dateFormat(date_format, arr['y1'][0]['x']); var ulast_txt = ''; var w = (this.chart_type == 'line')? 220:440; var a = (this.chart_type == 'line')? 37:200; if(typeof(arr['ulast']) != 'undefined') { ulast_txt = ' | '+tooltip_txt_arr.Underlying+': '+addcomma(arr['ulast'].toFixed(3))+''; w = (this.chart_type == 'line')? 300:530; a = (this.chart_type == 'line')? 100:250; } if(this.chart_type == 'line') { _open = arr['y1'][0]['y']; y_posX = arr['x'][1]-a; if(y_posX < 0) { y_posX = 0; } else if(y_posX+w > chart.chartWidth) { y_posX = chart.chartWidth-w; } chart.renderer.rect(y_posX, y_posY, w, 15, 0).attr({ fill: this.colors["xTooltip"], 'stroke-width': 0, 'zIndex':7, class: 'tooltipElement' }).add(); fontstyle = {color: '#fff', fontSize: '15px'}; chart.renderer.text('
'+datetime+' | '+'Last: '+_open+''+ulast_txt+'
', y_posX+5, (y_posY+11.5), true).css(fontstyle).attr(textattr).add(); } else { //var w = 440; var h = 15; if(chart.chartWidth < w) { w = chart.chartWidth; h = 30; } y_posX = arr['x'][1]-a+30; if(y_posX < 0) { y_posX = 0; } else if(y_posX+w > chart.chartWidth) { y_posX = chart.chartWidth-w; } chart.renderer.rect(y_posX, y_posY, w, h, 0).attr({ fill: this.colors["xTooltip"], 'stroke-width': 0, 'zIndex':7, class: 'tooltipElement' }).add(); fontstyle = {color: '#fff', fontSize: '15px'}; if(chart.chartWidth == w) { chart.renderer.text('
'+datetime+ulast_txt+'
', y_posX+5, (y_posY+11.5), true).css(fontstyle).attr(textattr).add(); chart.renderer.text('
'+tooltip_txt_arr.Open+': '+_open+' '+tooltip_txt_arr.Close+': '+_close+' '+tooltip_txt_arr.High+': '+_high+' '+tooltip_txt_arr.Low+': '+_low+'
', y_posX+5, (y_posY+26), true).css(fontstyle).attr(textattr).add(); //chart.renderer.text('Open: '+_open+' Close: '+_close+' High: '+_high+' Low: '+_low, y_posX+5, (y_posY+26)).css(fontstyle).attr(textattr).add(); } else { //chart.renderer.text(datetime+' | '+'Open: '+_open+' Close: '+_close+' High: '+_high+' Low: '+_low+'', y_posX+5, (y_posY+11.5)).css(fontstyle).attr(textattr).add(); chart.renderer.text('
'+datetime+' | '+tooltip_txt_arr.Open+': '+_open+' '+tooltip_txt_arr.Close+': '+_close+' '+tooltip_txt_arr.High+': '+_high+' '+tooltip_txt_arr.Low+': '+_low+''+ulast_txt+'
', y_posX+5, (y_posY+11.5), true).css(fontstyle).attr(textattr).add(); } } } }, changeChartType: function(type) { //console.log(this._data); if(type != this.chart_type) { if(type == 'candlestick') { this.chart.series[0].update({ type: type, color: (lang=='en') ? this.colors['candleDownEn'] : this.colors['candleDownKr'], lineWidth: 1 }); } else if(type == 'ohlc') { this.chart.series[0].update({ type: type, color: this.colors['line'], lineWidth: 1 }); } if(type == 'line') { this.chart.series[0].update({ type: type, lineWidth: 1.5, color: this.colors['line'] }); } this.chart_type = type; } }, drawUnderlyingChart: function(add) { /*if(action == 'add') { console.log(this.udata); }*/ var chart = this.chart; var index = null; $.each(chart.series, function(i, val) { if(val.name == 'ulast') { index = i; return false; } }); if(add) { if(index == null) { //add /*this.chart.update({ chart: { marginLeft: 55 } });*/ chart.addSeries({ id: 'ulast', name: 'ulast', type: 'line', data: this.udata, color: this.colors["uline"], yAxis: 2, lineWidth: 1.5 }); } else { chart.series[index].update({ data: this.udata }); } } else { if(index != null) { chart.series[index].remove(true); } } } }