trash-and-fire / svelte-lightweight-charts

Svelte wrapper for financial lightweight charts
MIT License
105 stars 13 forks source link

Always show the newest data at first #62

Closed MuslemRahimi closed 1 year ago

MuslemRahimi commented 1 year ago

Hi,

I have the issue that when i update new data to my chart via a button click (e.g. stock data from 2023) it does not show it immediately in the graph, i.e. it should show the new data instead of swiping right. I want that the should always show the newest data when the button was clicked.

Do you know how i can achieve this?

trash-and-fire commented 1 year ago

Try adding <TimeScale> with shiftVisibleRangeOnNewBar property.

<Chart>
     <TimeScale shiftVisibleRangeOnNewBar={true}/>
</Chart>
MuslemRahimi commented 1 year ago

Unfortunately it does not solve the issue. This is how my code look. When i click on a button the data of linear regression appears. But it does not show immediately the newest data


<div class = 'graph'>
<Chart {...options} width={innerWidth} height={height} container={{ref}} ref={(ref) => chart = ref}  >
  {#if chartMode === 'candleStick'}
    <CandlestickSeries
    data={candleStickData}
    priceScaleId="right"
    priceLineVisible= {false}
    />
    {:else}
    <LineSeries data={lineData}
    color="#d4d9d9"
    lineWidth={1.5}
    priceScaleId="right"
    priceLineVisible= {false}
    />
    {/if}
    <HistogramSeries
    data={volumeData}
    priceScaleId=""
    priceFormat={{type: 'volume'}}
    scaleMargins={{top: 0.8, bottom: 0}}/>

    {#if displayBBANDS}
    <LineSeries data={bbup}
    color="#00F13F"
    lineWidth={1.5}
    priceLineVisible= {false}
    />
    <LineSeries data={bbmiddle}
    color="#00F13F"
    lineWidth={1.5}
    priceLineVisible= {false}
    />
    <LineSeries data={bbdown}
    color="#00F13F"
    lineWidth={1.5}
    priceLineVisible= {false}
    />
    {/if}

    {#if displaySMA}
    <LineSeries data={sma}
    color="#039dfc"
    lineWidth={1.8}
    priceLineVisible= {false}
    />
    {/if}

    {#if displayEMA}
    <LineSeries data={ema}
    color="#fc035a"
    lineWidth={1.8}
    priceLineVisible= {false}
    />
    {/if}

    <!-- Linear Regression Model -->
    {#if rawLinearRegression !== null}
    <LineSeries 
    data={linearRegressionData}
    color="#ff8500"
    lineWidth={2.5}
    priceLineVisible= {false}
    lineStyle = {1}
    />
    {/if}

     <!-- Brownian-Motion Model -->
     {#if rawBrownian !== null}
     <!-- Upper Bound-->
     <LineSeries 
     data={brownianUpperData}
     color="#6095f7"
     lineWidth={2.5}
     priceLineVisible= {false}
     lineStyle = {1}
     />
     <!-- Lower Bound-->
     <LineSeries 
     data={brownianLowerData}
     color="#6095f7"
     lineWidth={2.5}
     priceLineVisible= {false}
     lineStyle = {1}
     />
     {/if}
     <TimeScale fixRightEdge={fixRight} fixLeftEdge={fixLeft} shiftVisibleRangeOnNewBar={true}/>
     <!-- It seems like there is some internal problems with lightweight-charts. To-do list added-->
    <TimeScale on:visibleLogicalRangeChange={handleChartLogicalRangeChange}/>
</Chart>
MuslemRahimi commented 1 year ago

here is a short demo of my problem: https://www.youtube.com/watch?v=kjBlhTLEC1g

Interestingly, the graph goes to the left when i click the predict button where the new data arrives.

trash-and-fire commented 1 year ago

Minimal demo: https://svelte.dev/repl/76105df7d580425596ca45063119f703?version=3.55.1

Please don't use two instances of <TimeScale> on the same chart. Each chart has only one TimeScale, therefore you should merge all time scale properties to the same element.

     <TimeScale
          fixRightEdge={fixRight} 
          fixLeftEdge={fixLeft} 
          shiftVisibleRangeOnNewBar={true}
          on:visibleLogicalRangeChange={handleChartLogicalRangeChange
     />

If you want to update data on series then add reactive={true} to related series.

trash-and-fire commented 1 year ago

A little advice. The component architecture of the library encourages decomposition into blocks. You can separate the Brownian-Motion Model into a separate component that will render two separate series within it.

<Chart>
     ...
    {#if rawBrownian !== null}
         <BrownianMotion data={brownianData}/>
    {/if}
</Chart>
trash-and-fire commented 1 year ago

I finally got time to watch your video.

shiftVisibleRangeOnNewBar Shift the visible range to the right (into the future) by the number of new bars when new data is added. Note that this only applies when the last bar is visible.

As I see on your video the last bar is invisible at the moment when you add new data. That is why it does not work. You need to get a reference to the price scale and manage visible range manually after adding a new data in this case.

For example you can use scrollToRealtime method.

PS: Good job

trash-and-fire commented 1 year ago

I will create an example.

trash-and-fire commented 1 year ago

Looks like there is an issue. https://svelte.dev/repl/6594b4d308ea44409397679358dd4f37?version=3.55.1

I will investigate this.

MuslemRahimi commented 1 year ago

Thank you so much. This really helps. So far the problem is solved from my side. If my startup succeeds i will definitely repay you for your hard work <3. Much appreciated brother

MuslemRahimi commented 1 year ago

Looks like there is an issue. https://svelte.dev/repl/6594b4d308ea44409397679358dd4f37?version=3.55.1

I will investigate this.

I do have also another problem. When im completely zoomed out and click on the button. It doesnt really show the new data. Is it possible to zoom in into the new data?

trash-and-fire commented 1 year ago

Can you make a video?

Actually you can have a full control over zoom and visible range using time scale ref. Look at it's api. There are a bunch of methods that you can use: fitContent, resetTimeScale, setVisibleLogicalRange, setVisibleRange, scrollToPosition and etc

MuslemRahimi commented 1 year ago

A video is not necessary. In your example https://svelte.dev/repl/6594b4d308ea44409397679358dd4f37?version=3.55.1 zoom completely out and shift to the left. Now click on the button you will see that the new data is not really visible because of the zoom. Can you modify the example where after the click the graph is zoomed in to the new data that was added?

trash-and-fire commented 1 year ago

Ok. I did not quite get what do you want =)

This is an example of managing visible range. https://svelte.dev/repl/dc2dd9c7c01e4c95bf037cbfb131baf0?version=3.55.1

For example before scrolling you can manually shrink visible range to 20 bars using

timescale.setVisibleLogicalRange({ from: 0, to: 20 });

Actually this moves the left edge of view to the first bar and the right edge to the 20th bar. You can move the camera at any different range as you need and then call scrollToRealtime to have nice animation.

If you need a smooth zoom to a specific range then it is quite complicated and requires manual animation using requestAnimationFrame and a series of calls setVisibleLogicalRange but it is also possible.

trash-and-fire commented 1 year ago

https://svelte.dev/repl/1546200259d145aa8c48c5ca25b4a586?version=3.55.1 this is linear interpolated smooth zoom from any range to the last 20 bars

MuslemRahimi commented 1 year ago

really nice, thanks