joinquant : 通过query获取申万各级指数行情、估值等数据

79 篇文章 6 订阅
79 篇文章 13 订阅

获取申万各级指数的行情、估值数据

import finance from jqdatasdk
import jqdatasdk as jq 
def get_sw_quote(index_code,startday,endday):
    '''获取指定日期的申万指数列表--行情'''
    q =  jq.query(finance.SW1_DAILY_PRICE).filter(
            finance.SW1_DAILY_PRICE.code==index_code,
            finance.SW1_DAILY_PRICE.date >=startday,
            finance.SW1_DAILY_PRICE.date < endday)
    df = finance.run_query(q)
    return df
    
    #df = get_sw_quote('801010','2019-02-05','2019-08-09')
        
    def get_sw_valuation_quote(index_code,startday,endday):
        '''获取指定日期的申万指数列表---估值行情'''
        q =  jq.query(finance.SW1_DAILY_VALUATION).filter(
                finance.SW1_DAILY_VALUATION.code==index_code,
                finance.SW1_DAILY_VALUATION.date >=startday,
                finance.SW1_DAILY_VALUATION.date < endday)
        df = finance.run_query(q)
        return df

#参数:
#query(finance.SW1_DAILY_PRICE):表示从finance.SW1_DAILY_PRICE这张表中查询申万一级行业指数的历史日行情数据,还可以指定所要查询的字段名,格式如下:query(库名.表名.字段名1,库名.表名.字段名2),多个字段用英文逗号分隔进行提取;如query(finance.SW1_DAILY_PRICE.code)。query函数的更多用法详见:query简易教程。
#finance.SW1_DAILY_PRICE:代表申万一级行业日行情数据表,收录了申万一级行业指数的历史日行情数据,表结构和字段信息如下:

#date 交易日 date N  
#code 指数编码 varchar(12) N 对应申万一级行业指数编码 
#name 指数名称 varchar(20) N  
#open 开盘指数 decimal(20,4)   
#high 最高指数 decimal(20,4)   
#low 最低指数 decimal(20,4)   
#close 收盘指数 decimal(20,4)   
#pre_close 昨收盘指数 decimal(20,4)  昨收盘指数用昨日的收盘指数填充 
#volume 成交量 decimal(20,4)  单位:股 
#money 成交额 decimal(20,4)  单位:元 
#change_pct 涨跌幅 decimal(10,4)  单位:% 
#filter(finance.SW1_DAILY_PRICE.code==801010):指定筛选条件,通过finance.SW1_DAILY_PRICE.code==801010可以查询指定行业(如农林牧渔801010)的日行情数据;除此之外,还可以对表中其他字段指定筛选条件,如finance.SW1_DAILY_PRICE.date=='2019-03-01',指定获取2019年3月1日的申万一级行业日行情数据。
#limit(n):限制返回的数据条数,n指定返回条数。

#
#返回结果:
#返回一个 dataframe,每一行对应数据表中的一条数据, 列索引是您所查询的字段名称

#记录了申万一级行业指数的每日估值数据,每天18:00更新。

#参数:
#query(finance.SW1_DAILY_VALUATION):表示从finance.SW1_DAILY_VALUATION这张表中查询申万一级行业指数的估值数据,还可以指定所要查询的字段名,格式如下:query(库名.表名.字段名1,库名.表名.字段名2),多个字段用英文逗号分隔进行提取;如query(finance.SW1_DAILY_VALUATION.code)。query函数的更多用法详见:query简易教程。
#finance.SW1_DAILY_VALUATION:代表申万一级行业指数估值表,收录了申万一级行业指数的历史估值数据,表结构和字段信息如下:

#date 交易日 date N  
#code 指数编码 varchar(12) N 对应申万一级行业指数编码 
#name 指数名称 varchar(20) N  
#turnover_ratio 换手率 decimal(10,4)  单位:% 
#pe 市盈率 decimal(20,4)  单位:倍;PE = 流通市值/最近4个季度的净利润;最近 4 个季度的净利润按如下方法计算: 1-4 月,最近 4 个季度的净利润=上一年度前 3 季度累计净利润+上上一年度的四季度净利润;5-8 月,最近 4 个季度的净利润=当年 1 季度净利润+前 1 年净利润-前 1 年 1 季度净利润;9-10 月,最近 4 个季度的净利润=当年中期净利润+前 1 年净利润-前 1 年中期净利润;11-12 月,最近 4 个季度的净利润=当年前 3 季度累计净利润+上1年年度净利润-上 1 年前 3 季度累计净利润 
#pb 市净率 decimal(20,4)  单位:倍;按照自由流通量加权的净资产倍率。 PB = 流通市值/按照流通市值计算的净资产;按照流通市值计算的净资产 = 最新净资产*流通股本/总股本 
#average_price 均价 decimal(20,4)  单位:元。指数成份股在统计期最后交易日收盘的简单算术平均价 
#money_ratio 成交额占比 decimal(10,4)  单位:%;成交额占比=某个行业成交额/所有行业成交额之和 
#circulating_market_cap 流通市值 decimal(20,4)  单位:元 
#average_circulating_market_cap 平均流通市值 decimal(20,4)  单位:元;平均流通市值=流通市值/所在行业股票数 
#dividend_ratio 股息率 decimal(10,4)  单位:%;按照自由流通量加权的现金股息率;dividend_ratio=Df/Vf;Df: 所有股票在截止日的一 个自然年(365日)中所累积派发的税前现金红利之和按照流通股本对应的分红量;Vf: 该行业成分股股的流通市值之和 
#filter(finance.SW1_DAILY_VALUATION.code==801010):指定筛选条件,通过finance.SW1_DAILY_VALUATION.code=='801010'可以查询指定行业(如农林牧渔801010)的估值数据;除此之外,还可以对表中其他字段指定筛选条件,如finance.SW1_DAILY_VALUATION.date=='2019-03-01',指定获取2019年3月1日的申万一级行业的估值数据。
#limit(n):限制返回的数据条数,n指定返回条数。

#
#返回结果:
#返回一个 dataframe,每一行对应数据表中的一条数据, 列索引是您所查询的字段名称
#
#注意:
#1.为了防止返回数据量过大, 我们每次最多返回3000行
#2.不能进行连表查询,即同时查询多张表的数据

查询 000001 2015 - 2017 年的整张合并利润表,且满足 net_profit(净利润) < 0 的条件

from jqdata import finance
q = query(finance.STK_INCOME_STATEMENT).filter(
        finance.STK_INCOME_STATEMENT.code=='000783.XSHE',              #选定股票  000783.XSHE
        finance.STK_INCOME_STATEMENT.end_date > '2005-01-01',          #指定查询时间段大于2005年1月1日
        finance.STK_INCOME_STATEMENT.end_date < '2018-01-01',          #指定查询时间段小于2018年1月1日
        finance.STK_INCOME_STATEMENT.net_profit <0,                    #指定查询到的数据中net_profit为负
        finance.STK_INCOME_STATEMENT.report_type == 0,                 #指定报告期类型为本期
        ).order_by(finance.STK_INCOME_STATEMENT.end_date.desc()  ).limit(5)   #根据end_date降序排序,并返回前5条数据 
finance.run_query(q)

查询平安银行2014年3-6月份的单季度报表

q = query(
      income.statDate,
      income.code,
      income.basic_eps,
      cash_flow.goods_sale_and_service_render_cash
  ).filter(
      income.code == '000001.XSHE',
  )

ret = get_fundamentals(q, statDate='2014q2')
ret

查询平安银行2014年的年报

q = query(
      income.statDate,
      income.code,
      income.basic_eps,
      cash_flow.goods_sale_and_service_render_cash
  ).filter(
      income.code == '000001.XSHE',
  )

ret = get_fundamentals(q, statDate='2014')
ret


# 查询平安银行2014年四个季度的季报, 放到数组中并拼接为dataframe
    
        q = query(
              income.statDate,
              income.code,
              income.basic_eps,
              balance.cash_equivalents,
              cash_flow.goods_sale_and_service_render_cash
          ).filter(
              income.code == '000001.XSHE',
          )
        
        rets = [get_fundamentals(q, statDate='2014q'+str(i)) for i in range(1, 5)]
        import pandas as pd
        pd.concat(rets)

in_ 判断某个字段的值是否在列表之中(一般用于查询多个标的)¶

stocks = ['000001.XSHE','600741.XSHG','600507.XSHG']
q = query(balance.code,balance.pubDate,balance.statDate,    # 指定返回的字段只包括code,pubDate,statDate,total_assets及total_sheet_owner_equities
          balance.total_assets,balance.total_sheet_owner_equities).filter(
             balance.code.in_(stocks)   #指定查询到的数据只包括code在 stocks中的数据
            )
get_fundamentals(q,date='2018-01-05')    #查询单季度数据中在2018-01-05之前发布的数据,没有未来函数

distinct 去重,用于查看数据库中某个字段都存在哪些值¶

#  查看十大流通股东中都有哪些类别
from jqdata import finance
q = query(
         finance.STK_SHAREHOLDER_FLOATING_TOP10.shareholder_class_id.distinct(),  #提取ID不同的数据
    finance.STK_SHAREHOLDER_FLOATING_TOP10.shareholder_class,
         ).order_by(finance.STK_SHAREHOLDER_FLOATING_TOP10.change_reason_id)  
df = finance.run_query(q)
df.tail()

~ 反向查询符号
q = query(
         finance.STK_SHAREHOLDER_FLOATING_TOP10.shareholder_class_id.distinct(),
    finance.STK_SHAREHOLDER_FLOATING_TOP10.shareholder_class,
         ).filter(
    ~finance.STK_SHAREHOLDER_FLOATING_TOP10.shareholder_class_id.in_(['307007','307001']),#等同于notin_
    )
finance.run_query(q)

运算和命名(label)

# label的作用是命名获得数据的标签,一般用于直接运算后的重命名
q = query(indicator.code.label('股票代码'),
        indicator.operating_profit.label('get_operating_profit'),
         (income.total_operating_revenue - income.total_operating_cost).label('my_operating_profit')
         ).filter(indicator.code=='600507.XSHG')
get_fundamentals(q)

or_ 或查询¶

from sqlalchemy.sql.expression import or_
get_fundamentals(query(
          valuation.code
      ).filter(
          or_(valuation.market_cap < 10,valuation.pe_ratio > 1000))).tail()  # 查询当天总市值小于1000亿或pe大于10亿的所有股票

contains/like/ilike 数据库中的字符串模糊匹配

•% 百分号通配符: 表示任何字符出现任意次数(可以是0次).


•_ 下划线通配符:表示只能匹配单个字符,不能多也不能少,就是一个字符.






from jqdata import finance
# 获取000001.XSHG每一年的年报   
df = finance.run_query(query(finance.FINANCE_INCOME_STATEMENT
                       ).filter(finance.FINANCE_INCOME_STATEMENT.code.in_(['000001.XSHE']),
#                 finance.FINANCE_INCOME_STATEMENT.end_date.like('%-12-31%'),    #sqlalchemy的版本,数据库的构建等问题可能导致查询报错,可以换以下两种方法尝试
#               finance.FINANCE_INCOME_STATEMENT.end_date.contains('12-31') ,    
              finance.FINANCE_INCOME_STATEMENT.end_date.ilike('_____12-31'),
                finance.FINANCE_INCOME_STATEMENT.report_type==0
                               ))

df.tail()

简化计算的方法(sqlalchemy.sql.func) 和 group_by

func中的函数可以完成常用的一些计算,配合group_by完成简单的统计
 下边以简单计算股票池/全市场每天的的等权重pe,pb为例
(当然,这个计算中一些细节并没有考虑到,实际还是以官方数据为准,可以通过聚源数据获取,具体下边会有演示)





from sqlalchemy.sql import func
from jqdata import finance
stocks = get_index_stocks('000016.XSHG')
q = query(valuation.day,
#           func.count('*'),       # 信息条数(也就是股票数量)
          (func.count()/func.sum(1/valuation.pe_ratio)).label('avg_pe'),  # 等权重pe
          (func.count()/func.sum(1/valuation.pb_ratio)).label('avg_pb'),  # 等权重pb
         ).group_by(valuation.day
                   ).filter(
    valuation.pe_ratio>0,   #排除亏损的
    valuation.pb_ratio>0,   
    valuation.day>'2009-12-01',  #设置一个时间
    valuation.code.in_(stocks)   #设置股票池,注释即为全市场
    )
df = finance.run_query(q)
df.set_index('day',inplace=True)
df.tail()

获取旧的申万指数列表和新的申万指数列表(14年有过改动)

from jqdata import *
def get_sw_quote(day=None):
    '''获取指定日期的申万指数列表'''
    day = get_trade_days(end_date=day,count=1)[-1]
    df = jy.run_query(query(
         jy.QT_SYWGIndexQuote.InnerCode.distinct().label('InnerCode')).filter(
        jy.QT_SYWGIndexQuote.TradingDay==day,
        ))
    code_df = jy.run_query(query(
         jy.SecuMain.SecuCode,jy.SecuMain.ChiName
        ).filter(
        jy.SecuMain.InnerCode.in_(df.InnerCode)))
    return code_df
df = get_sw_quote('2013-02-05')
df.tail()

查询申万行情( 包含行业pe/pb)¶

from jqdata import jy
from jqdata import *
import pandas as pd
#注意申万指数在2014年有一次大改,聚源使用的是为改变之前的代码,官网包含更改前和更改后的代码,如果遇到找不到的标的可以根据需求自行查找
#如801124 >>801121食品加工II
def get_sw_quote(code,end_date=None,count=None,start_date=None):
    '''获取申万指数行情,返回panel结构'''
    if isinstance(code,str):
        code=[code]
    days = get_trade_days(start_date,end_date,count)
    code_df = jy.run_query(query(
         jy.SecuMain.InnerCode,jy.SecuMain.SecuCode,jy.SecuMain.ChiName
        ).filter(
        jy.SecuMain.SecuCode.in_(code)))

    df = jy.run_query(query(
         jy.QT_SYWGIndexQuote).filter(
        jy.QT_SYWGIndexQuote.InnerCode.in_(code_df.InnerCode),
        jy.QT_SYWGIndexQuote.TradingDay.in_(days),
        ))
    df2  = pd.merge(code_df, df, on='InnerCode').set_index(['TradingDay','SecuCode'])
    df2.drop(['InnerCode','ID','UpdateTime','JSID'],axis=1,inplace=True)
    return df2.to_panel()

code = get_industries(name='sw_l2').index[:5]
df = get_sw_quote(code,end_date='2018-01-01',count=10)
df.to_frame(False).tail()



def get_zz_quote(code,end_date=None,count=None,start_date=None):
    '''获取中证指数行情,返回panel结构'''
    if isinstance(code,str):
        code=[code]
    code.sort()
    code = [x[:6] for x in code]
    days = get_trade_days(start_date,end_date,count)
    code_df = jy.run_query(query(
         jy.SecuMain.InnerCode,jy.SecuMain.SecuCode,jy.SecuMain.ChiName
        ).filter(
        jy.SecuMain.SecuCode.in_(code)).order_by(jy.SecuMain.SecuCode))
    df = jy.run_query(query(
             jy.QT_CSIIndexQuote).filter(
            jy.QT_CSIIndexQuote.IndexCode.in_(code_df.InnerCode),
            jy.QT_CSIIndexQuote.TradingDay.in_(days),
            ))
    df2  = pd.merge(code_df, df, left_on='InnerCode',right_on='IndexCode').set_index(['TradingDay','SecuCode'])
    df2.drop(['InnerCode','IndexCode','ID','UpdateTime','JSID','OpenInterest','SettleValue','IndexCSIType'],axis=1,inplace=True)
    return df2.to_panel()

panel = get_zz_quote(['000016.XSHG','000001.XSHG'],end_date='2019-01-21',count=10)
panel.ClosePrice.tail()

查询股息率(近12个月)¶

from jqdata import *
def DividendRatio(security_list,end_date,count=1):
    '''查询股息率(日更新)
    输入:股票池,截止日期,获取数量
    输出:panel结构,单位:1'''
    trade_days = get_trade_days(end_date=end_date,count = count)
    security_list.sort()
    secu_list = [x[:6] for x in security_list]
    code_df = jy.run_query(query(
         jy.SecuMain.InnerCode,jy.SecuMain.SecuCode,
    #     jy.SecuMain.ChiName,jy.SecuMain.CompanyCode
        ).filter(
        jy.SecuMain.SecuCode.in_(secu_list),jy.SecuMain.SecuCategory==1).order_by(jy.SecuMain.SecuCode))
    code_df['code'] = security_list
    df = jy.run_query(query(
#         jy.LC_DIndicesForValuation    #得到整表
        jy.LC_DIndicesForValuation.InnerCode,
                jy.LC_DIndicesForValuation.TradingDay,
                 jy.LC_DIndicesForValuation.DividendRatio,
                ).filter(jy.LC_DIndicesForValuation.InnerCode.in_(code_df.InnerCode),
                        jy.LC_DIndicesForValuation.TradingDay.in_(trade_days)
                        ))
    f_df = df.merge(code_df,on='InnerCode').set_index(['TradingDay','code']).drop(['InnerCode','SecuCode'],axis=1)
    panel = f_df.to_panel()
    return panel

securitys =get_index_stocks('399015.XSHE')
date='2018-01-01'
DividendRatio(securitys,date)

获取期货合约的基本信息(合约乘数、商品报价的计数单位、最小变动单位)¶

# lru缓存可以不要,加上后查询相同的合约可以避免重复数据库请求
from fastcache import clru_cache as lru_cache
@lru_cache(maxsize=128)
def future_basic_info(future):
    from jqdata import jy
    from numpy import nan
    import re
    if "9999" in future or "8888" in future:
        match = re.match(r"(?P<underlying_symbol>[A-Z]{1,})", future)
        if not match:
            raise ValueError("未知期货标的:{}".format(future))
        else:
            future = get_dominant_future(match.groupdict()["underlying_symbol"])
        
    q = query(jy.Fut_ContractMain).filter(jy.Fut_ContractMain.ContractCode == future.split(".")[0])
    result = jy.run_query(query_object=q).to_dict("record")
    if result:
        result = result.pop()
        min_point = re.match("(?P<value>^[0-9]+([.]{1}[0-9]+){0,1})", result["LittlestChangeUnit"]).groupdict(nan)["value"]
        return {"ContractUnit": result["CMValue"],
               "PriceScale": float(str(min_point)[:-1] + "1") if float(min_point) < 1 else 1,
               "MinPoint": float(min_point)}
    else:
        return {"ContractUnit": nan,
                "PriceScale": nan,
                "MinPoint": nan}
future_basic_info('IF1801.CCFX')

多个dataframe的合并 (数据拼接) 获取多份财务报表¶

#获取多年的季度度数据

import pandas as pd
def get_more_state_fund(q_object,year_list):
    df_list = []
    for year in year_list:
        rets = [get_fundamentals(q, statDate=str(year)+'q'+str(i)) for i in range(1, 5)]
        df = pd.concat(rets).set_index('statDate')  #个人习惯
        df_list.append(df)
    df_ = pd.concat(df_list,keys=year_list,axis=0) #axis=1或axis=0,依据个人习惯
    return df_

q = query(
    indicator.code,
      indicator.statDate,
    indicator.roe,
    indicator.inc_return,
    indicator.pubDate,
  ).filter(
      income.code.in_(['000001.XSHE','600507.XSHG']))
df = get_more_state_fund(q,['2017','2018'])
# df.loc[('2014',slice(None))]
df

#h获取多个年度财务数据

 import pandas as pd
    stock_list=['000001.XSHE','000527.XSHE','600970.XSHG','600875.XSHG','600880.XSHG']
    years = range(2005,2018)
    df_list=[]
    for year in years:
        df_year= get_fundamentals(query(
                 indicator.code, indicator.inc_return,indicator.roe
               ).filter(
                 indicator.code.in_(stock_list)
               ),statDate=year).set_index('code')
        df_list.append(df_year)
    name = [str(x) for x in range(2005,2017)]
    df=pd.concat(df_list,axis=1,keys=name)
    df
  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
## 讲师介绍: 近 5 年个人投资理财年化收益平均超 25%。如果你也想提升自己的睡后收入,轻松赚钱,那么这门课就是为你量身打造。课程基于一个完整真实的量化交易业务来讲授,并融入老师的理财经验以及使用编程技术辅助投资的技巧,让你面对各种复杂投资情况也能做到游刃有余。 ## 学习目标: 从不懂“理财”开始到实现自动交易,成为一个“技术流”理财高手 编程技术 + 核心量化策略 + 交易系统开发 + 讲师经验分享,学会用技术辅助理财 本课程从最基础的什么是量化开始讲起,即使对投资理财不了解同样可以学习,轻松入门无压力。 从如何获取数据开始,到实现实盘交易,课程对量化交易的每一步都进行细致讲解,为你铺开量化交易的每一个细节。 不仅仅只是教你学会使用某种工具,更会教给你量化交易的投资思想,让你面对各种情况都游刃有余。 ## 课程亮点: 设计适合自己并能适应市场的交易策略,才是量化交易的灵魂 课程亲手带你设计并实现两种交易策略,快速培养你的策略思维能力 1. 择时策略:通过这个策略学会如何利用均线,创建择时策略,优化股票买入卖出的时间点。2. 选股策略:掌握选股策略的核心逻辑,并基于收益率创建动量选股策略,并验证其有效性。 手把手带你打造一个易扩展、更安全、效率更高的量化交易系统 第三方平台大而全,不易扩展,效率还差,信息安全也是大问题,打造自己的交易平台才是更优解

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值