通达信批导出股票历史交易数据并用R语言写入SQLite数据库
要分析金融数据,首先要有数据,好在金融数据的比较容易获取,比如股票,通过看盘软件批量导出股票交易历史数据。下面就简单介绍从通达信批量导出历史交易数据,读取csv文件并简单处理后,在R语言下用sapply函数循环批量读取并写入SQLite数据库的教程。
其中使用数据库部分是针对无数据库基础的人的。使用的SQLite是一种轻量级的、不需要安装数据库软件也不需要配置环境的、直接安装对应的R包RSQLite即可使用的数据库,非常适合无数据库基础的R语言用户在R语言环境下管理自己的数据。同时,它也是专业级的,苹果iphone的ISO系统数据管理就是基于SQLite的,MAC 的OS X系统的从10.4后把SQLite这套相当出名的数据库软件放进了作业系统工具集里。
1
批量导出股票历史交易数据
因为实际分析过程中,即会用到复权数据也会用到未复权数据,所以2种数据我分别导出,我用的是通达信行情软件,以上证50指数成份股(截止2017年12月31日)为例,先导出前复权数据放到“../stock”中,再导出未复权的数据放到“../stock_F”中。
本文代码使用相对路径,“..” 代表代码文件所在文件夹的父文件夹,我的目录结构会在下面说明。不熟悉R语言文件和文件夹管理的可
回复“文件管理”
获取相应文件。1.1
先导前复权数据
打开通达信客户端,依次点选:菜单>系统>数据导出,如下图所示(如果交易数据没有下载到最新日期,软件会提示下载到最新日期,重新按上述步骤操作):
第一步:点击上图中“高级导出”
第二步:点击上图中的“添加品种”
第三步:选取要导出的股票
我们是要导出上证50指数成份股,所以在第一行先“指数板块”后在左侧选“上证50”,之后点“全选”,再点“确定”。
你可以根据需求选中相应的股票,比如:全部A股等。
第四步:设置导出选项
这一步有几点要特别注意:
位置1:选“日线”;
位置2:选文件夹,复权数据我放在“stock_F”下;
位置3:文件名格式要特别注意YY表市场(如SH表示上交所,SZ表示深交所),6个X表示代码,有些数据库表名不用数字开头,所以我们用YYXXXXXX.csv格式,写入数据库时用YYXXXXXX格式命名每个表;
位置4:复权选 “前复权”,分隔符选“逗号”,日期格式….
我们看一下导出的文件:
str
(dir
("../stock_F/"
))## chr [1:50] "SH600000.csv" "SH600016.csv" "SH600019.csv" ...1.2
导出未复权数据
再导出上证50指数成份股的未复权数据。
未复权数据导出选项设置
有几点与前一次不同:
位置2:选文件夹,复权数据我放在“stock”下;
位置3:未复权数据我们用XXXXXX.YY.csv格式命名文件,写入数据库时用我们将50个文件写入同一张表SH50_stocks,并用XXXXXX.YY格式做为“code”列,以区分不同代码的数据;
位置4:复权选 “前复权”。
我们看一下对应文件夹:
str
(dir
("../stock/"
))## chr [1:50] "600000.SH.csv" "600016.SH.csv" "600019.SH.csv" ...搞定,里面有50个文件。
dir()函数,它可以生成指定文件夹下的文件或文件夹的名称列表清单(格式为字符串向量),路径中的“..”代表代码文件所在的文件夹的父文件夹。
2
用R语言批量读取前复权股票历史交易数据
我们先读取前复权的数据,读取后每个文件(每只股票)在数据库中建一个表并用YYXXXXXX格式命名每个表,表名在文件名中提取,还记得导出的前复权文件名吗?这样滴“SH600000.csv”…
2.1
工作目录的目录结构
为了方便大家下载本文代码(地址见文末)和数据文件后直接运行代码,我使用相对路径,需要先对目录结构做一下说明。不熟悉代码的朋友可按下面目录创建目录和文件,即可直接运行本文代码(或按文末地址下载代码和数据文件直接运行代码)。
system
("tree /f d:/Rdata/knitr/WX_QuantFinanceWithR"
)从上面可以看出我的文件夹WX_QuantFinanceWithR下面文件夹和文件的位置,用到的3个分别是:
data_analysis
文件夹下的Read_stocks_to_SQLite.Rmd就是本文的rmarkdown源文件,同名的html是本文运行后输出文件。
rmarkdown是R语言运行环境RStudio所使用的扩展的markdown标签语言,是一种易学、易用,可实现代码、图文、数学公式等内容混合排版并输出为指定格式(包括:html、word、PDF等)的文档的标签语言,非常方便。 本文的源文件即为rmarkdown格式,你可以在文末提供的地址中下载,了解rmarkdown详细请
回复 “rmarkdown”
获取相应文章。stock
该文件夹放的是从行情软件导出的上证50成份股未复权的csv格式文件(2017年12月31日);
stock文件夹与data_analysis文件夹都在WX_QuantFinanceWithR文件夹下,而代码文件在data_analysis文件夹下的Read_stocks_to_SQLite.Rmd,所以路径中的“../stock”代表就是WX_QuantFinanceWithR文件夹下的stock文件夹。
stock_F
该文件夹放的是从行情软件导出的上证50成份股前复权的csv格式文件(2017年12月31日),注意文件名的格式不同,是在导出时分别设置的。
2.2
读取单个文件
因为本文的源代码文件在WX_QuantFinanceWithR/data_analysis/下,我们要读取的前复权股票历史交易数据在WX_QuantFinanceWithR/stock_F/中,使用相对路径应该是:“../stock_F/”。
2.2.1
列出文件列表
file_list <-
list.files
("../stock_F/"
,pattern =
"csv"
,full.names =
TRUE
)str
(file_list)卷 新加卷 的文件夹 PATH 列表卷序列号为 C2D1-47DA
D:\RDATA\KNITR\WX_QUANTFINANCEWITHR
│
├─data_analysis
│ data_manipulation_with_RSQLite.html
│ data_manipulation_with_RSQLite.Rmd
│
├─input
│ WX_QuantFinanceWithR_SQLite_data.db
│
│ WX_QuantFinanceWithR_SQLite_data.db
│
├─pic
│ 来源于公众号_R语言量化金融.png│
│
├─stock
│ 600000.SH.csv
│ 600016.SH.csv
│ 600019.SH.csv
│ ...省略46个文件..
│ 603993.SH.csv
│
└─stock_F
│ SH600000.csv
│ SH600016.csv
│ SH600019.csv
│ ...省略46个文件..
│ SH603993.csv
list.files()函数列出指定文件夹下的文件名(而不包含文件夹)列表(注意:dir()会包含文件夹名),下面代码中的2个参数:
参数pattern设为“csv” 表示只列出后缀为csv的文件,如果同文件夹下还有其它后缀的文件,该参数就有必要;
参数full.names设为TRUE 表示列出的文件名为包含路径的文件名(如果设为FALSE就会列出不带路径的文件名),因为我们指定的文件夹为相对路径,所以带路径的文件名也是相对路径。
2.2.2
读取第1个csv文件
SH600000_df <-
read.csv
(file_list[1
],header =
FALSE
,sep =
","
,stringsAsFactors =
FALSE
)head
(SH600000_df,2
)## V1 V2 V3 V4 V5 V6 V7## 1 1999/11/10 0.93 0.96 0.63 0.72 174085000 4859102208## 2 1999/11/11 0.70 0.79 0.70 0.72 29403400 821582208为了避免新手中文字符出现乱码错误,我们导出时没有勾选“生成导出头部”,所以参数header设为FALSE,R自动分配V1~V7的列名称,我们用下面的代码改列名。
names
(SH600000_df) <-
c
("date"
,"open"
,"high"
,"low"
,"close"
,"volume"
,"amt"
)tail
(SH600000_df,2
)## date open high low close volume amt## 4277 2017/12/29 12.52 12.62 12.51 12.59 16351826 205752880## 4278 数据来源:通达信 NA NA NA NA NA NA最后一行是数据来源的声明,我们需要删除这一行:
SH600000_df <-
SH600000_df[
-
nrow
(SH600000_df),]str
(SH600000_df)## "data.frame": 4277 obs. of 7 variables:## $ date : chr "1999/11/10" "1999/11/11" "1999/11/12" "1999/11/15" ...## $ open : num 0.93 0.7 0.73 0.77 0.74 0.58 0.66 0.69 0.62 0.57 ...## $ high : num 0.96 0.79 0.79 0.78 0.75 0.66 0.7 0.7 0.63 0.58 ...## $ low : num 0.63 0.7 0.72 0.72 0.57 0.56 0.61 0.61 0.55 0.53 ...## $ close : num 0.72 0.72 0.76 0.72 0.58 0.66 0.64 0.62 0.57 0.57 ...## $ volume: int 174085000 29403400 15007900 11921000 23223100 10052500 8446500 5374900 5535400 3843900 ...## $ amt : num 4.86e+09 8.22e+08 4.22e+08 3.33e+08 6.29e+08 ...删除后,数据框变为4272行,少了一行。
2.2.3
正确处理日期的格式避免写入SQLite数据库日期值错误
为了正确地将日期写入SQLite数据库,date列需要的格式为“2017-01-01”的字符串,而不是“2017-1-1”或是“2017/1/1”等(注意月和日的格式是两位字符表示),不是日期格式。虽然读入的“date”列默认是字符格式,但有时导出后的日期值的月和日的格式不是两位字符表示。这会导致,日期写入SQLite数据库后,有些值会不正确。这个是新手很容易碰到但较难解决问题。
我们先转为日期,再转为字符格式,就可保证这一点。
SH600000_df
$
date <-
as.character
(as.Date
(SH600000_df$
date))str
(SH600000_df)## "data.frame": 4277 obs. of 7 variables:## $ date : chr "1999-11-10" "1999-11-11" "1999-11-12" "1999-11-15" ...## $ open : num 0.93 0.7 0.73 0.77 0.74 0.58 0.66 0.69 0.62 0.57 ...## $ high : num 0.96 0.79 0.79 0.78 0.75 0.66 0.7 0.7 0.63 0.58 ...## $ low : num 0.63 0.7 0.72 0.72 0.57 0.56 0.61 0.61 0.55 0.53 ...## $ close : num 0.72 0.72 0.76 0.72 0.58 0.66 0.64 0.62 0.57 0.57 ...## $ volume: int 174085000 29403400 15007900 11921000 23223100 10052500 8446500 5374900 5535400 3843900 ...## $ amt : num 4.86e+09 8.22e+08 4.22e+08 3.33e+08 6.29e+08 ...2.3
数据库小白级SQLite数据库入门
读取数据后,将数据写入数据库,我用的是SQLite数据库,前面已介绍了。SQLite是一种轻量级的数据库,非常适合没有数据库基础的非专业人士用来管理自己的数据。有多“轻”呢?它不需要安装数据库管理软件、不需要配置软件环境。安装R包RSQLite(及依赖的包)后就可以直接使用。
安装RSQLite包后你就可以直接运行下面的代码体验一下,你会发现它像使用其它包一样,够“轻”吧。
安装并加载RSQLite包
install.packages(“RSQLite”)安装RSQLite包,如果提示还有其它依赖包需要安装,用install.packages()直接安装好即可。
library
(RSQLite)创建数据库连接
dbConnect
(SQLite
(),"../input/WX_QuantFinanceWithR_SQLite_data.db"
)上面这行代码会创建一个连接到指定文件夹下WX_QuantFinanceWithR_SQLite_data.db数据库文件的名叫con_wx的SQLite数据库连接,如果指定的文件夹下没有数据文件,就会在这个文件夹下创建一个空的WX_QuantFinanceWithR_SQLite_data.db数据库文件,并建立连接,之后就可通过这个连接操作(读、写、更新等)数据库中的数据。
对于没用过数据库的会问,用excel、csv、txt等格式保存文件不也是一样吗?
肯定不一样!
即不使用复杂的数据库操作,只以最简单地方式(数据库小白级)读、写数据,数据库也有以下几个优点:
创建带主键的表可以避免重复数据,尤其是重复写入时,主键重复的数据行会自动被忽略或替换(需要设置);
大表(百万/千万行或更大)可以按指定列(或多个列)条件筛选后读取所需的部门数据行,而不是全部行。
如果稍学一些入门级SQL,则可以大大提高数据操作效率,回复
“RSQLite”
获取相关文章。创建SQLite数据表
先创建表再写入数据。
sql_create <-
"CREATE TABLE if not exists "SH600000" (
"date" DATE,
"open" REAL,
"high" REAL,
"low" REAL,
"close" REAL,
"volume" INTEGER,
"amt" REAL,
PRIMARY KEY ("date" DESC) ON CONFLICT IGNORE);"
dbSendQuery
(con_wx,sql_create)## <SQLiteResult>## SQL CREATE TABLE if not exists "SH600000" (## ## "date" DATE, ## ## "open" REAL, ## ## "high" REAL, ## ## "low" REAL, ## ## "close" REAL, ## ## "volume" INTEGER, ## ## "amt" REAL, ## ## PRIMARY KEY ("date" DESC) ON CONFLICT IGNORE);## ROWS Fetched: 0 [complete]## Changed: 0dbListTables
(con_wx)## [1] "SH600000"创建数据表代码说明:
CREATE TABLE if not exists ‘SH600000’ 表示表SH600000不存在就创建,表名放在引号内。
创建的字段名称和类型放在括号内。
字段名称放在引号内,字段名称后是数据类型,字段名称与字段类型之间空一格。DATE是日期格式,REAL是浮点型值(以8字节IEEE浮点数存放),INTEGER是有符号整型值,TEXT是字符格式。
PRIMARY KEY (‘date’ DESC) 表示将date字段设为主键(倒序),可避免重复行并有排序保存数据等;
ON CONFLICT IGNORE 是指在写入数据时,如有重复就忽略(不写入)。除了忽略还可以选择“REPLACE”、“ABORT”、“FAIL”、“ROLLBACK”。
dbSendQuery(con_wx,sql_create) 将SQL语句sql_create通过con_wx提交给数据库引擎执行;
dbListTables(con_wx)查询con_wx所连接到的数据有哪些数据表。
SQLite标准的数据类型有5种,如下:
序号数据类型说明
1
NULL
空值。
2
INTEGER
带符号的整型,具体取决有存入数字的范围大小。
3
REAL
浮点数字,存储为8-byte IEEE浮点数。
4
TEXT
字符串文本。
5
BLOB
二进制对象。
同时,SQLite兼容MySQL的数据类型比如上面用到的date类型。
除了先创建表再写入数据外,还可以通过直接向数据库写入数据的方式创建表,见下文“向SQLite数据库写入数据”。
向SQLite数据库写入数据
dbWriteTable
(con_wx,"SH600000"
,SH600000_df,append =
TRUE
,row.names =
FALSE
)dbWriteTable
(con_wx,"SH600000_plus"
,SH600000_df,append =
TRUE
,row.names =
FALSE
)dbWriteTable()是写入数据库的函数,用到的参数说明如下:
con_wx 是之前创建的数据库连接;
SH600000 是前面创建的数据库中要写入的表名;
SH600000_df 是上文用read.csv读取的SH600000.csv中的数据;
append = TRUE 表示向表中添加数据;
row.names = FALSE 意思是不要把数据框的行号做为一列写入数据中。
写入不成功会有错误提示,首先检查append,row.names两个参数。
上面第二行代码中的SH600000_plus表,我们未没有创建,直接写入数据创建的表,写入成功。可按下文的方法查看数据库中表的表单。
查看数据库中的数据表清单
head
(dbListTables
(con_wx))## [1] "SH600000" "SH600000_plus"可以看到我们以直接写入数据的方式创建数据表SH60000_plus。不以这样创建的表不会创建主键,写入重复行时,不会自动忽略或覆盖,所以,最好是先创建带主键的数据表,再写入数据。
从数据库中读取数据(查询)
下面代码从表SH600000中查询整个表。
SH600000_SQLite <-
dbGetQuery
(con_wx,"select * from SH600000;"
)head
(SH600000_SQLite,2
)## date open high low close volume amt## 1 1999-11-10 0.93 0.96 0.63 0.72 174085000 4859102208## 2 1999-11-11 0.70 0.79 0.70 0.72 29403400 821582208dbGetQuery(con_wx,“select * from SH600000;”) 将SQL查询语句 “select * from SH600000;” 通过数据库连接con_wx提交并返回查询结果。
head(SH600000_SQLite,2)可以看出,表SH600000最早的记录是1999-11-10日的。下面代码返回日期大于等于2017-12-01的行。
SH600000_SQLite2 <-
dbGetQuery
(con_wx,"select * from SH600000 where date >= "2017-12-01";"
)head
(SH600000_SQLite2,2
)## date open high low close volume amt## 1 2017-12-29 12.52 12.62 12.51 12.59 16351826 205752880## 2 2017-12-28 12.60 12.66 12.53 12.54 23870824 300834016SQL语句中的 “where date >= ‘2017-12-01’”,表示按>= ’2017-12-01’的条件筛选date列。
清空数据表
dbSendQuery
(con_wx,"DELETE FROM SH600000;"
)#dbSendQuery(con_wx,"truncate table SH600000") #MySQL数据库用这句清空表。
head
(dbListTables
(con_wx))## <SQLiteResult>## SQL DELETE FROM SH600000;## ROWS Fetched: 0 [complete]## Changed: 4277## [1] "SH600000" "SH600000_plus"上面代码将con_wx连接到的数据库中的表SH600000中的数据清空,但表(结构)还在。
删除数据表
dbSendQuery
(con_wx,"DROP TABLE SH600000;"
)head
(dbListTables
(con_wx))## <SQLiteResult>## SQL DROP TABLE SH600000;## ROWS Fetched: 0 [complete]## Changed: 4277## [1] "SH600000_plus"上面代码将con_wx连接到的数据库中的表SH600000删除。
2.4
批量循环读取csv并写入SQLite数据库
result <-
sapply
(file_list,function
(full_name){ table_name <-
substr
(basename
(full_name),1
,8
) data_read <-
read.csv
(full_name,header =
FALSE
,sep =
","
) data_read <-data_read[
-
nrow
(data_read),]names
(data_read) <-
c
("date"
,"open"
,"high"
,"low"
,"close"
,"volume"
,"amt"
) data_read$
date <-
as.character
(as.Date
(data_read$
date)) sql_create <-
paste
("CREATE TABLE IF NOT EXISTS "
,table_name," (
"date" DATE,
"open" REAL,
"high" REAL,
"low" REAL,
"close" REAL,
"volume" INTEGER,
"amt" REAL,
PRIMARY KEY ("date" DESC) ON CONFLICT IGNORE);"
sep=
""
)dbSendQuery
(con_wx,sql_create)dbWriteTable
(con_wx,table_name,data_read,append =
TRUE
,row.names =
FALSE
)paste
(Sys.time
(),"写入表"
,table_name,"中"
,nrow
(data_read),"行。"
,sep=
""
)) })## [1] "2018-01-07 11:29:28写入表SH600000中4277行。"## [1] "2018-01-07 11:29:29写入表SH600016中4066行。"## [1] "2018-01-07 11:29:29写入表SH600019中3978行。"## [1] "2018-01-07 11:29:29写入表SH600028中3927行。"## [1] "2018-01-07 11:29:30写入表SH600029中3408行。"...省略44行...## [1] "2018-01-07 11:29:39写入表SH603993中1253行。"#dbListTables(con_wx)
上述代码说明:
file_list带路径的文件名向量,如:“../stock_F/SH600000.csv”;
basename(full_name) 从带路径的文件名中取基本文件名(不带路径),如:“SH600000.csv”;
substr(basename(full_name),1,8) 从基本文件名中取第1个到第8个字符,即:“SH600000”;
print()是输出每个表/每只股票写入的数据行数,循环过程中每循环有个输出是个好办法,一是知道执行到哪一步了,二是有异常报错时知道在哪个循环报的错。
dbDisconnect
(con_wx)dbDisconnect() 是断开连接,用完数据库要记得断开连接。
3
批量读写完整代码
我们继续读写无复权股票数据文件,这次我将50个文件写入同一个数据表,用股票代码作code列以区别不同的股票的数据,需要先创建带复合主键的数据表。
library
(RSQLite) con_wx <-
dbConnect
(SQLite
(),"../input/WX_QuantFinanceWithR_SQLite_data.db"
) sql_create <- "CREATE TABLE if not exists "SH50stocks" (
"code" TEXT,
"date" DATE,
"open" REAL,
"high" REAL,
"low" REAL,
"close" REAL,
"volume" INTEGER,
"amt" REAL,
PRIMARY KEY ("code","date") ON CONFLICT IGNORE);"
#这次设置复各主键,这个经常用到。
dbSendQuery
(con_wx,sql_create) file_list <-
list.files
("../stock/"
,pattern =
"csv"
,full.names =
TRUE
) result <-
sapply
(file_list,function
(full_name){ code <-
substr
(basename
(full_name),1
,9
)#将股票代码做为一列,与上文不同。
data_read <-
read.csv
(full_name,header =
FALSE
,sep =
","
) data_read <-data_read[
-
nrow
(data_read),]names
(data_read) <-
c
("date"
,"open"
,"high"
,"low"
,"close"
,"volume"
,"amt"
) data_read$
date <-
as.character
(as.Date
(data_read$
date))# 下面这一行是code在前为了将code做为第一列,与创建的数据表保持一致,避免写入错误。
data_read <-
data.frame
(code =
code,data_read)dbWriteTable
(con_wx,"SH50_stocks"
,data_read,append =
TRUE
,row.names =
FALSE
)paste
(Sys.time
(),"写入数据表SH50stocks中代码为:"
,code,nrow
(data_read),"行数据。"
),sep=
" "
) })## <SQLiteResult>## SQL CREATE TABLE if not exists "SH50stocks" (## ## "code" TEXT,## "date" DATE, ## "open" REAL, ## "high" REAL, ## "low" REAL, ## "close" REAL, ## "volume" INTEGER, ## "amt" REAL, ## PRIMARY KEY ("code","date") ON CONFLICT IGNORE);## ROWS Fetched: 0 [complete]## Changed: 0## [1] "2018-01-07 11:29:40 写入数据表SH50stocks中代码为: 600000.SH 4277 行数据。"## [1] "2018-01-07 11:29:40 写入数据表SH50stocks中代码为: 600016.SH 4066 行数据。"...省略47行...## [1] "2018-01-07 11:29:50 写入数据表SH50stocks中代码为: 603993.SH 1253 行数据。"3.1
结束查看写入数据库的表(只列出了前6个表):
head
(dbListTables
(con_wx),6
))## [1] "SH50_stocks" "SH50stocks" "SH600000" "SH600000_plus"## [5] "SH600016" "SH600019"查看2017-12-28日每只股票当天的交易记录:
12.28
<-
dbGetQuery
(con_wx,"select * from SH50_stocks where date = "2017-12-28" "
)head
(data.12.28
)## code date open high low close volume amt## 1 600000.SH 2017-12-28 12.60 12.66 12.53 12.54 23870824 300834016## 2 600016.SH 2017-12-28 8.43 8.46 8.39 8.39 56503202 475605024## 3 600019.SH 2017-12-28 8.32 8.69 8.29 8.65 94868348 811240064## 4 600028.SH 2017-12-28 6.10 6.20 6.06 6.18 135822802 835696064## 5 600029.SH 2017-12-28 11.78 12.06 11.68 11.91 60573416 719252160## 6 600030.SH 2017-12-28 18.06 18.45 17.98 18.12 102101410 1864400896查看某只股票600016.SH的2017-12-01日以来的历史交易记录:
dbGetQuery
(con_wx,"select * from SH50_stocks where code = "600016.SH" and date >= "2017-12-01" "
)head
(sh600016)## code date open high low close volume amt## 1 600016.SH 2017-12-01 8.79 8.86 8.68 8.83 133017638 1167279616## 2 600016.SH 2017-12-04 8.79 8.86 8.76 8.84 86831890 765035712## 3 600016.SH 2017-12-05 8.82 9.10 8.80 9.03 239648915 2152088320## 4 600016.SH 2017-12-06 8.95 8.99 8.81 8.87 108223628 964007552## 5 600016.SH 2017-12-07 8.83 8.90 8.72 8.87 101262539 892833536## 6 600016.SH 2017-12-08 8.84 8.88 8.78 8.82 74920149 660720320dbDisconnect
(con_wx)怎么样,用数据库比用excel、csv高效很多吧,而且以上只是很基本、很简单的SQL语句,尤其是:并不难。 要不要把上面的源代码下载下来试一下?地址下面有。
4
本文源代码及数据文件下载地址
下载地址
百度网盘下载链接:http://pan.baidu.com/s/1kU9cQmr 密码:r0q9。
本文由rmarkdown生成
rmarkdown在是R语言环境的markdown支持包,可实现 图+文+代码+复杂数学公式等
如下所示:
> sql_create <- "CREATE TABLE if not exists "SH600000" (+ "date" DATE, + "open" REAL, + "high" REAL, + "low" REAL, + "close" REAL, + "volume" INTEGER, + "amt" REAL, + PRIMARY KEY ("date" DESC));"> > dbSendQuery(con_wx,sql_create)
上述的下载地址中,包含本语言的rmarkdown源文件,
回复“rmarkdown”
可获取基于本文rmarkdown源文件的rmarkdown使用说明。比如本文的html格式在chrome下浏览的截图如下:
本文rmarkdown输出html文件在chrome下浏览的截图
- 过去20年买哪些股票最赚钱?
- 股票技术指标分析:MACD形态操作策略
- 股票抄底秘笈:实战中看K线形态来预测底部
- 股票买入技巧:三大经典k线买入形态
- 庄家做庄一只股票需要多少筹码,干货分享
- 美股三大股指小幅低开 税改来袭千亿美元股票回购潮渐起
- 股票技术分析:如何判断庄家是否吸筹和确认主力吸筹
- “年货”!分享我的股票交易体系,第二篇:建仓篇
- 翟敬勇:买股票就是买公司,四毛钱买一块钱的东西
- 逆向投资:丑陋的股票往往是漂亮的