生信人

找回密码
立即注册
搜索
热搜: 活动 交友 discuz
发新帖

0

收听

12

听众

318

主题
发表于 2024-9-3 23:40:53 | 查看: 642| 回复: 5

在量化分析中,投资者使用计算机编写程序,以历史市场数据为基础,通过模型建立和优化来判断市场趋势和进行投资决策。数据(包括行情数据、基本面数据、财务数据等等)是量化分析的基础。

1990 年底,上交所成立时,交易是依靠红马甲喊单撮合的。每个交易日,各家券商交易员挤在一起,手中抓着标着股票代码的小纸条,用力地喊着出价。每当一家券商的交易员大喊“买入”,一群卖方交易员便紧张地挤在一起,争相抛售股票。在这个拥挤的大厅里,每个人都面带紧张的表情,眼睛紧盯着交易屏幕,寻找着最新的交易信息。而每当一只股票价格发生波动,整个交易厅就会一片骚动。有些人会立即举起手中的纸条,向交易员报价,希望能够抓住市场机会。在这个手工竞价交易的时代,每个交易员的工作都非常繁琐,需要手动记录和处理大量的数据和信息。交易员们通常需要长时间地待在交易厅里,时刻准备着应对市场的变化。显然这种落后的交易方式下,是无法提供量化需要的条件的。

A 股的量化史可以追溯到 2005 年 8 月,当时嘉实元和稳健成长证券投资基金成立,主打量化投资策略。在此前后,一些券商、金融机构和软件服务商开始了相关数据的收集与整理。比如成立于 1997 年的万得 (Wind) 财经,它提供的数据涵盖了 A 股市场的股票、基金、债券、衍生品等多个领域,是 A 股市场的重要数据来源之一。随后,又出现了一批象通达信、同花顺、东方财富这样的行情软件开发商,他们也开始提供面向终端的行情数据和基于 API 的数据服务。

目前,机构投资者选择的金融终端主要有东方财富 Choice 以及 Wind 资讯金融终端,数据源(库)供应商主要有 Wind 资讯、恒生聚源、朝阳永续、天软、巨潮、天相、巨灵、国泰安、通联等。朝阳永续在分析师一致预期、盈利预测数据以及私募基金数据方面占据优势。天软科技在高频行情数据上比较突出。国泰安数据库主要为学术用途其中公司金融数据较为完善。

上面提到的这些厂商主要服务于金融机构。随着量化热潮的兴起,出现了向个人量化开发者和中小型投资机构出售量化数据的需求。这里面代表性的产品包括 pytdx,tushare,akshare,baostock,聚宽等等。

    2023年下半年起,越来越多的人开始使用XtQuant库来获取行情数据。XtQuant是迅投QMT的一个Python SDK,它可以与以极简模式运行的QMT进行通讯,以获取行情数据、财务数据,并能以API方式执行交易。<br>
    目前使用XtQuant获取普通行情数据是免费的,只要通过券商开通量化交易权限即可,开通这个权限,目前来看只有入金要求,没有费用。因此,QMT也可以算作是免费数据源。<br>
    不过,不是所有的券商都开通了这一业务。

考虑到这门课的受众是刚入门的量化爱好者,因此我们选择数据源时,要综合考虑价格、质量和易用性等多个因素。我们将按照价格从低到高的顺序,为大家着重介绍一些个人投资者可以承担的产品。至于更高端的产品,您可以在精通量化策略开发,能产生稳定的收益之后,再自行接入使用。

在深入到具体的各个数据源之前,我们需要先了解一点基础的证券知识。

1. 交易所及证券代码

A 股有三个交易所,即上交所、深交所和北交所。上交所成立最早,其下有主板和科创板两个板块;深交所次之,它下面有主板、中小板和创业板三个板块;北交所则刚刚成立一年多,只有一个板块。

设立多个交易所和板块,是因为资本市场需要为不同成长风格的企业都能提供融资,这也是世界范围内证券交易所的常态,比如我们熟知的美国市场,纳斯达克交易所就以接纳全球高科技企业为主,我们科创板的定位就类似于纳斯达克。在同一个板块的所有股票,它们都有相同的起始编号,不同的板块,起始号码则各不相同。比如创业板是以 300 和 301 起头,科创板则以 688 起头,中小板以 002 起头,等等。

股票代码在每个交易所内的编号都是唯一的,但在不同的交易所之间,可能存在冲突的情况。所有的号码段都是为股票分配的,那么在编制指数时,应该安排什么号段呢?由于指数的编制机制与股票发行机制大不相同,所以,我们没法给它分配固定的号段,只能由交易所自己见机行事。因此,指数的编号就有可能与其它交易所中经营的股票品种相冲突。比如,深发展是 A 股发行较早 的一支股票(现名平安银行),它的编号是 000001,在深交所上市。而上交所在成立半年多后,开始编制综合指数,也使用了 000001 的编号,这就与深发展相冲突了。

因此,我们要了解的第一个概念,就是只有证券名称加上交易所代码(前缀或者后缀),才能唯一确定一支证券品种。比如,有的软件系统使用 XSHE 指代深交所,使用 XSHG 来指代上交所。如此一来,000001.XSHE 就唯一指向深发展,而 000001.XSHG 就唯一指向上综指。这是一种比较科学的方法。我们也可以把 000001.XSHG 称为上综指的规范名称,而把 000001 称为深发展或者上综指的简码。

    我们平常在交流中,往往只使用简码。但当我们通过量化程序来获取数据时,则必须使用无歧义的代码。这个代码,相当于证券的身份证。

在这门课程中,我们主要使用 zillionare 来提供数据。不过,在介绍 zillionare 的数据方案之前,我们要先带大家学习第三方数据源的使用。因为 zillionare 本身也不能提供数据,它的数据也来自于第三方付费数据,定价也比较高,因此只在本课程中才能免费使用。

2. 除权和复权

股票存在配股、分拆、合并和发放股息等情形。当这些事件发生时,要么总股本数发生了变化(配股、分拆和合并的情形),要么每股包含的净权益发生了变化(发放股息)。这种情况下,每股包含的权益实际发生了变化,所以必须进行除权处理,这样才能保持财务上的一致性。

    假设A股公司总股数1亿股。当前价格10元。则该公司的市值为10亿元。年终公司决定进行拆股,给出10送10的方案,这样总股数将变更为2亿股。如果此时不对股价进行调整,则该公司的市值将凭空增长1倍。这显然是不合理的。

当除权发生时,股价就会出现较大的缺口。下图就显示了某支证券发生除权后,未进行复权处理的情况:

<div style="width:100%;text-align:center"> <img src="https://roim-picx-bpc.pages.dev/rest/kV9A67K.png" style="width:66%;margin: 10px auto;"> </div>

若使用未复权的价格来进行数据分析,将会出现技术指标发生实质性的改变(包括数据的统计特征),并且使用收益计算也会出现错误。

为了保证数据的连贯性,常通过前复权和后复权对价格序列进行调整。

2.1. 前复权

<div style="width:100%;text-align:center"> <img src="https://roim-picx-bpc.pages.dev/rest/xkMA67K.png" style="width:66%;margin: 10px auto;"> </div>

保持当前价格不变,将历史价格向前进行增减,从而使股价连续,这种方法被称为前复权。前复权用来看盘非常方便,能一眼看出股价的历史走势,叠加各种技术指标也比较顺畅,是各种行情软件默认的复权方式。这种方法虽然很常见,但也有两个缺陷需要注意。

第一,为了保证当前价格不变,每次股票除权除息,均需要重新调整历史价格,因此其历史价格是随时可变的。这会导致在不同时点看到的历史前复权价可能出现差异。如果我们使用的回测框架不能正确处理这种情况,将会引入未来数据。

第二,对于有持续分红的公司来说,长时间的前复权价,可能导致早期价格出现负值。即使一些数据源采用复权因子的做法,避免了负值的出现,但一旦早期价格低于(或者接近)1分钱这个事实上的最小单位,对价格的研究就不再有任何意义。

    如果某股的股价经过前复权,在早期它的价格变为0.008, 0.009, 0.001这样低于1分钱的数据,就会导致很多错误:因为股价的最小单位是0.01。即使部分软件能避免这个问题,继续复权时,股价变成7位小数之后,计算机由于单精度浮点数精度问题,将无法区分这些数字。

收藏回复 显示全部楼层 道具 举报

发表于 2024-9-3 23:41:13

2.2. 后复权

保证历史价格不变,在每次股票权益事件发生后,调整当前的股票价格的方法,被称为后复权。下图就是同一支股票,进行后复权的情况:

<div style="width:100%;text-align:center"> <img src="https://roim-picx-bpc.pages.dev/rest/q4sA67K.png" style="width:66%;margin: 10px auto;"> </div>

可以看出,无论是哪一种复权方式,股价走势都不受影响。但是,两种复权方式下,当前点的股价完全不同。最后一根bar的前复权价格总是等于未复权价格,但后复权价格则会大于未复权价格。

后复权价格和真实股票价格可能差别较大,不适合用来看盘,更不能用于交易。其优点在于,可以被看作投资者的长期财富增长曲线,反映投资者的真实收益率情况。如果使用后复权数据进行回测,不会引入未来数据,但是,它也存在很多问题。

比如,贵州茅台的后复权价格在2021年时,达到了近1.4万元。以这个价格进行回测,并且要满足最小成交单位1手的话,则每次交易要以140万元为最小成交单位。如果我们只有100万元的资金的话,那么策略永远无法执行。除此之外,还会有其它问题,这些我们将在介绍回测时,进行讲解。

3. Akshare

AkShare 是基于爬虫的财经数据接口库,目的是实现对股票、期货、期权、基金、外汇、债券、指数、数字货币等金融产品的基本面数据、实时和历史行情数据、衍生数据,从数据采集、数据清洗到数据落地的一套工具。它自身没有服务器,也不存储数据,数据来源于对大型财经网站的爬取,因此会受到网站限流等反爬措施限制。

Akshare 是一个 Python 库,我们使用 pip 来安装:

$ pip install akshare

3.1. 在jupyter环境下安装 akshare

%pip install akshare #安装后重启kernel

akshare 是免费数据,也无须注册账号。所以安装之后,就可以立即使用它来获取沪深 A 股的行情数据了。

在 akshare 中,获取证券数据的 API 格式多为 {type}_{zh|sz|sh|bj|cy|kc}_a_{spot|hist}_{server}的形式。显然,这里的'a'并表明是取 A 股数据。

type 是指证券的类型,即是'stock'还是'index';第二个字段对应交易所(或者板块),其取值可以是'zh'(取所有 A 股数据)、'sz'(取所有深证 A 股)、'sh'(取所有上证 A 股),'bj'(取所有北京交易所 A 股),'cy'(取所有创业板 A 股),'kc'(取所有科创板 A 股)等。

第三个字段用来区分要获取的数据是实时数据,还是历史数据,我们需要在 spot 和 hist 中进行选择。如果选择 spot,则表明是取实时数据,如果选择 hist,则表明是取历史数据。

server 字段可以为空(此时不需要带最后的'_'),此时表明从新浪服务器上取数据;也可以是'em'(表明从东方财富网上取数据),还可以是'tx'(表明从腾讯财经获取数据)。当然,不同的服务器,它们能提供的数据品种可能有所区别。

3.2. 实时股票数据

下面,我们就以获取创业板实时股票数据为例演示一下。根据上面的介绍,这个 api 应该是 stock_cy_a_spot:

import akshare as ak

bars = ak.stock_cy_a_spot()
bars[:10]

运行后提示错误:在 akshare 中没有 stock_cy_a_spot 这个方法。原因是,这个方法默认的服务器是新浪财经,但新浪财经并不提供实时数据。不过,东方财富提供了这个数据,所以,我们可以用 stock_cy_a_spot_em 这个 API:

import akshare as ak

bars = ak.stock_cy_a_spot_em()
bars[:10]

回复 显示全部楼层 道具 举报

发表于 2024-9-3 23:41:38

<div> <style scoped> .dataframe tbody tr th:only-of-type { vertical-align: middle; }

.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}

</style> <table border="1" class="dataframe"> <thead> <tr style="text-align: right;"> <th></th> <th>序号</th> <th>代码</th> <th>名称</th> <th>最新价</th> <th>涨跌幅</th> <th>涨跌额</th> <th>成交量</th> <th>成交额</th> <th>振幅</th> <th>最高</th> <th>...</th> <th>量比</th> <th>换手率</th> <th>市盈率-动态</th> <th>市净率</th> <th>总市值</th> <th>流通市值</th> <th>涨速</th> <th>5分钟涨跌</th> <th>60日涨跌幅</th> <th>年初至今涨跌幅</th> </tr> </thead> <tbody> <tr> <th>0</th> <td>1</td> <td>300047</td> <td>天源迪科</td> <td>8.74</td> <td>20.05</td> <td>1.46</td> <td>857436.0</td> <td>6.847485e+08</td> <td>21.70</td> <td>8.74</td> <td>...</td> <td>1.70</td> <td>15.60</td> <td>91.06</td> <td>1.67</td> <td>5.573888e+09</td> <td>4.804544e+09</td> <td>0.00</td> <td>0.00</td> <td>33.64</td> <td>0.00</td> </tr> <tr> <th>1</th> <td>2</td> <td>300068</td> <td>南都电源</td> <td>11.15</td> <td>20.02</td> <td>1.86</td> <td>1747767.0</td> <td>1.775260e+09</td> <td>21.10</td> <td>11.15</td> <td>...</td> <td>5.11</td> <td>21.06</td> <td>26.26</td> <td>1.77</td> <td>9.731221e+09</td> <td>9.253454e+09</td> <td>0.00</td> <td>0.00</td> <td>20.02</td> <td>-13.43</td> </tr> <tr> <th>2</th> <td>3</td> <td>300619</td> <td>金银河</td> <td>23.26</td> <td>20.02</td> <td>3.88</td> <td>119677.0</td> <td>2.659785e+08</td> <td>22.86</td> <td>23.26</td> <td>...</td> <td>2.29</td> <td>10.88</td> <td>-119.70</td> <td>1.90</td> <td>3.113255e+09</td> <td>2.558131e+09</td> <td>0.00</td> <td>0.00</td> <td>-17.72</td> <td>-45.40</td> </tr> <tr> <th>3</th> <td>4</td> <td>301311</td> <td>昆船智能</td> <td>17.69</td> <td>20.01</td> <td>2.95</td> <td>102765.0</td> <td>1.817164e+08</td> <td>2.04</td> <td>17.69</td> <td>...</td> <td>3.69</td> <td>11.78</td> <td>-78.16</td> <td>2.34</td> <td>4.245600e+09</td> <td>1.543317e+09</td> <td>0.00</td> <td>0.00</td> <td>-3.49</td> <td>-27.02</td> </tr> <tr> <th>4</th> <td>5</td> <td>300338</td> <td>*ST开元</td> <td>2.58</td> <td>20.00</td> <td>0.43</td> <td>541416.0</td> <td>1.323305e+08</td> <td>20.93</td> <td>2.58</td> <td>...</td> <td>1.96</td> <td>15.71</td> <td>-28.83</td> <td>-8.11</td> <td>1.038772e+09</td> <td>8.889312e+08</td> <td>0.00</td> <td>0.00</td> <td>89.71</td> <td>-42.02</td> </tr> <tr> <th>5</th> <td>6</td> <td>300382</td> <td>斯莱克</td> <td>6.07</td> <td>19.96</td> <td>1.01</td> <td>227966.0</td> <td>1.297854e+08</td> <td>20.75</td> <td>6.07</td> <td>...</td> <td>2.65</td> <td>3.63</td> <td>108.22</td> <td>1.77</td> <td>3.814957e+09</td> <td>3.813971e+09</td> <td>0.00</td> <td>0.00</td> <td>-6.90</td> <td>-38.25</td> </tr> <tr> <th>6</th> <td>7</td> <td>300032</td> <td>金龙机电</td> <td>3.89</td> <td>15.43</td> <td>0.52</td> <td>1394267.0</td> <td>5.441850e+08</td> <td>16.02</td> <td>4.04</td> <td>...</td> <td>5.15</td> <td>17.36</td> <td>-41.52</td> <td>4.20</td> <td>3.124330e+09</td> <td>3.124324e+09</td> <td>-0.26</td> <td>0.00</td> <td>20.81</td> <td>-38.35</td> </tr> <tr> <th>7</th> <td>8</td> <td>301030</td> <td>仕净科技</td> <td>22.94</td> <td>11.41</td> <td>2.35</td> <td>166971.0</td> <td>3.712511e+08</td> <td>16.03</td> <td>23.59</td> <td>...</td> <td>2.01</td> <td>9.81</td> <td>17.87</td> <td>2.37</td> <td>4.609835e+09</td> <td>3.906244e+09</td> <td>0.09</td> <td>-0.13</td> <td>-24.49</td> <td>-22.42</td> </tr> <tr> <th>8</th> <td>9</td> <td>300879</td> <td>大叶股份</td> <td>15.99</td> <td>10.89</td> <td>1.57</td> <td>205793.0</td> <td>3.327755e+08</td> <td>15.40</td> <td>17.30</td> <td>...</td> <td>4.83</td> <td>12.17</td> <td>25.72</td> <td>2.98</td> <td>2.723460e+09</td> <td>2.703142e+09</td> <td>0.25</td> <td>0.50</td> <td>26.50</td> <td>-7.68</td> </tr> <tr> <th>9</th> <td>10</td> <td>301611</td> <td>珂玛科技</td> <td>33.20</td> <td>10.23</td> <td>3.08</td> <td>303686.0</td> <td>1.036105e+09</td> <td>19.72</td> <td>36.14</td> <td>...</td> <td>1.39</td> <td>53.85</td> <td>52.02</td> <td>10.39</td> <td>1.447520e+10</td> <td>1.872417e+09</td> <td>-0.21</td> <td>-0.87</td> <td>315.00</td> <td>315.00</td> </tr> </tbody> </table> <p>10 rows × 23 columns</p> </div>

现在我们看到了 10 只股票的最新价格数据。在我们的实践中,我们尝试过每 5 秒更新一次全 A 市场的最新价格,因此可以在实盘中当准实时数据来使用。

3.3. 股票历史数据

在上一节,我们已经熟悉了 akshare 的 API 风格。获取股票历史数据的 api 与获取实时数据的类似,区别在于,我们需要将'spot'换成'hist',并且还需要传入一些参数。

比如,我们要获取'603777'这支股票在 2022 年下半年的日线数据:

import akshare as ak

bars = ak.stock_zh_a_hist('603777', 'daily', '20220701', '20221231', adjust='qfq')
bars[-10:]

回复 显示全部楼层 道具 举报

发表于 2024-9-3 23:41:55

<div> <style scoped> .dataframe tbody tr th:only-of-type { vertical-align: middle; }

.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}

</style> <table border="1" class="dataframe"> <thead> <tr style="text-align: right;"> <th></th> <th>日期</th> <th>股票代码</th> <th>开盘</th> <th>收盘</th> <th>最高</th> <th>最低</th> <th>成交量</th> <th>成交额</th> <th>振幅</th> <th>涨跌幅</th> <th>涨跌额</th> <th>换手率</th> </tr> </thead> <tbody> <tr> <th>115</th> <td>2022-12-19</td> <td>603777</td> <td>22.92</td> <td>21.98</td> <td>22.93</td> <td>21.79</td> <td>72351</td> <td>160911261.0</td> <td>4.97</td> <td>-4.14</td> <td>-0.95</td> <td>2.15</td> </tr> <tr> <th>116</th> <td>2022-12-20</td> <td>603777</td> <td>21.68</td> <td>21.04</td> <td>21.82</td> <td>20.99</td> <td>67956</td> <td>145445200.0</td> <td>3.78</td> <td>-4.28</td> <td>-0.94</td> <td>2.02</td> </tr> <tr> <th>117</th> <td>2022-12-21</td> <td>603777</td> <td>21.09</td> <td>21.52</td> <td>21.91</td> <td>20.97</td> <td>61263</td> <td>131969615.0</td> <td>4.47</td> <td>2.28</td> <td>0.48</td> <td>1.82</td> </tr> <tr> <th>118</th> <td>2022-12-22</td> <td>603777</td> <td>21.66</td> <td>21.08</td> <td>22.05</td> <td>21.06</td> <td>65508</td> <td>141759145.0</td> <td>4.60</td> <td>-2.04</td> <td>-0.44</td> <td>1.95</td> </tr> <tr> <th>119</th> <td>2022-12-23</td> <td>603777</td> <td>21.21</td> <td>21.23</td> <td>21.44</td> <td>20.58</td> <td>51991</td> <td>110081198.0</td> <td>4.08</td> <td>0.71</td> <td>0.15</td> <td>1.54</td> </tr> <tr> <th>120</th> <td>2022-12-26</td> <td>603777</td> <td>21.01</td> <td>21.14</td> <td>21.46</td> <td>20.87</td> <td>41897</td> <td>89235282.0</td> <td>2.78</td> <td>-0.42</td> <td>-0.09</td> <td>1.24</td> </tr> <tr> <th>121</th> <td>2022-12-27</td> <td>603777</td> <td>21.15</td> <td>21.53</td> <td>21.66</td> <td>20.95</td> <td>65113</td> <td>139783206.0</td> <td>3.36</td> <td>1.84</td> <td>0.39</td> <td>1.93</td> </tr> <tr> <th>122</th> <td>2022-12-28</td> <td>603777</td> <td>21.36</td> <td>20.86</td> <td>21.46</td> <td>20.05</td> <td>73322</td> <td>154293751.0</td> <td>6.55</td> <td>-3.11</td> <td>-0.67</td> <td>2.18</td> </tr> <tr> <th>123</th> <td>2022-12-29</td> <td>603777</td> <td>20.78</td> <td>21.90</td> <td>22.01</td> <td>20.64</td> <td>78289</td> <td>169758726.0</td> <td>6.57</td> <td>4.99</td> <td>1.04</td> <td>2.33</td> </tr> <tr> <th>124</th> <td>2022-12-30</td> <td>603777</td> <td>21.76</td> <td>21.47</td> <td>22.11</td> <td>20.91</td> <td>65970</td> <td>142369335.0</td> <td>5.48</td> <td>-1.96</td> <td>-0.43</td> <td>1.96</td> </tr> </tbody> </table> </div>

这里的参数依次是股票简码、周期类型、起始日期和复权方式。周期类型支持'daily'(日线),'weekly'(周线), 'monthly'(月线)。复权方式支持前复权('qfq') 和后复权('hfq')。如果需要未复权的原始价格,则可省略此参数。

分钟级别的数据,在 akshare 中被称为分时数据。通过新浪服务器(stock_zh_a_minute)可以取到半年左右的 1 分钟数据;通过东财(stock_zh_a_hist_min_em)则只能取到 5 天左右的 1 分钟数据。

3.4. 证券列表

我们在获取股票历史数据时,已经接触到了具体的股票代码。要记住所有的代码几乎是不可能的,因为现在 A 股已经到了 5000 支左右股票的规模。因此,我们需要一个索引,或者证券列表,让我们可以查询股票的代码、名字、上市日期等基本信息。

这个 API 就是 stock_info_{sh|sz|bj}_name_code。中间的字段是交易所的代码。

回复 显示全部楼层 道具 举报

发表于 2024-9-3 23:42:12
# import akshare as ak

ak.stock_info_sh_name_code()

<div> <style scoped> .dataframe tbody tr th:only-of-type { vertical-align: middle; }

.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}

</style> <table border="1" class="dataframe"> <thead> <tr style="text-align: right;"> <th></th> <th>证券代码</th> <th>证券简称</th> <th>公司全称</th> <th>上市日期</th> </tr> </thead> <tbody> <tr> <th>0</th> <td>600000</td> <td>浦发银行</td> <td>上海浦东发展银行股份有限公司</td> <td>1999-11-10</td> </tr> <tr> <th>1</th> <td>600004</td> <td>白云机场</td> <td>广州白云国际机场股份有限公司</td> <td>2003-04-28</td> </tr> <tr> <th>2</th> <td>600006</td> <td>东风股份</td> <td>东风汽车股份有限公司</td> <td>1999-07-27</td> </tr> <tr> <th>3</th> <td>600007</td> <td>中国国贸</td> <td>中国国际贸易中心股份有限公司</td> <td>1999-03-12</td> </tr> <tr> <th>4</th> <td>600008</td> <td>首创环保</td> <td>北京首创生态环保集团股份有限公司</td> <td>2000-04-27</td> </tr> <tr> <th>...</th> <td>...</td> <td>...</td> <td>...</td> <td>...</td> </tr> <tr> <th>1685</th> <td>605580</td> <td>恒盛能源</td> <td>恒盛能源股份有限公司</td> <td>2021-08-19</td> </tr> <tr> <th>1686</th> <td>605588</td> <td>冠石科技</td> <td>南京冠石科技股份有限公司</td> <td>2021-08-12</td> </tr> <tr> <th>1687</th> <td>605589</td> <td>圣泉集团</td> <td>济南圣泉集团股份有限公司</td> <td>2021-08-10</td> </tr> <tr> <th>1688</th> <td>605598</td> <td>上海港湾</td> <td>上海港湾基础建设(集团)股份有限公司</td> <td>2021-09-17</td> </tr> <tr> <th>1689</th> <td>605599</td> <td>菜百股份</td> <td>北京菜市口百货股份有限公司</td> <td>2021-09-09</td> </tr> </tbody> </table> <p>1690 rows × 4 columns</p> </div>

这会返回一个 DataFrame,共有'公司代码', '公司简称', '公司全称', '上市日期'等四列数据。如果我们将交易所代码替换成'sz'或者'bj',则会得到总股本、流通股本、所属行业、地区、报告日期等额外五列数据。同样类型的请求,返回结果在字段上不一致,这会带来策略使用上的一些不便。

    A股常常会有一些奇怪的炒作,比如2018年炒东方开头的股票、兔年炒带兔字的票,龙年炒带龙字的股票等。所以,我们还常常需要按股票名进行过滤。按名字进行模糊匹配,这个功能在omicron中有实现。

回复 显示全部楼层 道具 举报

发表于 2024-9-3 23:42:32

3.5. 交易日历

交易日历在量化中起到非常重要的作用。比如,我们要取截止 end日期的 250 根 K 线数据。如果使用的 API 只支持按起始日期来获取数据,那么我们将不得不自己来计算这个起始日期。而这个计算,我们不能依赖自然日历。此外,有了交易日历,一些后台任务也才能合理的规划。比如,如果这一周只交易到周三,那么对于机构来说,一般就应该在周三交易结束之后,进行周线级别的策略分析,而不是等到周六。

我们可以这样获取交易日历:

import akshare as ak

calendar = ak.tool_trade_date_hist_sina()
print(f"日历起始日:{calendar.iloc[0,0]}\n 日历截止日:{calendar.iloc[-1,0]}")
日历起始日:1990-12-19
 日历截止日:2024-12-31

在我这次运行的时候,上述代码运行将输出 1990-12-19 和 2024-12-31 这样两个日期。

Akshare 还提供了许多其它数据,比如像全市场市盈率这样比较重要的择时数据。我们在本章的最后一节,将会有机会看到它的运用。

3.6. 封装和改进建议

Akshare 轻量、免注册,还能获取实时价格数据。它的数据直接来源于大的财经网站,因此准确度较高,这也是我们推荐它的原因。不过,如果我们要在正式产品中使用 akshare 的话,建议进行一定程度的封装和改进:

  1. 服务器会对爬虫进行限流。在调用 akshare 失败后,我们需要采用退火算法进行延时等待;反之,如果我们不断重试的话,可能导致整个 IP 都被封掉。
  2. akshare 在其代码中引入了 tqdm,这是一个非常有名的进度条工具。但这个工具也引起了一些问题,比如你不能在一个没有连接到终端的程序中使用它(会导致异常退出)。在生产环境下,应用往往是以服务方式运行的,这些服务都不会连接到终端,因此,这些服务中,都不能使用 akshare。
  3. akshare 发出网络请求时,是以同步调用的方式进行的,可以改为异步调用以优化性能。
  4. akshare 的 api 设计中,绑定了服务器的指定。其实对普通用户来讲,我们只关心能否快速、精准地获取数据,不关心数据来自于哪个服务器。不仅如此,如果现在的这些服务器将来不能用了,要使用新的服务器,这也会使得我们必须修改自己的策略代码。因此,建议大家在使用 akshare 时,自己先进行一些封装和修改,再在策略里调用自己的封装包,以便即使 akshare 的一些 API 被弃用了,也不用改我们的策略代码,只用将接口实现改一下就好了。
  5. 需要做数据本地化。如果同一组织内多人同时使用,很容易触发服务器反爬机制,导致封 IP;如果在回测中使用它来频繁获取历史行情数据,也可能导致被封 IP。将数据本地化,使得绝大多数据数据存取都能在本地消化,数据基本上只从服务器上取一次,可以解决此问题。

3.7. 练习

  1. 如果我们通过 akshare 高频度地获取数据,就有可能被服务器封 IP。不过幸运地是,通过观察,我们发现服务器总是事先给出警告,如果在这种情况下,我们能主动加上延时等待,过一段时间后再试,则一般不会有问题。尝试使用 retry 这个库,写一段获取股票行情的代码,在 akshare 失败时,自动进行延时重试。延时重试的时间分别是 1, 2, 4, 8 秒。<br>提示: retry 库可以通过 pip install retry来安装。
  2. tqdm 在运行时,会需要一个终端,否则会报错。我们可以通过将上下文中的 stderr 替换成为 StringIO 对象,即可让其运行。<br>提示:需要用到 contextlib.redirect_stderr。这道题不要求大家复现错误情况(比较难),但要求能写出正确代码并运行成功。
  3. 通过 akshare 获取某支股票的历史数据两次,一次为不复权,一次为后复权,算出它的复权因子,以此推导出前复权价格。使用 akshare 再获取一次前复权数据,与你推导出来的数据进行对比。<br>提示:此题要求大家进行练习,但结果可能出人意料。
  4. 为CAPM模型提供数据

资本资产定价模型(CAPM)描述了资产的预期回报与市场系统风险之间的关系。它由威廉.夏普等人在1960年代提出。威廉.夏普获得了1990年的诺贝尔经济学奖。CAPM被认为是经济学的七个基本理论之一。

CAPM表示资产的预期收益等于无风险收益加上风险溢价。 CAPM的假设是投资者是理性的,希望获得最大化回报并尽可能降低风险。因此,CAPM 的目标是计算相对于无风险利率的给定风险溢价,投资者可以预期获得的回报。

在CAPM模型中,我们需要以下数据:

  1. 国债收益率
  2. 指数行情数据及成分股信息
  3. 个股数据

在本题中,我们不要求理解CAPM模型,只需要能为模型提供数据即可。

回复 显示全部楼层 道具 举报

您需要登录后才可以回帖 登录 | 立即注册

QQ|Archiver|手机版|小黑屋|生信人 ( 萌ICP备20244422号 )

GMT+8, 2024-11-21 20:48 , Processed in 0.139533 second(s), 35 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表