量化学习平台
文章
市场宽度
背离图
登录
注册
全市场选股?7年5倍不择时,回撤30%左右
策略
作者: 水滴
```python # 风险及免责提示:该策略由聚宽用户在聚宽社区分享,仅供学习交流使用。 # 原文一般包含策略说明,如有疑问请到原文和作者交流讨论。 # 原文网址:https://www.joinquant.com/post/35307 # 标题:全市场选股?7年5倍不择时,回撤30%左右 # 作者:Jacobb75 # 克隆自聚宽文章:https://www.joinquant.com/post/34964 # 标题:这个策略太牛逼了,今年赚了那么多 # 作者:wgl # 克隆自聚宽文章:https://www.joinquant.com/post/34862 # 标题:ROE+PB模型的优化 # 作者:wywy1995 # 导入函数库 import jqdata from jqlib.technical_analysis import * from jqdata import * import warnings # 初始化函数 def initialize(context): # 滑点高(不设置滑点的话用默认的0.00246) set_slippage(FixedSlippage(0.02)) # 国证A指数作为基准 set_benchmark('399317.XSHE') # 用真实价格交易 set_option('use_real_price', True) set_option("avoid_future_data", True) # 过滤order中低于error级别的日志 log.set_level('order', 'error') warnings.filterwarnings("ignore") # 选股参数 g.stock_num = 10 # 持仓数 g.position = 1 # 仓位 g.bond = '511880.XSHG' # 手续费 set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0005, close_commission=0.0005, min_commission=5), type='stock') # 设置交易时间 #run_weekly(my_trade, weekday=4, time='9:45', reference_security='000852.XSHG') run_monthly(my_trade, monthday=-4, time='11:30', reference_security='000852.XSHG') # 开盘时运行函数 def my_trade(context): # 获取选股列表并过滤掉:st,st*,退市,涨停,跌停,停牌 check_out_list = get_stock_list(context) log.info('今日自选股:%s' % check_out_list) adjust_position(context, check_out_list) # 2-2 选股模块 # 选出资产负债率后20%且大于0,优质资产周转率前20%,roa改善最多的股票列表 def get_stock_list(context): # type: (Context) -> list curr_data = get_current_data() yesterday = context.previous_date df_stocknum = pd.DataFrame(columns=['当前符合条件股票数量']) # 过滤次新股 #by_date = yesterday #by_date = datetime.timedelta(days=1200) by_date = yesterday - datetime.timedelta(days=1200) # 三年 initial_list = get_all_securities(date=by_date).index.tolist() # 0. 过滤创业板,科创板,st,今天涨跌停的,停牌的 initial_list = [stock for stock in initial_list if not ( (curr_data[stock].day_open == curr_data[stock].high_limit) or (curr_data[stock].day_open == curr_data[stock].low_limit) or curr_data[stock].paused #curr_data[stock].is_st #('ST' in curr_data[stock].name) or #('*' in curr_data[stock].name) #('退' in curr_data[stock].name) or #(stock.startswith('300')) or #(stock.startswith('688')) or #(stock.startswith('002')) )] df_stocknum = df_stocknum.append({'当前符合条件股票数量': len(initial_list)}, ignore_index=True) # 1,选出资产负债率由高到低后70%的,low_liability_list df = get_fundamentals( query( balance.code, balance.total_liability, balance.total_assets #balance.code, balance.total_non_current_liability,balance.total_non_current_assets ).filter( valuation.code.in_(initial_list) ) ).dropna() # df = df.fillna(0) df['ratio'] = df['total_liability'] / df['total_assets'] # 资产负债率 df = df.sort_values(by = 'ratio',ascending=False) low_liability_list = list(df.code)[int(0.3*len(list(df.code))):] df_stocknum = df_stocknum.append({'当前符合条件股票数量': len(low_liability_list)}, ignore_index=True) # 2,从low_liability_list中选出不良资产比率在总体中[20%-80%]范围内的的股票,proper_receivable_list df1 = get_fundamentals( query(balance.code, balance.total_assets, # 总资产 balance.bill_receivable, # 应收票据 balance.account_receivable, # 应收账款 balance.other_receivable, # 其他应收款 balance.good_will, # 商誉 balance.intangible_assets, # 无形资产 balance.inventories, # 存货 balance.constru_in_process,# 在建工程 ).filter( balance.code.in_(low_liability_list) ) ).dropna() df1 = df1.fillna(0) df1['bad_assets'] = df1.sum(axis=1) - df1['total_assets'] # 其中bad_assets占的比例 df1['ratio1'] = df1['bad_assets'] / df1['total_assets'] df1 = df1.sort_values(by = 'ratio1',ascending=False) proper_receivable_list = list(df1.code)[int(0.1*len(list(df1.code))):int(0.9*len(list(df1.code)))] df_stocknum = df_stocknum.append({'当前符合条件股票数量': len(proper_receivable_list)}, ignore_index=True) # 3,从proper_receivable_list中选出优质资产周转率前75%的公司,proper_receivable_list1 df2 = get_fundamentals( query(balance.code, balance.total_assets, # 总资产 balance.bill_receivable, # 应收票据 balance.account_receivable, # 应收账款 balance.other_receivable, # 其他应收款 balance.good_will, # 商誉 balance.intangible_assets, # 无形资产 balance.inventories, # 存货 balance.constru_in_process,# 在建工程 income.total_operating_revenue# 营业收入 ).filter( balance.code.in_(proper_receivable_list) ) ).dropna() df2 = df2.fillna(0) df2['good_assets'] = df2['total_assets'] - (df2.sum(axis=1) - df2['total_assets'] - df2['total_operating_revenue']) # 其中bad_assets占的比例 df2['ratio2'] = df2['total_operating_revenue'] / df2['good_assets'] df2 = df2.sort_values(by = 'ratio2',ascending=False) proper_receivable_list1 = list(df2.code)[:int(0.75*len(list(df2.code)))] df_stocknum = df_stocknum.append({'当前符合条件股票数量': len(proper_receivable_list1)}, ignore_index=True) # 4,从proper_receivable_list1中过去十二个季度ROA增长最多(前20%)的股票,按照ROA`增长量降序排列,roa_list df3 = get_history_fundamentals( proper_receivable_list1, fields=[indicator.code, indicator.roa], watch_date=yesterday, count=4, interval='1q' ).dropna() s_delta_avg = df3.groupby('code')['roa'].apply( lambda x: x.iloc[3] - x.mean() if len(x) == 4 else 0.0 #lambda x: x.iloc[11] - x.mean() if len(x) == 12 else 0.0 ).sort_values( ascending=False ) roa_list = list(s_delta_avg[:int(0.2 * len(s_delta_avg))].index) df_stocknum = df_stocknum.append({'当前符合条件股票数量': len(roa_list)}, ignore_index=True) ''' # 4,从proper_receivable_list1中过去十二个季度ROA增长最多(前20%)的股票,按照ROA`增长量降序排列,roa_list df3 = get_history_fundamentals( proper_receivable_list1, fields=[indicator.code, income.total_profit, # 净利润 balance.total_assets, # 总资产 balance.bill_receivable, # 应收票据 balance.account_receivable, # 应收账款 balance.other_receivable, # 其他应收款 balance.good_will, # 商誉 balance.intangible_assets, # 无形资产 balance.inventories, # 存货 balance.constru_in_process# 在建工程 ], watch_date=yesterday, count=4, interval='1q' ).dropna() df3['ratio3'] = df3['total_profit'] / (df3['total_assets'] - (df3.sum(axis=1) - df3['total_assets'] - df3['total_profit'])) s_delta_avg = df3.groupby('code')['ratio3'].apply( lambda x: x.iloc[3] - x.mean() if len(x) == 4 else 0.0 #lambda x: x.iloc[11] - x.mean() if len(x) == 12 else 0.0 ).sort_values( ascending=False ) ''' # 5.从过去五个季度ROA增长量前20%的股票中选出市净率大于0的按照资产负债率升序排列选出前g.stock_num个,final_list pb_list = get_fundamentals( query( valuation.code ).filter( valuation.code.in_(roa_list), #valuation.pb_ratio < 2, valuation.pb_ratio > 0.7, valuation.ps_ratio < 3, #valuation.ps_ratio > 0 #indicator.ocf_to_operating_profit > 1, #indicator.eps > 0 #indicator.roa ).order_by( valuation.pb_ratio.asc() #indicator.eps.desc() #valuation.circulating_market_cap.desc() ) )['code'].tolist() indicator.ocf_to_operating_profit df_stocknum = df_stocknum.append({'当前符合条件股票数量': len(pb_list)}, ignore_index=True) print(df_stocknum) final_list = pb_list[:g.stock_num] return final_list ''' last_list = pb_list[:g.stock_num] df_stock = pd.DataFrame(columns=['指数代码', '周期动量']) unit=g.unit BBI2 = BBI(last_list, check_date=context.current_dt, timeperiod1=3, timeperiod2=6, timeperiod3=12, timeperiod4=24,unit=unit,include_now=True) for stock in last_list:#运行中的指数 df_close = get_bars(stock, 1, unit, ['close'], end_dt=context.current_dt,include_now=True,)['close'] #读取index当天的收盘价 val = BBI2[stock]/df_close[0]#BBI除以交易当天11:15分的价格,大于1表示空头,小于1表示多头 df_stock = df_stock.append({'股票代码': stock, '周期动量': val}, ignore_index=True)#将数据写入df_index表格,索引重置 #按'周期动量'进行从大到小的排列。ascending=true表示降序排列,ascending=false表示升序排序,inplace = True:不创建新的对象,直接对原始对象进行修改 df_stock.sort_values(by='周期动量', ascending=False, inplace=True) final_list = df_stock['股票代码'].iloc[-1]#读取最后一行的股票代码 return final_list ''' def adjust_position(context, buy_stocks): #order_value(g.bond,context.portfolio.available_cash) for stock in context.portfolio.positions: if stock not in buy_stocks: order_target(stock, 0) # position_count = len(context.portfolio.positions) if g.stock_num > position_count: value = context.portfolio.cash * g.position / (g.stock_num - position_count) for stock in buy_stocks: if stock not in context.portfolio.positions: order_target_value(stock, value) if len(context.portfolio.positions) == g.stock_num: break ```
文章分类
关于作者
水滴
注册时间: