How do we create an OHLC chart with moving average using google chart API - google-api

I am using google API to create charts. I am able to create OHLC(Candlestick) charts. But I want to add an overlay of Moving Average to it. Can anyone please guide me as to how I can do it?
Thanks in advance.

Here's an example of how to add a moving average line to a CandlestickChart:
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('date', 'Date');
data.addColumn('number', 'Low');
data.addColumn('number', 'Open');
data.addColumn('number', 'Close');
data.addColumn('number', 'High');
var low, open, close = 45, high;
for (var i = 0; i < 30; i++) {
open = close;
close += ~~(Math.random() * 10) * Math.pow(-1, ~~(Math.random() * 2));
high = Math.max(open, close) + ~~(Math.random() * 10);
low = Math.min(open, close) - ~~(Math.random() * 10);
data.addRow([new Date(2014, 0, i + 1), low, open, close, high]);
}
// use a DataView to calculate an x-day moving average
var days = 5;
var view = new google.visualization.DataView(data);
view.setColumns([0, 1, 2, 3, 4, {
type: 'number',
label: days + '-day Moving Average',
calc: function (dt, row) {
// calculate average of closing value for last x days,
// if we are x or more days into the data set
if (row >= days - 1) {
var total = 0;
for (var i = 0; i < days; i++) {
total += dt.getValue(row - i, 3);
}
var avg = total / days;
return {v: avg, f: avg.toFixed(2)};
}
else {
// return null for < x days
return null;
}
}
}]);
var chart = new google.visualization.ComboChart(document.querySelector('#chart_div'));
chart.draw(view, {
height: 400,
width: 600,
chartArea: {
left: '7%',
width: '70%'
},
series: {
0: {
type: 'candlesticks'
},
1: {
type: 'line'
}
}
});
}
google.load("visualization", "1", {packages:["corechart"], callback: drawChart});
see it working here: http://jsfiddle.net/asgallant/74u6ox8b/

Related

Bubbles Background in AS3

I found 3 videos from SnorklTV.
https://www.youtube.com/watch?v=ZUM0i0DLKk0
https://www.youtube.com/watch?v=_44H68-QciU
https://www.youtube.com/watch?v=Z9NUkmQDB1k
There is a problem: GreenSock still works to use it, but it is no longer officially supported.
Error 1172: Definition com.greensock could not be found.
Code:
var bubbleMax: Number = 50;
var tl: TimelineMax = new TimelineMax();
function createBubble() {
var Bubble: Bubble = new Bubble();
Bubble.y = 380;
Bubble.x = randomRange(25, 610);
Bubble.alpha = 1;
addChild(Bubble);
var nestedTL: TimelineMax = new TimelineMax();
var speed: Number = randomRange(1, 3);
var wiggle: Number = randomRange(25, 50);
wiggle = Math.random() > .5 ? wiggle : -wiggle;
nestedTL.insert(TweenMax.to(Bubble, speed, {
y: -40,
ease:Quad.easeIn
}));
nestedTL.insert(TweenMax.to(Bubble, .5, {
scaleX: speed,
scaleY: speed,
alpha: randomRange(.5, 1)
}));
nestedTL.insert(TweenMax.to(Bubble, speed * .25, {
x: String(wiggle),
repeat: randomRange(1, 4),
yoyo: true
}));
tl.append(nestedTL, speed * -.89);
}
function randomRange(min: Number, max: Number): Number {
return min + (Math.random() * (max - min));
}
function init() {
for (var count: Number = 0; count < bubbleMax; count++) {
createBubble();
}
}
init();
Any ideas for the codes without importing Greensock?
import com.greensock.*;
import com.greensock.easing.*;
var bubbleMax: Number = 200;
var tl: TimelineMax = new TimelineMax();
function createBubble() {
var Bubble: bubble = new bubble();
Bubble.y = 430;
Bubble.x = randomRange(25, 610);
Bubble.alpha = 0;
addChild(Bubble);
Bubble.visible = true;
var nestedTL: TimelineMax = new TimelineMax();
var speed: Number = randomRange(1, 3);
var wiggle: Number = randomRange(25, 50);
wiggle = Math.random() > .5 ? wiggle : -wiggle;
nestedTL.insert(TweenMax.to(Bubble, speed, {
y: -40,
ease:Quad.easeIn
}));
nestedTL.insert(TweenMax.to(Bubble, .5, {
scaleX: speed,
scaleY: speed,
alpha: randomRange(.5, 1)
}));
nestedTL.insert(TweenMax.to(Bubble, speed * .25, {
x: String(wiggle),
repeat: randomRange(1, 4),
yoyo: true
}));
tl.append(nestedTL, speed * -.89);
}
function randomRange(min: Number, max: Number): Number {
return min + (Math.random() * (max - min));
}
function init() {
for (var count: Number = 0; count < bubbleMax; count++) {
createBubble();
}
}
init();

Bar chart is showing lines (thin bars) instead of bars [SOLVED]

I am trying to display a stacked bar chart with dates as xAxis. it display the number of sport session by type of sport.
The idea is to have for a specific time range the number of sessions displayed. For example for the last 4 weeks, the number of sessions per day will be displayed, and for the last 12 weeks, it will display the number of sessions per week.
These values are being calculated and displayed fine. The issue is that they are displayed as a 1px wide bar, instead of a "wide" automatically calculated bar width.
If someone have an idea how this fix this kind of issue... please help!
Data are structured as follows. I only show concerned data
const sessions_summary = [
{
activity_name: 'regular_biking',
date_time: '2020-03-18T15:57:47.853Z',
// ...
},
{
activity_name: 'swimming',
date_time: '2020-03-18T15:57:47.853Z'
},
{
activity_name: 'running',
date_time: '2020-03-19T15:57:47.853Z'
},
// ...
];
Crossfilter:
const ndx = crossfilter(sessions_summary);
const Dimension = ndx.dimension(function(d) {
return d3.timeDay(new Date(d.date_time));
});
Scaletime:
const today = new Date(new Date().toDateString());
const minDate = d3.timeDay(
new Date(
new Date().setDate(
today.getDate() - parseFloat(timeranges[timerange_name]) // 7 or 30 or 90 or 180 or 360 : number of days, depends on the interval selected in Select Entry
)
)
);
let maxDate = d3.timeDay(today);
maxDate = d3.timeDay.offset(maxDate, 1);
const scaletime = d3.scaleTime().domain([minDate, maxDate]);
Chart.x(scaletime);
const interval = intervals[timerange_name]; // d3.timeDay or d3.timeWeek or d3.timeMonth, depending on the choice made in Select Entry
Chart.xUnits(interval);
Group:
const types = [...new Set(sessions_summary.map(session => session.type))];
Group = Dimension.group(function(k) {
return interval(k);
}).reduce(
function(p, v) {
if (v.type in p.types) {
p.types[v.type]++;
} else {
p.types[v.type] = 1;
}
return p;
},
function(p, v) {
p.types[v.type]--;
if (p.types[v.type] === 0) {
delete p.types[v.type];
}
return p;
},
function() {
return {
types: {}
};
}
);
Chart.group(Group, types[0], sel_stack(types[0])).render();
for (let i = 1; i < types.length; i++) {
Chart.stack(Group, types[i], sel_stack(types[i]));
}
Bar Chart:
const Chart = dc.barChart('#sessions_chart');
Chart.width(968)
.height(240)
.elasticY(true)
.margins({
left: 40,
top: 10,
right: 20,
bottom: 40
})
.gap(5)
.centerBar(true)
.round(d3.timeDay.round)
.alwaysUseRounding(true)
.xUnits(d3.timeDays)
.brushOn(false)
.renderHorizontalGridLines(true)
.renderVerticalGridLines(false)
.dimension(Dimension)
.title(d => {
return (
'Date: ' +
new Date(d.key).toDateString() +
'\n' +
'Sessions: ' +
Object.keys(d.value.types)
);
});
Chart.legend(
dc
.legend()
.x(40)
.y(465)
.gap(10)
.horizontal(true)
.autoItemWidth(true)
);
Chart.render();
Complete code can be found on JSFiddle
Thanks in advance
[SOLVED]
The issue was the double xUnits, and the wrong use of d3.TimeDay instead of d3.TimeDays.

WebGL: Count the number of rendered vertices

Using the WebGL API, is there a way to count the number of vertices rendered within a given canvas? I've seen some tools that attempt to accomplish this task but some are giving strange results (e.g. Three.js' renderer.info.render is reporting my scene has 10,134.3 triangles).
Any help with using the raw WebGL API to count the number of rendered vertices (and, ideally, points and lines) would be greatly appreciated.
WebGL can't do this for you but you could can add your own augmentation.
The most obvious way is just to track your own usage. Instead of calling gl.drawXXX call functionThatTracksDrawingCountsXXX and track the values yourself.
You can also augment the WebGL context itself. Example
// copy this part into a file like `augmented-webgl.js`
// and include it in your page
(function() {
// NOTE: since WebGL constants are um, constant
// we could statically init this.
let primMap;
function addCount(ctx, type, count) {
const ctxInfo = ctx.info;
const primInfo = primMap[type];
ctxInfo.vertCount += count;
ctxInfo.primCount[primInfo.ndx] += primInfo.fn(count);
}
WebGLRenderingContext.prototype.drawArrays = (function(oldFn) {
return function(type, offset, count) {
addCount(this, type, count);
oldFn.call(this, type, offset, count);
};
}(WebGLRenderingContext.prototype.drawArrays));
WebGLRenderingContext.prototype.drawElements = (function(oldFn) {
return function(type, count, indexType, offset) {
addCount(this, type, count);
oldFn.call(this, type, count, indexType, offset);
};
}(WebGLRenderingContext.prototype.drawElements));
HTMLCanvasElement.prototype.getContext = (function(oldFn) {
return function(type, ...args) {
const ctx = oldFn.call(this, type, args);
if (ctx && type === "webgl") {
if (!primMap) {
primMap = {};
primMap[ctx.POINTS] = { ndx: 0, fn: count => count, };
primMap[ctx.LINE_LOOP] = { ndx: 1, fn: count => count, };
primMap[ctx.LINE_STRIP]= { ndx: 1, fn: count => count - 1, };
primMap[ctx.LINES] = { ndx: 1, fn: count => count / 2 | 0, };
primMap[ctx.TRIANGLE_STRIP] = { ndx: 2, fn: count => count - 2, };
primMap[ctx.TRIANGLE_FAN] = { ndx: 2, fn: count => count - 2, };
primMap[ctx.TRIANGLES] = { ndx: 2, fn: count => count / 3 | 0, };
};
ctx.info = {
vertCount: 0,
primCount: [0, 0, 0],
};
}
return ctx;
}
}(HTMLCanvasElement.prototype.getContext));
}());
// ---- cut above ----
const $ = document.querySelector.bind(document);
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, 1, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({canvas: $('canvas')});
const geometry = new THREE.BoxGeometry(1, 1, 1);
const items = [];
for (let i = 0; i < 50; ++i) {
let item;
switch(rand(0, 3) | 0) {
case 0:
case 1:
const material = new THREE.MeshBasicMaterial({
color: rand(0xFFFFFF) | 0,
wireframe: rand(0, 3) > 2,
});
item = new THREE.Mesh(geometry, material);
break;
case 2:
const pmat = new THREE.PointsMaterial({
color: rand(0xFFFFFF) | 0,
});
item = new THREE.Points(geometry, pmat);
break;
default:
throw "oops";
}
item.position.x = rand(-10, 10);
item.position.y = rand(-10, 10);
item.position.z = rand( 0, -50);
scene.add(item);
items.push(item);
}
camera.position.z = 5;
const countElem = $('#count');
function render(time) {
time *= 0.001;
resize();
// animate the items
items.forEach((items, ndx) => {
items.rotation.x = time * 1.2 + ndx * 0.01;
items.rotation.y = time * 1.1;
});
// turn on/off a random items
items[rand(items.length) | 0].visible = Math.random() > .5;
renderer.render(scene, camera);
// get the current counts
const info = renderer.context.info;
countElem.textContent = ` VERTS: ${info.vertCount}
POINTS: ${info.primCount[0]}
LINES: ${info.primCount[1]}
TRIANGLES: ${info.primCount[2]}`;
// zero out the count
renderer.context.info.vertCount = 0;
renderer.context.info.primCount = [0, 0, 0];
requestAnimationFrame(render);
}
requestAnimationFrame(render);
function rand(min, max) {
if (max === undefined) {
max = min;
min = 0;
}
return Math.random() * (max - min) + min;
}
function resize() {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
if (canvas.width !== width || canvas.height !== height) {
renderer.setSize(width, height, false);
camera.aspectRatio = width / height;
camera.updateProjectionMatrix();
}
}
body { border: 0; }
canvas { width: 100vw; height: 100vh; display: block; }
#ui { position: absolute; left: 1em; top: 1em; background: rgba(0,0,0,.5); color: white; padding: .5em; width: 10em; }
<canvas></canvas>
<div id="ui">
<pre id="count"></pre>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/92/three.min.js"></script>
Of course you might want to add support for drawArraysInstanced etc... and support for WebGL2.
We removed the amount of processed vertices from renderer.info.render since the important measurement is the amount or rendered primitives (so triangles, points, lines). Please read https://github.com/mrdoob/three.js/pull/13404 and the related issues/PRs for more information. If you still want to know how many vertices were processed, you need to count manually. WebGL can't do this for you.

d3.time/crossfilter days are off by one

I've been trying to create a dc.js rowchart showing stats per day, my dimension and group are
var dayNameFormat = d3.time.format("%A");
var weekDayFormat = d3.time.format('%w'); //weekday as a decimal number [0(Sunday),6].
var dayOfWeek = ndx.dimension(function(d) {
return weekDayFormat(d.date) + '.' + dayNameFormat(d.date);
});
var dayOfWeekGroup = dayOfWeek.group().reduce(
function(p, d) {
++p.count;
p.totalPoints += +d.points_per_date;
p.averagePoints = (p.totalPoints / p.count);
if (d.student_name in p.studentNames) {
p.studentNames[d.student_name] += 1
} else {
p.studentNames[d.student_name] = 1;
p.studentCount++;
}
return p;
},
function(p, d) {
--p.count;
p.totalPoints -= +d.points_per_date;
p.averagePoints = (p.totalPoints / p.count);
if (p.studentNames[d.student_name] === 0) {
delete p.studentNames[d.student_name];
p.studentCount--;
}
return p;
},
function() {
return {
count: 0,
totalPoints: 0,
averagePoints: 0,
studentNames: {},
studentCount: 0
};
});
and chart
dayOfWeekChart
.width(250)
.height(180)
.margins({
top: 20,
left: 20,
right: 10,
bottom: 20
})
.dimension(dayOfWeek)
.group(dayOfWeekGroup)
.valueAccessor(function(d) {
return d.value.totalPoints
})
.renderLabel(true)
.label(function(d) {
return d.key.split('.')[1] + '(' + d.value.totalPoints + ' points)';
})
.renderTitle(true)
.title(function(d) {
return d.key.split('.')[1];
})
.elasticX(true);
I expected the results to match those of my database query
The total values are correct, but the days have been offset by a day (Sunday has Monday's total)
My fiddle https://jsfiddle.net/santoshsewlal/txrLw9Lc/
I've been doing my head in trying to get this right, any help will be great.
Thanks
It appears to be a UTC date/time problem. Dealing with data from multiple time zones is always confusing!
All of your timestamps are very near to the next day - they are all timestamped at 22:00. So it depends on the timezone which day they should be interpreted as. I guess you might be in the eastern hemisphere, which adds a couple of hours to these timestamps when you read them in your spreadsheet?
You're chopping off the time with substr:
d.date = dateFormat.parse(d.activity_date.substr(0, 10));
I'd suggest trying to parse the whole time instead:
var dateFormat = d3.time.format('%Y-%m-%dT%H:%M:%S.%LZ');
data.forEach(function(d, i) {
d.index = i;
d.date = dateFormat.parse(d.activity_date);
However, I'm no expert in timezones so I can't promise anything. Just pointing out where the problem likely lies.

How to move handson table scroll bar to specific row and column..?

I'm trying find out a method or a way by which i can move handson tables scroll bar to specific row and column.
I tried using
selectCell (row: Number, col: Number, rows: Number, cols: Number, scrollToSelection: Boolean (Optional)) but it doesn't seems to work
here is the Fiddle link for it http://jsfiddle.net/hpfvc9bx/
$(document).ready(function () {
function createBigData() {
var rows = []
, i
, j;
for (i = 0; i < 1000; i++) {
var row = [];
for (j = 0; j < 6; j++) {
row.push(Handsontable.helper.spreadsheetColumnLabel(j) + (i + 1));
}
rows.push(row);
}
return rows;
}
var maxed = false
, resizeTimeout
, availableWidth
, availableHeight
, $window = $(window)
, $example1 = $('#example1');
var calculateSize = function () {
if(maxed) {
var offset = $example1.offset();
availableWidth = $window.width() - offset.left + $window.scrollLeft();
availableHeight = $window.height() - offset.top + $window.scrollTop();
$example1.width(availableWidth).height(availableHeight);
}
};
$window.on('resize', calculateSize);
var table = $example1.handsontable({
data: createBigData(),
colWidths: [55, 80, 80, 80, 80, 80, 80], //can also be a number or a function
rowHeaders: true,
colHeaders: true,
fixedColumnsLeft: 2,
fixedRowsTop: 2,
minSpareRows: 1,
stretchH: 'all',
contextMenu: true,
afterChange : function(changes){
console.log(changes);
}
});
$('.maximize').on('click', function () {
maxed = !maxed;
if(maxed) {
calculateSize();
}
else {
$example1.width(400).height(200);
}
$example1.handsontable('render');
});
$("#setSelectedRow").on('click',function(){
console.log(table);
table.select(9,3,12,6,true); // not working as it doesnt move scroll bar to specified column and range
})
function bindDumpButton() {
$('body').on('click', 'button[name=dump]', function () {
var dump = $(this).data('dump');
var $container = $(dump);
console.log('data of ' + dump, $container.handsontable('getData'));
});
}
bindDumpButton();
});
Can anyone please help me on this...
Thanks In advance...
You can move to specific cell using "selectCell" of handsontable.
You have use table.select(...) in $("#setSelectedRow").on('click',function(){....
It won't work as you are using table DOM element but you need to have "instance" of handsontable. That can be done as,
First Way:
var tblInstance = $example1.handsontable('getInstance');
And then apply "selectCell()" as
tblInstance.selectCell(rowNum, colNum);
Second Way:
Use $example1.handsontable("selectCell", rowNum, colNum);
Please refer to fiddle for the second way, in which :
$("#setSelectedRow").on('click',function(){
console.log(table);
$example1.handsontable("selectCell", 9, 5); // select 9th row's 5th column
})
Hope this will help you :)

Resources