bfolkens / py-market-profile

A library to calculate Market Profile (aka Volume Profile) for financial data from a Pandas DataFrame.
Other
356 stars 122 forks source link

POC, VAL and VAH difference with TradingView #16

Closed Xxobster closed 1 year ago

Xxobster commented 1 year ago

Hi,

First of all, thanks a million for the work. Amazing!

I'm using 1m candles from the Bybit exchange and when I compare the Volume Profile for a day with TradingView I'm getting different values, so I'm wondering what I'm doing wrong.

I've compared the candles and volume between my dataset and TV and they are the same.

Any help would be gladly appreciated :)

Thank you very much!

Here's the TV values: BTCUSDT Bybit

And here's what I'm getting: VolumeProfile1

Here's the data that I'm using: BTCUSDT Bybit.csv

bfolkens commented 1 year ago

Few things to check first:

  1. Make sure to account for TZ differences. The integer timestamp data will ofc be in UTC and so you'll want to make sure that matches with TV's window, pandas, etc.
  2. Value Areas can be computed with different algorithms, the two I've seen used the most is the one used in the library (+/- 1 step until satisfied) but the Dalton / Markets in Profile method does +/- 2 inc. steps until satisfied (and compares </>, etc). Not sure which the TV is using.
  3. You might want to chose a larger tick size on both the library and TV at first just for a sanity check.
Xxobster commented 1 year ago

Hi, thanks for your reply :)

Yes I confirm that I'm using UTC candles on both TV and MP.

I understand for the VA, but what about the POC? The difference is quite significant: TV: 26732 MP: 26439

If I understand correctly according to what's below (point 6.), the POC will change according to the VA's calculation?

Would that make sense to you to add the other way of calculating the VA and POC in your library? I can try to do it but I'm quite novice in py.

Here's some info about TV's calculations: Calculating Value Area (VA)

  1. Determine the total volume traded in the profile (total buys and sells).
  2. Take the number of total buys and sells and multiply it by .7 to determine what number is 70 percent of the total buys and sells. (70% is the default; however, any percentage can be used by the trader).
  3. Start at the Point of Control (POC), The row in the profile with the greatest total volume, and record its total volume number. The POC will be the first profile row added to the Value Area.
  4. Now look at the two rows above the POC (the initial value area) and add the total volume of both.
  5. Now look at the two rows beneath the POC (the initial value area) and add the total volume of both.
  6. Determine which of the total volume numbers is larger and add it to the total volume number of the POC found in step 3.
  7. Repeat steps 4 and 5 adding the larger of the next two numbers to the Value Area.
  8. Once the total volume of your Value Area matches or slightly surpasses the number found in step 2, the Value Area has been determined.
  9. The highest row within the Value Area will be your Value Area High (VAH) and the lowest row within the Value Area will be your Value Area Low (VAL).

Source: https://www.tradingview.com/support/solutions/43000502040-volume-profile/

bfolkens commented 1 year ago

Yes I don't think the POC shouldn't be off that much, which is why I wondered about the TZ offset.

Two more points to consider:

Also, can you send me a gist or the code for the screenshot above? I'll run it on my side and dig around...

Xxobster commented 1 year ago

I'm not sure how to use the tick_size, it determines the size of the rows, right? I'm probably using it wrong. On TV you have 2 options, either Ticks per Row or Number of Rows. I usually use 200 rows but I've tried both and compared with your library. Eventually I don't know how to correlate with the tick_size.

image

Here are the code, the data in sqlite format and the export in sqlite format. It imports the db from the same directory, calculates and then exports into a db. MP_tests.zip

For 2023-06-06 for instance (tick_size = 10): TV POC: 26711 / 26880 with MP TV VAL: 25842 / 25650 with MP TV VAH: 27339 / 27020 with MP

It probably comes from my misunderstanding of the tick_size. Any idea how I could correlate TV's parameters with your library's parameters?

Apparently the tick size on Bybit exchange is 0.01 but even with this value the results are quite off.

bfolkens commented 1 year ago

The following settings are relevant and the defaults are listed below:

tick_size = 0.05
prices_per_row = 1
row_size = 0.05 * 1 = 0.05

Just estimating from the chart screenshot above (since the modal has the size covered up), it looks like there's somewhere between 18 to 20 rows per $100 (assuming 20 then row_size = 5). So if you wanted to replicate the chart above, you would use the following settings:

tick_size = 5
prices_per_row = 1

or simply:

row_size = 5

Also, keep in mind whether the start/end timestamps are inclusive or exclusive (both with TV and this library). There's probably not much volume in that last 60 seconds, but good to match regardless.

Xxobster commented 1 year ago

Hi, thanks for your answer and for your explanations. I really appreciate that you're taking some time.

I've tried a lots of different values for both the TV indicator's parameters (number of rows, ticks per row) and the tick_size in order to find a match. I've noticed that when the spread of the day is short the values are very similar but as soon as the spread gets bigger, the difference is quite noticeable. At this point I still haven't figured out the reason.

I just have 2 more questions: So if I understand correctly, the smaller the row_size is the more precise the results are? Are you using this indicator in technical analysis?

Thanks again.

bfolkens commented 1 year ago

Sure no problem at all.

One possibility is that TV isn't using OHLCV data but rather raw tick data, or that TV is using a different period for the OHLCV data than in your CSV above. That could certainly lead to differences because the OHLCV is an approximation. One way to compare it would be to use a service that uses raw tick data to compute the POC/VA/etc (I know https://cignals.io does, for example).

Xxobster commented 1 year ago

Excellent, thanks for your reply :)