量化策略
双均线策略:
择时
# 导入函数库
from jqdata import *
# 初始化函数,设定基准等等
def initialize(context):
# 设定沪深300作为基准
set_benchmark(\'000300.XSHG\')
# 开启动态复权模式(真实价格)
set_option(\'use_real_price\', True)
# 过滤掉order系列API产生的比error级别低的log
log.set_level(\'order\', \'error\')
### 股票相关设定 ###
# 股票类每笔交易时的手续费是:买入时佣金万分之三,卖出时佣金万分之三加千分之一印花税, 每笔交易佣金最低扣5块钱
set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type=\'stock\')
g.security = [\'601318.XSHG\',]
g.p1 = 5
g.p2 = 60
def handle_data(context, data):
# print(get_current_data()[\'601318.XSHG\'].day_open)
# print(attribute_history(\'601318.XSHG\',5))
# order(\'601318.XSHG\',100)
# order_value(\'601318.XSHG\',10000)
for stock in g.security:
# 金叉:如果5日均线大于10日均线并且不持仓
# 死叉:如果5日均线小于10日均线并且持仓
df = attribute_history(stock,g.p2)
ma10 = df[\'close\'].mean()
ma5 = df[\'close\'][-5:].mean()
if ma10 > ma5 and stock in context.portfolio.positions:
# 死叉
order_target(stock,0)
if ma10 < ma5 and stock not in context.portfolio.positions:
# 金叉
order(stock,context.portfolio.available_cash * 0.8)
record(ma5=ma5,ma10=ma10)
因子选股策略
因子:选择股票的某种标准
增长率、市值、市盈率、ROE(净资产收益率)
选股策略
对于某个因子,选取表现最好的N只股票持仓
每隔一段时间调仓一次
小市值策略:选取股票池中市值最小的N只股票持仓
# 导入函数库
from jqdata import *
# 初始化函数,设定基准等等
def initialize(context):
set_benchmark(\'000002.XSHG\')
set_option(\'use_real_price\', True)
log.set_level(\'order\', \'error\')
set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type=\'stock\')
g.security = get_index_stocks(\'000002.XSHG\')
g.q = query(valuation).filter(valuation.code.in_(g.security))# valuation表
g.N = 20
# g.days = 0
run_monthly(handle_,1)# 每月第一个交易日
def handle_data(context, data):
# print(get_current_data()[\'601318.XSHG\'].day_open)
# print(attribute_history(\'601318.XSHG\',5))
# order(\'601318.XSHG\',100)
# order_value(\'601318.XSHG\',10000)
pass
def handle_(context):
df = get_fundamentals(g.q)[[\'code\',\'market_cap\']]# 查询数据
df = df.sort(\'market_cap\').iloc[:g.N,:]# 0.16.2 版本, # 获取沪深300以总市值排序
to_hold = df[\'code\'].values
for stock in context.portfolio.positions:
if stock not in to_hold:
order_target(stock,0)# 卖出
to_buy = [stock for stock in to_hold if stock not in context.portfolio.positions]
if len(to_buy)>0:
cash_per_stock = context.portfolio.available_cash/len(to_buy)
for stock in to_buy:
order_value(stock,cash_per_stock) # 买
"""
get_current_data
last_price : 最新价
high_limit: 涨停价
low_limit: 跌停价
paused: 是否停止或者暂停了交易, 当停牌、未上市或者退市后返回 True
is_st: 是否是 ST(包括ST, *ST),是则返回 True,否则返回 False
day_open: 当天开盘价
name: 股票现在的名称, 可以用这个来判断股票当天是否是 ST, *ST, 是否快要退市
"""
多因子选股策略
因子:选择股票的某种标准
增长率、市值、市盈率、ROE(净资产收益率)
选股策略
对于某个因子,选取表现最好的N只股票持仓
每隔一段时间调仓一次
小市值策略:选取股票池中市值最小的N只股票持仓
如何同时综合多个因子来选股?
评分模型:
每个股票针对每个因子进行评分,将评分相加
选出总评分最大的N只股票持仓
如何计算股票在某个因子下的评分:归一化(标准化) github/book/有
# 导入函数库
from jqdata import *
# 初始化函数,设定基准等等
def initialize(context):
set_benchmark(\'000002.XSHG\')
set_option(\'use_real_price\', True)
log.set_level(\'order\', \'error\')
set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type=\'stock\')
g.security = get_index_stocks(\'000002.XSHG\')
g.q = query(valuation,indicator).filter(valuation.code.in_(g.security))# valuation表
g.N = 20
# g.days = 0
run_monthly(handle_,1)# 每月第一个交易日
def handle_data(context, data):
# print(get_current_data()[\'601318.XSHG\'].day_open)
# print(attribute_history(\'601318.XSHG\',5))
# order(\'601318.XSHG\',100)
# order_value(\'601318.XSHG\',10000)
pass
def handle_(context):
df = get_fundamentals(g.q)[[\'code\',\'market_cap\',\'roe\']]# 查询数据
# 0-1归一化
df[\'market_cap\']=(df[\'market_cap\']-df[\'market_cap\'].min())/(df[\'market_cap\'].max()-df[\'market_cap\'].min())
df[\'roe\'] = (df[\'roe\']-df[\'roe\'].min())/(df[\'roe\'].max()-df[\'roe\'].min())
df[\'score\'] = df[\'roe\'] - df[\'market_cap\'] # 可以加权重 # 净资产收益率 - 总市值(亿元) # 已经归一化
df = df.sort(\'score\').iloc[-g.N:,:]# 0.16.2 版本, # 获取沪深300以总市值排序
to_hold = df[\'code\'].values
for stock in context.portfolio.positions:
if stock not in to_hold:
order_target(stock,0)# 卖出
to_buy = [stock for stock in to_hold if stock not in context.portfolio.positions]
if len(to_buy)>0:
cash_per_stock = context.portfolio.available_cash/len(to_buy)
for stock in to_buy:
order_value(stock,cash_per_stock) # 买
均值回归理论讲解 (选股策略)
均值回归:跌下去的迟早要涨上来
均值回归的理论基于以下观测:价格的波动一般会以它的均线为中心。也就是说,当标的价格由于波动而偏离移动均线时,他将调整并重新归于均线。(破产除外))
定义偏离程度(MA-P)/MA
均值回归策略 :在每个调仓日进行
计算股票池中所有股票的N日均线
计算股票池中所有股票与均线的偏离度
选取偏离度最高的M只股票并调仓
# 导入函数库
from jqdata import *
# 初始化函数,设定基准等等
def initialize(context):
set_benchmark(\'000002.XSHG\')
set_option(\'use_real_price\', True)
log.set_level(\'order\', \'error\')
set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type=\'stock\')
g.security = get_index_stocks(\'000002.XSHG\')
g.ma_days = 30
g.stock_num = 10
run_monthly(handle_,1)# 每月第一个交易日
def handle_data(context, data):
# print(get_current_data()[\'601318.XSHG\'].day_open)
# print(attribute_history(\'601318.XSHG\',5))
# order(\'601318.XSHG\',100)
# order_value(\'601318.XSHG\',10000)
pass
def handle_(context):
sr = pd.Series(index=g.security)
for stock in sr.index:
ma = attribute_history(stock,g.ma_days)[\'close\'].mean() # 30日均线
p = get_current_data()[stock].day_open
ratio = (ma-p)/ma
sr[stock] = ratio
tohold = sr.nlargest(g.stock_num).index # 和sort一样,速度更快
# print(tohold)
to_hold = tohold
for stock in context.portfolio.positions:
if stock not in to_hold:
order_target(stock,0)# 卖出
to_buy = [stock for stock in to_hold if stock not in context.portfolio.positions]
if len(to_buy)>0:
cash_per_stock = context.portfolio.available_cash/len(to_buy)
for stock in to_buy:
order_value(stock,cash_per_stock) # 买
布林带策略
布林带/布林线/保利加通道 (Bollinger Band): 由三条轨道线组成,其中上下两条线分别可以看成是价格的压力线和支撑线,在两条线之间是一条价格平均线
计算公式:
中间线 = 20日均线
up线 = 20日均线 + N*SD(20日收盘价)
down线 = 20日均线 - N*SD(20日收盘价)
布林带策略: 择时
当估价突破阻力线时,清仓
当估价跌破支撑线时,全仓买入
布林带策略研究:N的取值问题,布林带宽度等。
# 导入函数库
from jqdata import *
# 初始化函数,设定基准等等
def initialize(context):
set_benchmark(\'000300.XSHG\')
set_option(\'use_real_price\', True)
log.set_level(\'order\', \'error\')
set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type=\'stock\')
g.security = \'600036.XSHG\'
g.M = 20
g.k = 2
# 初始化此策略
def handle_data(context, data):
sr = attribute_history(g.security,g.M)[\'close\']
ma = sr.mean()
up = ma + g.k * sr.std()
down = ma -g.k * sr.std()
p = get_current_data()[g.security].day_open
cash = context.portfolio.available_cash
if p < down and g.security not in context.portfolio.positions:
order_value(g.security,cash)
elif p > up and g.security in context.portfolio.positions:
order_target(g.security,0)
PEG策略
任何一家公司股价如果定价合理的话,市盈率就会与收益增长率相等
市盈率 (PE) = 股价(p)/每股收益(eps)
市盈率 ≈ 市值/净收益
例如: 有一家包子铺,每年净收益为50万元,收益价格(市值)为100万元;
有一家家具店,每年净利润为100万元,市值为1000万元
每股收益(EPS)
估价(P)
市盈率(PE) = P/EPS
收益增长率(G) = (EPSi - EPSi-1) /EPSi-1
PEG = PE/(g*100)
pe越低,代表股价被低估的可能性越大,估价会涨的可能性越大
peg是一个综合指标,既考察价值,又兼顾成长性。peg估值法是应用成长型公司。
# 导入函数库
from jqdata import *
# 初始化函数,设定基准等等
def initialize(context):
set_benchmark(\'000002.XSHG\')
set_option(\'use_real_price\', True)
set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type=\'stock\')
g.security = get_index_stocks(\'000002.XSHG\')
g.q = query(valuation.code,valuation.pe_ratio,indicator.inc_net_profit_year_on_year).filter(valuation.code.in_(g.security))# valuation表
g.N = 20
# g.days = 0
run_monthly(handle_,1)# 每月第一个交易日
def handle_data(context, data):
# print(get_current_data()[\'601318.XSHG\'].day_open)
# print(attribute_history(\'601318.XSHG\',5))
# order(\'601318.XSHG\',100)
# order_value(\'601318.XSHG\',10000)
pass
def handle_(context):
df = get_fundamentals(g.q)# 查询数据
df = df[(df[\'pe_ratio\']>0)&(df[\'inc_net_profit_year_on_year\']>0)]
df[\'peg\'] = df[\'pe_ratio\']/df[\'inc_net_profit_year_on_year\']/100
df = df.sort(columns=[\'peg\'])
to_hold = df[\'code\'][:g.N].values # 先取列,在取行
print(to_hold)
# 0-1归一化
# df[\'market_cap\']=(df[\'market_cap\']-df[\'market_cap\'].min())/(df[\'market_cap\'].max()-df[\'market_cap\'].min())
# df[\'roe\'] = (df[\'roe\']-df[\'roe\'].min())/(df[\'roe\'].max()-df[\'roe\'].min())
# df[\'score\'] = df[\'roe\'] - df[\'market_cap\'] # 可以加权重 # 净资产收益率 - 总市值(亿元) # 已经归一化
# df = df.sort(\'score\').iloc[-g.N:,:]# 0.16.2 版本, # 获取沪深300以总市值排序
# to_hold = df[\'code\'].values
for stock in context.portfolio.positions:
if stock not in to_hold:
order_target(stock,0)# 卖出
to_buy = [stock for stock in to_hold if stock not in context.portfolio.positions]
if len(to_buy)>0:
cash_per_stock = context.portfolio.available_cash/len(to_buy)
for stock in to_buy:
order_value(stock,cash_per_stock) # 买
动量策略&反转策略
动量策略:如果某只股票在前一段时期表现较好,那么下一段时期该股票扔有良好表现
反转策略:如果某只股票在前一段时期表现不好,那么下一段时期该股票将会反转,即表现变好
计算股票池中所有股票在前一段时间的收益率
选择收益率最大(最小的)N只股票调仓
# 导入函数库
from jqdata import *
# 初始化函数,设定基准等等
def initialize(context):
set_option(\'use_real_price\', True)
set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type=\'stock\')
g.security = get_index_stocks(\'000002.XSHG\')
g.benchmark = \'000300.XSHG\'
set_benchmark(g.benchmark)
g.N = 10
run_monthly(handle_,1)# 每月第一个交易日
def handle_data(context, data):
# print(get_current_data()[\'601318.XSHG\'].day_open)
# print(attribute_history(\'601318.XSHG\',5))
# order(\'601318.XSHG\',100)
# order_value(\'601318.XSHG\',10000)
pass
def handle_(context):
stocks = get_index_stocks(\'000300.XSHG\')
df_close = history(30,field=\'close\',security_list=list(stocks)).T
df_close[\'ret\'] = (df_close.iloc[:,-1]-df_close.iloc[:,0])/df_close.iloc[:,0]
sorted_stocks = df_close.sort(\'ret\',ascending=False).index
to_hold = sorted_stocks[:g.N]
for stock in context.portfolio.positions:
if stock not in to_hold:
order_target(stock,0)# 卖出
to_buy = [stock for stock in to_hold if stock not in context.portfolio.positions]
if len(to_buy)>0:
cash = context.portfolio.available_cash
cash_per_stock = cash / len(to_buy)
for stock in to_buy:
order_value(stock,cash_per_stock) # 买
羊驼法则
买入历史收益最低的N只股票,调仓日留下反转程度大的股票,卖掉表现最差的M只股票,再买入收益率最低的M只股票。
起始时随机买入N只股票,每天卖掉收益率最差的M只,在随机买入剩余股票池的M只
随机选股,随机调仓
from jqdata import *
# 初始化函数,设定基准等等
def initialize(context):
set_benchmark(\'000300.XSHG\')
set_option(\'use_real_price\', True)
set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type=\'stock\')
g.security = get_index_stocks(\'000300.XSHG\')
g.period = 30
g.change = 1
g.init = True
g.N = 10
run_monthly(handle_,1)# 每月第一个交易日
def handle_data(context, data):
# print(get_current_data()[\'601318.XSHG\'].day_open)
# print(attribute_history(\'601318.XSHG\',5))
# order(\'601318.XSHG\',100)
# order_value(\'601318.XSHG\',10000)
pass
def get_sorted_stocks(context,stocks):
df = history(g.period,field=\'close\',security_list=stocks).T
df[\'ret\'] = (df.iloc[:,len(df.columns)-1]-df.iloc[:,0])/df.iloc[:,0]
df = df.sort(columns=\'ret\',ascending=False)
return df.index.values
def handle_(context):
if g.init:
stocks = get_sorted_stocks(context,g.security)[:g.N]
cash = context.portfolio.available_cash * 0.9/len(stocks)
for stock in stocks:
order_value(stock,cash)
g.init = False
return
stocks = get_sorted_stocks(context,context.portfolio.positions.keys())[:g.N]
for stock in stocks[-g.change:]:
order_target(stock,0)# 卖出
stocks = get_sorted_stocks(context,g.security)
for stock in stocks:
if len(context.portfolio.positions) >= g.N:
break
if stock not in context.portfolio.positions:
order_value(stock,context.portfolio.available_cash * 0.9)