一:积极投资法
格雷厄姆在《聪明的投资者》“积极型投资者”的六条选股标准
1.股票的市盈率低于市场水平
2.股票的市净率小于1.2
3.企业的流动比率要大于1.5
4.企业总借款不超过流动资产与总资产太多
5.最近5年净利润均大于零
6.利润増长处于较高水平
这其中有部分条件 对A股市场不太适用 。比如中国涨的好的股票市盈率和市净率都比较高。有很多科技股是部分年份亏损的。
根据中国市场的实践,对部分参数进行修改:得到一个简单策略
1 股票的市盈率高于市场平均水平
2 股票的市净率小于3
3 企业的流动比率要大于1.1
(流动比率(Current ratio),计算方法:流动比率=流动资产合计/流动负债合计。属于质量类因子)
4 企业长期负债与营运资金比率不超过5
(长期负债与营运资金比率(Long term debt to working capital)。计算方法:长期负债与营运资金比率=非流动负债合计/(流动资产合计-流动负债合计)。属于质量类因子)
5 利润増长处于较高水平:大于80%的股票
•买入条件:满足中国市场规则,则买入
•卖出条件:不满足中国市场规则有持仓,则卖出
def stock_sellection_Graham_positive_stock(context):'''股票的市盈率高于市场平均水平股票的市净率小于3企业的流动比率要大于1.1企业的长期负债 与营运资金(流动资产-流动负债)比率不超过5利润増长处于较高水平:大于80%的股票 '''previous_date = context.previous_dateaccount = context.get_account('fantasy_account')current_universe = context.get_universe( exclude_halt=True)#获取因子 5年收益增长率 收盘价 稀释每股收益data = DataAPI.MktStockFactorsOneDayGet(tradeDate=previous_date, secID=universe,field=['secID','tradeDate','PE','PB','CurrentRatio','LongDebtToWorkingCapital','NetProfitGrowRate'], pandas='1')data = data.dropna()#数据处理部分 #neg 流通市值data = data[(data.PB<3) & (data.PB)>0 &(data.PE > data.PE.quantile(0.9)) & (data.CurrentRatio>1.1) & (data.LongDebtToWorkingCapital < 5)&(data.NetProfitGrowRate >data.NetProfitGrowRate.quantile(0.9))]log.info(data)buy_list = data['secID'].tolist()print type(buy_list)return list(buy_list)

跑了下15年 牛市和股灾的回测 跑赢大盘20个点 还可以 调仓频率 较少
二 史蒂夫•路佛投资法
这个人也是一个比较牛逼的人 具体多牛我就不在这讲了 。他的选股法则
史蒂夫•路佛价值选股法则如下:
1 市净率低于全市场平均值的80%且小于1.5倍
2 以五年平均盈余计算的PE低于全市场平均值的70%且小于12倍
3 每股现金至少是股价的15% (现金流)
4 股息收益率不低于全市场平均值且不低于3%
5 股价现金流量比 低于 全市场平均值的75%
6 长期借款加未提拨退休金负债占总资本比率低于50% 负债比
7 流动比率高于全市场平均值 (偿还短期负债能力)
•结合中国实际情况后,原始标准调整如下:
1 市净率低于全市场均值的80%
2 五年平均盈余计算的PE高于全市场平均值的70%
(5年平均收益市值比(Five-year average earnings to price)。计算方法:5年平均收益市值比=近五年净利润(TTM)/近五年总市值)
3 不考虑股息收益率因素(中国股利的派发情况稀少)
4 股价现金流量比低于全市场平均值的75%
5 长期借款占总资本比率低于50%
6 流动比率高于全市场均值
满足 买入
买入后有持仓 股价涨到不满足 卖出。
Current ratio = Current assets / Current liabilities (流动资产 / 流动负债)
Quick ratio
=[cash + marketable securities + receivable] / Current liabilities
=[current asset - inventories] / Current liabilities
=【现金+有价证券+应收款项】/流动负债
=[流动资产-存货]/流动负债
Cash ratio
=[cash + marketable securities] / Current liabilities
第一部分 准备工作
import numpy as npimport pandas as pdimport talibimport datetimestart = '2015-01-01' # 回测起始时间end = '2016-01-01' # 回测结束时间universe = DynamicUniverse('A') # 证券池,支持股票、基金、期货、指数四种资产benchmark = 'HS300' # 策略参考标准freq = 'd' # 策略类型,'d'表示日间策略使用日线回测,'m'表示日内策略使用分钟线回测refresh_rate = 10 # 调仓频率,表示执行handle_data的时间间隔,若freq = 'd'时间间隔的单位为交易日,若freq = 'm'时间间隔为分钟# 配置账户信息,支持多资产多账户accounts = {'fantasy_account': AccountConfig(account_type='security', capital_base=10000000)}##每只股票买入卖出阈值Max_Position = 1000000def initialize(context):passdef handle_data(context):buy_list = stock_sellection_steve_stock(context)trading(buy_list,context)
第二部分 选股
def stock_sellection_steve_stock(context):previous_date = context.previous_dateaccount = context.get_account('fantasy_account')previous_date = previous_date.strftime('%Y%m%d')current_universe = context.get_universe( exclude_halt=True)security_position = account.get_positions()SV_factor = DataAPI.MktStockFactorsOneDayGet(tradeDate=previous_date, secID=current_universe, field=['secID','PB','ETP5','PCF','CurrentRatio','LongDebtToAsset'], pandas='1')SV_factor = SV_factor.dropna()SV_factor = SV_factor.set_index(['secID'])SV_factor = SV_factor[SV_factor['PCF']>0] #去掉现金流负的企业# ETP5 5年平均收益市值比(Five-year average earnings to price)。计算方法:5年平均收益市值比=近五年净利润(TTM)/近五年总市值。属于价值类因子。数据更新时间:T日21点30分。# PCF 市现率(Price-to-cash-flow ratio)。计算方法:总市值/经营活动产生的现金流量净额(TTM)#长期借款与资产总计之比(Long term loan to total assets)。计算方法:长期借款与资产总计之比=长期借款/总资产#流动比率(Current ratio),计算方法:流动比率=流动资产合计/流动负债合计。属于质量类因子SV_factor = SV_factor[(SV_factor['ETP5']>0.7*SV_factor['ETP5'].mean()) &(SV_factor['PCF']<0.75*SV_factor['PCF'].mean())& (SV_factor['LongDebtToAsset']<0.5) &(SV_factor['PB']< 0.8*SV_factor['PB'].mean()) & (SV_factor['CurrentRatio'] >SV_factor['CurrentRatio'].mean())]print(type(SV_factor))buy_list = SV_factor.indexprint(type(SV_factor))print(SV_factor)return list(buy_list)
第三部分 操作买入卖出 在这 多说一句 就是在策略中有单个股的持仓上限 为总资产的1/10 最多持仓为10个股
d = min(len(buy_list),int(cash)//Max_Position)
在buy_list 与 cash//max_positon选择较小的那个数字 即最多只买10只股票。
def trading(buy_list,context):account = context.get_account('fantasy_account')current_universe = context.get_universe( exclude_halt=True)security_position = account.get_positions()cash = account.cashfor sec in current_universe:if sec not in buy_list and sec in security_position:account.order_to(sec,0)cash += security_position[sec].amount * context.current_price(sec)d = min(len(buy_list),int(cash)//Max_Position)for sec in buy_list[:d]:if sec not in security_position:account.order(sec,Max_Position/ context.current_price(sec))
跑了下15年的 牛市和股灾的回撤 跑赢沪深300 60个点 很牛逼
跑了下 19年-20年的回测 也小幅跑赢大盘



调仓记录也不频繁 不错不错。




