Ejemplo n.º 1
0
def plot_ts(df,
            dv=[],
            fig=None,
            ax=None,
            figsize=(11, 6),
            backend='Agg',
            title='',
            chartformat='svg',
            debugTF=False,
            **optx):
    if len(df) < 1:
        return '', None, None
    sys.stderr.write("===start:{}()\n".format("plot_ts"))
    src = getKeyVal(optx, 'src', 'yh')
    #if isinstance(df,str):
    if not isinstance(df, pd.DataFrame):
        ticker = df
        from _alan_calc import pullStockHistory as psd
        ranged = getKeyVal(optx, 'ranged', '1d')
        gap = getKeyVal(optx, 'gap', '1m')
        datax = psd(ticker, gap=gap, ranged=ranged, days=1500, src=src)
        datax.rename(columns={'close': ticker}, inplace=True)
        df = datax[[ticker]]
        if src == 'fred':
            tk2 = ticker + '_PCTCHG'
            dx2 = psd(tk2, src=src, days=1500)
            if len(dx2) > 0:
                dv = datax[[ticker]]
                df = dx2[['close']]
        elif 'volume' in datax:
            dv = datax[['volume']]
    if 'volume' in df:
        dv = df[['volume']].copy()
        cs = list(df.columns)
        cs.pop(cs.index('volume'))
        df = df[cs]
    if backend is not None and len(backend) > 1:
        plt.switch_backend(backend)
    trendTF = getKeyVal(optx, 'trendTF', True)
    bottom = optx['bottom'] if 'bottom' in optx else 0.35
    chartpath, chartname = gen_chartpath(**optx)
    try:
        from _alan_pppscf import vertex_locator
        if not isinstance(df, pd.DataFrame):
            df = pd.DataFrame(data=df)
        if fig is None:
            sns.set_style("whitegrid", {'grid.linestyle': '--'})
            fig, ax = plt.subplots(figsize=figsize)
            ax.grid(False, axis='x')
            ax.spines['right'].set_color('none')
            ax.spines['top'].set_color('none')
            ax.spines['bottom'].set_color('none')
            ax.spines['left'].set_color('none')
        plt.plot(df.index, df.iloc[:, 0])
        plt.title(title)
        x_fmt = getKeyVal(optx, 'x_fmt', '')
        yunit = ['', '1,000', 'Million', 'Billion', 'Trillion']
        ymax = abs(df.iloc[:, 0]).max()
        ndg = max(int(math.log(ymax, 10) / 3), 1)
        nadj = (ndg - 1) * 3
        ylabel = yunit[ndg - 1] or ''
        if debugTF:
            sys.stderr.write("+++++ {} {} {} {}\n".format(
                ymax, ndg, nadj, yunit[ndg - 1]))
        if ndg > 1:
            ax.yaxis.set_major_formatter(
                FuncFormatter(lambda x, pos: '{:,g}'.format(x / 10**nadj)))
        else:
            ax.yaxis.set_major_formatter(
                FuncFormatter(lambda x, pos: '{:,g}'.format(x)))
        ax.set_ylabel(ylabel)
        if trendTF is True:
            npar = getKeyVal(optx, 'npar', 6)
            trendName = df._get_numeric_data().columns[0]
            dy = df[trendName]
            dg, dh = vertex_locator(dy, npar=npar, debugTF=debugTF)
            dg.plot(ax=ax, legend=False)
            if debugTF:
                sys.stderr.write("===plot data:\n {}\n".format(dg.tail()))
        if len(dv) > 0 and isinstance(dv, pd.DataFrame):
            axv = ax.twinx()
            kind2 = 'area' if src != 'fred' else 'line'
            color2 = 'lightgray' if src != 'fred' else 'gray'
            axv = dv.plot(ax=axv,
                          kind=kind2,
                          color=color2,
                          alpha=.4,
                          legend=False)
            y2max = dv.iloc[:, 0].max()
            ndg = max(int(math.log(y2max, 10) / 3), 1)
            nadj = (ndg - 1) * 3
            if ndg > 1:
                axv.yaxis.set_major_formatter(
                    FuncFormatter(lambda x, pos: '{:,g}'.format(x / 10**nadj)))
            else:
                axv.yaxis.set_major_formatter(
                    FuncFormatter(lambda x, pos: '{:,g}'.format(x)))
            ylabel2 = yunit[ndg - 1] or ''
            axv.set_ylabel(ylabel2)
            if debugTF:
                sys.stderr.write("===plot data:\n {}\n".format(dv.tail()))
        if debugTF:
            sys.stderr.write("===plot data:\n {}\n".format(df.tail(20)))
        plt.subplots_adjust(left=0.1, bottom=bottom)
        #if len(x_fmt)>0: # TBD, specify xticks format
        #	ax.xaxis.set_major_formatter(mdates.DateFormatter(x_fmt))
        ax.grid(linestyle='dotted', linewidth=0.5)
        if chartname is not None and len(chartname) > 5:
            plt.savefig(chartpath,
                        format=chartformat)  #, bbox_inches='tight',dpi=1000)
        elif backend is not None and backend.lower() == 'tkagg':
            plt.show(ax)
    except Exception as e:
        sys.stderr.write("**ERROR: {} @{}\n".format(str(e), "plot_ts"))
        sys.stderr.write("{}\n".format(locals()))
        return '', None, None
    return (chartpath, ax, fig)
Ejemplo n.º 2
0
def plot_stock_performance(df,
                           fig=None,
                           ax=None,
                           figsize=(11, 6),
                           backend='Agg',
                           title='',
                           chartformat='svg',
                           debugTF=True,
                           **optx):
    sys.stderr.write("===start:{}()\n".format("plot_stock_performance"))
    if not isinstance(df, pd.DataFrame):
        df = pd.DataFrame(data=df)
    if len(df) < 1:
        return '', None, None
    if backend is not None and len(backend) > 1:
        plt.switch_backend(backend)
    bottom = optx['bottom'] if 'bottom' in optx else 0.2
    chartpath, chartname = gen_chartpath(**optx)
    trendTF = getKeyVal(optx, 'trendTF', True)
    max_num = df['close'].max()
    max_num_date = df[df['close'] == max_num].iloc[-1].name
    min_num = np.min(df['close'])
    min_num_date = df[df['close'] == min_num].iloc[-1].name
    curr_num = df['close'][-1]
    curr_num_date = df[df['close'] == curr_num].iloc[-1].name
    open_num = df['close'].iloc[0]
    max_index = np.max(df.index)
    min_index = np.min(df.index)
    x_lim = min_index.replace(hour=16, minute=31)
    xprice = getKeyVal(optx, 'xprice', open_num)
    cpchg = getKeyVal(optx, 'cpchg', round((curr_num / open_num - 1) * 100, 2))
    max_ylim = np.max([max_num, xprice])
    min_ylim = np.min([min_num, xprice])
    try:
        from _alan_pppscf import vertex_locator
        if trendTF is True:
            try:
                npar = getKeyVal(optx, 'npar', 6)
                trendName = df._get_numeric_data().columns[0]
                dy = df[trendName]
                dg, dh = vertex_locator(dy, npar=npar, debugTF=debugTF)
                dh = dg
            except Exception as e:
                sys.stderr.write("**ERROR:{} @ {}\n".format(
                    str(e), "running vertex_locator()"))
                dh = {}
            #print(dh)
        else:
            dh = {}
        if not isinstance(df, pd.DataFrame):
            df = pd.DataFrame(data=df)
        if fig is None:
            plt.rcParams.update(plt.rcParamsDefault)
            sns.set_style("whitegrid", {'grid.linestyle': '--'})
            fig, ax = plt.subplots(figsize=figsize)
            fig.autofmt_xdate()
            ax.yaxis.set_major_formatter(StrMethodFormatter('{x:,.0f}'))
            plt.xlim(min_index - timedelta(minutes=5),
                     x_lim + timedelta(minutes=5))
            plt.ylim(min_ylim - (max_ylim - min_ylim) / 2,
                     max_ylim + (max_ylim - min_ylim) / 5)
            plt.subplots_adjust(bottom=0.2)
            #plt.xlabel('Time',fontsize=15)
            #plt.ylabel('price',fontsize=15)
            #hours = mdates.HourLocator(interval = 1)
            h_fmt = mdates.DateFormatter('%H:%M')
            #ax.xaxis.set_major_locator(hours)
            ax.xaxis.set_major_formatter(h_fmt)
            ax.grid(False, axis='x')
            ax.spines['right'].set_color('none')
            ax.spines['top'].set_color('none')
            ax.spines['bottom'].set_color('none')
            ax.spines['left'].set_color('none')
            plt.title(title, fontproperties=fontProp(size=15))
            plt.legend(frameon=False)
        plt.plot(df.index, df['close'])
        plt.plot([min_index, x_lim], [xprice, xprice], 'k--',
                 lw=1)  # plot open dash line
        plt.plot([curr_num_date, curr_num_date], [xprice, curr_num],
                 'k--',
                 lw=1)  # plot day pchg vertical line
        #plt.annotate('{}%'.format(round((curr_num/open_num-1)*100,2)), xy=(curr_num_date,open_num+(curr_num-open_num)/2),xytext=(0,6),fontsize=10,annotation_clip=True, textcoords="offset points",ha=('left'), va='center') # plot pchg number
        plt.scatter(max_num_date, max_num, s=20, color='g',
                    zorder=19)  #plot max point
        plt.scatter(min_num_date, min_num, s=20, color='r',
                    zorder=18)  #plot min point
        plt.scatter(curr_num_date, curr_num, s=40, zorder=20)  #plot curr point
        plt.annotate('{}'.format(round(max_num, 2)),
                     xy=(max_num_date, max_num),
                     xytext=(0, 20),
                     fontsize=10,
                     arrowprops=dict(arrowstyle='simple'),
                     annotation_clip=True,
                     textcoords="offset points",
                     ha=('right'),
                     va='bottom')  # plot max point number
        plt.annotate('{}'.format(round(min_num, 2)),
                     xy=(min_num_date, min_num),
                     xytext=(0, -20),
                     fontsize=10,
                     arrowprops=dict(arrowstyle='simple'),
                     annotation_clip=True,
                     textcoords="offset points",
                     ha=('left'),
                     va='top')  # plot min point number
        plt.annotate('{} | {}%'.format(round(curr_num, 2), round(cpchg, 2)),
                     xy=(curr_num_date, curr_num),
                     xytext=(0, 20),
                     fontsize=10,
                     arrowprops=dict(arrowstyle='simple'),
                     annotation_clip=True,
                     textcoords="offset points",
                     ha=('left'),
                     va='bottom')  # plot curr point number
        if len(dh) > 1:
            if dh.iloc[-1].values < dh.iloc[-2].values:
                ar_color = 'red'
            else:
                ar_color = 'green'
            plt.annotate('',
                         xy=(dh.iloc[-1].name, dh.iloc[-1] * 1.00),
                         xytext=(dh.iloc[-2].name, dh.iloc[-2] * 1.00),
                         arrowprops=dict(facecolor=ar_color, shrink=0.05),
                         annotation_clip=True)  # plot trend arrow
            plt.plot(dh.index, dh.values)
        if 'volume' in df:
            axv = ax.twinx()
            axv.grid(False, axis='both')
            axv.spines['right'].set_color('none')
            axv.spines['top'].set_color('none')
            axv.spines['bottom'].set_color('none')
            axv.spines['left'].set_color('none')
            axv.xaxis.set_major_formatter(h_fmt)
            axv.set_yticklabels([])
            axv.tick_params(right="off")
            plt.ylim(0, df['volume'].max() * 3.5)
            #axv.plot(df['volume'].index, df['volume'], color='gray',alpha=0.8)
            axv.fill_between(df['volume'].index, df['volume'], alpha=0.8)
        if debugTF:
            sys.stderr.write("===plot data:\n {}\n".format(df.tail()))
        plt.subplots_adjust(left=0.1, bottom=bottom)
        if chartname is not None and len(chartname) > 5:
            plt.savefig(chartpath,
                        format=chartformat)  #, bbox_inches='tight',dpi=1000)
        elif backend is not None and backend.lower() == 'tkagg':
            plt.show(ax)
    except Exception as e:
        sys.stderr.write("**ERROR: {} @{}\n".format(str(e),
                                                    "plot_stock_performance"))
        return '', None, None
    return (chartpath, ax, fig)
Ejemplo n.º 3
0
def plot_candlestick(datax,
                     tsidx=None,
                     chartType='chart',
                     title='',
                     block=True,
                     debugTF=False,
                     ax=None,
                     colorUD=['green', 'red'],
                     trendTF=False,
                     npar=12):
    '''
	plot candlestick ohlc/volume graph
	'''
    if chartType == 'minute':
        wadj = 24 * 60
        dtfmt = '%H:%M'
    else:
        wadj = 1
        dtfmt = '%m/%d/%y'
    if 'mpldatetime' not in datax and isinstance(
            tsidx[0], (datetime.date, datetime.datetime)):
        datax['mpldatetime'] = [mdates.date2num(x) for x in tsidx]
    newAr = datax[['mpldatetime', 'open', 'high', 'low', 'close']].values
    if debugTF is True:
        pqint(newAr[:10], file=sys.stderr)
    SP = datax.shape[0]
    if ax is None:
        fig = plt.figure(facecolor='#07000d', figsize=(11, 6))
        ax = plt.subplot2grid((1, 2), (0, 0), rowspan=1, colspan=2)
    colorup, colordown = colorUD
    fillcolor = '#00ffe8'
    candlestick_ohlc(ax,
                     newAr[-SP:],
                     width=0.6 / wadj,
                     colorup=colorup,
                     colordown=colordown)
    ax.xaxis_date()
    ax.autoscale_view()
    ax.xaxis.set_major_formatter(mdates.DateFormatter(dtfmt))
    ax.grid(True, color='w', linestyle='dotted', linewidth=0.5)
    plt.xticks(rotation=30)
    plt.ylabel('OHLC Price/Volume')
    plt.xlabel('Date Time')

    if trendTF is True:
        from _alan_pppscf import vertex_locator
        mpldate, closep = datax[['mpldatetime', 'close']].T.values
        dg, dh = vertex_locator(closep, npar=npar, debugTF=debugTF)
        trend = dg['trend'].values
        #axt = ax.twinx()
        #ax.plot(mpldate[-SP:],trend[-SP:], color='cyan',alpha=.5)
        ax.plot(mpldate[dg.index.values], trend, color='cyan', alpha=.5)
        if debugTF:
            pqint("time/trend: ",
                  mpldate[dg.index.values],
                  trend,
                  file=sys.stderr)

    if 'volume' in datax or 'marketVolume' in datax:
        if 'volume' not in datax and 'marketVolume' in datax:
            datax.rename(columns={'marketVolume': 'volume'}, inplace=True)
        mpldate, volume = datax[['mpldatetime', 'volume']].T.values
        axv = ax.twinx()
        axv.fill_between(mpldate[-SP:],
                         0,
                         volume[-SP:],
                         facecolor='lightblue',
                         alpha=.4)
        axv.axes.yaxis.set_ticklabels([])
        axv.grid(False)
        ###Edit this to 3, so it's a bit larger
        axv.set_ylim(0, 3 * volume.max())
    if len(title) > 0:
        ax.set_title("")
    if block is True:
        plt.show(ax)
    return ax
Ejemplo n.º 4
0
def plot_candlestickCombo(data,
                          stock,
                          MA1=5,
                          MA2=30,
                          savePng=False,
                          block=False,
                          pngDIR='.',
                          chartType='chart',
                          trendTF=False,
                          npar=15,
                          debugTF=False,
                          colorUD=['green', 'red'],
                          title=None):
    '''
	plot candlestick ohlc/macd/rsi/ma combo graph
	'''
    colorup, colordown = colorUD
    # prepare data
    if 'mpldatetime' not in data:
        data['mpldatetime'] = [mdates.date2num(x) for x in data.index]
    newAr = data[['mpldatetime', 'open', 'high', 'low', 'close',
                  'volume']].values
    mpldate, closep, volume = data[['mpldatetime', 'close', 'volume']].T.values
    rsi, macd, ema9, macdsigv = data[[
        'rsi', 'macd_ema', 'signal_macd', 'signal_value_macd'
    ]].T.values
    ma1c, ma2c = 'ma{}'.format(MA1), 'ma{}'.format(MA2)
    Av1, Av2 = data[[ma1c, ma2c]].T.values
    #SP = len(mpldate[MA2-1:])
    SP = newAr.shape[0]

    # start plotting
    fig = plt.figure(facecolor='#07000d', figsize=(11, 6))
    ax1 = plt.subplot2grid((6, 4), (1, 0),
                           rowspan=4,
                           colspan=4,
                           facecolor='#07000d')
    if chartType == 'minute':
        wadj = 24 * 60
        dtfmt = '%H:%M'
        bym = [0, 15, 30, 45] if SP <= 120 else [0, 30] if SP <= 360 else [0]
    else:
        wadj = 1
        dtfmt = '%m/%d/%y'
    candlestick_ohlc(ax1,
                     newAr[-SP:],
                     width=.6 / wadj,
                     colorup=colorup,
                     colordown=colordown)
    ax1.xaxis_date()
    ax1.autoscale_view()
    Label1 = str(MA1) + ' SMA'
    Label2 = str(MA2) + ' SMA'

    ax1.plot(mpldate[-SP:], Av1[-SP:], '#e1edf9', label=Label1, linewidth=1.5)
    ax1.plot(mpldate[-SP:], Av2[-SP:], '#4ee6fd', label=Label2, linewidth=1.5)

    if trendTF is True:
        from _alan_pppscf import vertex_locator
        dg, dh = vertex_locator(closep, npar=npar, debugTF=debugTF)
        trend = dg['trend'].values
        ax1.plot(mpldate[dg.index.values],
                 trend,
                 label='Trend',
                 color='cyan',
                 alpha=.5)
        #ax1.plot(mpldate[-SP:],trend[-SP:], label='Trend',color='cyan',alpha=.5)
        if debugTF is True:
            pqint("trendline:\n", dh, file=sys.stderr)

    ax1.grid(True, color='w', linestyle='dotted', linewidth=0.5)
    if chartType == 'minute':
        xlocator = mdates.MinuteLocator(byminute=bym, interval=1)
        ax1.xaxis.set_major_locator(xlocator)
    else:
        nbins = 8
        nsp = (SP / nbins) if SP > nbins * 2 else SP
        bymd = [1, 5, 10, 15, 20, 25
                ] if SP < 50 else [1, 15] if SP < 120 else [1]
        itv = 1 if SP < 160 else int(nsp / 30. + 0.97)
        xlocator = mdates.MonthLocator(bymonthday=bymd, interval=itv)
        ax1.xaxis.set_major_locator(xlocator)
        # check if min/max of xaxis should be included major ticks
        xtcks = list(ax1.get_xticks())
        x1, x2 = xtcks[:2]
        xmin, xmax = ax1.get_xlim()
        if (x1 - xmin) > (x2 - x1) * 0.6:
            xtcks = [xmin] + xtcks
        if (xmax - xtcks[-1]) > (x2 - x1) * 0.6:
            xtcks = xtcks + [xmax]
        ax1.set_xticks(xtcks)
        ax1.xaxis.set_minor_locator(mdates.MonthLocator(interval=1))
        #original
        #ax1.xaxis.set_major_locator(mticker.MaxNLocator(10))

    ax1.xaxis.set_major_formatter(mdates.DateFormatter(dtfmt))
    ax1.yaxis.label.set_color("w")
    ax1.spines['bottom'].set_color("#5998ff")
    ax1.spines['top'].set_color("#5998ff")
    ax1.spines['left'].set_color("#5998ff")
    ax1.spines['right'].set_color("#5998ff")
    ax1.tick_params(axis='y', color='w')
    plt.gca().yaxis.set_major_locator(mticker.MaxNLocator(prune='upper'))
    ax1.tick_params(axis='x', color='w')
    plt.ylabel('Stock price and Volume')

    maLeg = plt.legend(loc=9,
                       ncol=2,
                       prop={'size': 7},
                       fancybox=True,
                       borderaxespad=0.)
    maLeg.get_frame().set_alpha(0.4)
    textEd = pylab.gca().get_legend().get_texts()
    pylab.setp(textEd[0:5], color='w')

    volumeMin = 0

    ax0 = plt.subplot2grid((6, 4), (5, 0),
                           sharex=ax1,
                           rowspan=1,
                           colspan=4,
                           facecolor='#07000d')
    rsiCol = '#c1f9f7'
    posCol = '#386d13'
    negCol = '#8f2020'

    ax0.plot(mpldate[-SP:], rsi[-SP:], rsiCol, linewidth=1.5)
    ax0.axhline(70, color=negCol)
    ax0.axhline(30, color=posCol)
    ax0.fill_between(mpldate[-SP:],
                     rsi[-SP:],
                     70,
                     where=(rsi[-SP:] >= 70),
                     facecolor=negCol,
                     edgecolor=negCol,
                     alpha=0.5)
    ax0.fill_between(mpldate[-SP:],
                     rsi[-SP:],
                     30,
                     where=(rsi[-SP:] <= 30),
                     facecolor=posCol,
                     edgecolor=posCol,
                     alpha=0.5)
    plt.gca().yaxis.set_major_locator(mticker.MaxNLocator(prune='upper'))
    ax0.set_yticks([30, 70])
    ax0.yaxis.label.set_color("w")
    ax0.spines['bottom'].set_color("#5998ff")
    ax0.spines['top'].set_color("#5998ff")
    ax0.spines['left'].set_color("#5998ff")
    ax0.spines['right'].set_color("#5998ff")
    ax0.tick_params(axis='y', color='w')
    ax0.tick_params(axis='x', color='w')
    plt.ylabel('RSI')

    ax1v = ax1.twinx()
    ax1v.fill_between(mpldate[-SP:],
                      volumeMin,
                      volume[-SP:],
                      facecolor='lightgray',
                      alpha=.4,
                      step='pre')
    ax1v.axes.yaxis.set_ticklabels([])
    ax1v.grid(False)
    ###Edit this to 3, so it's a bit larger
    ax1v.set_ylim(0, 3 * volume.max())
    ax1v.spines['bottom'].set_color("#5998ff")
    ax1v.spines['top'].set_color("#5998ff")
    ax1v.spines['left'].set_color("#5998ff")
    ax1v.spines['right'].set_color("#5998ff")
    ax1v.tick_params(axis='x', color='w')
    ax1v.tick_params(axis='y', color='w')

    ax2 = plt.subplot2grid((6, 4), (0, 0),
                           sharex=ax1,
                           rowspan=1,
                           colspan=4,
                           facecolor='#07000d')
    fillcolor = '#00ffe8'
    ax2.plot(mpldate[-SP:], macd[-SP:], color='#4ee6fd', lw=2)
    ax2.plot(mpldate[-SP:], ema9[-SP:], color='#e1edf9', lw=1)
    # calc (macd-ema9) as signal_macd
    ax2.fill_between(mpldate[-SP:],
                     macdsigv[-SP:],
                     0,
                     alpha=0.5,
                     facecolor=fillcolor,
                     edgecolor=fillcolor)

    plt.gca().yaxis.set_major_locator(mticker.MaxNLocator(prune='upper'))
    ax2.spines['bottom'].set_color("#5998ff")
    ax2.spines['top'].set_color("#5998ff")
    ax2.spines['left'].set_color("#5998ff")
    ax2.spines['right'].set_color("#5998ff")
    ax2.tick_params(axis='x', colors='w')
    ax2.tick_params(axis='y', colors='w')
    plt.ylabel('MACD', color='w')
    ax2.yaxis.set_major_locator(mticker.MaxNLocator(nbins=5, prune='upper'))

    if title is None or len(title) < 1:
        title = stock.upper()
    plt.suptitle(title, color='w', fontproperties=prop)

    plt.setp(ax0.get_xticklabels(), rotation=30, visible=True)
    plt.setp(ax2.get_xticklabels(), rotation=30, visible=False)
    plt.setp(ax1.get_xticklabels(), rotation=30, visible=False)
    """
	locNews=int(len(mpldate)*.66)
	ax1.annotate('News!',(mpldate[locNews],Av1[locNews]),
		xytext=(0.8, 0.9), textcoords='axes fraction',
		arrowprops=dict(facecolor='white', shrink=0.05),
		fontsize=14, color = 'w',
		horizontalalignment='right', verticalalignment='bottom')
	"""

    plt.subplots_adjust(left=.09,
                        bottom=.14,
                        right=.94,
                        top=.95,
                        wspace=.20,
                        hspace=0.10)

    wintitle = "Candlestick OHLC View"
    fig.canvas.set_window_title(wintitle)
    if savePng is True:
        chartName = '{0}/OHLC_MACD_RSI_{1}.png'.format(pngDIR, stock.upper())
        fig.savefig(chartName, facecolor=fig.get_facecolor())
    else:
        plt.show(block=block)
    return fig, [ax0, ax1, ax2]
Ejemplo n.º 5
0
def plot_csvdata(df, nbins=6,rsiYN=False,title=None,pivot_value=None,pivot_group=None,pngname=None,x_fmt="%b-%d-%y",interpolateYN=True,backend="tkAgg",npar=15,tsTF=True,xaxis=None,trendTF=False,debugTF=False,ohlcTF=False,ohlcComboTF=False,lang='en',**kwargs):
	if debugTF:
		sys.stderr.write("===plot_csvdata VARS:\t{}\n".format(locals()))
	import matplotlib.dates as mdates
	import matplotlib.image as mimage
	import matplotlib.ticker as mticker
	#pltStyle=getKeyVal(kwargs,'pltStyle','dark_background')
	pltStyle=getKeyVal(kwargs,'pltStyle','classic')
	figsize=getKeyVal(kwargs,'figsize',(11,6))
	ylabel=getKeyVal(kwargs,'ylabel',None)
	fontpath=getKeyVal(kwargs,'fontpath',None)
	if fontpath is not None:
		prop.set_file(fontpath)
	if pltStyle in plt.style.available:
		plt.style.use(pltStyle)
	#- Use backend to 'tkAgg' for cronjob
	if pngname is None or len(pngname)<=4:
		plt.switch_backend(backend)

	#- Rename columns
	renColumns=getKeyVal(kwargs,'renColumns',{})
	if len(renColumns)>0:
		df = renameDict(df,mapper=renColumns)
	#- Create datetime index
	idxname='date'
	pbname=xaxis
	if isinstance(df.index,pd.DatetimeIndex):
		pass
	elif pbname in df.columns:
		sdate = str(df[pbname].iloc[0])
		if sdate.isdigit() == True:
			if int(sdate)>123456789:
				idxpt=[epoch_parser(x) for x in df[pbname]]
			else:
				idxpt=[ymd_parser(x,fmt="%Y%m%d") for x in df[pbname]]
		else:
			idxpt=[ymd_parser(x,fmt=x_fmt) for x in df[pbname]]
		df.set_index(pd.DatetimeIndex(idxpt),inplace=True)
		df.index.rename(idxname,inplace=True)
		df = df.drop(pbname,1)
	elif idxname in df.columns:
		df[idxname] = pd.to_datetime(df[idxname])
		df.set_index(idxname,inplace=True)
	else:
		df = df.reset_index(drop=True)

	#- Create 2nd dataframe 'df2' for 2-Yaxis plot
	from _alan_calc import subDF
	dux=getKeyVal(kwargs,'columns2',None)
	if dux is not None:
		colLst2=dux.split(',')
		df2=subDF(df,colLst2)
		df=subDF(df,colLst2,reverseTF=True)
	else:
		df2={}

	#- Create a pivot table
	trendName = None
	if pivot_group in df.columns and pivot_value in df.columns:
		trendName = df[pivot_group][0]
		df=df.pivot_table(index='date',columns=pivot_group,values=pivot_value)
		#- Rename columns
		renColumns=getKeyVal(kwargs,'renColumns',{})
		if len(renColumns)>0:
			df = renameDict(df,mapper=renColumns)

	#- Create linear-interpolation for missing data 
	if interpolateYN is True:
		df=df.apply(extrapolate_series,axis=0)


	#- Create return since inception
	if rsiYN is True:
		de=[] 
		for j in range(df.shape[1]): 
			inix = df.iloc[0,j] if df.iloc[0,j]>1 else 1
			de.append(df.iloc[:,j]/inix*100.-100)
		#de = [df.iloc[:,j]/df.iloc[0,j]*100.-100 for j in range(df.shape[1])] 
		df = pd.concat(de,axis=1)

	#- NO PLOTTING, just return data
	if 'plotTF' in kwargs and kwargs['plotTF'] is False:
		return df,{},{}

	#- Create trend curve
	if trendTF is True:
		try:
			from _alan_pppscf import vertex_locator
			if trendName is None:
				trendName = df._get_numeric_data().columns[0]
			dg, dh = vertex_locator(df[trendName],npar=npar,debugTF=debugTF)
			#df['trend'] = dg['trend'].values
			if debugTF is True:
				sys.stderr.write("{}\n{}\n".format("Trendline dh:",dh))
		except Exception as e:
			sys.stderr.write("**ERROR: {} @ {}\n".format(str(e),'trendline'))

	if title is None: 
		title="/".join(df.columns).upper()
		if rsiYN is True:
			title += " Return Since Inception"

	#- plot simple line plot
	if tsTF is False:
		df = df.reset_index(drop=True)

	if debugTF is True:
		sys.stderr.write("{}\n".format(df.head()))
		sys.stderr.write("{}\n".format(df.tail()))
	nobs=len(df.index)
	nsp = (nobs/nbins) if nobs>nbins*2 else nobs
	#ds=[y for j,y in enumerate(df.index) if j%nsp==0]
	#ax=df.plot(xticks=ds,title=title)
	colorUD = ['red','green'] if lang=='cn' else ['green','red']
	if ohlcComboTF is True:
		from alan_plot import plot_candlestickCombo
		from _alan_calc import run_tech
		chartType = 'minute' if pbname == 'epochs' else 'chart'
		#ma1=5;ma2=30
		ma1,ma2=sma=getKeyVal(kwargs,'sma',[5,30])
		datax = run_tech(df, pcol='close',winLst=sma,debugTF=debugTF,nanTF=True)
		if 'open' not in datax:
			return datax, None, None
		fig, axes = plot_candlestickCombo(datax,title,ma1,ma2,block=False,chartType=chartType,trendTF=trendTF,npar=npar,debugTF=debugTF,colorUD=colorUD,title=title)
		#plt.suptitle(title,fontsize=18,fontproperties=prop)
		if pngname is not None and len(pngname)>4 and '.' in pngname:
			ghLst = plt.gcf().canvas.get_supported_filetypes().keys()
			ghx = pngname.split('.')[-1]
			format = ghx.lower() 
			if ghx.lower() in ghLst:
				format = ghx.lower() 
			else:
				format = 'svg'
			pngname = pngname.replace(ghx,'svg')
			plt.savefig(pngname, format=format) #, bbox_inches='tight',dpi=1000)
		# skip the plot if pngname='noshow'
		elif pngname is None:
			plt.show(axes)
		return datax, fig, axes
	fig, ax=plt.subplots(figsize=figsize)
	if ohlcTF is True:
		if 'marketVolume' in df:
			df.rename(columns={'marketVolume': 'volume'},inplace=True)
		if 'open' not in df and 'close' in df:
			df['open']=df['high']=df['low']=df['close']
		elif 'open' not in df:
			return df, None, None
		from alan_plot import plot_candlestick
		chartType = 'minute' if pbname == 'epochs' else 'chart'
		ax = plot_candlestick(df,tsidx=df.index,chartType=chartType,title=title,block=False,debugTF=debugTF,ax=ax,trendTF=trendTF,npar=npar,colorUD=colorUD)
		x_fmt = "%H:%M" if chartType == 'minute' else x_fmt
	else:
		colorLst=['blue','red','green','salmon','lightgray','cyan']
		df.plot(ax=ax,grid=True,color=colorLst)
		#ax=df.plot(figsize=(11,6))
		ax.set_ylabel(df.columns[0])
		if trendTF is True:
                        dg.plot(ax=ax)
		if len(df2)>0:
			if debugTF:
				sys.stderr.write("DF2:\n{}\n{}\n".format(df2.tail(),df2.shape))
			axv = ax.twinx()
			df2.plot(ax=axv,kind='area',alpha=0.4,legend=False)
			axv.yaxis.set_major_formatter(FuncFormatter(lambda x,pos: '{:,.0f}'.format(x)))
	if rsiYN is True: # calc Returns Since Incept
		ax.set_ylabel("Returns Since Inception (%)")
	if ylabel is not None and len(ylabel)>0:
		ax.set_ylabel(ylabel,fontproperties=fontProp(size=12))
	ax.grid(linestyle='dotted',linewidth=0.5)
	if df.index._typ == "datetimeindex":
		mddfmt=mdates.DateFormatter(x_fmt)
		ax.xaxis.set_major_formatter(mddfmt)
		xtinterval=(df.index[1]-df.index[0])
		if xtinterval.days < 7 and  xtinterval.days>=1 : # daily data
			ax.set_xlim(df.index[0], df.index[-1])
			#ax.xaxis.set_major_locator(mdates.MonthLocator(interval=int(nsp/30.+0.97)))
			bymd = [1,5,10,15,20,25] if nobs<50 else [1,15] if nobs<120 else [1]
			itv = 1 if nobs<160 else int(nsp/30.+0.97)
			xlocator = mdates.MonthLocator(bymonthday=bymd,interval=itv)
			ax.xaxis.set_major_locator(xlocator)
			# check if min/max of xaxis should be included major ticks
			if debugTF is True:
				sys.stderr.write("{} {}\n".format( ax.get_xticks(),ax.get_xlim()))
			xtcks = list(ax.get_xticks())
			x1,x2 = xtcks[:2]
			xmin,xmax = ax.get_xlim()
			if (x1-xmin)>(x2-x1)*0.6:
				xtcks = [xmin] + xtcks
			if (xmax-xtcks[-1])>(x2-x1)*0.6:
				xtcks = xtcks + [xmax]
			ax.set_xticks(xtcks)
			ax.xaxis.set_minor_locator(mdates.MonthLocator(interval=1))
			if debugTF is True:
				sys.stderr.write("{}\n".format(ax.get_xticks()))
			sys.stderr.write("{}\n".format( "Daily data use MonthLocator"))
		elif xtinterval.seconds < 30: # second data
			locator = mdates.AutoDateLocator()
			locator.intervald[5] = [0,5,10,15,20,25,30,35,40,45,55]
			mddfmt = mdates.AutoDateFormatter(locator)
			mddfmt.scaled[1/(24.*60.)] = '%M:%S' 
			ax.xaxis.set_major_locator(locator)
			ax.xaxis.set_major_formatter(mddfmt)
			sys.stderr.write("{} {}\n".format( "Second data use AutoDateLocator",xtinterval.seconds))
		elif xtinterval.seconds < 100 : # minute data
			bym = [0,15,30,45] if nobs<=120 else [0,30] if nobs<=360 else [0]
			xlocator = mdates.MinuteLocator(byminute=bym, interval = 1)
			ax.xaxis.set_major_locator(xlocator)
			sys.stderr.write("{} {}\n".format( "Minute data use MinuteLocator",xtinterval.days))
		else: # periodic data
			sys.stderr.write("{}\n".format( "Periodic data use DayLocator" ))
			ax.xaxis.set_major_locator(mdates.DayLocator(interval=nsp))
	ax.xaxis.label.set_visible(False)
	plt.title(title,fontsize=30,fontproperties=prop)
	plt.xticks(rotation='20',fontsize=12)#,fontproperties=prop)
	if len(df.columns)>1 and ohlcTF is False:
		ax.legend(loc="upper left",prop=prop)
	#ax.legend().set_visible(False)
	#logo = mimage.imread("aicaas_icon.png")
	#plt.figimage(logo, xo=20,yo=420)
	plt.subplots_adjust(left=0.1,bottom=0.30)
	if pngname is not None and len(pngname)>4:
		plt.savefig(pngname)#, bbox_inches='tight',dpi=1000)
		sys.stderr.write("Save chart {} to {}\n".format(title,pngname))
	else:
		plt.show(ax)
	return df, fig, [ax]
Ejemplo n.º 6
0
def run_csv2plot(args, opts=None, optx=None):
    """
	plot time series data from csv file 
	"""
    #- Set input parameters
    if opts is None:
        opts, _ = opt_csv2plot([])
    if optx is not None:
        opts.update(optx)
    for ky, va in opts.items():
        exec("{}=va".format(ky))

    #- Get data in datafram with selected [columns]
    df = get_csvdata(args,
                     sep=sep,
                     src=src,
                     days=days,
                     start=start,
                     end=end,
                     columns=columns,
                     hdrLst=hdrLst)

    if df is None or len(df) < 1 or df.size < 1:
        return None
    if debugTF is True:
        print >> sys.stderr, df.head()

    #- Use backend to 'tkAgg' for cronjob
    if pngname is None or len(pngname) <= 4:
        plt.switch_backend(backend)

    #- Create datetime index
    idxname = 'date'
    pbname = xaxis
    if pbname in df.columns:
        from _alan_date import ymd_parser, epoch_parser
        sdate = str(df[pbname].iloc[0])
        if sdate.isdigit() == True:
            if int(sdate) > 123456789:
                idxpt = [epoch_parser(x) for x in df[pbname]]
            else:
                idxpt = [ymd_parser(x, fmt="%Y%m%d") for x in df[pbname]]
        else:
            idxpt = [ymd_parser(x, fmt=x_fmt) for x in df[pbname]]
        df.set_index(pd.DatetimeIndex(idxpt), inplace=True)
        df.index.rename(idxname, inplace=True)
        df = df.drop(pbname, 1)
    elif idxname in df.columns:
        df[idxname] = pd.to_datetime(df[idxname])
        df.set_index(idxname, inplace=True)
    else:
        df = df.reset_index(drop=True)

    #- Create a pivot table
    trendName = None
    if pivot_group in df.columns and pivot_value in df.columns:
        trendName = df[pivot_group][0]
        df = df.pivot_table(index='date',
                            columns=pivot_group,
                            values=pivot_value)

    #- Create linear-interpolation for missing data
    if interpolateYN is True:
        df = df.apply(extrapolate_series, axis=0)

    #- Create return since inception
    if rsiYN is True:
        de = []
        for j in range(df.shape[1]):
            inix = df.iloc[0, j] if df.iloc[0, j] > 1 else 1
            de.append(df.iloc[:, j] / inix * 100. - 100)
        #de = [df.iloc[:,j]/df.iloc[0,j]*100.-100 for j in range(df.shape[1])]
        df = pd.concat(de, axis=1)

    #- Create trend curve
    if trendTF is True:
        try:
            from _alan_pppscf import vertex_locator
            if trendName is None:
                trendName = df._get_numeric_data().columns[0]
            dg, dh = vertex_locator(df[trendName], npar=npar, debugTF=True)
            #df['trend'] = dg['trend'].values
            if debugTF is True:
                print >> sys.stderr, "Trendline dg:\n", dg
        except Exception, e:
            print >> sys.stderr, "**ERROR: {} @ {}".format(
                str(e), 'vertex_locator()')