# 克隆自聚宽文章:https://www.joinquant.com/post/1399
# 原标题:【量化课堂】多因子策略入门
# 原作者:JoinQuant量化课堂
#多因子策略入门新版
#作者:指指点点
'''
================================================================================
总体回测前
================================================================================
'''
#总体回测前要做的事情
def initialize(context):
set_params() #1设置策参数
set_variables() #2设置中间变量
set_backtest() #3设置回测条件
run_daily(handle_data_v2, "every_bar")
#1
#设置策参数
def set_params():
g.tc=15 # 调仓频率
g.yb=63 # 样本长度
g.N=20 # 持仓数目
g.factors=["market_cap","roe"] # 用户选出来的因子
# 因子等权重里1表示因子值越小越好,-1表示因子值越大越好
g.weights=[[1],[-1]]
#2
#设置中间变量
def set_variables():
g.t=0 #记录回测运行的天数
g.if_trade=False #当天是否交易
#3
#设置回测条件
def set_backtest():
set_option('use_real_price', True)#用真实价格交易
log.set_level('order', 'error')
'''
================================================================================
每天开盘前
================================================================================
'''
#每天开盘前要做的事情
def before_trading_start(context):
if g.t%g.tc==0:
#每g.tc天,交易一次行
g.if_trade=True
# 设置手续费与手续费
set_slip_fee(context)
# 设置可行股票池:获得当前开盘的沪深300股票池并剔除当前或者计算样本期间停牌的股票
g.all_stocks = set_feasible_stocks(get_index_stocks('000300.XSHG'),g.yb,context)
# 查询所有财务因子
# g.q = query(valuation,balance,cash_flow,income,indicator).filter(valuation.code.in_(g.all_stocks))
g.t+=1
#4
# 设置可行股票池
# 过滤掉当日停牌的股票,且筛选出前days天未停牌股票
# 输入:stock_list为list类型,样本天数days为int类型,context(见API)
# 输出:list
def set_feasible_stocks(stock_list,days,context):
# 得到前days天的所有股票,停牌开盘价是np.NAN
df =get_price(stock_list, count=days,end_date=context.current_dt,frequency='1d', fields=['open'],fill_paused=False,panel=False)
# 前days天有开盘价是np.NAN的股票代码
stopcode = df[df.open.isna()].code.drop_duplicates()
# 过滤停牌股票得到前days天未停牌股票的代码list:
feasible_stocks = df[~df.code.isin(stopcode)].code.unique().tolist()
return feasible_stocks
#5
# 根据不同的时间段设置滑点与手续费
def set_slip_fee(context):
# 将滑点设置为0
set_slippage(FixedSlippage(0))
# 根据不同的时间段设置手续费
dt=context.current_dt
log.info(type(context.current_dt))
if dt>datetime.datetime(2013,1, 1):
set_commission(PerTrade(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))
elif dt>datetime.datetime(2011,1, 1):
set_commission(PerTrade(buy_cost=0.001, sell_cost=0.002, min_cost=5))
elif dt>datetime.datetime(2009,1, 1):
set_commission(PerTrade(buy_cost=0.002, sell_cost=0.003, min_cost=5))
else:
set_commission(PerTrade(buy_cost=0.003, sell_cost=0.004, min_cost=5))
'''
================================================================================
每天交易时
================================================================================
'''
def handle_data_v2(context):
if g.if_trade==True:
# 计算现在的总资产,以分配资金,这里是等额权重分配
g.everyStock=context.portfolio.total_value/g.N
# 获得今天日期的字符串
todayStr=str(context.current_dt.date())
# 新代码,对应老代码,逻辑一致
toBuy = get_toBuy(todayStr)
# 对于不需要持仓的股票,全仓卖出
order_stock_sell(context,toBuy)
# 对于不需要持仓的股票,按分配到的份额买入
order_stock_buy(context,toBuy)
g.if_trade=False
##21
# 取股票新代码
def get_toBuy(todayStr):
# 获得因子排序
df = get_fundamentals(query(valuation,indicator).filter(valuation.code.in_(g.all_stocks)),todayStr)
df = df.set_index("code")[g.factors]
df.loc[df[df.market_cap.isna()].index,"market_cap"] = df.market_cap.mean()
df.loc[df[df.roe.isna()].index,"roe"] = df.roe.mean()
rankdf = df.rank(method='min',ascending=False)
# 计算每个股票的得分
rankdf['point'] = np.dot(rankdf.to_records(index=False).tolist(),[[1],[-1]])
# 对股票的得分进行排名,取前N名的股票
toBuy = rankdf.sort_values("point",ascending=False).head(g.N).index.tolist()
return toBuy
#6
#获得卖出信号,并执行卖出操作
#输入:context, data,toBuy-list
#输出:none
def order_stock_sell(context,toBuy):
#如果现有持仓股票不在股票池,清空
list_position=context.portfolio.positions.keys()
for stock in list_position:
if stock not in toBuy:
order_target(stock, 0)
#7
#获得买入信号,并执行买入操作
#输入:context, data,toBuy-list
#输出:none
def order_stock_buy(context,toBuy):
# 对于不需要持仓的股票,按分配到的份额买入
for s in g.all_stocks:
if s in toBuy:
order_target_value(s, g.everyStock)
'''
================================================================================
每天收盘后
================================================================================
'''
# 每日收盘后要做的事情(本策略中不需要)
def after_trading_end(context):
return
量化多因子
最新推荐文章于 2024-06-17 17:35:06 发布