Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement basic box drawing #1064

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open

Implement basic box drawing #1064

wants to merge 4 commits into from

Conversation

tpunt
Copy link

@tpunt tpunt commented Apr 17, 2022

Type of PR: Enhancement

PR checklist:

  • Addresses an existing issue: fixes #
  • Includes tests
  • Documentation update

Overview of change:

I have implemented basic box/rectangle drawing. This feature has been requested a few times in the past (#706, #408, in online chatrooms, on discord, etc). I realise it has been discussed to expose the raw canvas also as a potential solution, but it seems there is some complexity around this (e.g. there are multiple canvases). It also feels as though basic features such as this (that complement the line drawing abilities) would be much better suited to be integrated into the library itself (which would also benefit from having the objects rescaled upon the rescaling of axes).

Things done:

  • Box creation based upon two prices and two times
  • Box moving with the rescaling of the axes
  • Box border (with colour, styling, thickness, and the ability to disable it)
  • Box fill colour with configurable opacity

Things remaining to do:

  • Ability to add a title to the box
  • Add prices to the Y axis for the top/bottom of the box
  • Add tests
  • Update the documentation

If this is desirable to have in the main project, then I am happy to spend some more time on finishing things up. If this is not desirable though, then I'll simply use my fork, and this PR can be closed.

Code example:

const box = {
  lowPrice: 2713.0,
  highPrice: 2797.0,
  earlyTime: 1641409200,
  lateTime: 1641823200,
  borderColor: '#00008B',
  borderWidth: 3,
  borderStyle: LightweightCharts.LineStyle.Dashed,
  fillColor: '#0ff',
  fillOpacity: 0.2,
  borderVisible: true,
  axisLabelVisible: false,
  title: 'My box',
};

const createdBox = mainSeries.createBox(box);

// mainSeries.removeBox(createdBox);
Example pictures Screenshot 2022-04-17 at 16 52 55

ezgif-2-4852b5dc20

Is there anything you'd like reviewers to focus on?

Whether this feature is desirable to have in the core library.

PR Update:

See #1064 (comment) of this PR for more abilities.

@olablt
Copy link

olablt commented May 16, 2022

That is a great feature! Is it hard to add an option to have the static width and scale only vertically when the chart is zoomed?

@Swoorup
Copy link

Swoorup commented May 22, 2022

It would be nice if this also takes in an array of boxes. Also what about being able to update the boxes? Currently if I am not mistaken you'll have to remove and re-add it again?

I suppose a unified api/template would be handy across all markers, boxes, etc... (Add, Remove, Bulk Add, Bulk Delete, Update)?

@tpunt
Copy link
Author

tpunt commented May 22, 2022

That is a great feature! Is it hard to add an option to have the static width and scale only vertically when the chart is zoomed?

This could be added without much effort. I'm not quite sure what the use-case is for it, though (TradingView itself doesn't allow this either, unless I'm misunderstanding your comment).

@tpunt
Copy link
Author

tpunt commented May 22, 2022

It would be nice if this also takes in an array of boxes. Also what about being able to update the boxes? Currently if I am not mistaken you'll have to remove and re-add it again?

I suppose a unified api/template would be handy across all markers, boxes, etc... (Add, Remove, Bulk Add, Bulk Delete, Update)?

Yes, I'm not against adding any of these abilities. This PR only adds a very basic box drawing API that is supposed to mimic the pre-existing line drawing API. I'm happy to expand upon this if the maintainers would like this apart of the main repo. Otherwise, the box API in its current state is enough for my own private project needs, so I'll just close this PR.

@tpunt
Copy link
Author

tpunt commented May 22, 2022

For those looking to use this feature, I had to do a couple of extra things in order to integrate this into my own project via NPM:

  1. Add a prepare command to have node build the project upon installation (since the git repo doesn't have these files): change
  2. Remove the install hooks around git: change

I did both of these in my boxes-install branch, so for those looking to use this, they can simply execute the following:

npm install "https://github.com/tpunt/lightweight-charts.git#boxes-install"

@leosj
Copy link

leosj commented Jul 7, 2022

@tpunt can you add createBoxes api in it?

@tpunt
Copy link
Author

tpunt commented Jul 26, 2022

@leosj I'm happy to extend the API, but only if this feature gets added to this repo. I'm still waiting for the owners here to comment on this PR - right now, it looks as though they are not interested in adding new features to lightweight-charts. This is a shame because the charting library is excellent, but it really lacks some quite basic, but very useful abilities.

@ty11111111
Copy link

ty11111111 commented Jul 29, 2022

screen-20220729-154326.3.mp4

It seems that the box disappears completely when the height of the box exceeds the visible y-axis scale.

X-axis scale works fine.
Any hints on how to make the box show even if the visible y-axis is not inclusive of the height of the box?

Attached video to illustrate what I mean.

Edit: nvm I mixed up the lowPrice and highPrice in the box settings. It is working fine

@GorillaBus
Copy link

This works perfectly and is the unique feature I was requiring from Lightweight Charts. Thanks a ton for your work !!

@juniormcmillan
Copy link

This is great. Just what i was looking for!

Is it possible for someone to provide a method of including this in HTML such as

https://jsfiddle.net/adrianntf/6qea5ytv/

That would be great. Thanks

@tpunt tpunt dismissed a stale review via 39ac209 November 6, 2022 13:57
@tpunt
Copy link
Author

tpunt commented Nov 6, 2022

@juniormcmillan I'm not sure I understand why you'd want the ability to write HTML code, and have that display boxes on the chart. You could write JSON code to generate both HTML code and boxes, though.

@tpunt
Copy link
Author

tpunt commented Nov 6, 2022

Update

I've made an update to this PR. I wanted the ability to draw boxes that were rotated, but it appears that canvas does not allow you to draw boxes in that way. You can draw a simple box and then rotate it, but that would not scale properly with the axes on the chart. So instead of making a box a canvas rectangle, I've made it a series of connecting lines (which should have no functional change).

To take advantage of this new flexibility to draw arbitrary shapes, you can specify a list of corners (2 or more), rather than the old parameters lowPrice, highPrice, earlyTime, lateTime.

This is fully backwards compatible with the original PR (for those already relying upon it). Examples:

Diagonal box example
const box = {
        corners: [
                { time: 1641392200, price: 2902 },
                { time: 1641324200, price: 2902 },
                { time: 1641412200, price: 2750 },
                { time: 1641425200, price: 2750 },
        ],
        borderColor: '#00f',
        borderWidth: 3,
        borderStyle: LightweightCharts.LineStyle.Dashed,
        fillColor: '#0ff',
        fillOpacity: 0.3,
        borderVisible: true,
        axisLabelVisible: false,
        title: 'My box',
};

const createdBox = mainSeries.createBox(box);

// mainSeries.removeBox(createdBox);

Picture:
Screen Recording 2022-11-06 at 14 04 53

Arbitrary lines

Creating horizontal, vertical, and diagonal lines (of set lengths):

const shapes = [{
        corners: [
                { time: 1641392200, price: 2902 },
                { time: 1641412200, price: 2750 },
        ],
        borderColor: '#fff',
        borderWidth: 2,
        borderStyle: LightweightCharts.LineStyle.Dashed,
        fillColor: '#fff',
        fillOpacity: 0.3,
        borderVisible: true,
        axisLabelVisible: false,
        title: 'My box',
},{
        corners: [
                { time: 1641272200, price: 2875 },
                { time: 1641512200, price: 2875 },
        ],
        borderColor: '#fff',
        borderWidth: 2,
        borderStyle: LightweightCharts.LineStyle.Dashed,
        fillColor: '#fff',
        fillOpacity: 0.3,
        borderVisible: true,
        axisLabelVisible: false,
        title: 'My box',
},{
        corners: [
                { time: 1641812200, price: 2700 },
                { time: 1641812200, price: 2900 },
        ],
        borderColor: '#fff',
        borderWidth: 2,
        borderStyle: LightweightCharts.LineStyle.Dashed,
        fillColor: '#fff',
        fillOpacity: 0.3,
        borderVisible: true,
        axisLabelVisible: false,
        title: 'My box',
}];

for (shape of shapes) {
        const createdShape = mainSeries.createBox(shape);
        // mainSeries.removeBox(createdShape);
}

Picture:
Screenshot 2022-11-06 at 14 15 57

I realise the createBox name is now a bit of a misnomer - createShape would be more accurate. However, I'll leave it as-is to maintain backwards compatibility for others.

Changes are apart of the boxes and boxes-install branches, for those looking to use this.

@0x0tyy
Copy link

0x0tyy commented Nov 8, 2022

I haven't tried your updated code yet but from looking at it, am I correct in assuming that you can have more than 4 corners ?

@tpunt
Copy link
Author

tpunt commented Nov 9, 2022

@0x0tyy Yes, you can specify 2 or more corners. 2 corners just means a straight line (in any direction).

@mrle0pold
Copy link

mrle0pold commented Dec 10, 2022

Ive tried everything possible to disable the border and its still showing. Any clues what i did wrong?

Capture

image

@0x0tyy
Copy link

0x0tyy commented Dec 14, 2022

i tried to use this patch to create a kernel density estimated TPO market profile. Unfortunately, even after decreasing the tick size (to 1 , instead of 0.01), performance still drops after 2-3 profiles on screen.
I could decrease tick size further and overcome the jagged lines with beziercurves but I don't think it will make a huge difference. Anyone have any other suggestions for increasing performance?

screen-20221214-165408.2.mp4

@tpunt tpunt dismissed a stale review via 6aa61f8 December 18, 2022 17:38
@tpunt
Copy link
Author

tpunt commented Dec 18, 2022

@mrle0pold Good catch! When I moved things to line-based drawing, the default border was a thin black line. I've now made a commit (6aa61f8) to allow you to (once again) disable the border completely (borderVisible: false).

@tpunt
Copy link
Author

tpunt commented Dec 18, 2022

@0x0tyy I assume it is because of the number of points needing to be drawn in order to render such shapes. Would it be possible to render bars instead of curves (similar to other Volume Profile indicators on TradingView)? They would be much friendlier, since there will be far fewer points.

@eugene-korobko eugene-korobko mentioned this pull request Jan 12, 2023
2 tasks
@WISEPLAT
Copy link

Really cool opportunity! Please release it!

@cheriansk
Copy link

I was getting compile errors when taking the latest version of Light-weight charts with this code. Have fixed them and raised a PR in the form - cheriansk#1

@sharpkids
Copy link

Thank you @cheriansk for the commit, I ended up adding tpunt's changes for the package.json #1064 (comment) so that I can install the library with npm using the following command (just in case if someone else needs it):

npm install "https://github.com/sharpkids/lightweight-charts.git"

Because shapes are now drawn with lines, the default line fill is thin and black.
We must therefore override this when no border is desired.
@tpunt tpunt dismissed a stale review via 8070059 March 31, 2023 12:19
@mattou78400
Copy link

is there any plans of merging this and pushing to prod? and/or make it compatible with 4.0.1?

thanks!

@romfrancois
Copy link
Contributor

We'll soon release a plugin mechanism on top of the library that will allow you to achieve that request without necessarily awaiting for our approval.
Will update this ticket once we have something more concrete.

@tpunt
Copy link
Author

tpunt commented May 4, 2023

@mattou78400 This PR is already compatible with 4.0.1 - I rebased it against the master branch a month ago or so.

@erfinbadrian
Copy link

Hii ,
Is possible to draw box outside xAxis?

Like this :
image

Thank you
cc : @tpunt

@tpunt
Copy link
Author

tpunt commented May 12, 2023

@erfinbadrian Hey Erfin.

In the current branch, no, this is not possible. However, I had the exact same need, and so I implemented this in a boxes-offscreen branch. Note that in order to get things to work, you must pass in a timeframe parameter. This is because lightweight-charts has no concept of a timeframe when rendering candlesticks - it simply renders the OHLC objects you give it. This means you can technically pass in 3 minute candles with 15 minute candles (with 4 hour candles, etc) and the chart will render fine. In reality, this makes no sense. So in order to correctly calculate the distance offsceen, you need to pass in a timeframe parameter (a number in seconds) with the box options.

Note that the boxes-offscreen branch does not include the two commits from boxes-install (4a74c7d, 8c3f8b0), so you may want to cherry-pick them for a smoother npm install experience.

@LmfaoHax
Copy link

can you please share the built branch with us? because im getting so confused with the errors when i try to build it myself

@tpunt
Copy link
Author

tpunt commented May 20, 2023

@LmfaoHax I'm not sure I understand what you mean. I mentioned in one of the earlier comments that I made a couple of modifications to the build in the boxes-install branch so that you can do a simple npm install "https://github.com/tpunt/lightweight-charts.git#boxes-install". If that doesn't work, then you will need to post more information about the errors you're receiving.

@LmfaoHax
Copy link

@tpunt when i try to install it i get these:

npm ERR! code 1
npm ERR! git dep preparation failed
npm ERR! command /usr/local/bin/node /usr/local/lib/node_modules/npm/bin/npm-cli.js install --force --cache=/root/.npm --prefer-offline=false --prefer-online=false --offline=false --no-progress --no-save --no-audit --include=dev --include=peer --include=optional --no-package-lock-only --no-dry-run
npm ERR! npm WARN using --force Recommended protections disabled.
npm ERR! npm WARN deprecated trim@0.0.1: Use String.prototype.trim() instead
npm ERR! npm WARN deprecated rollup-plugin-terser@7.0.2: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser
npm ERR! npm WARN deprecated rimraf@4.1.4: Please upgrade to 4.3.1 or higher to fix a potentially damaging issue regarding symbolic link following. See isaacs/rimraf#259 for details.
npm ERR! npm WARN deprecated tslint@6.1.3: TSLint has been deprecated in favor of ESLint. Please see palantir/tslint#4534 for more information.
npm ERR! npm WARN deprecated puppeteer@13.7.0: < 19.4.0 is no longer supported
npm ERR! npm WARN deprecated puppeteer@13.7.0: < 19.4.0 is no longer supported
npm ERR! npm WARN deprecated puppeteer@13.7.0: < 19.4.0 is no longer supported
npm ERR! npm WARN deprecated puppeteer@13.7.0: < 19.4.0 is no longer supported
npm ERR! npm WARN deprecated puppeteer@13.7.0: < 19.4.0 is no longer supported
npm ERR! npm WARN deprecated puppeteer@13.7.0: < 19.4.0 is no longer supported
npm ERR! npm ERR! process terminated
npm ERR! npm ERR! signal SIGINT

@tpunt
Copy link
Author

tpunt commented May 21, 2023

@LmfaoHax This does not really look like an issue with this specific branch. Given that others have also not had problems here, I'm guessing this is specific to your dependencies and their required versions. You could try clearing the npm cache (npm cache clean --force) and reinstalling, though I expect more analysis on upgrading your dependencies will be needed.

@LmfaoHax
Copy link

@tpunt first of all thanks for your help. i managed to install it from boxes-install but now i use your first code example on this PR i get this error:

Failed to compile.
./src/index.js
Line 61:16: 'LightweightCharts' is not defined no-undef
Search for the keywords to learn more about each error.

i assume that it is related to

borderStyle: LightweightCharts.LineStyle.Dashed,

but i dont know what i should be replacing it with

@tpunt
Copy link
Author

tpunt commented May 22, 2023

@LmfaoHax My example was from the debug.html file provided with the library. You shouldn't need the LightweightCharts prefix in your app - e.g. in my Vue app, I import symbols from it:

import { createChart, LineStyle } from 'lightweight-charts';

// LineStyle.Dashed

@LmfaoHax
Copy link

@tpunt so i used it like the debug html and everything works like a charm. Thanks alot!

@syncros-juozas
Copy link

Is there a possibility to set a corner at an arbitrary time, not dependent on timeframe?

@tpunt
Copy link
Author

tpunt commented May 23, 2023

@syncros-juozas I'm not entirely sure what you mean. The only case where timeframe is used is for points that are off of the chart time scale (as I noted in my previous reply). Otherwise, timeframe is irrelevant.

Or do you mean having the ability to specify points that are not aligned to the centre of a candlestick?

@syncros-juozas
Copy link

@tpunt yes, points that are not aligned to the center of the candle

@tpunt
Copy link
Author

tpunt commented May 27, 2023

@syncros-juozas I don't believe this is possible, at least not without some heavy modifications to the underlying library. In a private branch, I have aligned some drawings to the left-side of a candle (rather than in the centre), but it is still relative to a candle's time.

@nuevofilipo
Copy link

I just want to thank you so much for adding this features, was searching for a viable library for so long, using plotly, but it gets to slow after a certain amount of styling and data added, so this is just awesome.

@nuevofilipo nuevofilipo mentioned this pull request Aug 30, 2023
@davydof
Copy link

davydof commented Sep 3, 2023

hi, any updates? =)

@tpunt
Copy link
Author

tpunt commented Sep 7, 2023

hi, any updates? =)

I'm trying to keep my PR updated with the latest changes in the master branch, since my personal project depends on this feature.

I'm still waiting on @romfrancois for an update on the plugin mechanism status. Once ready, I will try to recreate my features using the new plugin system, so that things are less burdensome to keep up-to-date with the latest changes.

@VIEWVIEWVIEW
Copy link

I'm still waiting on @romfrancois for an update on the plugin mechanism status. Once ready, I will try to recreate my features using the new plugin system, so that things are less burdensome to keep up-to-date with the latest changes.

Ping @romfrancois. Pretty please? :)

@SlicedSilver
Copy link
Contributor

I'm still waiting on @romfrancois for an update on the plugin mechanism status. Once ready, I will try to recreate my features using the new plugin system, so that things are less burdensome to keep up-to-date with the latest changes.

Ping @romfrancois. Pretty please? :)

It is close to release. The plugins support (and examples) are already on the master branch.

@SlicedSilver
Copy link
Contributor

Version 4.1 has been released which adds Plugin support.

We believe that this requested feature should be implemented as a plugin instead. As a result, we suggest closing this PR since it is unlikely that we would merge this to core library.

Since there has been a lot of interest on this PR (and feature) in general, I think that a Plugin which implements box drawing would be very popular. The example plugins include 'Rectangle Drawing Tool', this could be used as a potential starting point.

@erfinbadrian
Copy link

erfinbadrian commented Oct 4, 2023 via email

@stylustrader
Copy link

🎉 congrats.
Honestly lwc has come a long way. Hard to believe but this pull request kick started my js learning journey and learned how to hack away at lwc src code to implement my own custom series. I hope my system still has an edge over this new plugin system cause I mine has support for webgpu now for more perf rather than relying on CPU bound canvas ctx , among other things 😏
Excited to see what the community produces!

@oliverpolden
Copy link

It looks like this requirement stems from the need to outline price consolidation.
I created an issue specifically for drawing boxes for trades which can visually display whether the trade was a long/short, profit/loss, entry/exit price plus its stop and target.
The issue/feature request can be found under #1449 if anyone is interested.

@difurious
Copy link

I have a build that let's you create a box and other drawing tools. Check out here. The goal it to get it into a plugin.

@andymach
Copy link

@tpunt

can anybody here merge this draw box and multi-pane chart in one

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet