Bootstrap

AI顾投高级策略之四:詹姆斯.奥肖内西的价值投资法(建议收藏)

作者:老余捞鱼

原创不易,转载请标明出处及原作者。

写在前面的话:
詹姆斯·奥肖内西是一位著名的投资者,他的投资方法深受定量分析的影响,尤其是在价值投资领域中。他的方法通过使用历史数据和复杂的数学模型来识别被低估的股票,从而尝试系统地战胜市场。奥肖内西在他的书籍和研究中提出了几种策略,其中最著名的是“怎样击败市场”(How to Beat the Market)系列。通过这些策略,奥肖内西希望能找到市场中的误价股票,并通过长期持有这些股票获得超额回报。他的方法为价值投资提供了一种更科学、系统的方式,使其区别于更传统的、主观判断较多的价值投资策略。

奥肖内西的独特之处

  • 定量方法:他强调使用客观、可重复的方法来选择股票,减少人为情感和偏见的影响。
  • 多因子模型:不只依赖单一财务指标,而是综合考虑多个因素来评估股票的价值。
  • 历史数据验证:他的所有策略都基于历史数据的广泛测试,以证明其有效性。

        通过这些策略,奥肖内西希望能找到市场中的误价股票,并通过长期持有这些股票获得超额回报。他的方法为价值投资提供了一种更科学、系统的方式,使其区别于更传统的、主观判断较多的价值投资策略。

算法代码如下:

'''
策略选股
A. 股票的市值大于市场的中位数
B. 股票的股本大于市场的中位数
C. 股票的市现率大于0,从小到大排列,取前400只股票
D. 股票的市销率大于0,从小到大排列,取前400只股票
E. 股票的股息率从大到小排列,取前400只股票
F. 取上述5个条件满足下的前30只股票
交易方式:按月调仓
止损方式
A. 当个股价格低于成本价的7%时,卖出该股票
B. 当5日内大盘下跌13%时,卖出所有股票

'''

from datetime import timedelta, date
import pandas as pd

############################## 以下为主要函数 ################################
# 初始化函数 ##################################################################

def init(context):
 # 设置手续费为交易额的0.02%,最少5元
 set_commission(PerShare(type='stock', cost=0.0003, min_trade_cost=5.0))
 # 设置可变滑点,买入成交价 = 委托价 * (1 + 0.1%),卖出成交价 = 委托价 * (1 - 0.1%);
 set_slippage(PriceSlippage(0.002))
 context.selected = 400
 context.n = 30 # 持股数
 context.trade_date = range(1,13,1)
 ## 按月调用程序
 run_monthly(trade,date_rule=-1)
 
# 月末调仓函数 #################################################################
def trade(context, bar_dict):
 date = get_datetime()
 months = get_datetime().month
 if months in context.trade_date:
 
 
 ##获得购买股票列表
 market_cap_list = stocks_market_cap(context, bar_dict)
 PCF_list = stocks_PCF(context, bar_dict)
 PS_list = stocks_PS(context, bar_dict)
 capitalization_list = stocks_capitalization(context, bar_dict)
 DY_list = stocks_DY(context, bar_dict)
 ## 获得满足每种条件的股票池
 stock_list = list(set(market_cap_list)&set(PCF_list)&set(PS_list)&set(capitalization_list)&set(DY_list))
 log.info(len(stock_list))
 
 ## 卖出
 if len(context.portfolio.positions) > 0:
 for stock in list(context.portfolio.positions):
 if stock not in stock_list:
 order_target(stock, 0)
 ## 买入
 if len(stock_list) > 0:
 for stock in stock_list:
 if stock not in list(context.portfolio.positions):
 if len(context.portfolio.positions) < context.n :
 number = context.n - len(context.portfolio.positions)
 order_value(stock,context.portfolio.available_cash/number)
 else: 
 order_value(stock,context.portfolio.available_cash)
 
 else:
 pass

# 每日检查止损条件 ############################################################# 
def handle_bar(context, bar_dict):
 last_date = get_last_datetime().strftime('%Y%m%d')
 
 if len(context.portfolio.positions) > 0:
 # 止损:个股跌幅超过8%,卖出
 securities = list(context.portfolio.positions)
 for stock in securities:
 price = history(stock, ['close'], 1, '1d', False,'pre')
 if context.portfolio.positions[stock].cost_basis/price['close'][0]-1 < -0.08:
 order_target(stock, 0)
 #log.info('%s 止损:%s' %(last_date,stock))
 
 #止损:5天内大盘下跌13%,卖出
 price_bench = history('000300.SH', ['close'], 5, '1d', False,'pre')
 if price_bench['close'][-5]/price_bench['close'][-1]-1 > 0.13:
 if len(list(context.portfolio.positions))>0:
 for stock in list(context.portfolio.positions):
 order_target(stock, 0)

################## 以下为功能函数, 在主要函数中调用 ##########################

# 1 根据市值来筛选股票列表
def stocks_market_cap(context, bar_dict):
 last_date = get_last_datetime().strftime('%Y%m%d')
 market_cap = get_fundamentals(query(
 valuation.symbol,
 valuation.market_cap
 ).order_by(
 valuation.market_cap.desc()
 ),date = last_date)
 length = len(market_cap)
 market_cap = market_cap[:int(length/2)]
 return list(market_cap['valuation_symbol'])

# 2. 根据股本来筛选股票列表
def stocks_capitalization(context, bar_dict):
 last_date = get_last_datetime().strftime('%Y%m%d')
 capitalization = get_fundamentals(query(
 valuation.symbol,
 valuation.capitalization
 ).order_by(
 valuation.capitalization.desc()
 ),date = last_date)
 length = len(capitalization)
 capitalization = capitalization[:int(length/2)]
 return list(capitalization['valuation_symbol'])

# 3. 根据市现率来筛选股票列表
def stocks_PCF(context, bar_dict):
 last_date = get_last_datetime().strftime('%Y%m%d')
 PCF = get_fundamentals(query(
 valuation.symbol,
 valuation.pcf
 ).filter(
 valuation.pcf > 0
 ).order_by(
 valuation.pcf.asc()
 ).limit(
 context.selected
 ),date = last_date)
 return list(PCF['valuation_symbol'])

# 4. 根据市销率来筛选股票列表
def stocks_PS(context, bar_dict):
 last_date = get_last_datetime().strftime('%Y%m%d')
 PS = get_fundamentals(query(
 valuation.symbol,
 valuation.ps
 ).filter(
 valuation.ps>0
 ).order_by(
 valuation.ps.asc() 
 ),date = last_date)
 return list(PS['valuation_symbol'])

# 5. 根据股息率(每股收益/每股市价代替)来筛选股票列表

def stocks_DY(context, bar_dict):
 last_date = get_last_datetime().strftime('%Y%m%d')
 EPS = get_fundamentals(query(
 income.symbol,
 income.basic_eps
 ),date = last_date)
 stock_List = list(EPS['income_symbol'])
 close_price = history(stock_List,['close'],1,'1d',True,None)
 DY_stock = dict(zip(EPS['income_symbol'],EPS['income_basic_eps']))
 log.info(len(DY_stock)-len(EPS['income_symbol']))
 for stock in stock_List:
 try:
 DY_stock[stock] = DY_stock[stock]/close_price[stock]['close'][0]
 except:
 DY_stock[stock] = 0
 
 DY_stock = sorted(DY_stock.items(),key=lambda t:t[1],reverse=True) 
 return list(dict(DY_stock[:context.selected]).keys())


 本文内容仅仅是技术探讨和学习,并不构成任何投资建议。

原创不易,转载请标明出处及原作者。

;