三一投资管理公司价值选股策略十分简洁,仅考虑三个价值投资的指标:市盈率、市净率、股利收益率。我们做如下指标量化:
PE大于0且处于市场最低的30%
PB处于市场最低的30%
股息率处于市场最高的30%
前三个条件若选出的股票数量大于30,则选取股息率最高的30只股票
import datetime
from dateutil.parser import parse
import numpy as np
import pandas as pd
from CAL.PyCAL import *
cal = Calendar(‘China.SSE’)
def get_dividend_yields(begin_date,end_date,universe):
"""
给定股票列表和起始日期,返回在这段时间有分红的股票的股息率
Args:
universe (list of str): 股票列表(有后缀)
date (str): ’%Y%m%d格式
Returns:
list: 这段时间有分红的股票的股息率
Examples:
>> universe = set_universe('HS300')
>> buy_list = get_dividend_yields('20150909','20160909',universe)
"""
bonus = DataAPI.EquDivGet(eventProcessCD = '6',secID= universe ,beginDate = begin_date ,endDate= end_date ,field=['secID','perCashDiv','recordDate'],pandas="1")
dividend_yield = {}
for i in range(len(bonus)):
recordDate_price = DataAPI.MktEqudGet(secID=bonus['secID'][i],tradeDate= bonus['recordDate'][i], field=['closePrice'], pandas="1")
if len(recordDate_price) > 0:
dividend_yield[bonus['secID'][i]] = bonus['perCashDiv'][i]*100/recordDate_price['closePrice'][0]
return pd.Series(dividend_yield)
def TrinityInvestmentSelect(universe,date):
"""
给定股票列表和日期,返回三一投资管理公司选股法挑选的股票
Args:
universe (list of str): 股票列表(有后缀)
date (str or datetime): 常见日期格式支持
Returns:
list: 三一投资管理公司选股法挑选的股票
Examples:
>> universe = set_universe('HS300')
>> buy_list = TrinityInvestmentSelect(universe,'20160909')
"""
trade_date = date if isinstance(date,datetime.datetime) else parse(date)
trade_date = trade_date.strftime('%Y%m%d')
begin_date = cal.advanceDate(date, '-1Y', BizDayConvention.Following).strftime('%Y%m%d')
dividend_yields_series = get_dividend_yields(begin_date,trade_date,universe)
df_factor = DataAPI.MktStockFactorsOneDayProGet(tradeDate=trade_date,secID=universe,
field=['secID','PB','PE'],pandas="1")
df_factor = df_factor.dropna()
df_factor = df_factor[(df_factor['PB'] > 0) & (df_factor['PE'] > 0)]
df_factor = df_factor.set_index(['secID'])
df_factor = pd.concat([df_factor,dividend_yields_series],axis=1).rename(columns={0:'dividendRate'})
# 依据上述条件,筛选股票
df_factor = df_factor.dropna()
df_factor = df_factor[(df_factor['PB'] < df_factor['PB'].quantile(0.3)) & (df_factor['PE'] < df_factor['PE'].quantile(0.3)) & (df_factor['dividendRate'] > df_factor['dividendRate'].quantile(0.7))]
# print df_factor.sort_values(['dividendRate'],ascending=False)
return list(df_factor.sort_values(['dividendRate'],ascending=False).index[0:30])
start = ‘2010-01-01’ # 回测起始时间
end = ‘2016-09-19’ # 回测结束时间
benchmark = ‘HS300’ # 策略参考标准
universe = set_universe(‘A’) # 证券池,支持股票和基金
capital_base = 1000000 # 起始资金
freq = ‘d’ # 策略类型,’d’表示日间策略使用日线回测,’m’表示日内策略使用分钟线回测
refresh_rate = 20 # 调仓频率,表示执行handle_data的时间间隔,若freq = ‘d’时间间隔的单位为交易日,若freq = ‘m’时间间隔为分钟
def initialize(account): # 初始化虚拟账户状态
pass
def handle_data(account): # 每个交易日的买入卖出指令
buy_list = TrinityInvestmentSelect(account.universe,account.previous_date)
for stk in account.avail_security_position:
if stk not in buy_list:
order_to(stk, 0)
if len(buy_list) > 0:
weight = min(0.1,1.0/len(buy_list))
else:
weight = 0
for stk in buy_list:
if stk not in account.security_position:
order_pct_to(stk,weight)