Warning: file_exists(): open_basedir restriction in effect. File(/www/wwwroot/com.xiximiao.oa/com.cmstop/public/www/wp-content/db.php) is not within the allowed path(s): (/www/wwwroot/com.xiximiao.oa/com.cmstop/public/www/:/tmp/:/proc/:/var/log/nginx/:/www/wwwroot/com.xiximiao.oa/com.cmstop/public/:/www/wwwroot/com.xiximiao.oa/com.cmstop/vendor/:/www/wwwroot/com.xiximiao.oa/com.cmstop/ppk/) in /www/wwwroot/com.xiximiao.oa/com.cmstop/public/www/wp-includes/load.php on line 707
2042 市值,研发支出,roe,三因子,跑赢大盘.py » 轻知量化 QMT、PTrade、聚宽策略分享交流平台

2042 市值,研发支出,roe,三因子,跑赢大盘.py

# 风险及免责提示:该策略由聚宽用户分享,仅供学习交流使用。
# 原文一般包含策略说明,如有疑问建议到原文和作者交流讨论。
# 克隆自聚宽文章:https://www.joinquant.com/post/28499
# 标题:市值,研发支出,roe,三因子,跑赢大盘
# 作者:zyljq

# 克隆自聚宽文章:https://www.joinquant.com/post/1399
# 标题:【量化课堂】多因子策略入门
# 作者:JoinQuant量化课堂

#多因子策略入门
# 2015-01-01 到 2016-03-08, ¥2000000, 每天


'''
================================================================================
总体回测前
================================================================================
'''
import talib
#总体回测前要做的事情
def initialize(context):
    set_params()        #1设置策参数
    set_variables() #2设置中间变量
    set_backtest()   #3设置回测条件


#1
#设置策参数
def set_params():
    '''
    g.tc=15  # 调仓频率
    g.yb=63  # 样本长度
    g.N=20   # 持仓数目
    '''
    g.tc=15  # 调仓频率
    g.yb=63  # 样本长度
    g.N=9   # 持仓数目
    
    g.use_dynamic_target_market = True  # 是否动态改变大盘热度参考指标
    # g.target_market = '000300.XSHG'
    g.target_market = '399001.XSHE'
    g.empty_keep_stock = '511880.XSHG'  # 闲时买入的标的
    # g.empty_keep_stock = '601318.XSHG'#闲时买入的标的
    g.signal = 'BUY'  # 交易信号初始化
    g.emotion_rate = 0  # 市场热度
    g.lag = 5  # 大盘成交量连续跌破均线的天数,发出空仓信号 #5
    g.lag0 = 7  # 大盘成交量监控周期 #7
    g.lag1 = 13  # 比价均线周期 #13
    g.lag2 = 13  # 价格涨幅计算周期 #13
    
    
    
    
    
    '''
    g.factors=["market_cap","roe"] # 用户选出来的因子
    # 因子等权重里1表示因子值越小越好,-1表示因子值越大越好
    g.weights=[[1],[-1]]
    '''
    g.factors=["market_cap","development_expenditure","roe"] # 用户选出来的因子
    # 因子等权重里1表示因子值越小越好,-1表示因子值越大越好
    g.weights=[[-1],[-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))
        #print(g.q)
         
    g.t+=1
     
#4
# 设置可行股票池
# 过滤掉当日停牌的股票,且筛选出前days天未停牌股票
# 输入:stock_list为list类型,样本天数days为int类型,context(见API)
# 输出:list
def set_feasible_stocks(stock_list,days,context):
    # 得到是否停牌信息的dataframe,停牌的1,未停牌得0
    suspened_info_df = get_price(list(stock_list), start_date=context.current_dt, end_date=context.current_dt, frequency='daily', fields='paused')['paused'].T
    # 过滤停牌股票 返回dataframe
    unsuspened_index = suspened_info_df.iloc[:,0]<1 # 得到当日未停牌股票的代码list: unsuspened_stocks = suspened_info_df[unsuspened_index].index # 进一步,筛选出前days天未曾停牌的股票list: feasible_stocks=[] current_data=get_current_data() for stock in unsuspened_stocks: if sum(attribute_history(stock, days, unit='1d',fields=('paused'),skip_paused=False))[0]==0: feasible_stocks.append(stock) 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 after_trading_end(context):
    return


def EmotionMonitor():
    _cnt = g.lag0 + max(g.lag, 3)
    #volume = attribute_history(security=g.target_market, count=_cnt, unit='1d', fields='volume')['volume']
    volume = attribute_history(security=g.target_market, count=_cnt, unit='1d', fields='volume')['volume']
    v_ma_lag0 = talib.MA(volume, g.lag0)  # 前 g.lag0 - 1 个会变成nan
    #
    g.emotion_rate = round((volume[-1] / v_ma_lag0[-1] - 1) * 100, 2)  # 最后一天的成交量比成交量均值高%
    #
    vol_diff = (volume - v_ma_lag0)
    if vol_diff[-1] >= 0:
        ret_val = 1 if (vol_diff[-3:] >= 0).all() else 0  # 大盘成交量,最近3天都站在均线之上
    else:
        ret_val = -1 if (vol_diff[-g.lag:] < 0).all() else 0 # 大盘成交量,最近g.lag天都在均线之下 # return ret_val ''' ================================================================================ 每天交易时 ================================================================================ ''' def handle_data(context, data): if g.if_trade==True: # 计算现在的总资产,以分配资金,这里是等额权重分配 g.everyStock=context.portfolio.portfolio_value/g.N # 获得今天日期的字符串 todayStr=str(context.current_dt)[0:10] # 获得因子排序 a,b=getRankedFactors(g.factors,todayStr) # 计算每个股票的得分 points=np.dot(a,g.weights) # 复制股票代码 stock_sort=b[:] # 对股票的得分进行排名 points,stock_sort=bubble(points,stock_sort) # 取前N名的股票 toBuy=stock_sort[0:g.N].values # 对于不需要持仓的股票,全仓卖出 order_stock_sell(context,data,toBuy) # 对于不需要持仓的股票,按分配到的份额买入 order_stock_buy(context,data,toBuy) g.if_trade=False #6 #获得卖出信号,并执行卖出操作 #输入:context, data,toBuy-list #输出:none def order_stock_sell(context,data,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,data,toBuy): # 对于不需要持仓的股票,按分配到的份额买入 for i in range(0,len(g.all_stocks)): if indexOf(g.all_stocks[i],toBuy)>-1 :
            order_target_value(g.all_stocks[i], g.everyStock)


#8
#查找一个元素在数组里面的位置,如果不存在,则返回-1
#输入:元素,对应数组
#输出:-1
def indexOf(e,a):
    for i in range(0,len(a)):
        if e==a[i]:
            return i
    return -1


#9
#取因子数据
#输入:f-全局通用的查询,d-str
#输出:因子数据,股票的代码-dataframe
def getRankedFactors(f,d):
    # 获得股票的基本面数据,这个API里面有,g.q是一个全局通用的查询
    df = get_fundamentals(g.q,d)
    #print(df.shape)
    for i in range(0,df.shape[1],10):
        print( df.columns[i:i+10] )
    
    # 为了防止Python里面的浅复制现象,采用循环来定义二维数组
    res = [([0] * len(f)) for i in range(len(df))]
    # 把数据填充到刚才定义的数组里面
    for i in range(0,len(df)):
        for j in range(0,len(f)):
            res[i][j]=df[f[j]][i]
    # 用均值填充NaN值
    fillNan(res)
    '''
    for i in range(len(res)):
        res[i][0]=res[i][1]/res[i][0]
        del res[i][0]
    '''
    # 将数据变成排名
    #print(res)
    getRank(res)
    # 返回因子数据和股票的代码(这个是因为沪深300指数成分股一直在变,如果用未来的沪深300指数成分股在之前可能有一些股票还没上市)
    return res,df['code']

2025-02-20
⚠️
本站资源大多来自网络,仅供网友学习交流,未经作者或上传书面授权,请勿作他用。
站长 vx: xiangyin615 或者 留言反馈 ,我们将尽快处理。
Notice: When you of the legal rights be violate, please stir to vx: xiangyin615
个人中心
购物车
优惠劵
搜索