As I mentioned in that article “I Built the Best Renko Builder in Python 3 Years Ago“, after realizing that Python couldn’t handle my speed requirements, I started using Python only as a bridge and used JavaScript to build the Renko candles.
It’s more efficient and faster, but it requires more coding for the chart (though only once!).
you need to pass historical data to renko_builder function then stream tick data and send to update_renko function
Historical Renko Candle From Tick Data
function renko_builder(data) {
// renkosize = parseFloat(document.getElementById('renkosize_input').value)
let oo = [data.bid[0]];
let hh = [data.bid[0] + renkosize];
let ll = [data.bid[0]];
let cc = [data.bid[0] + renkosize];
let dd = [1];
for (let i = 0; i < data.bid.length; i++) {
if (data.bid[i] !== null) {
let lst = data.bid[i];
len = cc.length - 1;
if (cc.at(-1) > oo.at(-1)) {
if (lst >= (cc.at(-1) + renkosize)) {
calc = Math.round((lst - cc.at(-1)) / renkosize);
if (calc >= 2) {
for (let j = 0; j < Math.floor(calc); j++) {
dd.push(dd.at(-1) + 1);
oo.push(cc.at(-1));
hh.push(cc.at(-1) + renkosize);
ll.push(cc.at(-1));
cc.push(cc.at(-1) + renkosize);
}
} else {
dd.push(dd.at(-1) + 1);
oo.push(cc.at(-1));
hh.push(cc.at(-1) + renkosize);
ll.push(cc.at(-1));
cc.push(cc.at(-1) + renkosize);
}
} else if (lst <= (oo.at(-1) - renkosize)) {
calc = Math.round((oo.at(-1) - lst) / renkosize);
if (calc >= 2) {
for (let m = 0; m < Math.floor(calc); m++) {
if (m === 0) {
dd.push(dd.at(-1) + 1);
hh.push(oo.at(-1));
ll.push(oo.at(-1) - renkosize);
cc.push(oo.at(-1) - renkosize);
oo.push(oo.at(-1));
} else {
dd.push(dd.at(-1) + 1);
oo.push(cc.at(-1));
hh.push(cc.at(-1));
ll.push(cc.at(-1) - renkosize);
cc.push(cc.at(-1) - renkosize);
}
}
} else {
dd.push(dd.at(-1) + 1);
hh.push(oo.at(-1));
ll.push(oo.at(-1) - renkosize);
cc.push(oo.at(-1) - renkosize);
oo.push(oo.at(-1));
}
}
} else if (cc.at(-1) < oo.at(-1)) {
if (lst >= (oo.at(-1) + renkosize)) {
calc = Math.round((lst - oo.at(-1)) / renkosize);
if (calc >= 2) {
for (let bv = 0; bv < Math.floor(calc); bv++) {
if (bv === 0) {
dd.push(dd.at(-1) + 1);
hh.push(oo.at(-1) + renkosize);
ll.push(oo.at(-1));
cc.push(oo.at(-1) + renkosize);
oo.push(oo.at(-1));
} else {
dd.push(dd.at(-1) + 1);
oo.push(cc.at(-1));
hh.push(cc.at(-1) + renkosize);
ll.push(cc.at(-1));
cc.push(cc.at(-1) + renkosize);
}
}
} else {
dd.push(dd.at(-1) + 1);
hh.push(oo.at(-1) + renkosize);
ll.push(oo.at(-1));
cc.push(oo.at(-1) + renkosize);
oo.push(oo.at(-1));
}
} else if (lst <= (cc.at(-1) - renkosize)) {
calc = Math.round((cc.at(-1) - lst) / renkosize);
if (calc >= 2) {
for (let lm = 0; lm < Math.floor(calc); lm++) {
dd.push(dd.at(-1) + 1);
oo.push(cc.at(-1));
hh.push(cc.at(-1));
ll.push(cc.at(-1) - renkosize);
cc.push(cc.at(-1) - renkosize);
}
} else {
dd.push(dd.at(-1) + 1);
oo.push(cc.at(-1));
hh.push(cc.at(-1));
ll.push(cc.at(-1) - renkosize);
cc.push(cc.at(-1) - renkosize);
}
}
}
if (data.bid[i] > hh[hh.length - 1]){
hh[hh.length - 1] = data.bid[i]
}
if (data.bid[i] < ll[ll.length -1]){
ll[ll.length - 1] = data.bid[i]
}
}
}
t_candle = {
time:dd,
open:oo,
high:hh,
low:ll,
close:cc,
}
}JavaScriptExpand
Live Renko Candle From Tick Data
function update_renko(data) {
lst = data.bid;
if (t_candle.close.at(-1) > t_candle.open.at(-1)) {
if (lst >= (t_candle.close.at(-1) + renkosize)) {
calc = Math.round((lst - t_candle.close.at(-1)) / renkosize);
if (calc >= 2) {
for (let j = 0; j < Math.floor(calc); j++) {
t_candle.time.push(t_candle.time.at(-1) + 1);
t_candle.open.push(t_candle.close.at(-1));
t_candle.high.push(t_candle.close.at(-1) + renkosize);
t_candle.low.push(t_candle.close.at(-1));
t_candle.close.push(t_candle.close.at(-1) + renkosize);
}
} else {
t_candle.time.push(t_candle.time.at(-1) + 1);
t_candle.open.push(t_candle.close.at(-1));
t_candle.high.push(t_candle.close.at(-1) + renkosize);
t_candle.low.push(t_candle.close.at(-1));
t_candle.close.push(t_candle.close.at(-1) + renkosize);
}
} else if (lst <= (t_candle.open.at(-1) - renkosize)) {
calc = Math.round((t_candle.open.at(-1) - lst) / renkosize);
if (calc >= 2) {
for (let m = 0; m < Math.floor(calc); m++) {
if (m === 0) {
t_candle.time.push(t_candle.time.at(-1) + 1);
t_candle.high.push(t_candle.open.at(-1));
t_candle.low.push(t_candle.open.at(-1) - renkosize);
t_candle.close.push(t_candle.open.at(-1) - renkosize);
t_candle.open.push(t_candle.open.at(-1));
} else {
t_candle.time.push(t_candle.time.at(-1) + 1);
t_candle.open.push(t_candle.close.at(-1));
t_candle.high.push(t_candle.close.at(-1));
t_candle.low.push(t_candle.close.at(-1) - renkosize);
t_candle.close.push(t_candle.close.at(-1) - renkosize);
}
}
} else {
t_candle.time.push(t_candle.time.at(-1) + 1);
t_candle.high.push(t_candle.open.at(-1));
t_candle.low.push(t_candle.open.at(-1) - renkosize);
t_candle.close.push(t_candle.open.at(-1) - renkosize);
t_candle.open.push(t_candle.open.at(-1));
}
}
} else if (t_candle.close.at(-1) < t_candle.open.at(-1)) {
if (lst >= (t_candle.open.at(-1) + renkosize)) {
calc = Math.round((lst - t_candle.open.at(-1)) / renkosize);
if (calc >= 2) {
for (let bv = 0; bv < Math.floor(calc); bv++) {
if (bv === 0) {
t_candle.time.push(t_candle.time.at(-1) + 1);
t_candle.high.push(t_candle.open.at(-1) + renkosize);
t_candle.low.push(t_candle.open.at(-1));
t_candle.close.push(t_candle.open.at(-1) + renkosize);
t_candle.open.push(t_candle.open.at(-1));
} else {
t_candle.time.push(t_candle.time.at(-1) + 1);
t_candle.open.push(t_candle.close.at(-1));
t_candle.high.push(t_candle.close.at(-1) + renkosize);
t_candle.low.push(t_candle.close.at(-1));
t_candle.close.push(t_candle.close.at(-1) + renkosize);
}
}
} else {
t_candle.time.push(t_candle.time.at(-1) + 1);
t_candle.high.push(t_candle.open.at(-1) + renkosize);
t_candle.low.push(t_candle.open.at(-1));
t_candle.close.push(t_candle.open.at(-1) + renkosize);
t_candle.open.push(t_candle.open.at(-1));
}
} else if (lst <= (t_candle.close.at(-1) - renkosize)) {
calc = Math.round((t_candle.close.at(-1) - lst) / renkosize);
if (calc >= 2) {
for (let lm = 0; lm < Math.floor(calc); lm++) {
t_candle.time.push(t_candle.time.at(-1) + 1);
t_candle.open.push(t_candle.close.at(-1));
t_candle.high.push(t_candle.close.at(-1));
t_candle.low.push(t_candle.close.at(-1) - renkosize);
t_candle.close.push(t_candle.close.at(-1) - renkosize);
}
} else {
t_candle.time.push(t_candle.time.at(-1) + 1);
t_candle.open.push(t_candle.close.at(-1));
t_candle.high.push(t_candle.close.at(-1));
t_candle.low.push(t_candle.close.at(-1) - renkosize);
t_candle.close.push(t_candle.close.at(-1) - renkosize);
}
}
}
}JavaScriptExpand