-
Notifications
You must be signed in to change notification settings - Fork 653
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
Feature Request: Volume Profile on a chart with alpha argument #162
Comments
I did some looking into this and some experimenting with the code. It's a reasonable request. Haven't decided yet whether to provide Volume Profile, or simply provide the means for a horizontal bar chart (with alpha) and let the caller calculate the Volume Profile (which can be done relatively easily with a few lines of Pandas code). For now this is on the back burner, while working on some other enhancements. Will come back and revisit this in a few weeks. |
Market Profile is a very interesting charting mode, it normally goes standalone, off candlestick, pretty different. But it would be nice to have a Vertical view. I think this is way more than an enhancement and requires a lot of time and data reorganisation. Good luck |
Hi Daniel, I also use Volume Profile, provided by a trading plataform I am using. As I am interested in creating a kind of screener using Volume Profile, it would be very important to have the ways to do it, as it was possible with the mpl_finance. If you succeed to provide means for a horizontal bar chart and to plot it over the candlestick chart, it would be great! As the image below: Thanks! |
Will implement this at some point. In the meantime, here is a work-around example using one of the data files in the examples/data folder: import pandas as pd
import mplfinance as mpf
df = pd.read_csv('examples/data/yahoofinance-SPY-20080101-20180101.csv',index_col=0,parse_dates=True)
df = df.iloc[:150]
bucket_size = 0.0012 * max(df['Close'])
volprofile = df['Volume'].groupby(df['Close'].apply(lambda x: bucket_size*round(x/bucket_size,0))).sum()
mc = mpf.make_marketcolors(base_mpf_style='yahoo')
s = mpf.make_mpf_style(base_mpf_style='nightclouds',marketcolors=mc)
fig, axlist = mpf.plot(df,type='candle',returnfig=True,style=s,tight_layout=True)
vpax = fig.add_axes(axlist[0].get_position())
vpax.set_axis_off()
vpax.set_xlim(right=1.2*max(volprofile.values))
vpax.barh( volprofile.keys().values, volprofile.values, height=0.75*bucket_size, align='center', color='cyan', alpha=0.45)
mpf.show() The result: |
Hi Daniel, You are a genius!!! Your attention is outstanding! Thanks a lot! |
Hello Daniel ... Thank you for the wonderful work!! 5115.5 2021-09-21 08:14
5096.0 2021-09-21 09:30
5032.75 2021-09-21 09:33
5071.5 2021-09-21 09:35
5084.25 2021-09-21 11:32
5059.75 2021-09-21 12:52
5052.25 2021-09-21 14:46
5056.5 2021-09-21 15:50
5041.5 2021-09-21 15:54 |
please see #448 (comment) |
Hey Daniel, long time no speak -- @DanielGoldfarb would you ever be able to remember what is the role of the .apply(lambda...) bit in your market profile code? volprofile = df['Volume'].groupby(df['Close'].apply(lambda x: bucket_size*round(x/bucket_size,0))).sum() I am not guessing it and I would have omitted it in my mind, is it a sort of normalisation factor? I noticed this changes the volume chart: volprofile = df['Volume'].groupby(df['Close']).sum() Thank you, |
@manuelwithbmw It is obvious that we have to group the closing price by price slots (bucket_size) and not to be grouped by all available closing prices like in your example. To select bucket_size by predefined number of price slots we may use:
|
This (@AGG2017 's answer above) is correct. what you suggest: volprofile = df['Volume'].groupby(df['Close']).sum() would group together volumes only for close prices that are exactly the same close price as each other, which is very unlikely and therefore you may have as many volume bars as you have prices. Maybe, in some cases, this is what you want. However, more typically you want to divide the price range into slots or buckets, as @AGG2017 has shown above, and sum the volumes together that belong to a single bucket. That is what the lambda function in this code does, it finds all the closes that are within a given bucket, and sums together the volumes for all the closes in that bucket: volprofile = df['Volume'].groupby(df['Close'].apply(lambda x: bucket_size*round(x/bucket_size,0))).sum() To try to make this explanation a little more clear, what the lambda function is actually doing is rounding all the prices so that all of the prices that fall within a given bucket round to the exact same number (essentially the end of the bucket). In other words, each price is rounded to the nearest whole number of bucket_size's. |
BTW, I see a strange behavior of the final plot with the provided upper code example. When you select the last 150 bars of the data frame the issue is not well visible but when we remove the line
|
@AGG2017 The purpose of There really is no reason to have a similiar line of code in your own code except, as explained here, plotting too many rows may present difficulties in resolving the candlesticks, depending, in part, on the resolution of your display device. |
Interesting! The market/volume profile technique would need to see all the volumes for the day/the week/etc overlapping the candles in vertical as you did well, and designing one (or more) sort of Gaussian(s) bells around the (PoC) most common(s)/used volume(s) in that timeframe: Point of Control(s). So ideally, we would aggregate all the volumes (minute by minute --or within the chosen bucket size) for a daily Volume Profile, superimposing the Bell to the daily candlestick. All the volumes minute by minute (or within the chosen bucket size) for a weekly Volume Profile, superimposing that Bell to the weekly candlesticks. Anyway this quick code works well and allows me to play with it. Yes - the anomaly should be corrected as price have to be the same between candles and volumes. Personally I am going to tweak df = df.iloc[:nn] to have a number that suit my chosen dataframe and needs. |
Long time ago I started processing each intraday data for the tickers I need to have the volume profile for each day and for each week. Then I normalize it to 100% for the POC level and extract all levels >= 40, 60 and 80% as green, yellow and red resistence / support levels. Only one POC is not enough when we may have more than one zone of almost equal traded volume. Also for some strategies it is better this volume profile to be separated as red and green + total according to the close<>open prices. For longer term comparing maybe price*volume will be better because for some volatile stocks the volume @ $100 will be not the same as volume @ $300 which can happen in very short timeframe. I started looking for a code just to plot my already existing database of properly calculated volume profile and found this thread which is very helpful. Just one small offset that need to be fixed. |
I have used you little snippet from here (#162 (comment)) to use this volume profile method to plot option strike data on the chart. Thanks! My question is: Is it possible to move the position of the hbars on the x-axis? Ideally I would like it on the right where the most recent candle is, but really any where apart from this default position as some of the bars extend to the left (negative numbers) and are not visible where it is currently located. |
@grdnryn
The first technique is, in the call to The second technique is to call vpax = fig.add_axes(axlist[0].get_position())
vpax.set_axis_off()
vpax.set_xlim(right=1.6*max(vp_x))
vpax.barh( vp_y, vp_x, height=0.75*price_slot, align='center', color='cyan', alpha=0.45)
vpax.invert_xaxis()
mpf.show() |
Thank you Daniel. |
Is your feature request related to a problem? Please describe.
I would like to request an easy way to plot a volume profile on top of a chart on the Y-axis (see image)
Describe the solution you'd like
A function that takes two arguments. Volume and Price. To plot Volume by Price Level.
Describe alternatives you've considered
Haven't found any alternatives or easy ways to go about it. No "overlay" solutions exist?
Additional context
See attached image.
(https://i.stack.imgur.com/GEXCd.png)
The text was updated successfully, but these errors were encountered: