价值选股股票池策略
基于价值选股股票池策略(第一个量化策略,基于聚宽平台,之后会改进)
代码如下:
import jqdata
import pandas as pd
import numpy as np
import math
import talib as tl
from jqlib.technical_analysis import *
import statsmodels.api as sm
from pandas.stats.api import ols
def initialize(context):
g.stocksnum = 100 # 持有最小市值股票数
g.period = 10 # 轮动频率
log.set_level('order', 'error')
run_daily(daily, time='before_open') # 周期循环daily
run_daily(mktopen, time='every_bar')
g.days = 1 # 记录策略进行到第几天,初始为1
g.holdpct = 1
g.buylist=[]
def trade(context, buylist):
# 对于每个当下持有的股票进行判断:现在是否已经不在buylist里,如果是则卖出
for stock in context.portfolio.positions:
if stock not in buylist: # 如果stock不在buylist
order_target(stock, 0) # 调整stock的持仓为0,即卖出
# 将总资产(现金+股票)除以持股数g.stocksnum
position_per_stk = g.holdpct * context.portfolio.total_value / g.stocksnum
# 调整buylist中的每个股票持仓价值为position_per_stk
for stock in buylist:
order_target_value(stock, position_per_stk)
# 止损
def stop(context):
# 循环查看持仓的每个股票
for stock in context.portfolio.positions:
# 如果股票最新价格除以平均成本小于0.8,即亏损超过20%
if context.portfolio.positions[stock].price / context.portfolio.positions[stock].avg_cost < 0.8:
# 调整stock的持仓为0,即卖出
order_target(stock, 0)
# 输出日志:股票名 止损
print ("\n%s 止损" % stock)
def pick(context):
# 获取股票池
df = get_fundamentals(query(valuation.code, valuation.pb_ratio, indicator.roe))
# 进行pb,roe大于0筛选
df = df[(df['roe'] > 0) & (df['pb_ratio'] > 0)].sort('pb_ratio')
# 以股票名词作为index
df.index = df['code'].values
# 取roe倒数
df['1/roe'] = 1 / df['roe']
# 获取综合得分
df['point'] = df[['pb_ratio', '1/roe']].rank().T.apply(f_sum)
# 按得分进行排序,取指定数量的股票
df = df.sort('point')[:g.stocksnum]
# 取出前g.stocksnum名的股票代码,并转成list类型,buylist为选中的股票
g.buylist = list(df['code'][:g.stocksnum])
return g.buylist
def f_sum(x):
return sum(x)
def mktopen(context):
# 每分钟止损
stop(context)
def mkt_index(context):
mktindex = history(count=1, field='close', security_list=['000300.XSHG'])
mktindex = mktindex.ix[-1, '000300.XSHG']
date =context.current_dt.strftime("%Y-%m-%d")
ma20 = MA(['000300.XSHG'], check_date=date, timeperiod=20)
ma20 = ma20['000300.XSHG']
if mktindex > ma20:
return 1
return 0.5
def daily(context):
# 判断策略进行天数是否能被轮动频率整除余1
if g.days % g.period == 1:
buylist = pick(context)
g.holdpct = mkt_index(context)
trade(context, buylist)
else:
pass # 什么也不做
g.days = g.days + 1 # 策略经过天数增加1