标签归档:量化投资

教你用Python获取股票的历史分时成交数据

Pytdx是一个基于C++接口开发的Python第三方模块。

使用它我们能够很方便地获取通达信上的标准行情数据、历史行情数据、专业的财务数据,并且支持macOS系统,非常方便。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install pytdx

2.查询分时成交

为了能够查询数据,我们第一步需要创建API,连接通达信服务:

from pytdx.exhq import *
from pytdx.hq import *
api_hq = TdxHq_API()
api_hq = api_hq.connect('119.147.212.81', 7709)

第二步,使用这个API查询历史分时数据:

from pytdx.exhq import *
from pytdx.hq import *
api_hq = TdxHq_API()
api_hq = api_hq.connect('119.147.212.81', 7709)
print(api_hq.get_history_transaction_data(TDXParams.MARKET_SZ, "002560", 0, 500, 20220916))

效果如下:

[OrderedDict([('time', '14:29'),
              ('price', 7.91),
              ('vol', 582),
              ('buyorsell', 1)]),
 ... ...
]

请注意,查询的日期必须填写整数,不然会查询不到数据。

3.查询完整历史分时数据

在前面的示例中,我们查询了 002560 这个股票在 2022-09-16 的最后500条数据。

如果我们想要查询当天的全部数据,需要不断改变start和limit,即api_hq.get_history_transaction_data的第三个参数和第四个参数。

代码如下:

# 公众号: 二七阿尔量化
# 2022-09-17

from pytdx.exhq import *
from pytdx.hq import *
api_hq = TdxHq_API()
api_hq = api_hq.connect('119.147.212.81', 7709)

def get_all_trans_data(api, code, date):
    start = 0
    data = []
    while True:
        part = api.get_history_transaction_data(TDXParams.MARKET_SZ, code, start, 888, int(date))
        data.extend(part)
        if len(part) < 888:
            break
        start += 888
    return data
data = get_all_trans_data(api_hq, "002560", 20220916)
print(len(data))
# 3776

data 的格式如下:

数组里的顺序是乱的,因为我们请求数据的时候并不是按时间序列去请求的,因此还可以做数据规整化处理:

# 公众号: 二七阿尔量化
# 2022-09-17

from pytdx.exhq import *
from pytdx.hq import *
from collections import defaultdict
api_hq = TdxHq_API()
api_hq = api_hq.connect('119.147.212.81', 7709)

def get_all_trans_data(api, code, date):
    start = 0
    data = []
    while True:
        part = api.get_history_transaction_data(TDXParams.MARKET_SZ, code, start, 888, int(date))
        data.extend(part)
        if len(part) < 888:
            break
        start += 888
    return data
date = 20220916
data = get_all_trans_data(api_hq, "002560", date)
print(len(data))
# 3776
trans = defaultdict(list)
for tran in data:
    # "%Y%m%d %H:%M"
    trans[datetime.datetime.strptime(str(date) + " " + tran["time"], "%Y%m%d %H:%M")].append({
        "price": tran["price"],
        "volume": tran["vol"],
        "turnover": float(tran["price"]) * float(tran["vol"]) * 100,
    })
trans = dict(sorted(trans.items(), key=lambda x: x[0]))

这样,trans的数据就是格式化好的:

4.其他查询方法

除了历史分时数据,pytdx还可以查询:

股票行情数据:

api.get_security_quotes([(0, '000001'), (1, '600300')])
# 参数格式:[(市场代码, 股票代码), ...]

K线数据:

api.get_security_bars(9,0, '000001', 4, 3)

参数如下:

读取公司信息详情:

api.get_company_info_content(0, '000001', '000001.txt', 0, 100)
# 参数:市场代码, 股票代码, 文件名, 起始位置, 数量

读取财务信息:

api.get_finance_info(0, '000001')
# 参数:市场代码, 股票代码

还有其他更多的功能,大家可以阅读Pytdx的说明文档:

https://rainx.gitbooks.io/pytdx

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!


​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

用 Python 爬取A股龙虎榜历史数据

龙虎榜是A股的特色数据。它指每日两市中涨跌幅、换手率等由大到小的排名榜单,并从中可以看到龙虎榜单中的股票在哪个证券营业部的成交量较大。

该数据有助于了解当日异动个股的资金进出情况,判断是游资所为还是机构所为,抑或是拉萨集团散户大军。

上榜条件:

1、日价格涨幅偏离值±7%

2、日换手率达到20%

3、日价格振幅达到15%

4、连续三个交易日内,涨幅偏离值累计达到20%

每个条件都选前3名的上榜,深市是分主板、中小板、创业板分别取前3的。

龙虎榜数据是量化投资可依靠的数据源之一。

最简单的玩法是我们以股票上榜日的下一个交易日开盘价,作为买入价,下下个交易日的收盘价,作为卖出价。根据这两个数据,更新上榜日净买入该股的主力席位成功率。此后,系统自动选择有高成功率主力席位介入的股票进行自动化操作。

当然,还有其他玩法,需要我们自行发掘。本文只做抛砖引玉的作用,教你通过 Efinance 获取历史股票龙虎榜数据。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install efinance --upgrade

2.龙虎榜数据获取

获取最新的龙虎榜数据:

import efinance as ef
# 获取最新一个公开的龙虎榜数据(后面还有获取指定日期区间的示例代码)
dt_list = ef.stock.get_daily_billboard()
print(dt_list)
#       股票代码   股票名称        上榜日期  ...   成交额占总成交比          流通市值                                      上榜原因
# 
# 0   000593   德龙汇能  2022-09-01  ...  24.489978  3.132908e+09                  连续三个交易日内,跌幅偏离值累计达到20%的证券
# 1   000593   德龙汇能  2022-09-01  ...  28.569036  3.132908e+09                          日跌幅偏离值达到7%的前5只证券        
# ... ...
# 54  900915   中路B股  2022-09-01  ...  77.071460  6.791650e+09             有价格涨跌幅限制的日收盘价格涨幅偏离值达到7%的前五只证券       

获取历史龙虎榜数据:

import efinance as ef
# 获取指定日期区间的龙虎榜数据
start_date = '2021-08-20' # 开始日期
end_date = '2022-09-01' # 结束日期
dt_list = ef.stock.get_daily_billboard(start_date = start_date,end_date = end_date)
print(dt_list)

效果如下,会返回一个包含指定区间内所有龙虎榜数据的Dataframe:

         股票代码  股票名称        上榜日期                解读  ...   净买额占总成交比    成交额占总成交比          流通市值
             上榜原因
0      000593  德龙汇能  2022-09-01    主力做T,成功率40.14%  ...  -3.272621   24.489978  3.132908e+09       连续三个交易日内,跌幅偏离值累计达到20%的证券
1      000593  德龙汇能  2022-09-01    主力做T,成功率41.00%  ...  -8.620473   28.569036  3.132908e+09               日跌幅偏离值达到7%的前5只证券
2      000595  宝塔实业  2022-09-01  1家机构买入,成功率38.60%  ...   0.463642   15.610660  9.411956e+09               日涨幅偏离值达到7%的前5只证券
3      000670   盈方微  2022-09-01  普通席位买入,成功率35.67%  ...   4.406599   17.829750  6.234850e+09               日涨幅偏离值达到7%的前5只证券
4      000716   黑芝麻  2022-09-01  1家机构买入,成功率44.05%  ...   1.390889   16.455920  3.778881e+09                日换手率达到20%的前5只证券
...       ...   ...         ...               ...  ...        ...         ...           ...                            ...
18213  605580  恒盛能源  2021-08-20    买一主买,成功率33.33%  ...  88.945937  111.054054  6.640000e+08  有价格涨跌幅限制的日收盘价格涨幅偏离值达到7%的前三只证券
18214  688029  南微医学  2021-08-20  4家机构卖出,成功率55.82%  ... -18.529760   67.958326  9.001510e+09    有价格涨跌幅限制的日收盘价格跌 幅达到15%的前五只证券
18215  688408   中信博  2021-08-20  4家机构卖出,成功率47.86%  ...  -5.122340   93.739221  5.695886e+09      有价格涨跌幅限制的日价格振幅达到30%的前五只证券
18216  688556  高测股份  2021-08-20  上海资金买入,成功率60.21%  ...  -6.847351   63.922831  6.150250e+09    有价格涨跌幅限制的日收盘价格涨幅达到15%的前五只证券
18217  688636   智明达  2021-08-20  2家机构买入,成功率47.37%  ...  15.517464   54.552336  1.647410e+09    有价格涨跌幅限制的日收盘价格涨幅达到15%的前五只证券

[18218 rows x 16 columns]

3.其他数据

除了龙虎榜数据外,efinance 中比较有价值的数据是大小单数据。

股票最新一个交易日单子流入数据(分钟级):

import efinance as ef
print(ef.stock.get_today_bill('300750'))

#      股票名称    股票代码                时间        主力净流入      小单净流入        中单净流入        大单净流入      超大单净流入
# 0    宁德时代  300750  2022-09-01 09:31  -16227310.0   -13332.0   16240643.0  -32348972.0  16121662.0
# 1    宁德时代  300750  2022-09-01 09:32  -18437363.0   -13332.0   18450696.0  -46147932.0  27710569.0
# 2    宁德时代  300750  2022-09-01 09:33  -10363719.0   -13332.0   10377052.0  -39606699.0  29242980.0
# 3    宁德时代  300750  2022-09-01 09:34  -21867692.0   -13332.0   21881025.0  -46285941.0  24418249.0
# 4    宁德时代  300750  2022-09-01 09:35  -33428620.0   -13332.0   33441954.0  -49130994.0  15702374.0
# ..    ...     ...               ...          ...        ...          ...          ...         ...
# 235  宁德时代  300750  2022-09-01 14:56 -499053140.0 -1849704.0  500902854.0 -421625414.0 -77427726.0
# 236  宁德时代  300750  2022-09-01 14:57 -506019055.0 -1849704.0  507868768.0 -415876177.0 -90142878.0
# 237  宁德时代  300750  2022-09-01 14:58 -506439955.0 -1849704.0  508289668.0 -416297077.0 -90142878.0
# 238  宁德时代  300750  2022-09-01 14:59 -506439955.0 -1849704.0  508289668.0 -416297077.0 -90142878.0
# 239  宁德时代  300750  2022-09-01 15:00 -506439955.0 -1849704.0  508289668.0 -416297077.0 -90142878.0
# 
# [240 rows x 8 columns]

股票历史单子流入数据(日级):

import efinance as ef
print(ef.stock.get_history_bill('300750'))

还有基金公开持仓信息:

import efinance as ef
# 获取最新公开的持仓数据
print(ef.fund.get_invest_position('161725'))
# 基金代码    股票代码  股票简称   持仓占比  较上期变化        公开日期
# 0  161725  600809  山西汾酒  14.50  -0.70  2022-06-30
# 1  161725  000858   五粮液  14.33   1.50  2022-06-30
# 2  161725  000568  泸州老窖  14.14  -0.43  2022-06-30
# 3  161725  600519  贵州茅台  14.08  -2.70  2022-06-30
# 4  161725  002304  洋河股份  11.53  -0.05  2022-06-30
# 5  161725  000596  古井贡酒   4.27   1.00  2022-06-30
# 6  161725  000799   酒鬼酒   3.85   0.45  2022-06-30
# 7  161725  603369   今世缘   3.48  -0.27  2022-06-30
# 8  161725  600779   水井坊   2.18  -0.41  2022-06-30
# 9  161725  603589   口子窖   2.15  -0.15  2022-06-30

还有很多基本的K线和历史数据,基本上和之前介绍的akshare差不多,这里就不重复介绍了。

有兴趣使用的同学可以参考他们的官方Github文档,中文,可读性很强。

https://github.com/Micro-sheep/efinance

龙虎榜的数据其实非常有意思,可以捕捉到游资和机构的动作,下次有时间给大家介绍一个策略。

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!


​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

教你使用Python获得全世界所有市场的交易日历

Exchange_calendars 是一个用于查询证券交易日历的 Python 库。开箱即用,内含世界50+个交易所的交易日历,包括中国市场和港股市场,非常方便。

同时,如果你找到了Exchange_calendars 上没有的市场的交易日历,可以向他们提交PR,创建一个新的交易所日历

注意,本模块最低支持的Python版本为3.8.

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install exchange_calendars

2.基本使用

获取可用日历的列表:

import exchange_calendars as xcals
print(xcals.get_calendar_names(include_aliases=False))

结果如下:

['24/5', '24/7', 'AIXK', 'ASEX', 'BVMF', 'CMES', 'IEPA', 'XAMS', 'XASX', 'XBKK', 'XBOG', 'XBOM', 'XBRU', 'XBSE', 'XBUD', 'XBUE', 'XCBF', 'XCSE', 'XDUB', 'XETR', 'XFRA', 'XHEL', 'XHKG', 'XICE', 'XIDX', 'XIST', 'XJSE', 'XKAR', 'XKLS', 'XKRX', 'XLIM', 'XLIS', 'XLON', 'XMAD', 'XMEX', 'XMIL', 'XMOS', 'XNYS', 'XNZE', 'XOSL', 'XPAR', 'XPHS', 'XPRA', 'XSES', 'XSGO', 'XSHG', 'XSTO', 'XSWX', 'XTAE', 'XTAI', 'XTKS', 'XTSE', 'XWAR', 'XWBO', 'us_futures']

其中,XSHG就是中国的沪市、XHKG就是港股。

获取沪市日历:

import exchange_calendars as xcals
xshg = xcals.get_calendar("XSHG")

查询某个区间日程是否有开盘:

import exchange_calendars as xcals
xshg = xcals.get_calendar("XSHG")
print(xshg.schedule.loc["2021-12-29":"2022-08-12"])
                                open               break_start                 break_end                     close
2021-12-29 2021-12-29 01:30:00+00:00 2021-12-29 03:30:00+00:00 2021-12-29 05:00:00+00:00 2021-12-29 07:00:00+00:00
2021-12-30 2021-12-30 01:30:00+00:00 2021-12-30 03:30:00+00:00 2021-12-30 05:00:00+00:00 2021-12-30 07:00:00+00:00
2021-12-31 2021-12-31 01:30:00+00:00 2021-12-31 03:30:00+00:00 2021-12-31 05:00:00+00:00 2021-12-31 07:00:00+00:00
2022-01-04 2022-01-04 01:30:00+00:00 2022-01-04 03:30:00+00:00 2022-01-04 05:00:00+00:00 2022-01-04 07:00:00+00:00
2022-01-05 2022-01-05 01:30:00+00:00 2022-01-05 03:30:00+00:00 2022-01-05 05:00:00+00:00 2022-01-05 07:00:00+00:00
...                              ...                       ...                       ...                       ...
2022-08-08 2022-08-08 01:30:00+00:00 2022-08-08 03:30:00+00:00 2022-08-08 05:00:00+00:00 2022-08-08 07:00:00+00:00
2022-08-09 2022-08-09 01:30:00+00:00 2022-08-09 03:30:00+00:00 2022-08-09 05:00:00+00:00 2022-08-09 07:00:00+00:00
2022-08-10 2022-08-10 01:30:00+00:00 2022-08-10 03:30:00+00:00 2022-08-10 05:00:00+00:00 2022-08-10 07:00:00+00:00
2022-08-11 2022-08-11 01:30:00+00:00 2022-08-11 03:30:00+00:00 2022-08-11 05:00:00+00:00 2022-08-11 07:00:00+00:00
2022-08-12 2022-08-12 01:30:00+00:00 2022-08-12 03:30:00+00:00 2022-08-12 05:00:00+00:00 2022-08-12 07:00:00+00:00

[151 rows x 4 columns]

可见,他直接返回了这个区间中所有开盘的日期作为index,并附带了开盘和收盘的UTC时间(需要+8)。

如果你只需要开市的日期,可以这样:

# 公众号:二七阿尔量化
import exchange_calendars as xcals
xshg = xcals.get_calendar("XSHG")
xshg_range = xshg.schedule.loc["2021-12-29":"2022-08-12"]
print(xshg_range.index.strftime("%Y-%m-%d").tolist())

效果如下:

['2021-12-29', '2021-12-30', '2021-12-31', '2022-01-04', '2022-01-05', '2022-01-06', '2022-01-07', '2022-01-10', '2022-01-11', '2022-01-12', '2022-01-13', '2022-01-14', '2022-01-17', '2022-01-18', '2022-01-19', '2022-01-20', '2022-01-21', '2022-01-24', '2022-01-25', '2022-01-26', '2022-01-27', '2022-01-28', '2022-02-07', '2022-02-08', '2022-02-09', '2022-02-10', '2022-02-11', '2022-02-14', '2022-02-15', '2022-02-16', '2022-02-17', '2022-02-18', '2022-02-21', '2022-02-22', '2022-02-23', '2022-02-24', '2022-02-25', '2022-02-28', '2022-03-01', '2022-03-02', '2022-03-03', '2022-03-04', '2022-03-07', '2022-03-08', '2022-03-09', '2022-03-10', '2022-03-11', '2022-03-14', '2022-03-15', '2022-03-16', '2022-03-17', '2022-03-18', '2022-03-21', '2022-03-22', '2022-03-23', '2022-03-24', '2022-03-25', '2022-03-28', '2022-03-29', '2022-03-30', '2022-03-31', '2022-04-01', '2022-04-06', '2022-04-07', '2022-04-08', '2022-04-11', '2022-04-12', '2022-04-13', '2022-04-14', '2022-04-15', '2022-04-18', '2022-04-19', '2022-04-20', '2022-04-21', '2022-04-22', '2022-04-25', '2022-04-26', '2022-04-27', '2022-04-28', '2022-04-29', '2022-05-05', '2022-05-06', '2022-05-09', '2022-05-10', '2022-05-11', '2022-05-12', '2022-05-13', '2022-05-16', '2022-05-17', '2022-05-18', '2022-05-19', '2022-05-20', '2022-05-23', '2022-05-24', '2022-05-25', '2022-05-26', '2022-05-27', '2022-05-30', '2022-05-31', '2022-06-01', '2022-06-02', '2022-06-06', '2022-06-07', '2022-06-08', '2022-06-09', '2022-06-10', '2022-06-13', '2022-06-14', '2022-06-15', '2022-06-16', '2022-06-17', '2022-06-20', '2022-06-21', '2022-06-22', '2022-06-23', '2022-06-24', '2022-06-27', '2022-06-28', '2022-06-29', '2022-06-30', '2022-07-01', '2022-07-04', '2022-07-05', '2022-07-06', '2022-07-07', '2022-07-08', '2022-07-11', '2022-07-12', '2022-07-13', '2022-07-14', '2022-07-15', '2022-07-18', '2022-07-19', '2022-07-20', '2022-07-21', '2022-07-22', '2022-07-25', '2022-07-26', '2022-07-27', '2022-07-28', '2022-07-29', '2022-08-01', '2022-08-02', '2022-08-03', '2022-08-04', '2022-08-05', '2022-08-08', '2022-08-09', '2022-08-10', '2022-08-11', '2022-08-12']

3.高级使用

判断某一天是否为交易日:

# 公众号:二七阿尔量化

import exchange_calendars as xcals
xshg = xcals.get_calendar("XSHG")
print(xshg.is_session("2022-12-30"))
# True

获取某一天后的N个交易日:

# 公众号:二七阿尔量化

import exchange_calendars as xcals
xshg = xcals.get_calendar("XSHG")
print(xshg.sessions_window("2022-12-30", 7))
# DatetimeIndex(['2022-12-30', '2023-01-03', '2023-01-04', '2023-01-05',
#               '2023-01-06', '2023-01-09', '2023-01-10'],
#              dtype='datetime64[ns]', freq='C')

获取某一天后的下一个交易日:

# 公众号:二七阿尔量化

import exchange_calendars as xcals
xshg = xcals.get_calendar("XSHG")
print(xshg.date_to_session("2022-01-01", direction="next"))
# 2022-01-04 00:00:00

获取某一天后的上一个交易日:

# 公众号:二七阿尔量化

import exchange_calendars as xcals
xshg = xcals.get_calendar("XSHG")
print(xshg.date_to_session("2022-01-01", direction="previous"))
# 2021-12-31 00:00:00

获取分钟级交易区间:

import exchange_calendars as xcals
xshg = xcals.get_calendar("XSHG")
print(xshg.session_minutes("2022-01-04"))
# DatetimeIndex(['2022-01-04 01:30:00+00:00', '2022-01-04 01:31:00+00:00',
#                '2022-01-04 01:32:00+00:00', '2022-01-04 01:33:00+00:00',
#                '2022-01-04 01:34:00+00:00', '2022-01-04 01:35:00+00:00',
#                '2022-01-04 01:36:00+00:00', '2022-01-04 01:37:00+00:00',
#                '2022-01-04 01:38:00+00:00', '2022-01-04 01:39:00+00:00',
#                ...
#                '2022-01-04 06:50:00+00:00', '2022-01-04 06:51:00+00:00',
#                '2022-01-04 06:52:00+00:00', '2022-01-04 06:53:00+00:00',
#                '2022-01-04 06:54:00+00:00', '2022-01-04 06:55:00+00:00',
#                '2022-01-04 06:56:00+00:00', '2022-01-04 06:57:00+00:00',
#                '2022-01-04 06:58:00+00:00', '2022-01-04 06:59:00+00:00'],
#               dtype='datetime64[ns, UTC]', length=240, freq=None)

交易时间按指定数字分割:

import exchange_calendars as xcals
xshg = xcals.get_calendar("XSHG")
print(xshg.trading_index(
    "2021-12-30", "2021-12-31", period="30T", force=True
))
# IntervalIndex([[2021-12-30 01:30:00, 2021-12-30 02:00:00), [2021-12-30 02:00:00, 2021-12-30 02:30:00), [2021-12-30 02:30:00, 2021-12-30 03:00:00), [2021-12-30 03:00:00, 2021-12-30 03:30:00), [2021-12-30 05:00:00, 2021-12-30 05:30:00) ... [2021-12-31 03:00:00, 2021-12-31 03:30:00), [2021-12-31 05:00:00, 2021-12-31 05:30:00), [2021-12-31 05:30:00, 2021-12-31 06:00:00), [2021-12-31 06:00:00, 2021-12-31 06:30:00), [2021-12-31 06:30:00, 2021-12-31 07:00:00)],
#               closed='left',
#               dtype='interval[datetime64[ns, UTC]]')

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!


​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

教你使用Akshare获取A股可转债相关信息

Akshare是一个非常好用的开源A股数据获取模块,它是基于 Python 的财经数据接口库,目的是实现对A股、美股、期货等金融产品的基本面数据、实时和历史行情数据、衍生数据从数据采集、数据清洗到数据落地的一套工具,主要用于学术研究目的。

今天我们就来学习用它获取可转债的相关数据。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install akshare --upgrade

目前 AKShare 仅支持 Python 3.7(64 位) 及以上版本。如果遇到 xxx has no attribute xxx, 大概率是Python版本的问题。

2.获取基本信息

获取沪深可转债的基本信息,基本信息中包括债券代码、债券简称、申购日期、申购代码、申购上限、正股代码、正股简称、正股价、转股价、转股价值、债现价、转股溢价率、发行规模、中签号发布日、中签率、上市时间等信息。:

import akshare as ak

bond_zh_cov_df = ak.bond_zh_cov()
print(bond_zh_cov_df)

一个使用小示例:如果你想要将可转债代码和正股代码对应起来:

# 公众号:二七阿尔量化
import akshare as ak

bond_zh_cov_df = ak.bond_zh_cov()
code_map = bond_zh_cov_df.set_index("债券代码")
code_map = code_map.to_dict()
cb_stock_code = code_map["正股代码"]
print(cb_stock_code)

效果如下:

{'113652': '603568', '118015': '688595', '127067': '000703', '123153': '300956', '123152': '300727', '113651': '603992', '118014': '688556', '113061': '601689', '118013': '688208', '127066': '002850', '118012': '688321', '118011': '688689', '113650': '603916', '123151': '300869', '123150': '300406', '118010': '688026', '113649': '603810', '118009': '688059', .....}

在code_map.to_dict()后的变量里,我们可以获取可转债代码与其任意字段的map字典, 比如转股溢价率:

# 公众号:二七阿尔量化
import akshare as ak

bond_zh_cov_df = ak.bond_zh_cov()
code_map = bond_zh_cov_df.set_index("债券代码")
code_map = code_map.to_dict()
cb_stock_code = code_map["正股代码"]
temp_data = code_map["转股溢价率"]
print(temp_data)
# {'113652': 4.55, '118015': 7.98, '127067': 12.66, '123153': 7.61, '123152': -4.81, '113651': 3.24, '118014': 1.19, '113061': -17.82, '118013': 10.36, '127066': 0.6, '118012': 2.55, '118011': 9.79, '113650': 19.75, '123151': 34.24, '123150': 26.08, '118010': 15.41, '113649': 34.8, '118009': 41.44, '111005': 15.72, '118008': 42.31, '110087': 31.92  ......

3.获取行情数据

获取可转债的日线行情:

import akshare as ak
bond_zh_hs_cov_daily_df = ak.bond_zh_hs_cov_daily(symbol="sh113542")
print(bond_zh_hs_cov_daily_df)
#            date    open    high     low   close   volume
# 4    2019-08-29  108.68  108.99  108.56  108.71    69900
# ..          ...     ...     ...     ...     ...      ...
# 705  2022-07-22  110.03  110.86  110.03  110.40    50830
# [706 rows x 6 columns]

获取可转债分钟级行情数据:

import akshare as ak

bond_zh_hs_cov_min_df = ak.bond_zh_hs_cov_min(symbol="sz123124", period='1', adjust='', start_date="1979-09-01 09:32:00", end_date="2222-01-01 09:32:00")
print(bond_zh_hs_cov_min_df)
#                       时间       开盘       收盘  ...  成交量       成交额       最新价
# 0    2022-07-22 09:30:00  116.200  116.200  ...   67   77854.0  116.2000
# ..                   ...      ...      ...  ...  ...       ...       ...
# 239  2022-07-22 14:59:00  116.000  116.000  ...    0       0.0  115.7802
# 240  2022-07-22 15:00:00  116.000  116.000  ...   97  112520.0  115.7819

bond_zh_hs_cov_min 支持以下参数:symbol(转债代码)、period(分钟级数据周期)、adjust(复权类型)、start_date(起始时间)、end_date(终止时间)。

其中 period 支持 ‘1’, ‘5’, ’15’, ’30’, ’60’ 分钟级数据。

adjust 支持前复权(“qfq”), 后复权(“hfq”), 或不复权(空值 “”)。

4.可转债比价表

可转债比价表中有转股溢价率、纯债溢价率以及赎回强赎的触发价,有时候也是我们参考的重要指标:

import akshare as ak

bond_cov_comparison_df = ak.bond_cov_comparison()
print(bond_cov_comparison_df)

#       序号    转债代码   转债名称 转债最新价  ...     纯债价值     开始转股日      上市日期      申购日期
# 0      1  113652  伟22转债     -  ...        -  20230130         -  20220722
# 1      2  127067   恒逸转2     -  ...  88.8369  20230127         -  20220721
# 2      3  123153   英力转债     -  ...  95.5621  20230130         -  20220721

除了这些数据以外,akshare中还有可转债价值分析、溢价率分析数据,以及集思录相关数据,大家有兴趣可以访问akshare文档查看:

https://www.akshare.xyz/data/bond/bond.html

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!


​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

量化投资—A股实时挖掘热点的3种方法

在A股市场做短线投资,最重要的就是找到“市场合力”,找准资金的流向,找准市场情绪。

尤其对于打板策略而言,找准A股市场上的实时热点是最重要的。

今天二七阿尔量化就来讲讲几种挖掘市场上的热点的方法。

1.人气榜

在我们之前的文章中,曾经监控过人气榜的数据及变化:《Prometheus 实战教程 + Grafana + Python — 实时监控东方财富人气榜股票》,这篇文章讲述了如何抓取东方财富人气榜数据及如何监控股票的排名,有兴趣的朋友可以看看。

通过人气榜,我们能找到最近热门的股票(不一定是最新的):

根据人气榜前20名,结合同花顺的个股概念的前三个概念,我们能总结出最近的热点概念是什么,代码如下:

import requests
from collections import defaultdict
from bs4 import BeautifulSoup

for code in codes:
    res = fetch_code_ths_basic(code)
    print(f'{code}: {res}')
    for concept in res:
        results[concept] += 1
print(sorted(results.items(), key=lambda x: (x[1], x[0]), reverse=True))
000957: ['燃料电池', '新能源汽车', '无人驾驶']
000722: ['水利', '绿色电力', '养老概念']
000755: ['绿色电力', '地方国资改革']
002374: ['PPP概念', '污水处理', '区块链']
300068: ['动力电池回收', '锂电池', '储能']
000404: ['冷链物流', '家用电器', '节能环保']
002514: ['医疗废物处理', '换电概念', '智能电网']
300274: ['储能', '光伏概念', '充电桩']
000629: ['钒电池', '钛白粉概念', '半年报预增']
002466: ['盐湖提锂', '动力电池回收', '锂电池']
002090: ['电力物联网', '智能电网', '充电桩']
002031: ['机器人概念', '工业4.0', '工业母机']
002761: ['水利', '装配式建筑', '新型城镇化']
000601: ['绿色电力', '充电桩', '光伏概念']
002594: ['比亚迪概念', '无人驾驶', '新能源汽车']
300827: ['储能', '光伏概念', '智能电网']
002204: ['核电', '振兴东北', '半年报预增']
000155: ['动力电池回收', '宁德时代概念', '锂电池']
301120: ['绿色电力', '风电', '智能电网']
000625: ['华为汽车', '无人驾驶', '燃料电池']
[('绿色电力', 4), ('智能电网', 4), ('锂电池', 3), ('无人驾驶', 3), ('动力电池回收', 3), ('光伏概念', 3), ('充电桩', 3), ('储能', 3), ('燃料电池', 2), ('水利', 2), ('新能源汽车', 2), ('半年报预增', 2), ('风电', 1), ('钛白粉概念', 1), ('钒电池', 1), ('装配式
建筑', 1), ('节能环保', 1), ('盐湖提锂', 1), ('电力物联网', 1), ('污水处理', 1), ('比亚迪概念', 1), ('核电', 1), ('机器人概念', 
1), ('新型城镇化', 1), ('换电概念', 1), ('振兴东北', 1), ('工业母机', 1), ('工业4.0', 1), ('家用电器', 1), ('宁德时代概念', 1), 
('地方国资改革', 1), ('华为汽车', 1), ('医疗废物处理', 1), ('区块链', 1), ('冷链物流', 1), ('养老概念', 1), ('PPP概念', 1)]

可见,近期的热点是 “绿色电力”, “智能电网”, “锂电池”, “光伏” 等概念。

但是,总结出来的这个热点概念具有一定的延迟,它并不一定能代表最新的市场热点,因为一次涨停、两次涨停并无法把该股带到前20名中。能在前20名的,很可能是最近连板的妖股。

最典型的比如这两天发酵的”储能”概念,只有一只股票在前20名中,但实际上储能概念这几天流入了不少资金。

2.人气飙升榜

那么有没有可能检测到正在飙升的概念呢?我觉得人气飙升板或许可以尝试一下:

我将飙升榜前一百名的股票都抓取后,统计它们的概念,结果如下:

[('专精特新', 13), ('新能源汽车', 12), ('科创次新股', 10), ('锂电池', 9), ('芯片概念', 8), ('宁德时代概念', 7), ('华为概念', 7), ('军工', 7), ('人民币贬值受益', 7), ('5G', 7), ('特斯拉', 5), ('注册制次新股', 5), ('机器人概念', 5), ('储能', 5), ('无人机', 4), ('新材料概念', 4), ('央企国资改革', 4), ('医疗器械概念', 4), ('超级电容', 3), ('航空发动机', 3), ('稀土永磁', 3), ('生物医药', 3), ('燃料电池', 3), ('消费电子概念', 3), ('氢能源', 3), ('比亚迪概念', 3), ('智能制造', 3), ('大飞机', 3), ('华为汽车', 3), ('OLED', 3), ('高铁', 2), ('高端装备', 2), ('郭台铭概念', 2), ('辅助生殖', 2), ('融资融券', 2), ('节能照明', 2), ('网红经济', 2), ('粤港澳大湾区', 2), ('第三代半导体', 2), ('眼科医疗', 2), ('特高压', 2), ('沪股通', 2), ('汽车电子', 2), ('污水处理', 2), ('标
普道琼斯A股', 2), ('机器视觉', 2), ('智能电网', 2), ('智能医疗', 2), ('无人驾驶', 2), ('工业母机', 2), ('工业4.0', 2), ('小米概 
念', 2), ('安防', 2), ('口罩', 2), ('动力电池回收', 2), ('冬奥会', 2), ('军民融合', 2), ('光伏概念', 2), ('健康中国', 2), ('两轮
车', 2), ('PCB概念', 2), ('鸿蒙概念', 1), ('集成电路概念', 1), ('钠离子电池', 1), ('金属回收', 1), ('金刚石(线)', 1), ('跨境电
商', 1), ('超级高铁', 1), ('节能环保', 1), ('自由贸易港', 1), ('腾讯概念', 1), ('肝炎概念', 1), ('网络直播', 1), ('网络安全', 1), ('统一大市场', 1), ('百度概念', 1), ('电子身份证', 1), ('生物疫苗', 1), ('特钢概念', 1), ('汽车拆解概念', 1), ('民营医院', 1), ('核准制次新股', 1), ('智能物流', 1), ('智能家居', 1), ('智慧灯杆', 1), ('智慧城市', 1), ('新冠治疗', 1), ('富士康概念', 1), ('壳资源', 1), ('培育钻石', 1), ('垃圾分类', 1), ('地方国资改革', 1), ('国产航母', 1), ('国产操作系统', 1), ('固废处理', 1), ('卫 
星导航', 1), ('医美概念', 1), ('北京自贸区', 1), ('北交所概念', 1), ('动物疫苗', 1), ('创投', 1), ('农机', 1), ('养老概念', 1), 
('共享单车', 1), ('光刻胶', 1), ('元宇宙', 1), ('传感器', 1), ('仿制药一致性评价', 1), ('互联网医疗', 1), ('云计算', 1), ('乡村 
振兴', 1), ('WiFi 6', 1), ('PPP概念', 1), ('PM2.5', 1), ('MSCI概念', 1), ('C2M概念', 1), ('3D打印', 1)]

除去专精特新和科创次新股这样的大概念,新能源汽车、锂电池、芯片概念位居前排,不愧是碳中和主赛道。

但是这个真的是实时热点吗?我还没有测试过,让我们多观察几天。

3.消息面

我觉得这一个是最能提前预测到热点板块的方法。比如这两天的储能,是由这个消息引爆的:

通过对这个简报进行自然语言处理分析,我们能迅速获得主题及感情色彩:

# 二七阿尔量化
from snownlp import SnowNLP

text = "【光伏发电迎爆发式增长 有储能企业订单量翻8倍】财联社7月13日电,据国家能源局数据显示,2022年1-5月,全国太阳能发电新增装机2371万千瓦,同比增幅为139%。截至5月底,全国太阳能发电装机容量约32789万千瓦,同比增长24%。随着光伏市场的火热,对于储能的需求也持续增长,甚至出现了供不应求的局面。在江苏常州新北区的一家光伏储能系统生产企业内,记者看到,整条产线都在满负荷运行,生产着储能系统所需要的锂电池电芯。负责人表示,现在生产量是去年的5倍,接到的订单量是去年的8倍。光伏发电具有波动性,无法满足电网的全天候调度需求,从2021年以来,宁夏、辽宁、安徽、江苏等地陆续在新能源上网等相关文件中提出了对储能配套等的具体要求。在当前光伏装机量攀升的背景下,储能系统的销量开始大幅增长。"
s = SnowNLP(text)
print('提取文本关键词([TextRank]:',s.keywords(3))
print('提取文本摘要([TextRank]:',s.summary(3))
print('感情色彩(输出为positive概率):',s.sentiments)  

结果如下:

提取文本关键词([TextRank]: ['储能', '增长', '月']
提取文本摘要([TextRank]: ['【光伏发电迎爆发式增长 有储能企业订单量翻8倍】财联社7月13日电', '在江苏常州新北区的一家光伏储能系统生产企业内', '对于储能
的需求也持续增长']
感情色彩(输出为positive概率): 0.7465336870736243

从中我们就提取出了储能这个关键词,并知道其感情色彩为正面。通过对一些简报和快讯进行命名实体识别,并识别其感情色彩,我们也能够快速分析一个概念是否可以成为热门概念。

A股市场判断热点和情绪的方法还有很多,比如韭菜公社的言论、淘股吧各路游资的言论,实际上都可以被量化为因子进行研究,有兴趣的同学可以试试。

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!


​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

Pandas TA 一个能帮助你迅速计算技术指标的神器

Pandas TA 是一个基于Pandas模块开发的,具有上百个技术指标和常用指标的开源模块。它包括但不限于能够绘制62种蜡烛形态(晨星、乌云、十字星、孕线等等)、130个技术指标,如移动平均线、macd、hma、布林带、obv、aron、squeeze等等各种指标。

下面就来讲一下这个神器的安装和使用方法,如果对你有帮助,记得点个赞和在看支持一下哦。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install pandas_ta

此外,如果你想使用上全部指标,你需要安装TA-Lib

pip install Ta-Lib

安装TA-Lib的时候可能会遇到没有VC++14.0的报错,这时候我们需要手动安装,在 https://www.lfd.uci.edu/~gohlke/pythonlibs/#ta-lib 中下载你对应的Python版本的 TA-Lib whl文件。

下载完成后执行以下命令:

# 公众号:二七阿尔量化
pip install D:\path\TA_lib‑0.4.24‑cp38‑cp38‑win_amd64.whl

就能成功手动安装 Ta-lib

2.基本使用

为了方便介绍使用方法,我下载了沪深300的分钟级数据,如果你需要本文的全部代码及数据,请在二七阿尔量化公众号后台回复:pandas_ta 下载。

首先看看我们的数据类型:

# 公众号:二七阿尔量化
import pandas as pd
import pandas_ta as ta

sh300data = pd.read_csv("sh300_1min.csv")

print(sh300data)

#        Unnamed: 0                  day      open      high       low     close     volume
# 0               0  2022-03-07 10:47:00  4406.223  4406.352  4405.662  4405.922   54345400
# 1               1  2022-03-07 10:48:00  4406.172  4406.175  4403.834  4403.918   70803100
# 2               2  2022-03-07 10:49:00  4403.333  4403.333  4402.235  4402.340   49632500
# 3               3  2022-03-07 10:50:00  4402.330  4402.519  4401.838  4402.519   48159200

默认情况下,pandas ta 取  open 、high、low、close、volumeadj_close 列作为指标参数,本文的列名正好对应的上,无需再去特别命名。

先试试收益率计算:

sh300data = sh300data.set_index("day")
print(sh300data.ta.log_return(cumulative=True, append=True))
# 2022-03-07 10:47:00    0.000000
# 2022-03-07 10:48:00   -0.000455
# 2022-03-07 10:49:00   -0.000813
# 2022-03-07 10:50:00   -0.000773
# 2022-03-07 10:51:00   -0.000826

验证一下结果:

>>> (- 4405.922 + 4403.918) / 4405.922
-0.00045484236897518966
>>> (- 4403.918 + 4402.34) / 4403.918
-0.00035831729836920665
>>> -0.00045484236897518966 + -0.00035831729836920665
-0.0008131596673443963

结果对得上,注意我们传递了cumulative=True参数,因此每次都会将前面的收益率累加。

试一下常用指标 sma:

sma10 = sh300data.ta.sma(length=10)
print(sma10)
# day
# 2022-03-07 10:47:00          NaN
# 2022-03-07 10:48:00          NaN
# 2022-03-07 10:49:00          NaN
# 2022-03-07 10:50:00          NaN
# 2022-03-07 10:51:00          NaN
#                          ...
# 2022-07-08 14:55:00    4429.3936
# 2022-07-08 14:56:00    4428.9421
# 2022-07-08 14:57:00    4428.5996
# 2022-07-08 14:58:00    4428.3280
# 2022-07-08 15:00:00    4428.1877
# Name: SMA_10, Length: 20000, dtype: float64

支持以下全部技术指标:aberration, above, above_value, accbands, ad, adosc, adx, alma, amat, ao, aobv, apo, aroon, atr, bbands, below, below_value, bias, bop, brar, cci, cdl_pattern, cdl_z, cfo, cg, chop, cksp, cmf, cmo, coppock, cross, cross_value, cti, decay, decreasing, dema, dm, donchian, dpo, ebsw, efi, ema, entropy, eom, er, eri, fisher, fwma, ha, hilo, hl2, hlc3, hma, hwc, hwma, ichimoku, increasing, inertia, jma, kama, kc, kdj, kst, kurtosis, kvo, linreg, log_return, long_run, macd, mad, massi, mcgd, median, mfi, midpoint, midprice, mom, natr, nvi, obv, ohlc4, pdist, percent_return, pgo, ppo, psar, psl, pvi, pvo, pvol, pvr, pvt, pwma, qqe, qstick, quantile, rma, roc, rsi, rsx, rvgi, rvi, short_run, sinwma, skew, slope, sma, smi, squeeze, squeeze_pro, ssf, stc, stdev, stoch, stochrsi, supertrend, swma, t3, td_seq, tema, thermo, tos_stdevall, trima, trix, true_range, tsi, tsignals, ttm_trend, ui, uo, variance, vhf, vidya, vortex, vp, vwap, vwma, wcp, willr, wma, xsignals, zscore

试一下十字星(Doji Candlestick)形态:

doji = sh300data.ta.cdl_pattern(name="doji")
print(doji)
#                      CDL_DOJI_10_0.1
# day
# 2022-03-07 10:47:00              0.0
# 2022-03-07 10:48:00              0.0
# 2022-03-07 10:49:00              0.0
# 2022-03-07 10:50:00              0.0
# 2022-03-07 10:51:00              0.0
# ...                              ...
# 2022-07-08 14:55:00              0.0
# 2022-07-08 14:56:00            100.0
# 2022-07-08 14:57:00              0.0
# 2022-07-08 14:58:00              0.0
# 2022-07-08 15:00:00              0.0

这里的值如果出现 100 ,就是出现DOJI形态。支持以下全部蜡烛形态:

2crows, 3blackcrows, 3inside, 3linestrike, 3outside, 3starsinsouth, 3whitesoldiers, abandonedbaby, advanceblock, belthold, breakaway, closingmarubozu, concealbabyswall, counterattack, darkcloudcover, doji, dojistar, dragonflydoji, engulfing, eveningdojistar, eveningstar, gapsidesidewhite, gravestonedoji, hammer, hangingman, harami, haramicross, highwave, hikkake, hikkakemod, homingpigeon, identical3crows, inneck, inside, invertedhammer, kicking, kickingbylength, ladderbottom, longleggeddoji, longline, marubozu, matchinglow, mathold, morningdojistar, morningstar, onneck, piercing, rickshawman, risefall3methods, separatinglines, shootingstar, shortline, spinningtop, stalledpattern, sticksandwich, takuri, tasukigap, thrusting, tristar, unique3river, upsidegap2crows, xsidegap3methods

由于62种蜡烛形态太多了,你可能需要一次性捞出来,Pandas TA也支持你这么做:

# 公众号:二七阿尔量化
import pandas as pd
import pandas_ta as ta

sh300data = pd.read_csv("sh300_1min.csv")
sh300data = sh300data.set_index("day")
all_candle = sh300data.ta.cdl_pattern(name="all")
print(all_candle)
#                      CDL_2CROWS  CDL_3BLACKCROWS  CDL_3INSIDE  ...  CDL_UNIQUE3RIVER  CDL_UPSIDEGAP2CROWS  CDL_XSIDEGAP3METHODS
# day                                                            ...
# 2022-03-07 10:47:00         0.0              0.0          0.0  ...               0.0                  0.0                   0.0      
# 2022-03-07 10:48:00         0.0              0.0          0.0  ...               0.0                  0.0                   0.0      
# 2022-03-07 10:49:00         0.0              0.0          0.0  ...               0.0                  0.0                   0.0      
# 2022-03-07 10:50:00         0.0              0.0          0.0  ...               0.0                  0.0                   0.0      
# 2022-03-07 10:51:00         0.0              0.0          0.0  ...               0.0                  0.0                   0.0      
# ...                         ...              ...          ...  ...               ...                  ...                   ...      
# 2022-07-08 14:55:00         0.0              0.0          0.0  ...               0.0                  0.0                   0.0      
# 2022-07-08 14:56:00         0.0              0.0          0.0  ...               0.0                  0.0                   0.0      
# 2022-07-08 14:57:00         0.0              0.0        100.0  ...               0.0                  0.0                   0.0      
# 2022-07-08 14:58:00         0.0              0.0          0.0  ...               0.0                  0.0                   0.0      
# 2022-07-08 15:00:00         0.0              0.0          0.0  ...               0.0                  0.0                   0.0      

# [20000 rows x 62 columns]

3.高级使用

Pandas TA 还支持策略的使用:

# 公众号:二七阿尔量化
import pandas as pd
import pandas_ta as ta
from multiprocessing import Process, freeze_support

sh300data = pd.read_csv("sh300_1min.csv")
sh300data = sh300data.set_index("day")
CustomStrategy = ta.Strategy(
    name="Momo and Volatility",
    description="SMA 50,200, BBANDS, RSI, MACD and Volume SMA 20",
    ta=[
        {"kind": "sma", "length": 50},
        {"kind": "sma", "length": 200},
        {"kind": "bbands", "length": 20},
        {"kind": "rsi"},
        {"kind": "macd", "fast": 8, "slow": 21},
        {"kind": "sma", "close": "volume", "length": 20, "prefix": "VOLUME"},
    ]
)


if __name__ == '__main__':
    freeze_support()
    sh300data.ta.strategy(CustomStrategy)
    print(sh300data)
    #                          Unnamed: 0      open      high       low  ...  MACD_8_21_9  MACDh_8_21_9  MACDs_8_21_9  VOLUME_SMA_20
    # day                                                            ...
    # 2022-03-07 10:47:00           0  4406.223  4406.352  4405.662  ...          NaN           NaN           NaN            NaN        
    # 2022-03-07 10:48:00           1  4406.172  4406.175  4403.834  ...          NaN           NaN           NaN            NaN        
    # 2022-03-07 10:49:00           2  4403.333  4403.333  4402.235  ...          NaN           NaN           NaN            NaN        
    # 2022-03-07 10:50:00           3  4402.330  4402.519  4401.838  ...          NaN           NaN           NaN            NaN        
    # 2022-03-07 10:51:00           4  4402.376  4402.699  4402.129  ...          NaN           NaN           NaN            NaN        
    # ...                         ...       ...       ...       ...  ...          ...           ...           ...            ...        
    # 2022-07-08 14:55:00       19995  4428.123  4428.371  4427.098  ...    -1.700179     -0.244194     -1.455985     50578250.0        
    # 2022-07-08 14:56:00       19996  4427.209  4427.688  4426.886  ...    -1.725356     -0.215496     -1.509860     53128625.0        
    # 2022-07-08 14:57:00       19997  4427.279  4428.605  4427.279  ...    -1.583555     -0.058956     -1.524599     55393515.0        
    # 2022-07-08 14:58:00       19998  4428.268  4428.458  4428.268  ...    -1.426088      0.078808     -1.504897     53840375.0        
    # 2022-07-08 15:00:00       19999  4427.963  4428.781  4427.963  ...    -1.241029      0.211094     -1.452123     60235755.0        

    # [20000 rows x 18 columns]

可以看到,策略其实就是让你将一些技术指标提前配置好,通过调用策略能够自动将这些技术指标附加到你的数据集上,非常方便。

此外,策略计算的时候会用到多进程,多进程的并行数量也是可以控制的:

# 设置为4个核心,即最多4个并行
sh300data.ta.cores = 4

# 设置为0则不用多进程
sh300data.ta.cores = 0

# 查看并行数量
print(sh300data.ta.cores)
# 0

好啦,关于Pandas TA我们就先介绍到这里啦,如果你需要了解更多内容,可以访问官方文档:

https://github.com/twopirllc/pandas-ta

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!


​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

量化投资的强化学习神器!FinRL 入门指南

关于强化学习的基础知识,可以阅读我们以前发表的一篇基础文章:

什么是强化学习?预测股票的效果如何?

使用强化学习预测股价,类似于心理学中的操作性条件反射原理,你需要在决策的时候采取合适的行动 (Action) 使奖励最大化。与监督学习预测未来的数值不同,强化学习根据输入的状态(如当日开盘价、收盘价等),输出系列动作(例如:买进、持有、卖出),并对好的动作结果不断进行奖励,对差的动作结果不断进行惩罚,使得最后的收益最大化,实现自动交易。

如果你从头开始编写一套强化学习的代码,时间成本和试错成本会比较高。而本文的主角 FinRL 框架,能够帮助你极大地减少学习成本、时间成本和试错成本。下面就介绍一下 FinRL 的使用方法。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

# 首先克隆项目
git clone https://github.com/AI4Finance-Foundation/FinRL.git
# 进入刚克隆的项目,安装依赖
cd FinRL
pip install 

请注意 Python 版本要大于等于 3.7。此外,如果你的当前Python环境下安装了 zipline,请 pip uninstall 掉 zipline,因为Zipline与FinRL不兼容。

可能出现的错误:

如果你出现以下红字提示:

error: command 'swig.exe' failed: No such file or directory

请使用conda安装swig:

conda install swig

然后重新执行 pip install . 即可。

2.模型训练

运行官方示例的时候会使用到雅虎财经的数据,雅虎财经在中国已经关闭服务,因此你会需要VPN才能下载雅虎财经的数据。

cd FinRL
python Stock_NeurIPS2018.py

运行的时候大概率会遇到这个问题(2022-07-03):

FileNotFoundError: Please set your own ALPACA_API_KEY and ALPACA_API_SECRET in config_private.py

这是官网的一个不严谨实现导致的,你可以将 finrl/main.py 中25~30行的代码移动到第100行,如下所示:

此外,在运行代码的时候,你可能会遇到无法下载数据的问题,这是因为雅虎财经在中国已经关闭服务,你需要在 Stock_NeurIPS2018.py 的第172行代码 fetch_data 函数中添加proxy参数:

# 公众号:二七阿尔量化
# 此处我的代理是10809端口,你应该按需修改
df = YahooDownloader(start_date = '2009-01-01',
                     end_date = '2021-10-31',
                     ticker_list = config_tickers.DOW_30_TICKER
                     ).fetch_data(proxy={"http": "http://127.0.0.1:10809", "https": "https://127.0.0.1:10809"})

此外,在 finrl/finrl_meta/preprocessor/preprocessors.py 的第191行,你也需要增加proxy参数:

# 公众号:二七阿尔量化
# 此处我的代理是10809端口,你应该按需修改
df_vix = YahooDownloader(
            start_date=df.date.min(), end_date=df.date.max(), ticker_list=["^VIX"]
        ).fetch_data(proxy={"http": "http://127.0.0.1:10809", "https": "https://127.0.0.1:10809"})

正常运行起来的模型训练如下图所示:

下面是我简化版的到SAC模型训练为止的全部代码:

# 公众号:二七阿尔量化
from finrl import config
from finrl import config_tickers
from finrl.main import check_and_make_directories

import pandas as pd

from finrl.finrl_meta.preprocessor.yahoodownloader import YahooDownloader
from finrl.finrl_meta.preprocessor.preprocessors import FeatureEngineer, data_split
from finrl.finrl_meta.env_stock_trading.env_stocktrading import StockTradingEnv
from finrl.agents.stablebaselines3.models import DRLAgent

import sys
sys.path.append("../FinRL-Library")

import itertools

from finrl.config import (
    DATA_SAVE_DIR,
    TRAINED_MODEL_DIR,
    TENSORBOARD_LOG_DIR,
    RESULTS_DIR,
)

check_and_make_directories([DATA_SAVE_DIR, TRAINED_MODEL_DIR, TENSORBOARD_LOG_DIR, RESULTS_DIR])


'''
# Part 1. 下载数据
'''

df = YahooDownloader(
    start_date='2009-01-01',
    end_date='2021-10-31',
    ticker_list=config_tickers.DOW_30_TICKER
).fetch_data(proxy={"http": "http://127.0.0.1:10809", "https": "https://127.0.0.1:10809"})


print(f"config_tickers.DOW_30_TICKER: {config_tickers.DOW_30_TICKER}")


print(f"df.shape: {df.shape}")


df.sort_values(['date','tic'],ignore_index=True).head()


'''
# Part 2: 数据预处理
'''

fe = FeatureEngineer(
                    use_technical_indicator=True,
                    tech_indicator_list=config.INDICATORS,
                    use_vix=True,
                    use_turbulence=True,
                    user_defined_feature = False)

processed = fe.preprocess_data(df)


list_ticker = processed["tic"].unique().tolist()
list_date = list(pd.date_range(processed['date'].min(),processed['date'].max()).astype(str))
combination = list(itertools.product(list_date,list_ticker))

processed_full = pd.DataFrame(combination,columns=["date","tic"]).merge(processed,on=["date","tic"],how="left")
processed_full = processed_full[processed_full['date'].isin(processed['date'])]
processed_full = processed_full.sort_values(['date','tic'])

processed_full = processed_full.fillna(0)


processed_full.sort_values(['date','tic'],ignore_index=True).head(10)

# 训练集
train = data_split(processed_full, '2009-01-01','2020-07-01')
# 测试集
trade = data_split(processed_full, '2020-07-01','2021-10-31')

print(f"len(train): {len(train)}")
print(f"len(trade): {len(trade)}")
print(f"train.tail(): {train.tail()}")
print(f"trade.head(): {trade.head()}")
print(f"config.INDICATORS: {config.INDICATORS}")
stock_dimension = len(train.tic.unique())
state_space = 1 + 2*stock_dimension + len(config.INDICATORS)*stock_dimension
print(f"Stock Dimension: {stock_dimension}, State Space: {state_space}")

buy_cost_list = sell_cost_list = [0.001] * stock_dimension
num_stock_shares = [0] * stock_dimension

env_kwargs = {
    "hmax": 100,
    "initial_amount": 1000000,
    "num_stock_shares": num_stock_shares,
    "buy_cost_pct": buy_cost_list,
    "sell_cost_pct": sell_cost_list,
    "state_space": state_space,
    "stock_dim": stock_dimension,
    "tech_indicator_list": config.INDICATORS,
    "action_space": stock_dimension,
    "reward_scaling": 1e-4
}


e_train_gym = StockTradingEnv(df = train, **env_kwargs)

env_train, _ = e_train_gym.get_sb_env()
print(f"type(env_train): {type(env_train)}")


'''
# Part 3: 模型训练
'''
agent = DRLAgent(env = env_train)
SAC_PARAMS = {
    "batch_size": 128,
    "buffer_size": 1000000,
    "learning_rate": 0.0001,
    "learning_starts": 100,
    "ent_coef": "auto_0.1",
}

model_sac = agent.get_model("sac", model_kwargs = SAC_PARAMS)


trained_sac = agent.train_model(model=model_sac,
                             tb_log_name='sac',
                             total_timesteps=60000)

3.模型测试

在这一部分,我们将使用测试集进行模拟交易,检验模型的效果。

在env_kwargs中,我们设置了初始资金为1000000美元,测试也会以这个初始资金为起点。

# 测试
e_trade_gym = StockTradingEnv(df=trade, turbulence_threshold=70, risk_indicator_col='vix', **env_kwargs)
df_account_value, df_actions = DRLAgent.DRL_prediction(
    model=trained_sac,
    environment=e_trade_gym
)
print(f"df_account_value.tail(): {df_account_value.tail()}")

如下:

此外,df_actions内保存了每天的持仓记录:

print(f"df_actions.head(): {df_actions.head()}")

调用 backtest_stats 函数,能获得完整的回测结果:

print("==============Get Backtest Results===========")
now = datetime.datetime.now().strftime('%Y%m%d-%Hh%M')

perf_stats_all = backtest_stats(account_value=df_account_value)
perf_stats_all = pd.DataFrame(perf_stats_all)
perf_stats_all.to_csv("./"+config.RESULTS_DIR+"/perf_stats_all_"+now+'.csv')

结果如下所示:

可以见到,模型的年化收益为30%,累计净值收益为43%.

但是这段时间为美股的牛市,我们还需要以道琼斯指数为基准计算超额收益,才能更直观地展示模型的效果:

print("==============Get Baseline Stats===========")
baseline_df = get_baseline(
        ticker="^DJI",
        start = df_account_value.loc[0,'date'],
        end = df_account_value.loc[len(df_account_value)-1,'date'])

stats = backtest_stats(baseline_df, value_col_name = 'close')

可见模型还是具有超额收益的,我们将其绘制为图表更清晰地表达:

backtest_result = backtest_plot(df_account_value, 
             baseline_ticker = '^DJI', 
             baseline_start = df_account_value.loc[0,'date'],
             baseline_end = df_account_value.loc[len(df_account_value)-1,'date'])
with open("backtest_result.html", "w") as file:
    file.write(backtest_result)

作者给我们内置了许多漂亮的回测图表,非常好用。但我们只需要看最关键的cumulative returns. 从图中可以看到这个模型(绿色的线条)一开始的表现并不如指数,但是到了后面,它的表现渐渐优于指数。

当然,这是官方给的示例数据,大家可以用自己的因子补充数据,将模型完善地更好。本文的示例中使用的是SAC模型,你也可以尝试其他的强化学习模型。

总之,Finrl 只能提供你一双”巨人的肩膀“,你应该根据自己的实际业务场景和数据类型使用不同的优化方法。

4.其他

FinRL不只能支持美股,它还支持A股的部分数据源,如聚宽、米筐和Tushare:

以downloader为例,用法很简单,库中提供了 Tushare 的 downloader, 你只需要把:

from finrl.finrl_meta.preprocessor.yahoodownloader import YahooDownloader

替换为:

from finrl.finrl_meta.preprocessor.tusharedownloader import TushareDownloader

并进行相应的代码修改即可,当然,除此之外还有许多细节问题需要处理,由于文章篇幅的问题,我们留到下篇文章再给大家介绍。

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!


​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

超实用!教你 Python 获取并下载美股数据

yfinance 是一个使用 Yahoo! 获取数据的 Python 第三方模块。它支持获取最细到1分钟级的历史数据及股票基本面数据,是免费获得美股分钟级及以上粒度数据的不二之选。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install yfinance

2.yfinance 基本使用

通过yfinance你可以使用一样命令下载任意美股股票的数据,比如:

import yfinance as yf

# 单股
data = yf.download("AAPL", start="2017-01-01", end="2017-04-30")
#                  Open       High        Low      Close  Adj Close     Volume
# Date
# 2017-01-03  28.950001  29.082500  28.690001  29.037500  27.257641  115127600
# 2017-01-04  28.962500  29.127501  28.937500  29.004999  27.227135   84472400
# 2017-01-05  28.980000  29.215000  28.952499  29.152500  27.365593   88774400
# 2017-01-06  29.195000  29.540001  29.117500  29.477501  27.670671  127007600
# 2017-01-09  29.487499  29.857500  29.485001  29.747499  27.924126  134247600
# ......

# 多股
data = yf.download("SPY AAPL", start="2017-01-01", end="2017-04-30",
                   group_by="ticker")
#                  AAPL                                   ...         SPY
#                  Open       High        Low      Close  ...         Low       Close   Adj Close     Volume
# Date                                                    ...
# 2017-01-03  28.950001  29.082500  28.690001  29.037500  ...  223.880005  225.240005  205.509079   91366500
# 2017-01-04  28.962500  29.127501  28.937500  29.004999  ...  225.610001  226.580002  206.731735   78744400
# 2017-01-05  28.980000  29.215000  28.952499  29.152500  ...  225.479996  226.399994  206.567459   78379000
# 2017-01-06  29.195000  29.540001  29.117500  29.477501  ...  225.899994  227.210007  207.306549   71559900
# ......

默认是获取天级别的数据,如果你需要获取分钟级的,只需要添加interval参数:

import yfinance as yf

# 单股
data = yf.download("AAPL", start="2022-05-18", end="2022-05-23", interval="1m")
print(data)

#                                  Open        High         Low       Close   Adj Close   Volume
# Datetime
# 2022-05-17 12:00:00-04:00  148.000000  148.050003  147.839996  147.865005  147.865005        0
# 2022-05-17 12:01:00-04:00  147.869507  147.919998  147.779999  147.889893  147.889893   123746
# 2022-05-17 12:02:00-04:00  147.889999  147.929993  147.750000  147.907394  147.907394    92847
# 2022-05-17 12:03:00-04:00  147.904999  147.929993  147.785004  147.839996  147.839996    79266
# 2022-05-17 12:04:00-04:00  147.839996  147.895004  147.779999  147.860001  147.860001    58905
# ......

它支持的分钟级参数有:1m,2m,5m,15m,30m,60m,90m等等

此外还支持小时级和天线、周线、月线级别:1h,1d,5d,1wk,1mo,3mo等等

获取到的数据类型就是Dataframe,因此你还可以直接保存为csv文件:

# 公众号:Python 实用宝典
import yfinance as yf

data = yf.download("AAPL", start="2022-05-18", end="2022-05-23", interval="1m")
data.to_csv("aapl_20220518_20220523.csv")
# 保存到本地,命名为 aapl_20220518_20220523.csv

3.通过yfinance获取股票基本数据

如果你需要获取一只股票的基本数据,如市值、市盈率、股息等,你可以通过定义一只股票的Ticker,利用其info属性获取:

# 公众号:Python 实用宝典
import yfinance as yf

aapl = yf.Ticker("aapl")
print(aapl.info)
# {'zip': '95014', 'sector': 'Technology', 'fullTimeEmployees': 154000, 'longBusinessSummary': 'Apple ......

这个字典比较长,这里省略显示了,里面包含了比如市盈率(PE)等信息:

# 公众号:Python 实用宝典
import yfinance as yf

aapl = yf.Ticker("aapl")
aapl.info['forwardPE']
# 20.974085

你还可以获取每次派息数据:

# 公众号:Python 实用宝典
import yfinance as yf

aapl = yf.Ticker("aapl")
print(aapl.dividends)
# Date
# 1987-05-11    0.000536
# 1987-08-10    0.000536
# 1987-11-17    0.000714
# 1988-02-12    0.000714
# 1988-05-16    0.000714
#                 ...
# 2021-05-07    0.220000
# ...             ...

获取资产负债表:

# 公众号:Python 实用宝典
import yfinance as yf

aapl = yf.Ticker("aapl")
print(aapl.balancesheet)
#                              2021-09-25    2020-09-26    2019-09-28    2018-09-29
# Total Liab                 2.879120e+11  2.585490e+11  2.480280e+11  2.585780e+11
# Total Stockholder Equity   6.309000e+10  6.533900e+10  9.048800e+10  1.071470e+11
# Other Current Liab         5.357700e+10  4.786700e+10  4.324200e+10  3.929300e+10
# Total Assets               3.510020e+11  3.238880e+11  3.385160e+11  3.657250e+11
# Common Stock               5.736500e+10  5.077900e+10  4.517400e+10  4.020100e+10
# ......

现金流数据:

# 公众号:Python 实用宝典
import yfinance as yf

aapl = yf.Ticker("aapl")
print(aapl.cashflow)
#                                              2021-09-25    2020-09-26    2019-09-28    2018-09-29
# Investments                               -2.819000e+09  5.335000e+09  5.809300e+10  3.084500e+10
# Change To Liabilities                      1.400200e+10 -1.981000e+09 -2.548000e+09  9.172000e+09
# Total Cashflows From Investing Activities -1.454500e+10 -4.289000e+09  4.589600e+10  1.606600e+10
# ......

新闻数据:

# 公众号:Python 实用宝典
import yfinance as yf

aapl = yf.Ticker("aapl")
print(aapl.news)
# [{'uuid': '476a41c6-c6dc-3050-9b8f-c3777c8485b2', 'title': "Dow Jones Futures Rise After 'Hard' Reality Hits Market; What To Do Now", 'publisher': "Investor's Business Daily", 
# 'link': 'https://finance.yahoo.com/m/476a41c6-c6dc-3050-9b8f-c3777c8485b2/dow-jones-futures-rise-after.html', 
# 'providerPublishTime': 1653305573, 'type': 'STORY'}, {'uuid': '721d466d-5394-3f3c-a9c3-b0920d44c7f3' ......

总之,有了yfinance这个神器,除了高频数据你无法获取之外,其他的美股数据你都能获取得到,有需要的小伙伴可以试试,非常好用。

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!


​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

教你用Python计算对量化交易至关重要的VWAP指标

成交量加权平均价格 (VWAP) 在金融业中是指特定时间范围内交易价值与交易总数量的比率。它具有三个重要的特点和优势,为交易者提供了对价格趋势的洞察方法。机构和交易者使用 VWAP 来识别买卖区域,并帮助衡量市场情绪。

1.为什么要用VWAP?

VWAP有三个重要的特点:

1. VWAP可以帮助我们了解市场情绪。当证券价格高于VWAP线时,市场对它是乐观看涨的。当价格低于VWAP线时,市场是悲观看跌的。这一点我们可以从下图直观地了解。

2. 许多日内交易者和大型机构投资者以及养老金计划都使用VWAP来作为衡量自己的交易是否会影响市场的重要指标。 比如机构交易者想要卖出自己重要的头寸时,他们的目标是以VWAP或更高的价格卖出。他们会用几种VWAP盘中策略来确定三件事(趋势、谁在影响价格、确定支撑位和压力位)。

3. VWAP及其与证券价格平均值(HLC)的1个标准差可以作为潜在的支撑和阻力,如下图所示。

2 如何用Python计算VWAP

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install pandas

VWAP的计算公式如下:

TP =(最高价+最低价+收盘价)/3

V = 成交量

VWAP = (TP_1 * V_1 + TP_2 * V_2 + TP_n * V_n)/n

例如,如果一只股票以 10 美元交易 1000 股,然后以 11 美元交易 100 股,则最终交易价格为 11 美元;但是,VWAP 将更接近 10:

(1000 * 10 + 100 * 11)/(1000 + 100)) = 10.09

接下来,我们制造一些假数据来准备计算VWAP:

# Get imports
import datetime
import pandas as pd

# Create example dataframe
df = pd.DataFrame(
index=[datetime.datetime(2021,1,1,1),
datetime.datetime(2021,1,1,2),
datetime.datetime(2021,1,1,3),
datetime.datetime(2021,1,1,4)],
data={
  'low':[9,10,11,12],
  'close':[10,11,12,13],
  'high':[11,12,13,14],
  'volume':[1000,750,500,250]
  }
)
df.index.rename('date', inplace=True)

数据如下:

                    low  close  high  volume
date
2021-01-01 01:00:00    9     10    11    1000
2021-01-01 02:00:00   10     11    12     750
2021-01-01 03:00:00   11     12    13     500
2021-01-01 04:00:00   12     13    14     250

VWAP的计算方法如下,这里采用了HLC(open、low、close)的平均值作为基准计算对象:

# Create VWAP function
def vwap(df):
    v = df['volume'].values
    tp = (df['low'] + df['close'] + df['high']).div(3).values
    return df.assign(vwap=(tp * v).cumsum() / v.cumsum())

vwap(df)

计算完成后会在原来的数据上添加一列vwap列:

                     low  close  high  volume       vwap
date
2021-01-01 01:00:00    9     10    11    1000  10.000000
2021-01-01 02:00:00   10     11    12     750  10.428571
2021-01-01 03:00:00   11     12    13     500  10.777778
2021-01-01 04:00:00   12     13    14     250  11.000000

验证一下:

# Verify VWAP
## 以第二行为例
(10*1000 + 11*750) / (1000+750)
10.428571 # 正确

3.VWAP的缺点

没有全能的指标,VWAP也有其自身的缺点。

1.滞后性。和其他的移动平均线一样,VWAP也是一个滞后的指标,而且随着日内交易量的累计,滞后性会越来越严重。

2.仅适用于短期图表,如秒级、分钟级。

4.VWAP 策略

我们已经知道VWAP的运行特点,那么如何利用这些特点进行交易呢?

利用其回调的特点。当股价在一天内显着超过 VWAP 和移动平均线时,它们可能会回调。你可以选择在股价大幅度上涨时卖空股票,也可以选择在回调时等待入场。

Fade策略。这个策略是一个逆势策略,它在强劲势头的运动后采取相反的立场。利用VWAP发的支撑和压力作为其入场和出场的信号。

午后走高策略。这是一个油管老哥(Tim Bohen)观察出来的策略,他发现热门股票早盘走高,并且价格持续保持在vwap上方的股票,午后走高突破的几率非常大。

当然,所有策略都应该被回测后再确定是否有效。以上策略只是一个根据VWAP做交易的思路,你还可以结合其他指标进行策略的开发和回测,有兴趣的同学可以试试看。

本文参考文章:https://analyzingalpha.com/blog/vwap

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!


​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

FreqTrade—又强又简单的加密货币自动交易机器人

Freqtrade 是一个用 Python 编写的免费开源加密货币交易机器人。它旨在支持所有主要交易所并通过 Telegram 或 webUI 进行控制。功能包含回测、绘图和资金管理工具以及通过机器学习的策略优化。

目前支持的交易所:

特性:

  •  基于 Python 3.8+:适用于任何操作系统 – Windows、macOS 和 Linux。
  •  持久性:持久性是通过 sqlite 实现的。
  •  Dry-run:不花钱运行机器人。
  •  回测:模拟买入/卖出策略。
  •  通过机器学习进行策略优化:使用机器学习通过真实的交易所数据优化买入/卖出策略参数。
  •  边缘头寸规模计算您的胜率、风险回报率、最佳止损位并在为每个特定市场建立头寸之前调整头寸规模。
  •  白名单加密货币:选择你要交易的加密货币或使用动态白名单。
  •  黑名单加密货币:选择你想要避免的加密货币。
  •  内置 WebUI:内置 Web UI 来管理你的机器人。
  •  可通过 Telegram管理:使用 Telegram 管理机器人。
  •  以法定货币显示盈亏:以法定货币显示你的盈亏。
  •  表现状态报告:提供你当前交易的表现状态。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

在Linux/MacOS下,三行命令就能完成安装:

git clone -b develop https://github.com/freqtrade/freqtrade.git
cd freqtrade
./setup.sh --install

如果你无法克隆此项目,请在Python实用宝典公众号后台回复:freqtrade 下载。

Windows环境下打开Cmd(开始—运行—CMD),输入命令安装依赖:

git clone https://github.com/freqtrade/freqtrade.git
cd freqtrade
# 安装ta-lib
pip install build_helpers/TA_Lib-0.4.24-cp38-cp38-win_amd64.whl
pip install -r requirements.txt
pip install -e .
freqtrade

请注意,此处安装ta-lib时项目方提供了python3.8/3.9/3.10,其他Python版本请自行搜索下载。

输入freqtrade时,显示以下信息说明安装成功:

(freqtrade) D:\CODE\trader\freqtrade>freqtrade
2022-02-17 19:40:50,174 - freqtrade - ERROR - Usage of Freqtrade requires a subcommand to be specified.
To have the bot executing trades in live/dry-run modes, depending on the value of the `dry_run` setting in the config, run Freqtrade as `freqtrade trade [options...]`.
To see the full list of options available, please use `freqtrade --help` or `freqtrade <command> --help`.

2.快速开始

下面教你如何开发一个简单的交易策略。

一个策略文件往往包含这些东西:

  • 指标
  • 购买规则
  • 卖出规则
  • 建议最低投资回报率
  • 强烈推荐止损

Freqtrade使用 Pandas 作为基础数据结构,它底层的OHLCV都是以Dataframe的格式存储的。

Dataframe数据流中每一行数据代表图表上的一根K线,最新的K线始终是数据库中最后一根。

> dataframe.head()
                       date      open      high       low     close     volume
0 2021-11-09 23:25:00+00:00  67279.67  67321.84  67255.01  67300.97   44.62253
1 2021-11-09 23:30:00+00:00  67300.97  67301.34  67183.03  67187.01   61.38076
2 2021-11-09 23:35:00+00:00  67187.02  67187.02  67031.93  67123.81  113.42728
3 2021-11-09 23:40:00+00:00  67123.80  67222.40  67080.33  67160.48   78.96008
4 2021-11-09 23:45:00+00:00  67160.48  67160.48  66901.26  66943.37  111.39292

Pandas 提供了计算指标的快速方法。为了从这种速度中受益,建议不要使用循环,而是使用矢量化方法。

矢量化操作在整个数据范围内执行计算,因此,与遍历每一行相比,在计算指标时要快得多。

dataframe.loc[(dataframe['rsi'] > 30), 'buy'] = 1

类似于上面这样的赋值方法,会自动设置rsi大于30的数据的buy列的值为1。

买入规则

def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
    """
    Based on TA indicators, populates the buy signal for the given dataframe
    :param dataframe: DataFrame populated with indicators
    :param metadata: Additional information, like the currently traded pair
    :return: DataFrame with buy column
    """
    dataframe.loc[
        (
            (qtpylib.crossed_above(dataframe['rsi'], 30)) &  # Signal: RSI crosses above 30
            (dataframe['tema'] <= dataframe['bb_middleband']) &  # Guard
            (dataframe['tema'] > dataframe['tema'].shift(1)) &  # Guard
            (dataframe['volume'] > 0)  # Make sure Volume is not 0
        ),
        'buy'] = 1

    return dataframe

请注意,一定要不修改并返回”open”, “high”, “low”, “close”, “volume”列,这些是基础行情数据,如果返回错误的数据将可能会导致一些奇怪数据的产生。

如上所示的方法中,符合条件的数据的buy值会被设为1代表买入,否则为0或nan值。

卖出规则

def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
    """
    Based on TA indicators, populates the sell signal for the given dataframe
    :param dataframe: DataFrame populated with indicators
    :param metadata: Additional information, like the currently traded pair
    :return: DataFrame with buy column
    """
    dataframe.loc[
        (
            (qtpylib.crossed_above(dataframe['rsi'], 70)) &  # Signal: RSI crosses above 70
            (dataframe['tema'] > dataframe['bb_middleband']) &  # Guard
            (dataframe['tema'] < dataframe['tema'].shift(1)) &  # Guard
            (dataframe['volume'] > 0)  # Make sure Volume is not 0
        ),
        'sell'] = 1
    return dataframe

与买入类似,这里不赘述了。

最小投资回报率

在类中增加这个初始化变量,能控制投资回报率:

minimal_roi = {
    "40": 0.0,
    "30": 0.01,
    "20": 0.02,
    "0": 0.04
}

上述配置意味着:

  • 只要达到 4% 的利润就卖出
  • 达到 2% 利润时卖出(20 分钟后生效)
  • 达到 1% 利润时卖出(30 分钟后生效)
  • 交易未亏损时卖出(40 分钟后生效)

此处的计算包含费用。

要完全禁用 ROI,请将其设置为一个非常高的数字:

minimal_roi = {
    "0": 100
}

虽然从技术上讲并没有完全禁用,但一旦交易达到 10000% 利润,它就会卖出。

止损

强烈建议设置止损,以保护资金免受不利的剧烈波动。

设置 10% 止损的示例:

stoploss = -0.10

一个完整代码如下:

# pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
# flake8: noqa: F401
# isort: skip_file
# --- Do not remove these libs ---
from re import A
import numpy as np  # noqa
import pandas as pd  # noqa
from pandas import DataFrame

from freqtrade.strategy import (BooleanParameter, CategoricalParameter, DecimalParameter,
                                IStrategy, IntParameter)

# --------------------------------
# 你自己所需要的模块放在这里
import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib


# This class is a sample. Feel free to customize it.
class SampleStrategy(IStrategy):
    """
    This is a sample strategy to inspire you.
    More information in https://www.freqtrade.io/en/latest/strategy-customization/
    You can:
        :return: a Dataframe with all mandatory indicators for the strategies
    - Rename the class name (Do not forget to update class_name)
    - Add any methods you want to build your strategy
    - Add any lib you need to build your strategy
    You must keep:
    - the lib in the section "Do not remove these libs"
    - the methods: populate_indicators, populate_buy_trend, populate_sell_trend
    You should keep:
    - timeframe, minimal_roi, stoploss, trailing_*
    """
    # Strategy interface version - allow new iterations of the strategy interface.
    # Check the documentation or the Sample strategy to get the latest version.
    INTERFACE_VERSION = 2

    # 设定最小投资回报
    minimal_roi = {
        "60": 0.01,
        "30": 0.02,
        "0": 0.04
    }

    # 止损
    stoploss = -0.10

    # 指标参数
    buy_rsi = IntParameter(low=1, high=50, default=30, space='buy', optimize=True, load=True)
    sell_rsi = IntParameter(low=50, high=100, default=70, space='sell', optimize=True, load=True)

    # K线时间
    timeframe = '5m'

    # 在新K线出现时执行
    process_only_new_candles = False

    # These values can be overridden in the "ask_strategy" section in the config.
    use_sell_signal = True
    sell_profit_only = False
    ignore_roi_if_buy_signal = False

    # 预准备K线数
    startup_candle_count: int = 30

    # 下单类型
    order_types = {
        'buy': 'limit',
        'sell': 'limit',
        'stoploss': 'market',
        'stoploss_on_exchange': False
    }

    # 订单有效时间(gtc: 除非取消否则一直有效)
    order_time_in_force = {
        'buy': 'gtc',
        'sell': 'gtc'
    }

    plot_config = {
        'main_plot': {
            'tema': {},
            'sar': {'color': 'white'},
        },
        'subplots': {
            "MACD": {
                'macd': {'color': 'blue'},
                'macdsignal': {'color': 'orange'},
            },
            "RSI": {
                'rsi': {'color': 'red'},
            }
        }
    }

    def informative_pairs(self):
        """
        Define additional, informative pair/interval combinations to be cached from the exchange.
        These pair/interval combinations are non-tradeable, unless they are part
        of the whitelist as well.
        For more information, please consult the documentation
        :return: List of tuples in the format (pair, interval)
            Sample: return [("ETH/USDT", "5m"),
                            ("BTC/USDT", "15m"),
                            ]
        """
        return []

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Adds several different TA indicators to the given DataFrame
        Performance Note: For the best performance be frugal on the number of indicators
        you are using. Let uncomment only the indicator you are using in your strategies
        or your hyperopt configuration, otherwise you will waste your memory and CPU usage.
        :param dataframe: Dataframe with data from the exchange
        :param metadata: Additional information, like the currently traded pair
        :return: a Dataframe with all mandatory indicators for the strategies
        """

        # Momentum Indicators
        # ------------------------------------

        dataframe['adx'] = ta.ADX(dataframe)
        dataframe['rsi'] = ta.RSI(dataframe)
        stoch_fast = ta.STOCHF(dataframe)
        dataframe['fastd'] = stoch_fast['fastd']
        dataframe['fastk'] = stoch_fast['fastk']

        # MACD
        macd = ta.MACD(dataframe)
        dataframe['macd'] = macd['macd']
        dataframe['macdsignal'] = macd['macdsignal']
        dataframe['macdhist'] = macd['macdhist']

        # MFI
        dataframe['mfi'] = ta.MFI(dataframe)

        # Bollinger Bands
        bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
        dataframe['bb_lowerband'] = bollinger['lower']
        dataframe['bb_middleband'] = bollinger['mid']
        dataframe['bb_upperband'] = bollinger['upper']
        dataframe["bb_percent"] = (
            (dataframe["close"] - dataframe["bb_lowerband"]) /
            (dataframe["bb_upperband"] - dataframe["bb_lowerband"])
        )
        dataframe["bb_width"] = (
            (dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
        )

        # Parabolic SAR
        dataframe['sar'] = ta.SAR(dataframe)

        # TEMA - Triple Exponential Moving Average
        dataframe['tema'] = ta.TEMA(dataframe, timeperiod=9)

        hilbert = ta.HT_SINE(dataframe)
        dataframe['htsine'] = hilbert['sine']
        dataframe['htleadsine'] = hilbert['leadsine']

        return dataframe

    def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Based on TA indicators, populates the buy signal for the given dataframe
        :param dataframe: DataFrame populated with indicators
        :param metadata: Additional information, like the currently traded pair
        :return: DataFrame with buy column
        """
        dataframe.loc[
            (
                # Signal: RSI crosses above 30
                (qtpylib.crossed_above(dataframe['rsi'], self.buy_rsi.value)) &
                (dataframe['tema'] <= dataframe['bb_middleband']) &  # Guard: tema below BB middle
                (dataframe['tema'] > dataframe['tema'].shift(1)) &  # Guard: tema is raising
                (dataframe['volume'] > 0)  # Make sure Volume is not 0
            ), 'buy'] = 1

        return dataframe

    def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Based on TA indicators, populates the sell signal for the given dataframe
        :param dataframe: DataFrame populated with indicators
        :param metadata: Additional information, like the currently traded pair
        :return: DataFrame with sell column
        """
        dataframe.loc[
            (
                # Signal: RSI crosses above 70
                (qtpylib.crossed_above(dataframe['rsi'], self.sell_rsi.value)) &
                (dataframe['tema'] > dataframe['bb_middleband']) &  # Guard: tema above BB middle
                (dataframe['tema'] < dataframe['tema'].shift(1)) &  # Guard: tema is falling
                (dataframe['volume'] > 0)  # Make sure Volume is not 0
            ), 'sell'] = 1
        return dataframe
        

3.启动机器人

启动机器人前还需要设定配置,配置模板在 config/examples 下面。

比如币安的配置,你还需要输入key和secret:

"exchange": {
        "name": "binance",
        "key": "your_exchange_key",
        "secret": "your_exchange_secret",
  	    ......
	}
}

启动机器人:

freqtrade trade --strategy AwesomeStrategy --strategy-path /some/directory  -c path/far/far/away/config.json

–strategy-path 指定策略文件位置

-c 参数指定配置文件位置

比如我把策略放在了user_data/strategies下,配置放在了config_examples下,这么输入命令启动机器人即可:

freqtrade trade --strategy SampleStrategy --strategy-path user_data/strategies  -c config_examples/config_binance.example.json

由于篇幅问题,本文只是介绍了freqtrade的冰山一角,在启动机器人前,一定要进行回测并进行模拟交易。它还有TG通知功能、WebUI管理界面,详细的使用方法大家可以参考官方教程:

https://www.freqtrade.io/en/stable/

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!


​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典