赞
踩
全文1.8w字,先带大家认识量化交易和量化回测框架,最后带你手把手实现第一个股票策略。
目录
1.1 定义
量化交易(量化投资)是指借助现代统计学和数学(机器学习)的方法,利用计算机技术来进行交易的证券投资方式。
量化交易 从庞大的历史数据中海选能带来超额收益的多种“大概率”事件以制定策略,用数量模型验证及固化这些规律和策略,然后严格执行已固化的策略来指导投资,以求 获得可以持续的、稳定且高于平均收益的超额回报。
1.2 掌握技能
1、分类
关于这三种分类,不用记忆它们的定义。我们课程主要的量化投资方法是市场中性的策略。
2、 三种分类特点以及要求
1、金融专业出生,对金融市场环境非深入了解(交易员、基金经理)
2、基本了解金融基础、投资知识,对数据挖掘、机器学习方法擅长,挖掘股票等的价值 (quanter)
3、非常擅长算法,C/C++ ,编写程序化的一些交易方法 (程序化交易员)
3、 金融产品以及衍生品的常用投资技术
注:比特币不属于衍生品,通常使用的也是趋势策略,少部分使用高频策略
4、 量化交易的优势
1、量化交易全球的发展历史
2、 国内量化交易的发展历史
我们通过一张图来对比国内国外的发展历史
2012年到2016年量化对冲策略管理的资金规模增长了20倍,管理期货策略更是增长了30倍,增长的速度是所有策略中最快的。相比美国量化基金发展历程,中国现在基本处于美国90年代至21世纪之间的阶段。
1、 量化交易研究流程
量化回测框架提供完整的数据,以及回测机制进行策略评估研究,并能够实时进行模拟交易。为实盘交易提供选择。我们的研究一般在回测平台当中做
1.1 分析结果
我们最终想要的结果就是在回测当中表现的较好的分析方法和策略。比如:
1.2 什么是策略
量化策略是指使用计算机作为工具,通过一套固定的逻辑来分析、判断和决策。 量化策略既可以自动执行,也可以人工执行。其实策略也可以理解为,分析数据之后,决策买什么以及交易时间。
1.3 流程包含的内容
2、 量化开发和研究岗位要求
1、 基础回测框架
Zipline本身只支持美国的证券,无法更好的使用数据,本地运行速度慢
2、云端的框架
这些线上平台提供了本地专业版,但是需要收费
3、不去实现一个回测框架的原因
4、RiceQuant回测平台介绍
网址: https://www.ricequant.com/
1、体验创建策略、运行策略流程
1.1 创建策略
1.2 策略界面
2、 策略界面功能、运行介绍
2.1 一个完整的策略需要做的事情
2.2 策略初始设置介绍
关于高级的设置其他部分,在介绍交易函数时介绍
2.3 策略主体运行流程分析
调用的顺序为:
2.4 策略结果分析
回测完成后,在'回测结果'页面会展示回测的仓位、盈亏、交易、风险等信息
1、 数据接口种类
2、 获取行业、板块以及概念股票列表
2.1 关于股票代码以及代码补齐
RiceQuant上的股票代码标记
股票自动搜索及补全
当您输入了这个组合键之后,Ricequant在线IDE就会进入股票代码搜索和自动完成模式,接着您可以输入任何一种进行搜索和自动补全:
2.2 获取行业
industry - 行业股票列表
industry(code)
获得属于某一行业的所有股票列表。
参数
参数 | 类型 | 注释 |
---|---|---|
code | str OR industry_code item | 行业名称或行业代码。例如,农业可填写industry_code.A01 或 'A01' |
返回
获得属于某一行业的所有股票的order_book_id list。
范例
- def init(context):
- stock_list = industry('A01')
- logger.info("农业股票列表:" + str(stock_list))
2.3 获取板块
sector - 板块股票列表
sector(code)
获得属于某一板块的所有股票列表。
参数
参数 | 类型 | 注释 |
---|---|---|
code | str OR sector_code items | 板块名称或板块代码。例如,能源板块可填写'Energy'、'能源'或sector_code.Energy |
返回
属于该板块的股票order_book_id或order_book_id list.
范例
- def init(context):
- ids1 = sector("consumer discretionary")
- ids2 = sector("非必需消费品")
- ids3 = sector("ConsumerDiscretionary")
- assert ids1 == ids2 and ids1 == ids3
- logger.info(ids1)
支持的行业获取如下,想要了解全球行业划分标准参考全球行业标准分类:
板块代码 | 中文板块名称 | 英文板块名称 |
---|---|---|
Energy | 能源 | energy |
Materials | 原材料 | materials |
ConsumerDiscretionary | 非必需消费品 | consumer discretionary |
ConsumerStaples | 必需消费品 | consumer staples |
HealthCare | 医疗保健 | health care |
Financials | 金融 | financials |
InformationTechnology | 信息技术 | information technology |
TelecommunicationServices | 电信服务 | telecommunication services |
Utilities | 公共服务 | utilities |
Industrials | 工业 | industrials |
2.4 获取概念
参考:https://www.ricequant.com/api/python/chn#data-methods-concept
2.5 获取指数成分股
index_components - 指数成分股
index_components(order_book_id, date=None)
获取某一指数的股票构成列表,也支持指数的历史构成查询。
参数 | 类型 | 说明 |
---|---|---|
order_book_id | str | 指数代码,可传入order_book_id |
date | str, date, datetime, pandas Timestamp | 查询日期,默认为策略当前日期。如指定,则应保证该日期不晚于策略当前日期 |
返回
构成该指数股票的order_book_id list
常见的指数获取代码为
2.6 自定义股票池,提供给handle_bar使用
我们可以通过context的参数,相当于提供一个全局变量来获取
- def init(context):
- # 在context中保存全局变量
- context.s1 = "000001.XSHE"
-
- # context.s2 = "601390.XSHG"
- # 获取行业
- # context.stock_list = industry("C39")
- # 获取指数成分股
- context.hs300 = index_components("000300.XSHG")
-
-
- def before_trading(context):
- logger.info(context.hs300)
- logger.info("before_trading")
3、获取股票合约数据
3.1 history_bars - 某一合约历史数据
history_bars(order_book_id, bar_count, frequency, fields=None, skip_suspended=True, include_now=False)
获取指定合约的历史行情,同时支持日以及分钟历史数据。不能在init中调用。
参数
参数 | 类型 | 注释 |
---|---|---|
order_book_id | str | 合约代码,必填项 |
bar_count | int | 获取的历史数据数量,必填项 |
frequency | str | 获取数据什么样的频率进行。'1d'或'1m'分别表示每日和每分钟,必填项。您可以指定不同的分钟频率,例如'5m'代表5分钟线 |
fields | strOR str list | 返回数据字段。必填项。见下方列表 |
skip_suspended | bool | 是否跳过停牌,默认True,跳过停牌 |
include_now | bool | 是否包括不完整的bar数据。默认为False,不包括。举例来说,在09:39的时候获取上一个5分钟线,默认将获取到09:31~09:35合成的5分钟线。如果设置为True,则将获取到09:36~09:39之间合成的"不完整"5分钟线 |
返回
ndarray ,方便直接与talib等计算库对接,效率较history返回的DataFrame更高。
获取的字段内容如下
fields | 字段名 |
---|---|
datetime | 时间戳 |
open | 开盘价 |
high | 最高价 |
low | 最低价 |
close | 收盘价 |
volume | 成交量 |
total_turnover | 成交额 |
datetime | int类型时间戳 |
open_interest | 持仓量(期货专用) |
basis_spread | 期现差(股指期货专用) |
settlement | 结算价(期货日线专用) |
prev_settlement | 结算价(期货日线专用) |
3.2 代码以及注意的问题
- # 如果想在今天运行,获取从几天开始前几天一些数据
- # 获取前5天的收盘价,开盘价
- # 股票代号,间隔,频率,交易指标
- data = history_bars(context.s1, 5, '1d', 'close')
-
- # 获取多个指标
- data = history_bars(context.s1, 5, '1d', ['close', 'open'])
-
- # 如果回测是每日的,不支持获取分钟数据
- data = history_bars(context.s1, 5, '1m', ['close', 'open'])
问题:这里的频率跟回测的频率区别?
3.3 其它-通过bar_dict获取
获取合约当前价格的bar_dict,
Bar对象
属性 | 类型 | 注释 |
---|---|---|
order_book_id | str | 合约代码 |
symbol | str | 合约简称 |
datetime | datetime.datetime | 时间戳 |
open | float | 开盘价 |
close | float | 收盘价 |
high | float | 最高价 |
low | float | 最低价 |
volume | float | 成交量 |
total_turnover | float | 成交额 |
prev_close | float | 昨日收盘价 |
limit_up | float | 涨停价 |
limit_down | float | 跌停价 |
isnan | bool | 当前bar数据是否有行情。例如,获取已经到期的合约数据,isnan此时为True |
suspended | bool | 是否全天停牌 |
prev_settlement | float | 昨结算(期货日线数据专用) |
settlement | float | 结算(期货日线数据专用) |
注意,在股票策略中bar对象可以拿到所有股票合约的bar信息
- # 只能获取当前的交易信息
- logger.info(bar_dict[context.s1].close)
注:只能获取当前运行日期的,不能获取之前日期
4、获取财务数据
4.1 get_fundamentals - 查询财务数据
get_fundamentals(query, entry_date=None, interval='1d', report_quarter=False)
获取历史财务数据表格。目前支持中国市场超过400个指标,具体请参考 财务数据文档 。目前仅支持中国市场。需要注意,一次查询过多股票的财务数据会导致系统运行缓慢。(entry_date在回测当中不去要提供)
注意这里的数据指标类别虽然有400多种,但是RQ平台的这些指标数据质量不高,很多指标没有经过运算处理成需要的指标,跟我们在讲金融数据处理的时候列出来的那些财务指标差别比较大。
参数
参数 | 类型 | 说明 |
---|---|---|
query | SQLAlchemyQueryObject | SQLAlchmey的Query对象。其中可在'query'内填写需要查询的指标,'filter'内填写数据过滤条件。具体可参考 sqlalchemy's query documentation 学习使用更多的方便的查询语句。从数据科学家的观点来看,sqlalchemy的使用比sql更加简单和强大 |
entry_date | str, datetime.date, datetime.datetime, pandasTimestamp | 查询财务数据的基准日期,应早于策略当前日期。默认为策略当前日期前一天。 |
interval | str | 查询财务数据的间隔,默认为'1d'。例如,填写'5y',则代表从entry_date开始(包括entry_date)回溯5年,返回数据时间以年为间隔。'd' - 天,'m' - 月, 'q' - 季,'y' - 年 |
report_quarter | bool | 是否显示报告期,默认为False,不显示。'Q1' - 一季报,'Q2' - 半年报,'Q3' - 三季报,'Q4' - 年报 |
返回
pandas DataPanel 如果查询结果为空,返回空pandas DataFrame 如果给定间隔为1d, 1m, 1q, 1y,返回pandas DataFrame
4.2 如何获取指标-query查询
通过fundamentals获取以上的属性
q = query(fundamentals.eod_derivative_indicator.pe_ratio)
4.3 过滤指标条件
- # 增加条件过滤掉不符合的股票代码
- # 默认直接获取A股是所有的股票这个指标数据
- # order_by默认是升序
- # limit:选择固定数量的股票,获取20个股票交易
- q = query(fundamentals.eod_derivative_indicator.pe_ratio,
- fundamentals.eod_derivative_indicator.pcf_ratio).filter(
- fundamentals.eod_derivative_indicator.pe_ratio > 20,
- fundamentals.eod_derivative_indicator.pcf_ratio > 15,
- ).order_by(
- fundamentals.eod_derivative_indicator.pe_ratio
- ).limit(20)
-
- # 想要从沪深300指数的一些股票去进行筛选
- # 通过fundamentals.stockcode去限定股票池
- q = query(fundamentals.eod_derivative_indicator.pe_ratio,
- fundamentals.eod_derivative_indicator.pcf_ratio).filter(
- fundamentals.eod_derivative_indicator.pe_ratio > 20,
- ).order_by(
- fundamentals.eod_derivative_indicator.pe_ratio
- ).filter(
- fundamentals.stockcode.in_(context.hs300)
- ).limit(20)
-
-
- # 获取财务数据,默认获取的是dataframe,entry_date在回测当中不去要提供
- fund = get_fundamentals(q)
- # 注释:每个表都有一个stockcode在用来方便通过股票代码来过滤掉查询的数据
问题:一般选择一些满足财务数据的股票时间并不是每天去获取,而是间隔一周、一个月去获取一次?怎么取获取呢?
4、scheduler定时器定时数据获取
4.1 API介绍
4.1.1 scheduler.run_daily - 每天运行
scheduler.run_daily(function)
每日运行一次指定的函数,只能在init内使用。
注意,schedule一定在其对应时间点的handle_bar之前执行,如果定时运行函数运行时间较长,则中间的handle_bar事件将会被略过。
参数
参数 | 类型 | 注释 |
---|---|---|
function | function | 使传入的function每日运行。注意,function函数一定要包含(并且只能包含)context, bar_dict两个输入参数 |
返回
无
4.1.2 scheduler.run_monthly - 每月运行
scheduler.run_monthly(function,tradingday=t)
每月运行一次指定的函数,只能在init内使用。
注意:
tradingday
的负数表示倒数。tradingday
表示交易日,如某月只有三个交易日,则此月的tradingday=3与tradingday=-1表示同一。参数
参数 | 类型 | 注释 |
---|---|---|
function | function | 使传入的function每日交易开始前运行。注意,function函数一定要包含(并且只能包含)context, bar_dict两个输入参数 |
tradingday | int | 范围为[-23,1], [1,23] ,例如,1代表每月第一个交易日,-1代表每月倒数第一个交易日,用户必须指定 |
返回
无
4.2 添加定时器之后的策略运行顺序
比如我们添加了这样一段代码:
- def init(context):
- # 定义一个每天运行一个定时器
- scheduler.run_daily(get_data)
- # 每个一个月去获取财务数据,每隔一周去获取财务数据
- scheduler.run_monthly(get_data, tradingday=1)
4.3 代码
- def get_data(context, bar_dict):
- # logger.info("-------")
- # 进行每月的第一天去调整要买卖的股票
- q = query(fundamentals.eod_derivative_indicator.pe_ratio,
- fundamentals.eod_derivative_indicator.pcf_ratio).filter(
- fundamentals.eod_derivative_indicator.pe_ratio > 20,
- ).order_by(
- fundamentals.eod_derivative_indicator.pe_ratio
- ).filter(
- fundamentals.stockcode.in_(context.hs300)
- ).limit(20)
-
- # 获取财务数据
- data = get_fundamentals(q)
-
- logger.info("这个月更新的股票池")
- logger.info(data.T)
1、用于股票的交易函数
更多详细内容参考:https://www.ricequant.com/api/python/chn#methods-implement-after-trading
1.1 交易函数API
1.1.1 order_shares - 指定股数交易(股票专用)
order_shares(id_or_ins, amount, style=MarketOrder())
落指定股数的买/卖单,最常见的落单方式之一。如有需要落单类型当做一个参量传入,如果忽略掉落单类型,那么默认是市价单(market order)。
参数
参数 | 类型 | 注释 |
---|---|---|
id_or_ins | str或instrument对象 | order_book_id或symbol或instrument对象,用户必须指定 |
amount | float-required | 需要落单的股数。正数代表买入,负数代表卖出。将会根据一手xx股来向下调整到一手的倍数,比如中国A股就是调整成100股的倍数。 |
style | OrderType | 订单类型,默认是市价单。目前支持的订单类型有:style=MarketOrder() and style=LimitOrder(limit_price) |
返回
Order对象
范例
order_shares('000001.XSHE', 2000)
order_shares('000001.XSHE', -2000)
order_shares('000001.XSHE', 1000, style=LimitOrder(10))
1.1.2 order_target_value - 目标价值下单(股票专用)
order_target_value(id_or_ins, cash_amount, style=OrderType)
买入/卖出并且自动调整该证券的仓位到一个目标价值(暂不支持卖空)。如果还没有任何该证券的仓位,那么会买入全部目标价值的证券。如果已经有了该证券的仓位,则会买入/卖出调整该证券的现在仓位和目标仓位的价值差值的数目的证券。需要注意,如果资金不足,该API将不会创建发送订单。
参数
参数 | 类型 | 注释 |
---|---|---|
id_or_ins | str或instrument对象 | order_book_id或symbol或instrument object,用户必须指定 |
cash_amount | float-required | 最终的该证券的仓位目标价值 |
style | OrderType | 订单类型,默认是市价单。目前支持的订单类型有:style=MarketOrder()style=LimitOrder(limit_price) |
返回
Order对象
范例
order_target_value('000001.XSHE', 10000)
1.1.3 order_target_percent - 目标比例下单(股票专用)
order_target_percent(id_or_ins, percent, style=OrderType)
买入/卖出证券以自动调整该证券的仓位到占有一个指定的投资组合的目标百分比(暂不支持卖空)。
其实我们需要计算一个position_to_adjust (即应该调整的仓位)
position_to_adjust = target_position - current_position
投资组合价值等于所有已有仓位的价值和剩余现金的总和。买/卖单会被下舍入一手股数(A股是100的倍数)的倍数。目标百分比应该是一个小数,并且最大值应该<=1,比如0.5表示50%。
如果position_to_adjust
计算之后是正的,那么会买入该证券,否则会卖出该证券。 需要注意,如果资金不足,该API将不会创建发送订单。
参数
参数 | 类型 | 注释 |
---|---|---|
id_or_ins | str或instrument对象 | order_book_id或symbol或instrument object,用户必须指定 |
percent | float-required | 仓位最终所占投资组合总价值的目标百分比。 |
style | OrderType | 订单类型,默认是市价单。目前支持的订单类型有:style=MarketOrder()style=LimitOrder(limit_price) |
返回
order对象
范例
order_target_percent('000001.XSHE', 0.15)
1.2 交易注意事项
出现以下情况,我们的交易会被回测平台自动拒单
- portfolio内可用资金不足
- 下单数量不足一手(股票为100股)
- 下单价格超过当日涨跌停板限制
- 当前可卖(可平)仓位不足
- 股票当日停牌
- 合约已经退市(到期)或尚未上市
1.3 何为市价单和限价单
撮合机制
我们加入了允许用户自定义撮合机制的功能。您可以在策略编辑页面"更多"选项下选择不同的撮合机制。目前提供的撮合方式有以下两种:
市价单与限价单
1、限价单(LimitOrder)如果买单价格>=参考价,或卖单价格<=参考价,以参考价加入滑点影响成交(买得更高,卖得更低)。市价单(MarketOrder)直接以以参考价加入滑点影响成交。
2、成交数量都不超过当前bar成交量的25%。某一分钟成交量10000股,那么回测的时候我们做限制成交不能超过2500股 。一旦超过,市价单会在部分成交之后被自动撤单;限价单会一直在订单队列中等待下一个bar数据撮合成交,直到当日收盘。当日收盘后,所有未成交限价单都将被系统自动撤单。
拓展: 需要注意,在当前的分钟回测撮合模式下,用户在回测中无法通过在scheduler调用的函数中一次性实现 卖出 -> 资金释放 -> 买入 这种先卖后买的逻辑的。因为在分钟回测中,卖出并不能立刻成交。
handle_bar
内下单,在该handle_bar结束时统一撮合成交(成交价取决于撮合机制以及滑点设置)。handelbar
内下单,下单时立刻撮合成交(成交价取决于撮合机制以及滑点设置)。总结
为了更好模拟实际交易中订单对市场的冲击,我们引入滑点的设置。您可以在策略编辑页面"更多"选项下进行滑点设置,允许设置的范围是[0, 1)。该设置将在一定程度上使最后的成交价"恶化",也就是买得更贵,卖得更便宜。我们的滑点方式是按照最后成交价的一定比例进行恶化。例如,设置滑点为0.1,那么如果原本买入交易的成交价为10元,则设置之后成交价将变成11元,即买得更贵。
注:真是交易不需要
1.4 交易的费用
相关介绍参考:https://www.ricequant.com/api/python/chn#backtests-margin
一旦发生了交易,投资组合的资金就会发生变化!那么接下来要介绍的投资组合是什么?
2、投资组合
我们看一张图
2.1 定义
投资组合是由投资人或金融机构所持有的股票、债券、金融衍生产品等组成的集合,目的是分散风险。
2.2 如何查看投资组合的信息
还记得我们之前提到的一个叫context的参数吗,这个参数当中就包含了投资组合的信息
context属性
context.now
使用以上的方式就可以在handle_bar
中拿到当前的bar的时间,比如day bar的话就是那天的时间,minute bar的话就是这一分钟的时间点。
返回数据类型为datetime.datetime
context.portfolio
该投资组合在单一股票或期货策略中分别为股票投资组合和期货投资组合。在股票+期货的混合策略中代表汇总之后的总投资组合。
context.stock_account
获取股票资金账户信息。
portfolio对象
属性 | 类型 | 注释 |
---|---|---|
cash | float | 可用资金,为子账户可用资金的加总 |
frozen_cash | float | 冻结资金,为子账户冻结资金加总 |
total_returns | float | 投资组合至今的累积收益率 |
daily_returns | float | 投资组合每日收益率 |
daily_pnl | float | 当日盈亏,子账户当日盈亏的加总 |
market_value | float | 投资组合当前的市场价值,为子账户市场价值的加总 |
total_value | float | 总权益,为子账户总权益加总 |
units | float | 份额。在没有出入金的情况下,策略的初始资金 |
unit_net_value | float | 单位净值 |
static_unit_net_value | float | 静态单位权益 |
transaction_cost | float | 当日费用 |
pnl | float | 当前投资组合的累计盈亏 |
start_date | datetime.datetime | 策略投资组合的回测/实时模拟交易的开始日期 |
annualized_returns | float | 投资组合的年化收益率 |
positions | dict | 一个包含所有仓位的字典,以order_book_id作为键,position对象作为值,关于position的更多的信息可以在下面的部分找到。 |
Position对象
position就代表着当前我们的仓位中有哪些股票正持有,position.keys()可以获取
属性 | 类型 | 注释 |
---|---|---|
order_book_id | str | 合约代码 |
quantity | int | 当前持仓股数 |
pnl | float | 持仓累计盈亏 |
sellable | int | 该仓位可卖出股数。T+1的市场中sellable = 所有持仓-今日买入的仓位 |
market_value | float | 获得该持仓的实时市场价值 |
value_percent | float | 获得该持仓的实时市场价值在总投资组合价值中所占比例,取值范围[0, 1] |
avg_price | float | 平均建仓成本 |
2.3 代码
- # 查看我们的投资组合信息,仓位、资金
- # 查看股票账户信息
- logger.info("股票账户信息:")
- logger.info(context.stock_account)
-
- # 卖出股票就要从持有的这些股票当中去选择
- logger.info(context.portfolio.positions)
-
- # 交易的价格计算
- # 当日的:close * 股数
- logger.info("投资组合的资金:%f" % context.portfolio.cash)
- logger.info("投资组合的市场价值:%f" % context.portfolio.market_value)
- logger.info("投资组合的总价值:%f" % context.portfolio.total_value)
2.4 查看交易情况界面
1、策略评价指标
2、 收益指标
2.1 回测收益率
策略在期限内的收益率。
2.2 年化收益率
采用了复利累积以及Actual/365 Fixed的年化方式计算得到的年化收益。
我们更加注重年化收益率,对于股票来讲,年化达到15~30%已经算是比较好的策略。年化收益率越高越好
2.3 基准收益率
相同条件下,一个简单的买入并持有基准合约策略的收益率(默认基准合约为沪深300指数,这里假设指数可交易,最小交易单位为1)。
基准收益率拿来对比我们的策略收益率,策略的表现期望超过基准收益率才获得了比较好的收益
3、 风险指标
风险指标指的是在获得收益的时候,承担一些风险值
3.1 最大回撤
最大回撤越小越好,最大回撤最好保持10~30%之间
4、单位风险收益指标
4.1 夏普比率
举例而言,假如国债的回报是4%,而您的投资组合预期回报是16%,您的投资组合的标准偏差是5%,那么用16%-4%,可以得出12%(代表您超出无风险投资的回报),再用12%÷5%=2.4,代表投资者风险每增长1%,换来的是2.4%的多余收益。夏普比率越大,说明单位风险所获得的风险回报越高。
最终夏普比率越高越好,达到1.5以上已经是很好的结果
1、 选股简单介绍
不管是技术分析还是基本面分析,我们在进行投资的时候都会选择某些表现较好的股票来作为一个股票池,从中进行交易的判断(技术分析)或者直接购买。
2、 需求
3、 代码
- # 可以自己import我们平台支持的第三方python模块,比如pandas、numpy等。
- # 每日选股:获得市盈率大于50且小于65,营业总收入前10的股票
- # 买卖:买入每天选出来的10只,卖出不符合条件
- # 调仓按照月调仓,投资对象HS300
-
-
- # 在这个方法中编写任何的初始化逻辑。context对象将会在你的算法策略的任何方法之间做传递。
- def init(context):
- # 在context中保存全局变量
- # context.s1 = "000001.XSHE"
- # 实时打印日志
- # logger.info("RunInfo: {}".format(context.run_info))
- # 定义一个选股的范围
- context.hs300 = index_components("000300.XSHG")
-
- scheduler.run_monthly(get_data, tradingday=1)
-
-
- def get_data(context, bar_dict):
-
- # 删掉两个条件
- # .filter(
- # fundamentals.eod_derivative_indicator.pe_ratio > 50
- # ).filter(
- # fundamentals.eod_derivative_indicator.pe_ratio < 65
- # )
-
- # 选股
- q = query(fundamentals.eod_derivative_indicator.pe_ratio,
- fundamentals.income_statement.revenue
- ).order_by(
- fundamentals.income_statement.revenue.desc()
- ).filter(
- fundamentals.stockcode.in_(context.hs300)
- ).limit(10)
-
- fund = get_fundamentals(q)
-
- # 行列内容以及索引一起进行转置
- # print(fund.T)
- context.stock_list = fund.T.index
-
-
- # before_trading此函数会在每天策略交易开始前被调用,当天只会被调用一次
- def before_trading(context):
-
- pass
-
-
-
- # 你选择的证券的数据更新将会触发此段逻辑,例如日或分钟历史数据切片或者是实时数据切片更新
- def handle_bar(context, bar_dict):
- # 开始编写你的主要的算法逻辑
-
- # bar_dict[order_book_id] 可以拿到某个证券的bar信息
- # context.portfolio 可以拿到现在的投资组合信息
-
- # 使用order_shares(id_or_ins, amount)方法进行落单
-
- # TODO: 开始编写你的算法吧!
- # order_shares(context.s1, 1000)
-
- # 在这里才能进行交易
- # 先判断仓位是否有股票,如果有,卖出(判断在不在新的股票池当中)
- if len(context.portfolio.positions.keys()) != 0:
-
- for stock in context.portfolio.positions.keys():
-
- # 如果旧的持有的股票不在新的股票池当中,卖出
- if stock not in context.stock_list:
-
- order_target_percent(stock, 0)
-
- # 买入最新的每日更新的股票池当中的股票
- # 等比例资金买入,投资组合总价值的百分比平分10份
- weight = 1.0 / len(context.stock_list)
-
- for stock in context.stock_list:
-
- order_target_percent(stock, weight)
-
- # after_trading函数会在每天交易结束后被调用,当天只会被调用一次
- def after_trading(context):
- pass
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。