Ventures of an ex indie game developer

Python Finance Plot closing in on v1.0

I just added support for non-time series in finplot. The original idea of finplot was to only support backtesting of trading algorithms based on time series, but as the user base grew I decided to accommodate some of the n00b day traders, especially as I saw things like this guy using matplotlib for the most elementary junk.

I created an example of how to use such things:

The first four plots are super-simple to create. This is the most basic incarnation:

import finplot as fplt
import yfinance as yf

# download and create window with five plots in
btc = yf.download('BTC-USD', '2014-09-01')
ax1,ax2,ax3,ax4,ax5 = fplt.create_plot('Bitcoin/Dollar long term analysis', rows=5)

# plot 1, price
fplt.plot(btc.Close, color='#000', legend='Price', ax=ax1)

# plot 2, daily returns
daily_ret = btc.Close.pct_change()*100
fplt.plot(daily_ret, width=3, color='#000', legend='Daily returns %', ax=ax2)

# histogram over daily returns since some time 2014
fplt.hist(daily_ret, bins=60, ax=ax3)

# bar charts of % change per year
fplt.bar(btc.Close.resample('Y').last().pct_change().dropna(), ax=ax4)

The fifth and last plot shows spot-traded Bitcoin return averaged per month (over the last six years). I draw this plot using a heat map. It goes something like this:

# calculate monthly returns, display as a 4x3 heatmap
# 1. diff every month since 2014
months = btc['Adj Close'].resample('M').last().pct_change().dropna().to_frame() * 100
# 2. get month names
months.index = mnames = months.index.month_name().to_list()
# 3. get the 12 month's names in order
mnames = mnames[mnames.index('January'):][:12]
# 4. average returns per month
mrets = [months.loc[mname].mean()[0] for mname in mnames]
# 5. create a matrix, where the columns are the Y-axis titles in the heat map case (normally price)
hmap = pd.DataFrame(columns=[2,1,0], data=np.array(mrets).reshape((3,4)).T)
# 6. use the range index as X-coordinates (if no DateTimeIndex is found, the first column is used as X)
hmap = hmap.reset_index()
# 7. plot the colored rectangles with a linear color curve
fplt.heatmap(hmap, rect_size=1, colcurve=lambda x: x, ax=ax5)
# 8. add a month name and its returns per square
for j,mrow in enumerate(np.array(mnames).reshape((3,4))):
    for i,month in enumerate(mrow):
        s = month+' %+.2f%%'%hmap.loc[i,2-j]
        fplt.add_text((i, 2.5-j), s, anchor=(0.5,0.5), ax=ax5)

The full example can be found here.

It wasn't all bad making these changes, as I was able to stabilize and generalize the code in a couple of places when doing so. Also nice to be able to reduce the tutorial code of CryptoZweed by around 85% while still maintaining the same functionality. That is a testament to exactly how good finplot's API is.

What's new?

The new functionality in finplot are bar charts and histograms. They differ from, for example, volume plots in that they are not linked when zooming and panning (compare histogram and the two topmost plots in the gif above). There are some small details such as hiding/showing the axes depending on what type of series we're showing, but I won't bore you with the details.

I feel very good about this. I think we're moving on version 1.0, and I've solved all the things I need myself, and it seems most of the things others need too. For some weird reason the package has had 2-3000 downloads per month for half a year now. I never knew there were so many traders out there. Hope they all are making cewl bots and getting rich! :D

About the author

Mitt foto
Gothenburg, Sweden