【问题标题】:Matplotlib with JSON files带有 JSON 文件的 Matplotlib
【发布时间】:2014-02-20 15:58:14
【问题描述】:

我试图结合两种代码源但无济于事。我正在使用带有 json 文件(也在下面列出)的默认 finance2.py matplotlib 示例(在下面列出)。代码的“finance.fetch_historical_yahoo”部分通过 yahoo 从 .csv 中提取数据,并将其放入 numpy 数组中。问题是,我不需要翻译 yahoo 的数据,我需要以 matplotlib 库可读的方式翻译 JSON 数据。

finance2.py:

import datetime
import numpy as np
import matplotlib.colors as colors
import matplotlib.finance as finance
import matplotlib.dates as mdates
import matplotlib.ticker as mticker
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
import matplotlib.font_manager as font_manager
import json #to load json libraries for json data

startdate = datetime.date(2006,1,1)
today = enddate = datetime.date.today()
ticker = 'SPY'


fh = finance.fetch_historical_yahoo(ticker, startdate, enddate) #would like this call to be json
# a numpy record array with fields: date, open, high, low, close, volume, adj_close)

r = mlab.csv2rec(fh); fh.close()
r.sort()


def moving_average(x, n, type='simple'):
    """
    compute an n period moving average.

    type is 'simple' | 'exponential'

    """
    x = np.asarray(x)
    if type=='simple':
        weights = np.ones(n)
    else:
        weights = np.exp(np.linspace(-1., 0., n))

    weights /= weights.sum()


    a =  np.convolve(x, weights, mode='full')[:len(x)]
    a[:n] = a[n]
    return a

def relative_strength(prices, n=14):
    """
    compute the n period relative strength indicator
    http://stockcharts.com/school/doku.php?id=chart_school:glossary_r#relativestrengthindex
    http://www.investopedia.com/terms/r/rsi.asp
    """

    deltas = np.diff(prices)
    seed = deltas[:n+1]
    up = seed[seed>=0].sum()/n
    down = -seed[seed<0].sum()/n
    rs = up/down
    rsi = np.zeros_like(prices)
    rsi[:n] = 100. - 100./(1.+rs)

    for i in range(n, len(prices)):
        delta = deltas[i-1] # cause the diff is 1 shorter

        if delta>0:
            upval = delta
            downval = 0.
        else:
            upval = 0.
            downval = -delta

        up = (up*(n-1) + upval)/n
        down = (down*(n-1) + downval)/n

        rs = up/down
        rsi[i] = 100. - 100./(1.+rs)

    return rsi

def moving_average_convergence(x, nslow=26, nfast=12):
    """
    compute the MACD (Moving Average Convergence/Divergence) using a fast and slow exponential moving avg'
    return value is emaslow, emafast, macd which are len(x) arrays
    """
    emaslow = moving_average(x, nslow, type='exponential')
    emafast = moving_average(x, nfast, type='exponential')
    return emaslow, emafast, emafast - emaslow


plt.rc('axes', grid=True)
plt.rc('grid', color='0.75', linestyle='-', linewidth=0.5)

textsize = 9
left, width = 0.1, 0.8
rect1 = [left, 0.7, width, 0.2]
rect2 = [left, 0.3, width, 0.4]
rect3 = [left, 0.1, width, 0.2]


fig = plt.figure(facecolor='white')
axescolor  = '#f6f6f6'  # the axes background color

ax1 = fig.add_axes(rect1, axisbg=axescolor)  #left, bottom, width, height
ax2 = fig.add_axes(rect2, axisbg=axescolor, sharex=ax1)
ax2t = ax2.twinx()
ax3  = fig.add_axes(rect3, axisbg=axescolor, sharex=ax1)



### plot the relative strength indicator
prices = r.adj_close
rsi = relative_strength(prices)
fillcolor = 'darkgoldenrod'

ax1.plot(r.date, rsi, color=fillcolor)
ax1.axhline(70, color=fillcolor)
ax1.axhline(30, color=fillcolor)
ax1.fill_between(r.date, rsi, 70, where=(rsi>=70), facecolor=fillcolor, edgecolor=fillcolor)
ax1.fill_between(r.date, rsi, 30, where=(rsi<=30), facecolor=fillcolor, edgecolor=fillcolor)
ax1.text(0.6, 0.9, '>70 = overbought', va='top', transform=ax1.transAxes, fontsize=textsize)
ax1.text(0.6, 0.1, '<30 = oversold', transform=ax1.transAxes, fontsize=textsize)
ax1.set_ylim(0, 100)
ax1.set_yticks([30,70])
ax1.text(0.025, 0.95, 'RSI (14)', va='top', transform=ax1.transAxes, fontsize=textsize)
ax1.set_title('%s daily'%ticker)

### plot the price and volume data
dx = r.adj_close - r.close
low = r.low + dx
high = r.high + dx

deltas = np.zeros_like(prices)
deltas[1:] = np.diff(prices)
up = deltas>0
ax2.vlines(r.date[up], low[up], high[up], color='black', label='_nolegend_')
ax2.vlines(r.date[~up], low[~up], high[~up], color='black', label='_nolegend_')
ma20 = moving_average(prices, 20, type='simple')
ma200 = moving_average(prices, 200, type='simple')

linema20, = ax2.plot(r.date, ma20, color='blue', lw=2, label='MA (20)')
linema200, = ax2.plot(r.date, ma200, color='red', lw=2, label='MA (200)')


last = r[-1]
s = '%s O:%1.2f H:%1.2f L:%1.2f C:%1.2f, V:%1.1fM Chg:%+1.2f' % (
    today.strftime('%d-%b-%Y'),
    last.open, last.high,
    last.low, last.close,
    last.volume*1e-6,
    last.close-last.open )
t4 = ax2.text(0.3, 0.9, s, transform=ax2.transAxes, fontsize=textsize)

props = font_manager.FontProperties(size=10)
leg = ax2.legend(loc='center left', shadow=True, fancybox=True, prop=props)
leg.get_frame().set_alpha(0.5)


volume = (r.close*r.volume)/1e6  # dollar volume in millions
vmax = volume.max()
poly = ax2t.fill_between(r.date, volume, 0, label='Volume', facecolor=fillcolor, edgecolor=fillcolor)
ax2t.set_ylim(0, 5*vmax)
ax2t.set_yticks([])


### compute the MACD indicator
fillcolor = 'darkslategrey'
nslow = 26
nfast = 12
nema = 9
emaslow, emafast, macd = moving_average_convergence(prices, nslow=nslow, nfast=nfast)
ema9 = moving_average(macd, nema, type='exponential')
ax3.plot(r.date, macd, color='black', lw=2)
ax3.plot(r.date, ema9, color='blue', lw=1)
ax3.fill_between(r.date, macd-ema9, 0, alpha=0.5, facecolor=fillcolor, edgecolor=fillcolor)


ax3.text(0.025, 0.95, 'MACD (%d, %d, %d)'%(nfast, nslow, nema), va='top',
         transform=ax3.transAxes, fontsize=textsize)

#ax3.set_yticks([])
# turn off upper axis tick labels, rotate the lower ones, etc
for ax in ax1, ax2, ax2t, ax3:
    if ax!=ax3:
        for label in ax.get_xticklabels():
            label.set_visible(False)
    else:
        for label in ax.get_xticklabels():
            label.set_rotation(30)
            label.set_horizontalalignment('right')

    ax.fmt_xdata = mdates.DateFormatter('%Y-%m-%d')



class MyLocator(mticker.MaxNLocator):
    def __init__(self, *args, **kwargs):
        mticker.MaxNLocator.__init__(self, *args, **kwargs)

    def __call__(self, *args, **kwargs):
        return mticker.MaxNLocator.__call__(self, *args, **kwargs)

# at most 5 ticks, pruning the upper and lower so they don't overlap
# with other ticks
#ax2.yaxis.set_major_locator(mticker.MaxNLocator(5, prune='both'))
#ax3.yaxis.set_major_locator(mticker.MaxNLocator(5, prune='both'))

ax2.yaxis.set_major_locator(MyLocator(5, prune='both'))
ax3.yaxis.set_major_locator(MyLocator(5, prune='both'))

plt.show()

.json 文件:

{
        "instrument" : "EUR_USD",
        "granularity" : "D",
        "candles" : [
                {
                        "time" : "2014-02-17T22:00:00Z",
                        "openMid" : 1.259445,
                        "highMid" : 1.259955,
                        "lowMid" : 1.251825,
                        "closeMid" : 1.257955,
                        "volume" : 61184,
                        "complete" : true
                },
                {
                        "time" : "2014-02-18T22:00:00Z",
                        "openMid" : 1.257975,
                        "highMid" : 1.259955,
                        "lowMid" : 1.251825,
                        "closeMid" : 1.252945,
                        "volume" : 67528,
                        "complete" : false
                }
        ]
}

我什至不是在寻找一个明确的答案,即使是在正确的方向上的一点在这个时候也会非常有帮助。

提前致谢

【问题讨论】:

  • fetch_historical_yahoo 下方的行告诉您您的数据应该是什么样子。那么,你尝试过什么?向我们展示一些代码(仅相关部分),您可以在其中尝试将 json 输入转换为 numpy 记录数组。
  • 读json应该从json.load() docs.python.org/2/library/json.html#json.load开始
  • 这里的代码太多了。很少有人愿意涉足与您的问题无关的那么多代码。请将此减少到重现您的问题所需的最少代码量。

标签: python json numpy matplotlib


【解决方案1】:

这是一个部分答案 - 它显示了如何将 json 解压缩为行 (row_wise) 或列 (col_wise) 的列表。

import json
import numpy as np
# json embedded here, but could be read in from text file
json_string = """{
        "instrument" : "EUR_USD",
        "granularity" : "D",
        "candles" : [
                {
                        "time" : "2014-02-17T22:00:00Z",
                        "openMid" : 1.259445,
                        "highMid" : 1.259955,
                        "lowMid" : 1.251825,
                        "closeMid" : 1.257955,
                        "volume" : 61184,
                        "complete" : true
                },
                {
                        "time" : "2014-02-18T22:00:00Z",
                        "openMid" : 1.257975,
                        "highMid" : 1.259955,
                        "lowMid" : 1.251825,
                        "closeMid" : 1.252945,
                        "volume" : 67528,
                        "complete" : false
                }
        ]
       }"""

candles = json.loads(json_string)['candles']
col_heads = ['time', 'openMid', 'highMid', 'lowMid', 'closeMid', 'volume']
f = lambda c: [c[col] for col in col_heads]
row_wise = [col_heads[:]]
row_wise.extend([f(candle) for candle in candles])
for row in row_wise: print row
print
col_wise = zip(*row_wise)
for col in col_wise: print col

剩下的就是构建一个 numpy recarray:这是 mlab.csv2rec() 产生的。这是留给 numpy 大师的练习(我不是!;)

【讨论】:

    【解决方案2】:

    您可以使用 pandas 更简洁地解决此问题。这是解决您的问题的相关信息。抱歉,我没有时间根据您的特定用例自定义所有代码。如果您重新访问此内容并希望我这样做,请告诉我。

    来自the docs

    >>> data = [{'state': 'Florida',
    ...          'shortname': 'FL',
    ...          'info': {
    ...               'governor': 'Rick Scott'
    ...          },
    ...          'counties': [{'name': 'Dade', 'population': 12345},
    ...                      {'name': 'Broward', 'population': 40000},
    ...                      {'name': 'Palm Beach', 'population': 60000}]},
    ...         {'state': 'Ohio',
    ...          'shortname': 'OH',
    ...          'info': {
    ...               'governor': 'John Kasich'
    ...          },
    ...          'counties': [{'name': 'Summit', 'population': 1234},
    ...                       {'name': 'Cuyahoga', 'population': 1337}]}]
    >>> from pandas.io.json import json_normalize
    >>> result = json_normalize(data, 'counties', ['state', 'shortname',
    ...                                           ['info', 'governor']])
    >>> result
             name  population info.governor    state shortname
    0        Dade       12345    Rick Scott  Florida        FL
    1     Broward       40000    Rick Scott  Florida        FL
    2  Palm Beach       60000    Rick Scott  Florida        FL
    3      Summit        1234   John Kasich     Ohio        OH
    4    Cuyahoga        1337   John Kasich     Ohio        OH
    

    现在您可以使用pandas dataframe to visualize the data

    In [1]: import matplotlib.pyplot as plt
    
    In [2]: ts = pandas.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000))
    
    In [3]: ts = ts.cumsum()
    
    In [4]: ts.plot()
    Out[4]: <matplotlib.axes._subplots.AxesSubplot at 0x1120939d0>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-01
      • 2013-07-03
      • 1970-01-01
      • 2023-03-30
      • 2020-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多