Отобразить прямоугольники над осью дата-время в matplotlib? - PullRequest
0 голосов
/ 28 апреля 2018

Итак, я пытаюсь вручную создать график свечей с помощью matplotlib, используя errorbar для дневных цен максимумов и минимумов и Rectangle() для скорректированных цен закрытия и открытия. Этот вопрос , казалось, имел все предпосылки для достижения этой цели.

Я попытался использовать все вышеперечисленное очень точно, но проблема нанесения чего-либо по оси x, равной datetime64[ns], не давала мне конца ошибкам, поэтому я дополнительно попытался включить совет здесь при построении графика на дату и время.

Это мой код, с извинениями за беспорядок:

import pandas as pd
import datetime as dt
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

from matplotlib.collections import PatchCollection
from matplotlib.patches import Rectangle

def makeCandles(xdata,high,low,adj_close,adj_open,fc='r',ec='None',alpha=0.5):

    ## Converting datetimes to numerical format matplotlib can understand.
    dates = mdates.date2num(xdata)

    ## Creating default objects
    fig,ax = plt.subplots(1)

    ## Creating errorbar peaks based on high and low prices
    avg = (high + low) / 2
    err = [high - avg,low - avg]

    ax.errorbar(dates,err,fmt='None',ecolor='k')

    ## Create list for all the error patches
    errorboxes = []

    ## Loop over data points; create "body" of candlestick 
    ## based on adjusted open and close prices

    errors=np.vstack((adj_close,adj_open))
    errors=errors.T

    for xc,yc,ye in zip(dates,avg,errors):
        rect = Rectangle((xc,yc-ye[0]),1,ye.sum())
        errorboxes.append(rect)

    ## Create patch collection with specified colour/alpha
    pc = PatchCollection(errorboxes,facecolor=fc,alpha=alpha,edgecolor=ec)

    ## Add collection to axes
    ax.add_collection(pc)

    plt.show()

С моими данными, похожими на

enter image description here

Это то, что я пытаюсь запустить, сначала получая таблицу цен от quandl,

import quandl as qd
api =  '1uRGReHyAEgwYbzkPyG3'
qd.ApiConfig.api_key = api 

data = qd.get_table('WIKI/PRICES', qopts = { 'columns': ['ticker', 'date', 'high','low','adj_open','adj_close'] }, \
                        ticker = ['AMZN', 'XOM'], date = { 'gte': '2014-01-01', 'lte': '2016-12-31' })
data.reset_index(inplace=True,drop=True)

makeCandles(data['date'],data['high'],data['low'],data['adj_open'],data['adj_close'])

Код выполняется без ошибок, но выводит пустой график. Итак, я прошу совета о том, как нанести эти прямоугольники на даты и время. Для ширины прямоугольников я просто положил равномерную "1", потому что. Я не знаю простого способа указать ширину даты и времени прямоугольника. Я был бы очень признателен за опытную помощь.

РЕДАКТИРОВАТЬ: Это сюжет, который я сейчас получаю, превратив мой xdata в matplotlib mdates: enter image description here

До того, как я преобразовал xdata через mdates, с xdata в качестве моей оси X везде, это была одна из ошибок, которые я продолжал получать: enter image description here

1 Ответ

0 голосов
/ 02 июня 2018

Чтобы получить сюжет, который вы хотите, есть пара вещей, которые необходимо учитывать. Сначала вы выполняете поиск по акциям AMZN и XOM, и отображение обоих сделает график, который вы хотите, забавным, потому что данные довольно далеко друг от друга. Во-вторых, графики свечей, на которых вы строите график каждый день в течение нескольких лет, будут очень переполнены. Наконец, вам нужно отформатировать порядковые даты обратно по оси X.

Как уже упоминалось в комментариях, вы можете использовать встроенную функцию matplotlib candlestick2_ohlc (хотя и не рекомендуется), доступную через mpl_finance, установите, как показано в этом ответе. Я решил использовать исключительно диаграмму matplotlib со встроенными панелями ошибок.

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import quandl as qd
from matplotlib.dates import DateFormatter, WeekdayLocator, \
    DayLocator, MONDAY

# get data
api = '1uRGReHyAEgwYbzkPyG3'
qd.ApiConfig.api_key = api
data = qd.get_table('WIKI/PRICES', qopts={'columns': ['ticker', 'date', 'high', 'low', 'open', 'close']},
                    ticker=['AMZN', 'XOM'], date={'gte': '2014-01-01', 'lte': '2014-03-10'})
data.reset_index(inplace=True, drop=True)

fig, ax = plt.subplots(figsize = (10, 5))
data['date'] = mdates.date2num(data['date'].dt.to_pydatetime()) #convert dates to ordinal
tickers = list(set(data['ticker'])) # unique list of stock names
for stock_ind in tickers:
    df = data[data['ticker'] == 'AMZN'] # select one, can do more in a for loop, but it will look funny

    inc = df.close > df.open
    dec = df.open > df.close

    ax.bar(df['date'][inc],
           df['open'][inc]-df['close'][inc],
           color='palegreen',
           bottom=df['close'][inc],
           # this yerr is confusing when independent error bars are drawn => (https://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.errorbar)
           yerr = [df['open'][inc]-df['high'][inc], -df['open'][inc]+df['low'][inc]],
           error_kw=dict(ecolor='gray', lw=1))

    ax.bar(df['date'][dec],
           df['close'][dec]-df['open'][dec],
           color='salmon', bottom=df['open'][dec],
           yerr = [df['close'][dec]-df['high'][dec], -df['close'][dec]+df['low'][dec]],
           error_kw=dict(ecolor='gray', lw=1))

    ax.set_title(stock_ind)

#some tweaking, setting the dates
mondays = WeekdayLocator(MONDAY)  # major ticks on the mondays
alldays = DayLocator()  # minor ticks on the days
weekFormatter = DateFormatter('%b %d')  # e.g., Jan 12
dayFormatter = DateFormatter('%d')  # e.g., 12
ax.xaxis.set_major_locator(mondays)
ax.xaxis.set_minor_locator(alldays)
ax.xaxis.set_major_formatter(weekFormatter)
ax.set_ylabel('monies ($)')

plt.show()

Graph

...