andredumas / techan.js

A visual, technical analysis and charting (Candlestick, OHLC, indicators) library built on D3.
http://techanjs.org/
MIT License
2.4k stars 537 forks source link

Zooming and feed example #208

Open artjoma opened 6 years ago

artjoma commented 6 years ago

Hi ! I try to create a diagram with zooming and feed functionality. Every time after add new bar(OHLC) called redraw and zoom reset to default. How can I fix it ?

`

            data = data.map(function(d) {
                return {
                    date: new Date(d.Date * 1000),
                    open: +d.Open,
                    high: +d.High,
                    low: +d.Low,
                    close: +d.Close,
                    volume: +d.Volume
                };
            }).sort(function(a, b) { return d3.ascending(accessor.d(a), accessor.d(b)); });

            zoomableInit = x.zoomable().domain([indicatorPreRoll, data.length]).copy(); // Zoom in a little to hide indicator preroll
            yInit = y.copy();

            redraw();

            function redraw(){
                var accessor = candlestick.accessor();
                x.domain(data.map(accessor.d));
                // Show only 150 points on the plot
                x.zoomable().domain([data.length-130, data.length]);
                y.domain(techan.scale.plot.ohlc(data.slice(indicatorPreRoll)).domain());
                yVolume.domain(techan.scale.plot.volume(data).domain());

                svg.select("g.candlestick").datum(data).call(candlestick);
                svg.select("g.close.annotation").datum([data[data.length-1]]).call(closeAnnotation);
                svg.select("g.volume").datum(data).call(volume);

                svg.select("g.crosshair.ohlc").call(ohlcCrosshair).call(zoom);

                draw();

            //3-Jun-14,62.62,63.42,62.32,62.87,32216707
            // Set next timer expiry
            setTimeout(function() {
                data.push({
                    date: new Date((date + 1) * 1000),
                    open: +62.62,
                    high: +63.42,
                    low: +62.32,
                    close: +62.87,
                    volume: +32216707
                });

                redraw();
            }, (Math.random()*1000)+1900); // Randomly pick an interval to update the chart
            }
        });`
MartyIX commented 6 years ago

I needed something like that so I used the following boolean flag:

let update = x.zoomable().domain()[1] >= feed.length - 10;

where the rationale is that when zoom contains the latest 10 bars, then it is safe to redraw the chart because it will not reset user zooming.

https://pastebin.com/7wmAQ0SM

Yet, it's just a workaround. I guess there is a better solution.

ale316 commented 6 years ago

I'm not sure how similar your example is to mine, but I was able to add data to my zoomable series without resetting the chart to default.

This is my zoomed function. Some of the stuff is defined above, but note how I'm storing rescaledY and rescaledX to a variable.

var rescaledY;
var rescaledX;
function zoomed() {
    rescaledY = d3.event.transform.rescaleY(y);
    rescaledX = d3.event.transform.rescaleX(zoomableInit);
    yAxis.scale(rescaledY);
    candlestick.yScale(rescaledY);

    // Emulates D3 behaviour, required for financetime due to secondary zoomable scale
    x.zoomable().domain(rescaledX.domain());

    draw();
}

Now in the redraw function (called when new data is added to my series), if either rescaledY or rescaledX are defined, I rescale.

function redraw(d) {
    var accessor = candlestick.accessor();
    x.domain(d.map(accessor.d));
    y.domain(techan.scale.plot.ohlc(d, accessor).domain());
    zoomableInit = x.zoomable().clamp(true).copy();

    if (rescaledY || rescaledX) {
        yAxis.scale(rescaledY);
        candlestick.yScale(rescaledY);
        x.zoomable().domain(rescaledX.domain());
    }

    svg.select('g.x.axis').call(xAxis);
    svg.select('g.y.axis').call(yAxis);

    svg.select("g.candlestick").datum(d).call(candlestick);
}

Hope this helps.

dashko commented 5 years ago

Bump.