使用 PGFPlots 绘制财务数据

使用 PGFPlots 绘制财务数据

我最近对用 绘制财务数据很感兴趣pgfplots。我试图实现的风格与使用 gnuplot 可以生成的风格类似。但是,我熟悉pgfplots并喜欢它的输出,这就是为什么我更喜欢使用前者。到目前为止,我找不到任何类似的尝试或例子。

我正在尝试创建类似于在这些 gnuplot 示例。显然,折线图并不重要,但我感兴趣的是使用“金融条形图”和蜡烛图进行绘图,但主要是金融条形图。下面我提供了一个从链接页面中获取的示例。

目前我不知道从哪里开始。示例中的 gnuplot 代码非常简洁,我希望使用 达到类似的简洁程度pgfplots。但是,我不确定这是否可行。

有人知道如何使用财务条形图或蜡烛图绘制时间序列吗pgfplots?我很想知道你能想出什么。

带有黑色“财务条”的图表。


更新 1

我花了一些时间对此进行简短的调整。我包括了一些接近蜡烛图格式的内容,以及一个小的数据文件来说明这一点。感谢@Torbjørn T. 提供的链接答案 — 您将看到它在示例中完成了大部分繁重的工作。

AAPL.csv:

date,open,high,low,close,volume
2013-02-08,67.7142,68.4014,66.8928,67.8542,158168416
2013-02-11,68.0714,69.2771,67.6071,68.5614,129029425
2013-02-12,68.5014,68.9114,66.8205,66.8428,151829363
2013-02-13,66.7442,67.6628,66.1742,66.7156,118721995
2013-02-14,66.3599,67.3771,66.2885,66.6556,88809154
2013-02-15,66.9785,67.1656,65.7028,65.7371,97924631
2013-02-19,65.8714,66.1042,64.8356,65.7128,108854046
2013-02-20,65.3842,65.3842,64.1142,64.1214,118891367
2013-02-21,63.7142,64.1671,63.2599,63.7228,111596821
2013-02-22,64.1785,64.5142,63.7999,64.4014,82583823

几乎可以正常工作的示例代码:

\documentclass[border=3mm]{standalone}
\usepackage{pgfplotstable}
\pgfplotsset{compat=1.10}
\usepgfplotslibrary{statistics}

\makeatletter
\pgfplotsset{
    boxplot prepared from table/.code={
        \def\tikz@plot@handler{\pgfplotsplothandlerboxplotprepared}%
        \pgfplotsset{
            /pgfplots/boxplot prepared from table/.cd,
            #1,
        }
    },
    /pgfplots/boxplot prepared from table/.cd,
        table/.code={\pgfplotstablecopy{#1}\to\boxplot@datatable},
        row/.initial=0,
        make style readable from table/.style={
            #1/.code={
                \pgfplotstablegetelem{\pgfkeysvalueof{/pgfplots/boxplot prepared from table/row}}{##1}\of\boxplot@datatable
                \pgfplotsset{boxplot/#1/.expand once={\pgfplotsretval}}
            }
        },
        make style readable from table=lower whisker,
        make style readable from table=upper whisker,
        make style readable from table=lower quartile,
        make style readable from table=upper quartile,
        make style readable from table=median,
        make style readable from table=lower notch,
        make style readable from table=upper notch
}
\makeatother

\pgfplotstableread[col sep=comma]{aapl.csv}\datatable

\begin{document}
\begin{tikzpicture}
\begin{axis}[
    boxplot/draw direction=y,
    cycle list={{red},{black}},
    title={AAPL Candlestick Chart},
    xlabel={Date},
    ylabel={Price / USD}
    ]
\pgfplotstablegetrowsof{\datatable}
\pgfmathtruncatemacro\TotalRows{\pgfplotsretval-1}
\pgfplotsinvokeforeach{0,...,\TotalRows}
{
    \addplot+[
    boxplot prepared from table={
        table=\datatable,
        row=#1,
        lower whisker=low,
        upper whisker=high,
        lower quartile=open,
        upper quartile=close,
        median=close,
    },
    boxplot prepared={
        whisker extend=\pgfkeysvalueof{/pgfplots/boxplot/box extend}*0,
        every whisker/.style={thick}  
    },
    fill,fill opacity=0.5,
    ]
    coordinates {};
}
\end{axis}
\end{tikzpicture}
\end{document}

我已将输出附在下面;它开始看起来像我希望的那样。有些地方并不完美。例如,您可以看到穿过图中间的须线,其中上四分位数和下四分位数排列错误。一个快速而粗糙的解决方法是将不透明度设置为 1。

我把颜色循环设置为红色和黑色,以启发任何知道如何根据数据智能地分配颜色的人。

我欢迎对此进行任何改进或尝试财务标准。再次感谢。 我的烛台


更新2

我对此进行了更多的尝试。这是我的解决方案,它使用财务条形图进行绘图。我认为如果愿意的话,这个想法也可以扩展到正确格式化烛台。我不得不手动设置限制。也许最好的办法是先运行我之前的解决方案,以白色绘制,以确定绘图大小,然后在顶部生成输出。

请参阅下面的代码和输出。与以前一样,欢迎任何改进。

\documentclass[border=3mm]{standalone}
\usepackage{pgfplotstable}
\pgfplotsset{compat=1.10}

\pgfplotsset{
    select row/.style={
        x filter/.code={\ifnum\coordindex=#1\else\def\pgfmathresult{}\fi}
    }
}

\newcommand{\financebar}[5]{
% takes arguements date (x coord), open, close, high, low 
\edef\tmp{\noexpand\draw (axis cs:#1,#5) -- (axis cs:#1,#4);}\tmp
\edef\tmp{\noexpand\draw (axis cs:#1,#2) -- (axis cs:{#1-0.5},#2);}\tmp
\edef\tmp{\noexpand\draw (axis cs:#1,#3) -- (axis cs:{#1+0.5},#3);}\tmp
}

\pgfplotstableread[col sep=comma]{aapl.csv}\datatable
\begin{document}
\begin{tikzpicture}
\begin{axis}[
    cycle list={{red},{black}},
    title={AAPL Finance Bar Chart},
    xlabel={Date},
    ylabel={Price / USD},
    xmin=0, xmax=11,
    ymin=63, ymax=69.75 
    ]
    
\pgfplotstablegetrowsof{\datatable}
\pgfmathtruncatemacro\TotalRows{\pgfplotsretval-1}
\pgfplotsinvokeforeach{0,...,\TotalRows}
{
    
    \pgfplotstablegetelem{#1}{open}\of{\datatable}\edef\openPrice{\pgfplotsretval}
    \pgfplotstablegetelem{#1}{close}\of{\datatable}\edef\closePrice{\pgfplotsretval}
    \pgfplotstablegetelem{#1}{high}\of{\datatable}\edef\highPrice{\pgfplotsretval}
    \pgfplotstablegetelem{#1}{low}\of{\datatable}\edef\lowPrice{\pgfplotsretval}

    \financebar{#1+1}{\openPrice}{\closePrice}{\highPrice}{\lowPrice}
}
\end{axis}
\end{tikzpicture}
\end{document}

在此处输入图片描述

答案1

我们可以通过使用包中的函数R检索相关数据并使用包集合中的函数绘制烛台和移动平均线来实现这一点。此示例在很大程度上遵循了 Matt Dancho在此处发布的他的包的插图:tq_gettidyquantggplottidyversetidyquant使用 tidyquant 绘制图表

在此处输入图片描述

\documentclass[a4paper,10pt]{article}
\usepackage{tikz}
\pagestyle{empty}

<<Setup,echo=FALSE>>=
suppressPackageStartupMessages({
library(tidyverse)
library(tidyquant)
library(tikzDevice)
})

theme_set(theme_bw() +
          theme(axis.text.x     = element_text(face="bold",size=14,angle=0, hjust=0.5),
                axis.text.y     = element_text(face="bold",size=14,hjust=1),
                axis.title      = element_text(face="bold",size=16),
                plot.title      = element_text(face="bold",size=14)))
@

<<GetData,echo=FALSE>>=
#https://cran.r-project.org/web/packages/tidyquant/vignettes/TQ04-charting-with-tidyquant.html#candlestick-chart
# Get AAPL and AMZN Stock Prices
start <- as_date("2015-09-01")
end <- as_date("2017-01-15")
AAPL <- tq_get("AAPL", get = "stock.prices", from = start, to = end)

@

\begin{document}
<<Candlestick,device='tikz',echo=FALSE>>=
AAPL %>%
    ggplot(aes(x = date, y = close)) +
    geom_candlestick(aes(open = open, high = high, low = low, close = close)) +
    geom_ma(ma_fun = SMA, n = 3, linetype = "dotted", size = 1.25,color="green") +
    labs(title = "AAPL Candlestick Chart",
         subtitle = "24 Nov 2016 - 15 Jan 2017",
         y = "Closing Price", x = "") + 
    coord_x_date(xlim = c(as_date("2016-11-24"), end+days(2)),
                 ylim = c(105, 120))
@

\end{document}

相关内容