选股器
大约 9 分钟
market_scanner 选股器
说明
通过不同的技术指标条件来扫描全市场行情,帮助您筛选出满足特定投资需求的标的列表。
技术指标条件包含如下几类:基础指标、累积指标、财务指标,多标签指标,具体参数含义请参考下面的说明。
参数
参数 | 类型 | 是否必填 | 说明 |
---|---|---|---|
market | tigeropen.common.consts.Market | Yes | US 美股,SG 新股,HK港股 |
filters | list[StockFilter] | Yes | 过滤器列表,共有四类,见下方说明 |
sort_field_data | tigeropen.quote.domain.filter.SortFilterData | No | 排序字段对象,主要属性,如下所示 |
∟ field | enum | No | 排序字段, tigeropen.common.consts.filter_fields 中的字段枚举, 如 StockField, AccumulateField |
∟ sort_dir | tigeropen.common.consts.SortDirection | No | 排序方向,包括:不排序,升序,降序 |
page | int | No | 当前页码(从0开始) |
page_size | int | No | 每页返回的数据量,最大支持配置成:200 |
StockFilter 参数说明:
参数 | 类型 | 是否必填 | 说明 |
---|---|---|---|
field | tigeropen.common.consts.filter_fields.FilterField | Yes | 共四类 field,见下方说明 |
filter_min | float | No | 区间下限(闭区间),不传代表下限为 -∞ 如果为百分位数,不需要加%,例如10%,数值为10即可 |
filter_max | float | No | 区间上限(闭区间),不传代表上限为 +∞ |
is_no_filter | bool | No | 是否禁用本Filter,如果为True,则本过滤器不生效 |
accumulate_period | tigeropen.common.consts.filter_fields.AccumulatePeriod | No | 累计周期枚举,仅当field为 AccumulateField 时需要指定 |
financial_period | tigeropen.common.consts.filter_fields.FinancialPeriod | No | 财务周期枚举,仅当field为 FinancialField 时需要指定 |
tag_list | list[int|str] | No | 标签列表,仅当field为MultiTagField时需要指定 |
StockFilter 的field字段有如下枚举类型 (导入路径 tigeropen.common.consts.filter_fields
)
类型 | 说明 |
---|---|
StockField | 简单指标筛选条件,包括价格(高开低收,最新价等),成交量,股本,市值,涨跌幅,市盈率,换手率等因子。筛选字段含义说明: 筛选字段说明 |
AccumulateField | 累积指标筛选条件,包括累积涨跌幅,资产增长率,净利润增长率,每股收益,净利润,营业利润,营业收入,ROA(净资产收益率),经营现金流,资产负债率等。累积指标周期可以是:近五分钟,近5日,10日,20日,近半年,一年,两年,五年,一季度报,三季度报,中报等等。筛选字段含义说明:筛选字段说明 |
FinancialField | 财务指标筛选条件,包括毛利,净利率,总负债/股东权益,总负债/总资产,流动比率,资产回报率,净利润,经营现金流,总资产,港股通净买入额,年化收益率等等。财务指标目前只支持LTM(最近12个月的年报指标)类型的财报查询。筛选字段含义说明:筛选字段说明 |
MultiTagField | 多标签关联关系筛选条件,基于行业,概念,历史股价新高(当天股价和历史价格相比),52周内股价新高(当天股价和最近52周相比),是否为OTC,是否支持期权,股票类型(股票,ETF),是否破发等指标来选股。筛选字段含义说明:筛选字段说明 |
筛选参数中的价格字段对应的币种和该标的所在市场的货币类型保持一致,比如美股:USD,港股:HKD,新股:SGD 等。
返回
tigeropen.quote.domain.filter.ScannerResult
其结构如下:
class ScannerResult:
def __init__(self, page, page_size, total_page, total_count, items):
# 当前页码,从0开始
self.page = page
# 总页数
self.total_page = total_page
# 数据总条数
self.total_count = total_count
# 分页大小
self.page_size = page_size
# 结果数据列表
self.items: ScannerResultItem = list()
# 筛选出的股票symbol列表汇总
self.symbols = list()
# 其中 items 的每项为:
class ScannerResultItem:
def __init__(self, symbol, market, base_data_list=None, accumulate_data_list=None, financial_data_list=None,
multi_tag_data_list=None):
self.symbol = symbol
self.market = market
self.field_data = dict()
# 可使用 filter 作为 key 取出对应filter字段的值, 参加下方示例
示例
from datetime import datetime
from tigeropen.quote.quote_client import QuoteClient
from tigeropen.tiger_open_config import get_client_config
from tigeropen.common.consts import TradingSession, Market
from tigeropen.quote.domain.filter import OptionFilter, StockFilter, SortFilterData
from tigeropen.common.consts.filter_fields import StockField, AccumulateField, FinancialField, MultiTagField, \
FinancialPeriod, AccumulatePeriod
client_config = get_client_config(private_key_path='私钥路径', tiger_id='your tiger id', account='your account')
quote_client = QuoteClient(client_config)
def test_market_scanner():
# 股票基本数据过滤(is_no_filter为True时表示不启用该过滤器)
base_filter1 = StockFilter(StockField.FloatShare, filter_min=1e7, filter_max=1e13, is_no_filter=True)
base_filter2 = StockFilter(StockField.MarketValue, filter_min=1e8, filter_max=1e14, is_no_filter=False)
# 按财报时间过滤
base_filter3 = StockFilter(StockField.EarningDate, filter_min=int(datetime.strptime('2021-01-01', '%Y-%m-%d').timestamp() * 1000),
filter_max=int(datetime.strptime('2023-12-31', '%Y-%m-%d').timestamp() * 1000)
, is_no_filter=False)
# 周期累计数据过滤
accumulate_filter = StockFilter(AccumulateField.ChangeRate, filter_min=0.01, filter_max=1, is_no_filter=False,
accumulate_period=AccumulatePeriod.Last_Year)
# 财务数据过滤
financial_filter = StockFilter(FinancialField.LYR_PE, filter_min=1, filter_max=100, is_no_filter=False,
financial_period=FinancialPeriod.LTM)
# 多标签数据过滤,需要先获取 tag_list, 如果有值则根据情况传值,如果没值则不传 tag_list 参数; 对于布尔类型的字段,一般 tag_list 为空,不需要传值
tags = quote_client.get_market_scanner_tags(market=Market.US, tag_fields=[MultiTagField.OptionsAvailable])
if not tags:
tag_list = []
else:
# 需要根据实际情况,换成想要过滤的tag, 如field 为 MultiTagField.Industry 时, tag_list = ['BK4209']
tag_list = ['BK4209']
multi_tag_filter = StockFilter(MultiTagField.isOTC, tag_list=tag_list)
# 排序字段
sort_field_data = SortFilterData(StockField.FloatShare, sort_dir=SortDirection.ASC)
# 请求的开始页码
begin_page = 0
page_size = 50
# 是否为最后一页数据
is_last_page = False
# 筛选后的symbol列表
scanner_result_symbols = set()
while not is_last_page:
# filters参数里填需要使用的过滤器
result = quote_client.market_scanner(market=Market.US,
filters=[base_filter1, base_filter2,
# base_filter3,
accumulate_filter,
financial_filter,
multi_tag_filter],
sort_field_data=sort_field_data,
page=begin_page,
page_size=page_size)
print(result)
if result.total_page:
for item in result.items:
# item的类型为 ScannerResultItem
symbol = item.symbol
market = item.market
# 可以字典的形式获取某个filter的字段对应的值
base_filter1_value = item[base_filter1]
accumulate_filter_value = item[accumulate_filter]
print(
f'page:{result.page}, symbol:{symbol}, base_filter1 value:{base_filter1_value}, accumulate_filter value:{accumulate_filter_value}')
print(f'current page symbols:{result.symbols}')
scanner_result_symbols.update(result.symbols)
time.sleep(1)
# 处理分页
if result.page >= result.total_page - 1:
is_last_page = True
else:
begin_page = result.page + 1
print(f'scanned symbols:{scanner_result_symbols}')
返回示例
ScannerResult({'page': 0, 'total_page': 208, 'total_count': 1040, 'page_size': 5,
'items': [
ScannerResultItem({'symbol': 'DNP', 'market': 'US',
'field_data': {
<StockField.FloatShare: 13>: 0.0,
<StockField.MarketValue: 17>: 3855828898.39,
<AccumulateField.ChangeRate: 1>: 0.043925,
<FinancialField.LYR_PE: 45>: 7.359675,
<MultiTagField.isOTC: 3>: '0'}}),
ScannerResultItem({'symbol': 'FEN', 'market': 'US',
'field_data': {
<StockField.FloatShare: 13>: 0.0,
<StockField.MarketValue: 17>: 278571284.64,
<AccumulateField.ChangeRate: 1>: 0.063893,
<FinancialField.LYR_PE: 45>: 6.45728,
<MultiTagField.isOTC: 3>: '0'}}),
ScannerResultItem({'symbol': 'FDUS', 'market': 'US',
'field_data': {
<StockField.FloatShare: 13>: 0.0,
<StockField.MarketValue: 17>: 462844356.0,
<AccumulateField.ChangeRate: 1>: 0.079202,
<FinancialField.LYR_PE: 45>: 3.986464,
<MultiTagField.isOTC: 3>: '0'}}),
ScannerResultItem({'symbol': 'KYN', 'market': 'US',
'field_data': {
<StockField.FloatShare: 13>: 0.0,
<StockField.MarketValue: 17>: 1181621680.4,
<AccumulateField.ChangeRate: 1>: 0.122898,
<FinancialField.LYR_PE: 45>: 3.268946,
<MultiTagField.isOTC: 3>: '0'}}),
ScannerResultItem({'symbol': 'TYG', 'market': 'US',
'field_data': {
<StockField.FloatShare: 13>: 0.0,
<StockField.MarketValue: 17>: 381692896.0,
<AccumulateField.ChangeRate: 1>: 0.180812,
<FinancialField.LYR_PE: 45>: 2.853998,
<MultiTagField.isOTC: 3>: '0'}})],
'symbols': ['FEN', 'DNP', 'FDUS', 'KYN', 'TYG']})
示例1 筛选股息率大于 5%, 营收3年复合增长率大于 10% 的股票
from tigeropen.quote.quote_client import QuoteClient
from tigeropen.tiger_open_config import get_client_config
from tigeropen.common.consts import TradingSession
from tigeropen.quote.domain.filter import OptionFilter, StockFilter, SortFilterData
from tigeropen.common.consts.filter_fields import StockField, AccumulateField, FinancialField, MultiTagField, \
FinancialPeriod, AccumulatePeriod
client_config = get_client_config(private_key_path='私钥路径', tiger_id='your tiger id', account='your account')
quote_client = QuoteClient(client_config)
def test_market_scanner1():
# 股息率大于 5%
base_filter = StockFilter(StockField.DivideRate, filter_min=0.05)
# 营业收入三年增长率 或者叫 营收3年复合增长率
financial_filter = StockFilter(FinancialField.TotalRevenues3YrCagr, filter_min=0.1)
# 请求的开始页码
begin_page = 0
page_size = 50
# 是否为最后一页数据
is_last_page = False
# 筛选后的symbol列表
scanner_result_symbols = set()
while not is_last_page:
# filters参数里填需要使用的过滤器
result = quote_client.market_scanner(market=Market.US,
filters=[
base_filter,
financial_filter,
],
page=begin_page,
page_size=page_size)
print(result)
if result.total_page:
for item in result.items:
symbol = item.symbol
market = item.market
# 可以字典的形式获取某个filter的字段对应的值
base_filter_value = item[base_filter]
financial_filter_value = item[financial_filter]
print(
f'page:{result.page}, symbol:{symbol}, base_filter value:{base_filter_value}, financial_filter value:{financial_filter_value}')
print(f'current page symbols:{result.symbols}')
scanner_result_symbols.update(result.symbols)
time.sleep(1)
# 处理分页
if result.page >= result.total_page - 1:
is_last_page = True
else:
begin_page = result.page + 1
print(f'scanned symbols:{scanner_result_symbols}')
get_market_scanner_tags
获取多标签关联筛选字段的标签值
说明
获取多标签关联筛选字段的标签值,暂只支持获取行业和概念标签集合。
参数
参数 | 类型 | 是否必填 | 说明 |
---|---|---|---|
market | tigeropen.common.consts.Market | Yes | US 美股,SG 新股,HK港股 |
tag_fields | list[tigeropen.common.consts.filter_fields.MultiTagField] | Yes | 支持的字段枚举值:MultiTagField.Industry,MultiTagField.Concept |
返回
list. 其中每一项如下
字段 | 类型 | 说明 |
---|---|---|
market | str | 市场代码(US:美股,CN:沪深,HK:港股) |
multi_tag_field | str | 多标签字段 |
tag_list | list[str] | 多标签字段可以用来过滤的标签集合 |
示例
from tigeropen.quote.quote_client import QuoteClient
from tigeropen.tiger_open_config import get_client_config
from tigeropen.common.consts import TradingSession, Market
from tigeropen.common.consts.filter_fields import MultiTagField
client_config = get_client_config(private_key_path='私钥路径', tiger_id='your tiger id', account='your account')
quote_client = QuoteClient(client_config)
field_list = [ MultiTagField.Concept, MultiTagField.Industry]
result = quote_client.get_market_scanner_tags(market=Market.US, fields=field_list)
print(result)
返回示例
[{'market': 'US', 'multi_tag_field': 'MultiTagField_Concept', 'tag_list': [{'tag': 'BK4565', 'value': 'NFT概念'}, {'tag': 'BK4564', 'value': '太空概念'}, {'tag': 'BK4567', 'value': 'ESG概念'}, {'tag': 'BK4566', 'value': '资本集团'}, {'tag': 'BK4568', 'value': '美国抗疫概念'}, {'tag': 'BK4561', 'value': '索罗斯持仓'}, {'tag': 'BK4560', 'value': '网络安全概念'}, {'tag': 'BK4563', 'value': '昨日强势股'}, {'tag': 'BK4562', 'value': 'SPAC上市公司'}, {'tag': 'BK4575', 'value': '芯片概念'}, {'tag': 'BK4578', 'value': 'CAR-T'}, {'tag': 'BK4577', 'value': '网络游戏'}, {'tag': 'BK4570', 'value': '地缘局势概念股'}, {'tag': 'BK4572', 'value': '航空租赁'}, {'tag': 'BK4571', 'value': '数字音乐概念'}, {'tag': 'BK4574', 'value': '无人驾驶'}, {'tag': 'BK4573', 'value': '虚拟现实'}, {'tag': 'BK4543', 'value': 'AI'}, {'tag': 'BK4542', 'value': '充电桩'}, {'tag': 'BK4545', 'value': '锂电池'}, {'tag': 'BK4544', 'value': 'ARK ETF合集'}, {'tag': 'BK4547', 'value': 'WSB热门概念'}, {'tag': 'BK4546', 'value': '3D打印'}, {'tag': 'BK4549', 'value': '软银资本持仓'}, {'tag': 'BK4548', 'value': '巴美列捷福持仓'}, {'tag': 'BK4541', 'value': '氢能源'}, {'tag': 'BK4540', 'value': '固态电池'}, {'tag': 'BK4554', 'value': '元宇宙及AR概念'}, {'tag': 'BK4553', 'value': '喜马拉雅资本持仓'}, {'tag': 'BK4556', 'value': '基因编辑'}, {'tag': 'BK4555', 'value': '新能源车'}, {'tag': 'BK4558', 'value': '双十一'}, {'tag': 'BK4557', 'value': '大麻股'}, {'tag': 'BK4559', 'value': '巴菲特持仓'}, {'tag': 'BK4550', 'value': '红杉资本持仓'}, {'tag': 'BK4552', 'value': 'Archegos爆仓风波概念'}, {'tag': 'BK4551', 'value': '寇图资本持仓'}, {'tag': 'BK4529', 'value': 'IDC概念'}, {'tag': 'BK4528', 'value': 'SaaS概念'}, {'tag': 'BK4521', 'value': '英国银行股'}, {'tag': 'BK4520', 'value': '美国基建股'}, {'tag': 'BK4523', 'value': '印度概念'}, {'tag': 'BK4522', 'value': '非洲概念'}, {'tag': 'BK4525', 'value': '远程办公概念'}, {'tag': 'BK4524', 'value': '宅经济概念'}, {'tag': 'BK4527', 'value': '明星科技股'}, {'tag': 'BK4526', 'value': '热门中概股'}, {'tag': 'BK4539', 'value': '次新股'}, {'tag': 'BK4532', 'value': '文艺复兴科技持仓'}, {'tag': 'BK4531', 'value': '中概回港概念'}, {'tag': 'BK4534', 'value': '瑞士信贷持仓'}, {'tag': 'BK4533', 'value': 'AQR资本管理(全球第二大对冲基金)'}, {'tag': 'BK4536', 'value': '外卖概念'}, {'tag': 'BK4535', 'value': '淡马锡持仓'}, {'tag': 'BK4538', 'value': '云计算'}, {'tag': 'BK4537', 'value': '激光雷达概念'}, {'tag': 'BK4530', 'value': '医药外包概念'}, {'tag': 'BK4507', 'value': '流媒体概念'}, {'tag': 'BK4506', 'value': '内地教育股'}, {'tag': 'BK4509', 'value': '腾讯概念'}, {'tag': 'BK4508', 'value': '社交媒体'}, {'tag': 'BK4501', 'value': '段永平概念'}, {'tag': 'BK4500', 'value': '航空公司概念'}, {'tag': 'BK4503', 'value': '景林资产持仓'}, {'tag': 'BK4502', 'value': '阿里概念'}, {'tag': 'BK4505', 'value': '高瓴资本持仓'}, {'tag': 'BK4504', 'value': '桥水持仓'}, {'tag': 'BK4518', 'value': 'OLED概念'}, {'tag': 'BK4517', 'value': '邮轮概念'}, {'tag': 'BK4519', 'value': '光伏太阳能'}, {'tag': 'BK4510', 'value': '在线教育'}, {'tag': 'BK4512', 'value': '苹果概念'}, {'tag': 'BK4511', 'value': '特斯拉概念'}, {'tag': 'BK4514', 'value': '搜索引擎'}, {'tag': 'BK4513', 'value': '直播概念'}, {'tag': 'BK4516', 'value': '特朗普概念'}, {'tag': 'BK4515', 'value': '5G概念'}, {'tag': 'BK4587', 'value': 'ChatGPT概念'}, {'tag': 'BK4589', 'value': 'SVB概念'}, {'tag': 'BK4588', 'value': '碎股'}, {'tag': 'BK4581', 'value': '高盛持仓'}, {'tag': 'BK4580', 'value': '工业 4.0'}, {'tag': 'BK4583', 'value': '猴痘概念'}, {'tag': 'BK4582', 'value': 'ESG ETF-MSCI'}, {'tag': 'BK4585', 'value': 'ETF&股票定投概念'}, {'tag': 'BK4584', 'value': '避孕概念'}]}]