量化学习平台
文章
市场宽度
背离图
登录
注册
搞市场最靓的仔!指数ETF动量轮动策略-2
策略
作者: 水滴
```python # 风险及免责提示:该策略由聚宽用户在聚宽社区分享,仅供学习交流使用。 # 原文一般包含策略说明,如有疑问请到原文和作者交流讨论。 # 原文网址:https://www.joinquant.com/post/46429 # 标题:搞市场最靓的仔!指数ETF动量轮动策略-2 # 作者:野蛮生涨 # 原回测条件:2020-01-01 到 2024-02-03, ¥100000, 每天 # 导入函数库 from jqdata import * import random # 初始化函数,设定基准等等 def initialize(context): # 设定沪深300作为基准 set_benchmark('000300.XSHG') set_option("avoid_future_data", True) # 开启动态复权模式(真实价格) set_option('use_real_price', True) # 输出内容到日志 log.info() log.info('初始函数开始运行且全局只运行一次') # 过滤掉order系列API产生的比error级别低的log # log.set_level('order', 'error') ### 股票相关设定 ### # 股票类每笔交易时的手续费是:千分之一印花税,买入时佣金万分之2.5,卖出时佣金万分之2.5, 每笔交易佣金最低扣5块钱 # 基金类每笔交易时的手续费是:无印花税,买入时佣金万分之1,卖出时佣金万分之1, 每笔交易佣金最低扣5块钱 #set_order_cost(OrderCost(close_tax=0.001, open_commission=0.00025, close_commission=0.00025, min_commission=5), type='stock') set_order_cost(OrderCost(close_tax=0.000, open_commission=0.0001, close_commission=0.0001, min_commission=5), type='fund') # 设置滑点,ETF单价较低滑点高了对影响较大 set_slippage(PriceRelatedSlippage(0.001),type='fund') # 开盘前运行 run_daily(before_market_open, time='before_open', reference_security='000300.XSHG') # 收盘后运行 run_daily(after_market_close, time='after_close', reference_security='000300.XSHG') # 日线策略,指定时间运行,如果后期要分钟级这里需要改成分钟级handle_data run_daily(my_trade, time='14:50', reference_security='000300.XSHG') g.stocks={ '510500.XSHG', # 中证500ETF '510300.XSHG', # 沪深510300 '510050.XSHG', # 上证50 '159949.XSHE', # 创业板50 '513100.XSHG', # 纳指ETF '513500.XSHG', # 标普500 '159920.XSHE', # 恒生ETF '513520.XSHG', # 日经ETF '513030.XSHG', # 德国30 '162411.XSHE', # 华宝油气 '159985.XSHE'} # 豆粕ETF # 持仓状态 g.position={'ETF_HOLD':'0', 'STATUS':0, 'HOLD_NUM':0} ## 开盘前运行函数 def before_market_open(context): # 输出运行时间 log.info('函数运行时间(before_market_open):'+str(context.current_dt.time())) print("持仓情况:{0}".format(g.position)) def after_code_changed(context): log.info('函数运行时间(after_code_changed):'+str(context.current_dt.time())) # 更换后代码执行,尤其需要注意持仓情况 print("持仓情况:{0}".format(g.position)) def my_trade(context): N=21 # N日前收盘价的涨幅 # 该list用于存放计算出来的结果,并按动量排序 SEC_LIST=[] SEC_LIST_DETAIL={} R_LIST=[] curr_data = get_current_data() for security in g.stocks: close_data1 = attribute_history(security, 30, unit='1d', fields=['close'])['close'] # 不包含当天数据 #log.debug(close_data1) # 有些ETF成立时间较短,取不到数据则直接退出 curr_price = curr_data[security].last_price # 当前价 #his_n_price = close_data1[-N] # 特定的一个历史价 #his_n_price = (sum(close_data1[-(N-1):])+curr_price)/N # N日均线 his_n_price = sum(close_data1[-23:-20])/3 # 21日前3日均线 if curr_price!=curr_price or his_n_price!=his_n_price or curr_price<0.01 or his_n_price<0.01: log.warning("未取到[%s]分钟级数据,直接退出!!!" % (curr_data[security].name)) return #continue #R = (curr_price - his_n_price)*100/his_n_price # 当前价较前N日前价格的涨幅 # 用一天的价格进行判断,有时候一天涨跌太大,导致频繁换仓适得其反,用近3日均价跟21日前3日均价的涨幅来pa稍微平滑一点 R = (close_data1[-2]+close_data1[-1]+curr_price-sum(close_data1[-23:-20]))*100/sum(close_data1[-23:-20]) base_price = close_data1[-N] # 特定的一个历史价,也也可以换为MA均线 # 回测偶尔有遇到到R结果一致的情况,导致排序出错,如果有重复的加一个随机数 if R in R_LIST: R = R + random.random()/1000 R_LIST.append(R) SEC_LIST.append((R,security,curr_price,base_price)) # 将ETF进行排序 SEC_LIST.sort(reverse=True) ETF_No1 = SEC_LIST[0][1] if g.position['STATUS']==0: # 大于历史价才买进 if SEC_LIST[0][2] > SEC_LIST[0][3]*1.001: log.info("目前空仓买入:%s" % ETF_No1) order_target_value(ETF_No1, context.portfolio.cash) g.position['STATUS'] = 1 g.position['ETF_HOLD'] = ETF_No1 elif g.position['STATUS']==1: if g.position['ETF_HOLD'] == ETF_No1: # 跌破历史价卖出 if SEC_LIST[0][2] < SEC_LIST[0][3]*0.999: log.info("持仓%s排名第一,但小于历史价需要卖出" % g.position['ETF_HOLD']) order_target_value(g.position['ETF_HOLD'], 0) g.position['STATUS'] = 0 g.position['ETF_HOLD'] = ' ' else: log.info("持仓%s排名第一,继续持仓" % g.position['ETF_HOLD']) else: if SEC_LIST[0][2] > SEC_LIST[0][3]*1.001: order_target_value(g.position['ETF_HOLD'], 0) order_target_value(ETF_No1, context.portfolio.cash) g.position['ETF_HOLD'] = ETF_No1 ## 收盘后运行函数 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)) log.info('一天结束') log.info('##############################################################\n\n') ```
文章分类
关于作者
水滴
注册时间: