# 标题:基于大盘PE标准差偏离度的聪明基金定投策略
# 作者:逆熵者
'''
========================================================================
# 指数基金PE估值弹性定投
# 作者: 逆熵者
大约一年的定投资金作为初始资金建立底仓,每月向账户中固定增加资金
每周四定投,根据PE估值调整用完所有资金或卖掉所有持仓所需的周数
根据PE移动平均线和标准差划定高低线
低于低线采取买入模式,越低买光全部资金所需周数越少
高于高线采取卖出模式,越高卖出所有持仓所需周数越少
两线之间为合理区间,按照预订周数定投
========================================================================
'''
# 导入函数库
from jqdata import *
from jqlib.technical_analysis import *
import numpy as np
import datetime
'''
========================================================================
# 初始化函数,设定基准等等
========================================================================
'''
def initialize(context):
# 设置对比基准
g.benchmark = '000300.XSHG'
set_benchmark(g.benchmark)
# 开启动态复权模式(真实价格)
set_option('use_real_price', True)
# 避免未来函数
set_option("avoid_future_data", True)
# 输出内容到日志 log.info()
log.info('初始函数开始运行且全局只运行一次')
# 初始化高低估线
g.stdpeH = 1.5
g.stdpeL = 1.2
g.now_pe = 1
######实盘无效#######
# 为全部交易品种设定固定金额滑点(单位元)
set_slippage(FixedSlippage(0.02))
### 股票相关设定 ###
# 股票类每笔交易时的手续费是:买入时佣金万3,卖出时佣金万分3,加千分之一印花税, 每笔交易佣金最低扣5块钱
set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
### 场内基金设定 ###
# 场内基金类每笔交易时的手续费是:买入时佣金万3,卖出时佣金万3,加千分之一印花税, 每笔交易佣金最低扣5块钱
set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003 , close_commission=0.0003, min_commission=5), type='fund')
# 修改代码后运行
def after_code_changed(context): # 修改代码后运行
# 设置交易标的
g.security = '510300.XSHG'
# 设置日志过滤等级
log.set_level('order', 'error')
g.weeks = 50 #正常估值时多少周投完本金
# 运行函数(reference_security为运行时间的参考标的;传入的标的只做种类区分)
# 每天开盘前运行
run_daily(before_market_open, time='before_open', reference_security=g.security)
# 每周倒数第二天运行交易函数
run_weekly(market_open, -2, time='open', reference_security=g.security)
# 每天收盘后运行
run_daily(after_market_close, time='after_close', reference_security=g.security)
# 每周开盘前运行
run_weekly(code_run_weekly, 1, time='before_open')
# 每月第6个交易日增加账户资金(发工资)
run_monthly(wages_monthily, 6, time='before_open')
'''
========================================================================
# 每天开盘前运行函数
========================================================================
'''
def before_market_open(context):
# 日志输出运行时间
log.info('=====================美好的一天开始了==========================')
log.info('【开盘前】(before_market_open):'+str(context.current_dt.time()))
# 获取昨天时间
g.date = date = context.previous_date
previous_date = context.previous_date
# 给微信发送消息(添加模拟交易,并绑定微信生效)
# send_message('总资产:%s元'%context.portfolio.total_value)
# send_message('持股市值:%s元'%context.portfolio.positions_value)
# send_message('当前持仓:%s'%context.portfolio.positions.keys())
log.info('总资产:%s元' % context.portfolio.total_value)
log.info('持股市值:%s元' % context.portfolio.positions_value)
'''
========================================================================
# 开盘时运行交易函数
========================================================================
'''
def market_open(context):
# 日志输出运行时间
log.info('【开盘时】(market_open):'+str(context.current_dt.time()))
# 计算当前估值
qtt = QuantTiming(context.previous_date,g.security)
# g.ema_speed = qtt.ema_speed()
g.now_pe = qtt.now()
# 获取目标周数
target_weeks = qtt.how_many_weeks()
# # 获取当前仓位
# now_position = float(context.subportfolios[0].positions_value) / float(context.subportfolios[0].total_value)
if target_weeks < 0:
# 计算目标价值(周数为负,所以值为负)
target_value = context.portfolio.positions_value + context.portfolio.positions_value / target_weeks
log.info("【卖出】 %s" % (g.security))
# 卖出
order_target_value(g.security, target_value)
elif target_weeks > 0:
# 计算目标价值(周数为正,所以值为正)
target_value = context.portfolio.positions_value + context.portfolio.available_cash / target_weeks
log.info("【买入】 %s" % (g.security))
# 买入
order_target_value(g.security, target_value)
else:
pass
'''
========================================================================
# 每天收盘后运行函数
========================================================================
'''
def after_market_close(context):
# 日志输出运行时间
log.info(str('【收盘后】(after_market_close):'+str(context.current_dt.time())))
# 得到当天所有成交记录
trades = get_trades()
for _trade in trades.values():
log.info('成交记录:'+str(_trade))
if g.now_pe > g.stdH:
g.pe_status = '高估'
elif g.now_pe < g.stdL:
g.pe_status = '低估'
else:
g.pe_status = '合理'
# 记录当天的PE
g.last_pe = g.now_pe
log.info('大盘状态:%s'%g.pe_status)
log.info('PE宏观高估线:%s'%g.stdH)
log.info('大盘标准化PE:%s'%g.now_pe)
log.info('PE宏观低估线:%s'%g.stdL)
log.info('当前仓位比例:%f'%(context.portfolio.positions_value/context.portfolio.total_value))
# log.info('大盘MA变化率:%s'%g.ema_speed)
log.info('##########################一天结束############################')
log.info(' ')
# 绘制相关参考图线
record(
PE=g.now_pe,
高估=g.stdH,
低估=g.stdL,
当前仓位=1 + 0.5 * context.portfolio.positions_value/context.portfolio.total_value,
)
'''
========================================================================
## 设定每周运行
========================================================================
'''
def code_run_weekly(context):
qtt = QuantTiming(context.previous_date,g.security)
g.stdpeH,g.stdpeL = qtt.std()
# 高低估线
g.stdH = g.stdpeH
g.stdL = g.stdpeL
# 每月发工资后账户增加5000元
def wages_monthily(context):
inout_cash(5000, pindex=0)
之后完整策略代码解锁后查看:
