1

I am trying to add an arrow on a given date and price to mpf plot. To do this i have the following code:

import pandas as pd
import yfinance as yf
import datetime
from dateutil.relativedelta import relativedelta
import pandas as pd, mplfinance as mpf, matplotlib.pyplot as plt

db = yf.download(tickers='goog', start=datetime.datetime.now()-relativedelta(days=7), end= datetime.datetime.now(), interval="5m")
db = db.dropna()
a = db['Close'][31:32]
test =  mpf.make_addplot(a, type='scatter', markersize=200, marker='^')
mpf.plot(db, type='candle', style= 'charles', addplot=test)

But it is producing the following error:

ValueError: x and y must be the same size

Could you please advise how can i resolve this.

Slartibartfast
  • 1,058
  • 4
  • 26
  • 60

2 Answers2

3

The data passed into mpf.make_addplot() must be the same length as the dataframe passed into mpf.plot(). To plot only some points, the remaining points must be filled with nan values (float('nan'), or np.nan).

You can see this clearly in the documentation at cell **In [7]** (and used in the following cells). See there where the signal data is generated as follows:

def percentB_belowzero(percentB,price):
    import numpy as np
    signal   = []
    previous = -1.0
    for date,value in percentB.iteritems():
        if value < 0 and previous >= 0:
            signal.append(price[date]*0.99)
        else:
            signal.append(np.nan)  # <- Make `nan` where no marker needed.
        previous = value
    return signal

Note: alternatively the signal data can be generated by first initializing to all nan values, and then replacing those nans where you want your arrows:

signal = [float('nan')]*len(db)
signal[31] = db['Close'][31:32]
test =  mpf.make_addplot(signal, type='scatter', markersize=200, marker='^')
...
Daniel Goldfarb
  • 6,937
  • 5
  • 29
  • 61
  • 1
    I was curious about the title of the question, so I added an annotated version. I can do most of the work with these two approaches. – r-beginners Feb 22 '22 at 14:58
2

If your ultimate goal is to add an arrow to the title of the question, you can add it in the way shown in @Daniel Goldfarb's How to add value of hlines in y axis using mplfinance python. I used this answer to create a code that meets the end goal. As you can see in the answer, the way to do this is to get the axis and then add an annotation for that axis, where 31 is the date/time index and a[0] is the closing price.

import pandas as pd
import yfinance as yf
import datetime
from dateutil.relativedelta import relativedelta
import pandas as pd
import mplfinance as mpf
import matplotlib.pyplot as plt

db = yf.download(tickers='goog', start=datetime.datetime.now()-relativedelta(days=7), end= datetime.datetime.now(), interval="5m")
db = db.dropna()
a = db['Close'][31:32]

#test =  mpf.make_addplot(a, type='scatter', markersize=200, marker='^')
fig, axlist = mpf.plot(db, type='candle', style= 'charles', returnfig=True)#addplot=test

axlist[0].annotate('X', (31, a[0]), fontsize=20, xytext=(34, a[0]+20),
                   color='r', 
                   arrowprops=dict(
                       arrowstyle='->',
                       facecolor='r',
                       edgecolor='r'))
                    
mpf.show()

enter image description here

r-beginners
  • 31,170
  • 3
  • 14
  • 32
  • Could you please advise how can i replace 31 with a datetime index for `x` in the plot ? – Slartibartfast Feb 23 '22 at 03:18
  • 1
    I also tried to use the date/time index without success. I checked the official reference and it says the value used is a float value, so using mdates.date2num() to convert it did not work. I guess I will have to get the index from the date and time I want to set from the dataframe. `db.index.get_loc(pd.Timestamp('2022-02-16 12:05:00-0500', tz='America/New_York'))`-> `31` – r-beginners Feb 23 '22 at 03:49
  • 1
    See this:[https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.annotate.html](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.annotate.html) – r-beginners Feb 23 '22 at 03:55