学习笔记

获取聚宽常用数据

print('---------------------获取聚宽常用数据----------------------')
'''聚宽官方的数据网站:https://www.joinquant.com/data'''

#获取指数成分股
'''获取指数成分股可使用get_index_stocks(index_symbol,date=None),该函数会返回指定指数的成分股的股票代码list
参数index_symbol表示指数代码,
参数date表示查询日期,默认为None即当天,会随着回测日期的变化而变化,相当于context.current_dt,如果要指定日期,可以按照'2022-10-01'这样的格式填写
'''
#获取2022年10月1日的沪深300成分股
stocks=get_index_stocks('000300.XSHG','2022-10-01')
log.info(stocks)
print('--------------------------获取股票行情数据--------------------------------')

print('------------SecurityUnitData基本属性----------------')
'''
open:时间段开始价格
close:时间段结束时价格
low:最低价
high:最高价
volume:成交的股票数量
money:成交的金额
factor:前复权因子
avg:这段时间的平均价
pre_close:前一个单位时间结束时的价格
paused:这只股票是否停牌,1代表停牌,0代表未停牌
'''


'''history()与attribute_history()的区别应该在于,前者可以获取多只股票的某一项数据,而后者可以获取单只股票的多项数据'''


print('------------------history函数-------------------')
'''history()函数用于获取历史数据,可查询多个标的单个数据字段,返回数据格式为DataFrame数据表或字典

history(count, unit='1d', field='avg', security_list=None, df=True, skip_paused=False, fq='pre')
· count是一个数字,指定要返回的行数
· unit表示单位时间长度,几天或者几分钟,1天就是1d,1分钟就是1m,不论是按天还是按分钟回测,都能拿到这两种单位的数据,
需要注意的是,当数字大于1时,field仅支持['open', 'close', 'high', 'low', 'volume', 'money']这几个标准字段
· security_list表示要获取数据的股票列表,如果参数的值为None,表示查询context,universe中所有股票的数据,
contex.universe需要用set_universe来指定,比如set_universe(['000002.xshe','000006.XSHE'])
· df参数值为True时,返回[pandas.DataFrame],False则返回一个dict字典
当返回字典时,股票代码会作为键,numpy数组会作为值,对应pandas数据表形式下的每一列
pandas数据表创建和操作速度相对较慢,很多情况并不需要使用,但默认df参数是True,如果回测速度很慢可以考虑将参数设为False
· skip_paused表示是否跳过未交易日期(停牌、未上市或已退市),
如果不跳过,则停牌时会使用停牌前的数据进行填充,(具体请看SecurityUnitData的paused属性),上市前或退市后,数据都为nan
skip_paused参数默认为False,如果跳过,则行索引不再是日期,因为不同股票的交易日期可能不一样
· 复权选项(对股票/基金的价格字段、成交量字段及factor字段生效):
’pre‘:前复权,(根据'use_real_price'选项不同含义会有所不同, 参见[set_option]), 默认是前复权
'None':不复权,返回实际价格
'post':返回后复权


'''
#history()函数示例
a=history(10,unit='1d',field='open',security_list=['002202.XSHE','000002.XSHE'],df=True,skip_paused=False,fq='pre')
print(a)
#或者
p=history(2, '1d', 'open',['002202.XSHE','000002.XSHE'])
print(p)
'''
2022-01-29 00:00:00 - INFO  -             002202.XSHE  000002.XSHE
2022-01-17        14.65        19.45
2022-01-18        14.78        19.73
2022-01-19        14.88        20.53
2022-01-20        14.69        20.71
2022-01-21        14.70        20.64
2022-01-24        14.36        20.33
2022-01-25        14.55        20.34
2022-01-26        14.25        19.76
2022-01-27        14.63        19.33
2022-01-28        14.47        19.40'''
#如果设置df参数为False,即返回字典dict,返回的数据如下:
'''
2022-01-29 00:00:00 - INFO  - {'002202.XSHE': array([14.65, 14.78, 14.88, 14.69, 14.7, 14.36, 14.55, 14.25, 14.63,
       14.47]), '000002.XSHE': array([19.45, 19.73, 20.53, 20.71, 20.64, 20.33, 20.34, 19.76, 19.33,
       19.4])}'''

#返回过去5天的平均价(暂时没明白什么是平均价)
p=history(5, security_list=['000001.XSHE', '000002.XSHE'])

h['000001.XSHE'][-1] #000001(平安银行)昨天(数组最后一项)的平均价
h.iloc[-1] #所有股票在昨天的平均价, 一个pd.Series对象, index是股票代号
h.iloc[-1]['000001.XSHE'] #000001(平安银行)昨天(数组最后一项)的平均价
h.mean() # 取得每一列的平均值

## set_universe 之后可以,调用 history 可以不用指定 security_list
set_universe(['000001.XSHE']) # 设定universe
history(5) # 获取universe中股票的过去5天(不包含今天)的每天的平均价
history(5, '1m') # 获取universe中股票的过去5分钟(不包含当前分钟)的每分钟的平均价
print('---------------attribute_history()函数----------------')
'''attribute_history()可用来获取历史数据,可查询单个标的多个数据字段,返回数据格式为DataFrame数据表或字典Dict
attribute_history(security,count,unit='1d',fileds=['open','close','high','low','volume','money'],skip_paused=True,df=True,fq='pre')
security表示股票代码,count指定返回集的行数
查看某只股票的历史数据,可以选这只股票的多个属性,默认跳过停牌日期
当取天数据时,不包括当天的,即使实在停盘后;分钟数据不包括当前分钟的数据,没有未来;
'''
#获取平安银行前3天(大前天、前天和昨天)的开盘价、收盘价以及成交量
p=attribute_history(security='000001.XSHE',count=3,fields=['open','close','volume'])
print(p)
'''
2022-10-21 09:30:00 - INFO  -              open  close      volume
2022-10-18  11.55  11.48  94683709.0
2022-10-19  11.42  11.29  92398968.0
2022-10-20  11.23  11.20  78192323.0'''
print('----------------------------Pandas.DataFrame--------------------')
'''这是一种二维表结构的功能强大的数据类型,常用于数据处理与分析
DataFrame是一个二维表,包括index(行标签、索引)、columns(列标签)、values(值)这3个部分
聚宽系统已自动加载,所以不需要手动import'''
''假设t表示一张数据表'''
#获取数据表的index
print(t.index)
'''返回结果是datatimeindex类型,特殊不常用并且建议新手回避:
DatetimeIndex(['2016-08-30', '2016-08-31', '2016-09-01'], dtype='datetime64[ns]', freq=None, tz=None)'''

#获取clolumns
print(t.columns)    #Index([u'money', u'high', u'open'], dtype='object')

#可以通过list()函数将获取的index转换成list
print(list(t.columns))

#获取values
print(t.values)
'''返回结果是一个嵌套的list
  # [[  5.61854066e+08   9.33000000e+00   9.29000000e+00]
  # [  4.63875763e+08   9.36000000e+00   9.32000000e+00]
  # [  4.54848634e+08   9.38000000e+00   9.35000000e+00]]'''

print('---选择DataFrame某几列---')
#按标签获取列
print(t.loc[:,['open','close','列标签']])
'''
  # 结果如下
  #             open  high
  # 2016-08-29  9.28  9.31
  # 2016-08-30  9.29  9.33
  # 2016-08-31  9.32  9.36'''


#按位置获取某几列
print(t.iloc[:,[0:2]])  #[0:2]表示位置,从0开始(不包含2?)
'''  #                    money  open
  # 2016-08-29  5.322954e+08  9.28
  # 2016-08-30  5.618541e+08  9.29
  # 2016-08-31  4.638758e+08  9.32'''

#英文冒号【:】代表全部,loc或iloc都能适用
print(t.iloc[:,:])
'''
  #                    money  high  open
  # 2016-08-29  5.322954e+08  9.31  9.28
  # 2016-08-30  5.618541e+08  9.33  9.29
  # 2016-08-31  4.638758e+08  9.36  9.32'''

#返回后的数据依然是DataFrame类型,用.values可以获取数据
print(t.iloc[:,[0:2]].values)
'''
  # 结果如下,是个list
  # [[  5.61854066e+08   9.29000000e+00]
  # [  4.63875763e+08   9.32000000e+00]
  # [  4.54848634e+08   9.35000000e+00]]'''


print('''------选择DataFrame某几行------''')
#按标签获取某几行
print(t.loc[['2016-08-29','2016-08-31'],:])
'''这样的写法会报错,原因是当前的行标签类型是DataFrameTimeIndex,并非字符串,因此使用标签名时要注意数据类型。
时间类型的处理往往比较麻烦,因此行标签或列标签是时间类型的情况建议新手回避,改用位置获取'''

#按位置获取某几行
print(t.iloc[[0,2],:])
# 结果如下
#                    money  high  open
# 2016-08-29  5.322954e+08  9.31  9.28
# 2016-08-31  4.638758e+08  9.36  9.32

'''英文冒号【:】表示全部'''
print(t.iloc[:,:])
# 结果如下
#                    money  high  open
# 2016-08-29  5.322954e+08  9.31  9.28
# 2016-08-30  5.618541e+08  9.33  9.29
# 2016-08-31  4.638758e+08  9.36  9.32


#DataFrame行列转置(行转换成列,列转换成行),方法是.T
print(t.T)
# 结果如下
#          2016-08-29    2016-08-30    2016-08-31
# money  5.322954e+08  5.618541e+08  4.638758e+08
# high   9.310000e+00  9.330000e+00  9.360000e+00
# open   9.280000e+00  9.290000e+00  9.320000e+00
print('---------------------获取股票单季度/年度财务数据-----------------------')
#具体的使用说明参考聚宽官方文档
#https://www.joinquant.com/help/api/help#Stock:获取单季度年度财务数据
#www.joinquant.com/help/api/help#Stock:财务数据列表

'''财务报表简称财报,是用来向股东汇报企业经营情况的,上市公司必须按季度公布财报,
一年有4个个季度,所以财报发布顺序是:一季报、半年报(中报)、三季报以及年报,
而具体的发布日期并非固定,年报要求年度结束的4个月内披露,半年报是上半年结束的2个月内,一季报与三季报是季度结束的1个月内。
特别的向总市值、市盈率这种跟股价挂钩的市值数据是每天更新的'''

'''获取单季度/年度财务数据用到的API是get_fundamentals()
get_fundamentals(query_object,Date=None,statDate=None)

query_object是一个sqlalchemy.orm.query.Query对象, 可以通过全局的 query 函数获取 Query 对象

date表示查询日期,字符串,格式类似'2020-02-02'或者[datetime.date]/[datetime.datetime]对象,可以是None,使用默认日期,这个默认日期在回测与研究模块上有差别:
在回测模块上,默认值会随着日期的变化而变化,相当于context.current_dt的前一天(因为实际生活中我们只能看见前一天的财报和市值数据,所以要用前一天)
在研究模块上,使用平台财务数据的最新日期,一般是昨天,如果传入的Date不是交易日,则使用这个日期之前的最近一个交易日

statDate表示财报统计的季度或者年份,是一个字符串,有两种格式
季度格式:'年+q+季度序号 ',比如'2019q1'
年度各市:填入年份数字即可,比如'2022'


Date与statDate参数只能选择其中一个,当两个参数都没传入时,默认使用Date数据
· 传入Date时,查询指定日期收盘后所能看到的最近(对市值来说,最后一天,对其他表来说,最近一个季度)的数据,
我们会查找上市公司在这个日期之前(包括此日期)发布的数据,不会有未来函数

· 传入statDate时,查询statDate指定的季度或者年份的财务数据
需要注意的是:由于公司财报发布不及时,一般是看不到当季或年度数据的,回测中使用statDate可能会有未来数据,需要注意规避
由于估值表每日更新,当按季度或者年份查询时,返回季度或者年份最后一天的数据
由于资产负债数据这个表示存量性质的,查询年度数据是返回第四季度的数据
银行业、保险、券商只有年报数据,需传入statDate参数,当传入date数据或statDate的参数为季度时,返回空值,需要注意规避未来函数

get_fundamentals()会返回一个[pandas.DataFrame],每一行对应数据库返回的每一行(可能是几个表的联合查询结果的一行),列索引是你查询的所有字段,
需要注意的是:为了避免返回数据量过大,聚宽每次最多返回1万行;相关股票上市前或退市后,财务数据返回各字段为空
'''
#查询'000002.XSHE'的所有市值数据,时间是2022-02-02
q=query(valuation).filter(valuation.code=='000002.XSHE')
df=get_fundamentals(q,'2022-02-02')
#打印出总市值
log.info(df['market_cap'][0])

#获取多只股票在某一日期的市值与利润
#df=get_fundamentals(query(valuation,income).filter(valuation.code.in_(['000002'.XSHE,'000003'.XSHE])),date='2022-02-02')
df = get_fundamentals(query(
        valuation, income
    ).filter(
        # 这里不能使用 in 操作, 要使用in_()函数
        valuation.code.in_(['000001.XSHE', '600000.XSHG'])
    ), date='2019-10-12')

#query_object参数以及快速上手模板
'''query_object参数是要求传入一个query对象用于描述所需的数据,展开讲述有点麻烦,
一个快速上手的模板可以用来产生query_object参数,多数情况可以用这个模板套'''
#快速上手模板,比较长的话可以分行写
query(表.字段).filter(筛选条件).order_by(排序方法).limt(数量上限)

'''筛选条件跟if条件判断时用的条件一样,多个条件用逗号隔开代表 与(and )的关系,
要用到复杂的与或非的逻辑关系时,在此处and、or、not是不能用的,要对应的改用【&】【|】【~】

排序的写法比较简单,就是要作为排序标准的字段后面加.desc()即由大到小,或.asc()即有小到大

数量上限可以自己设置,代表最多返回的数据条数,但聚宽限制最多返回1万行'''
# 例子
# 获取 市值表.股票代码,资产负债表.未分配利润
q = query(valuation.code, balance.retained_profit
          # 筛选 市值大于100 并且 市盈率小于10
          ).filter(valuation.market_cap > 100, valuation.pe_ratio < 10
                   # 排序 按市值从大到小排
                   ).order_by(valuation.market_cap.desc()
                              # 数量 上限10条数据
                              ).limit(10)
w = get_fundamentals(q)
print(w)

# 结果如下:
#           code  retained_profit
# 0  601398.XSHG     8.566400e+11
# 1  601939.XSHG     7.400340e+11
# 2  601288.XSHG     4.644490e+11
# 3  601988.XSHG     5.267460e+11
# 4  600036.XSHG     1.816520e+11
# 5  601328.XSHG     9.208500e+10
# 6  600000.XSHG     1.037620e+11
# 7  600016.XSHG     1.277570e+11
# 8  601166.XSHG     1.573490e+11
# 9  601998.XSHG     1.298680e+11

发表回复